grafana/public/app/plugins/datasource/zipkin/utils/graphTransform.ts
Josh Hunt 3c6e0e8ef8
Chore: ESlint import order (#44959)
* Add and configure eslint-plugin-import

* Fix the lint:ts npm command

* Autofix + prettier all the files

* Manually fix remaining files

* Move jquery code in jest-setup to external file to safely reorder imports

* Resolve issue caused by circular dependencies within Prometheus

* Update .betterer.results

* Fix missing // @ts-ignore

* ignore iconBundle.ts

* Fix missing // @ts-ignore
2022-04-22 14:33:13 +01:00

101 lines
2.8 KiB
TypeScript

import { DataFrame, NodeGraphDataFrameFieldNames as Fields } from '@grafana/data';
import { getNonOverlappingDuration, getStats, makeFrames, makeSpanMap } from '../../../../core/utils/tracing';
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;
}