Submit
Path:
~
/
/
usr
/
share
/
grafana
/
public
/
app
/
plugins
/
datasource
/
zipkin
/
utils
/
File Content:
graphTransform.ts
import { DataFrame, NodeGraphDataFrameFieldNames as Fields } from '@grafana/data'; import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '@grafana/o11y-ds-frontend'; import { ZipkinSpan } from '../types'; interface Node { [Fields.id]: string; [Fields.title]: string; [Fields.subTitle]: string; [Fields.mainStat]: string; [Fields.secondaryStat]: string; [Fields.color]: number; } interface Edge { [Fields.id]: string; [Fields.target]: string; [Fields.source]: string; } export function createGraphFrames(data: ZipkinSpan[]): DataFrame[] { const { nodes, edges } = convertTraceToGraph(data); const [nodesFrame, edgesFrame] = makeFrames(); for (const node of nodes) { nodesFrame.add(node); } for (const edge of edges) { edgesFrame.add(edge); } return [nodesFrame, edgesFrame]; } function convertTraceToGraph(spans: ZipkinSpan[]): { nodes: Node[]; edges: Edge[] } { const nodes: Node[] = []; const edges: Edge[] = []; const traceDuration = findTraceDuration(spans); const spanMap = makeSpanMap((index) => { if (index >= spans.length) { return undefined; } return { span: spans[index], id: spans[index].id, parentIds: spans[index].parentId ? [spans[index].parentId!] : [], }; }); for (const span of spans) { const ranges: Array<[number, number]> = spanMap[span.id].children.map((c) => { const span = spanMap[c].span; return [span.timestamp, span.timestamp + span.duration]; }); const childrenDuration = getNonOverlappingDuration(ranges); const selfDuration = span.duration - childrenDuration; const stats = getStats(span.duration / 1000, traceDuration / 1000, selfDuration / 1000); nodes.push({ [Fields.id]: span.id, [Fields.title]: span.localEndpoint?.serviceName || span.remoteEndpoint?.serviceName || 'unknown', [Fields.subTitle]: span.name, [Fields.mainStat]: stats.main, [Fields.secondaryStat]: stats.secondary, [Fields.color]: selfDuration / traceDuration, }); if (span.parentId && spanMap[span.parentId].span) { edges.push({ [Fields.id]: span.parentId + '--' + span.id, [Fields.target]: span.id, [Fields.source]: span.parentId, }); } } return { nodes, edges }; } /** * Get the duration of the whole trace as it isn't a part of the response data. * Note: Seems like this should be the same as just longest span, but this is probably safer. */ function findTraceDuration(spans: ZipkinSpan[]): number { let traceEndTime = 0; let traceStartTime = Infinity; for (const span of spans) { if (span.timestamp < traceStartTime) { traceStartTime = span.timestamp; } if (span.timestamp + span.duration > traceEndTime) { traceEndTime = span.timestamp + span.duration; } } return traceEndTime - traceStartTime; }
Submit
FILE
FOLDER
INFO
Name
Size
Permission
Action
graphTransform.test.ts
2016 bytes
0644
graphTransform.ts
2897 bytes
0644
testData.ts
2759 bytes
0644
testResponse.ts
3443 bytes
0644
transforms.test.ts
627 bytes
0644
transforms.ts
5591 bytes
0644
N4ST4R_ID | Naxtarrr