signoz/frontend/src/utils/spanToTree.ts

126 lines
3.3 KiB
TypeScript
Raw Normal View History

/* eslint-disable no-restricted-syntax */
Fe: Feat/trace detail (#764) * feat: new trace detail page flame graph * feat: new trace detail page layout * test: trace detail is wip * chore: trace details in wip * feat: trace detail page timeline component * chore: spantoTree is updated * chore: gantchart is updated * chore: onClick is added * chore: isSpanPresentInSearchString util is added * chore: trace graph is updated * chore: added the hack to work * feat: is span present util is added * chore: in span ms is added * chore: tooltip is updated * WIP: chore: trace details changes are updated * feat: getTraceItem is added * feat: trace detail page is updated * feat: trace detail styling changes * feat: trace detail page is updated * feat: implement span hover, select, focus and reset * feat: reset focus * feat: spanId as query table and unfurling * feat: trace details is updated * chore: remove lodash * chore: remove lodash * feat: trace details is updated * feat: new trace detail page styling changes * feat: new trace detail page styling changes * feat: improved styling * feat: remove horizontal scrolling * feat: new trace detail page modify caret icon * chore styles are updated * Revert "chore: Trace styles" * chore styles are updated * feat: timeline normalisation * chore: remove mock data * chore: sort tree data util is added and selected span component is updated * chore: trace changes are updated * chore: trace changes are updated * chore: trace changes are updated * feat: refactored time units for new trace detail page * chore: remove mockdata * feat: new trace detail page themeing and interval loop fix * chore: error tag is updated * chore: error tag is updated * chore: error tag is updated * chore: error tag is updated * chore: console is removed * fix: error tag expand button * chore: expanded panel is updated * feat: scroll span from gantt chart intoview * chore: trace detail is removed Co-authored-by: Pranshu Chittora <pranshu@signoz.io>
2022-03-03 19:04:23 +05:30
import { cloneDeep } from 'lodash-es';
import { ITraceForest, ITraceTree, Span } from 'types/api/trace/getTraceItem';
const getSpanReferences = (
rawReferences: string[] = [],
): Record<string, string>[] => {
return rawReferences.map((rawRef) => {
const refObject: Record<string, string> = {};
rawRef
.replaceAll('{', '')
.replaceAll('}', '')
.replaceAll(' ', '')
.split(',')
.forEach((rawRefKeyPair) => {
const [key, value] = rawRefKeyPair.split('=');
refObject[key] = value;
});
return refObject;
});
};
2021-01-18 02:18:49 +05:30
// This getSpanTags is migrated from the previous implementation.
const getSpanTags = (spanData: Span): { key: string; value: string }[] => {
const tags = [];
if (spanData[7] !== null && spanData[8] !== null) {
if (typeof spanData[7] === 'string' && typeof spanData[8] === 'string') {
tags.push({ key: spanData[7], value: spanData[8] });
} else if (spanData[7].length > 0 && spanData[8].length > 0) {
for (let j = 0; j < spanData[7].length; j += 1) {
tags.push({ key: spanData[7][j], value: spanData[8][j] });
2021-01-18 02:18:49 +05:30
}
}
}
return tags;
};
2021-01-18 02:18:49 +05:30
// eslint-disable-next-line sonarjs/cognitive-complexity
export const spanToTreeUtil = (inputSpanList: Span[]): ITraceForest => {
const spanList = cloneDeep(inputSpanList);
const traceIdSet: Set<string> = new Set();
const spanMap: Record<string, ITraceTree> = {};
const createTarceRootSpan = (
spanReferences: Record<string, string>[],
): void => {
spanReferences.forEach(({ SpanId, TraceId }) => {
traceIdSet.add(TraceId);
if (SpanId && !spanMap[SpanId]) {
spanMap[SpanId] = {
id: SpanId,
name: `Missing Span (${SpanId})`,
children: [],
serviceColour: '',
serviceName: '',
startTime: null as never,
tags: [],
time: null as never,
value: null as never,
isMissing: true,
};
2021-01-18 02:18:49 +05:30
}
});
};
spanList.forEach((span) => {
const spanReferences = getSpanReferences(span[9] as string[]);
const spanObject = {
id: span[1],
name: span[4],
value: parseInt(span[6], 10),
time: parseInt(span[6], 10),
startTime: span[0],
tags: getSpanTags(span),
children: [],
serviceName: span[3],
hasError: !!span[11],
serviceColour: '',
event: span[10].map((e) => {
return (
JSON.parse(decodeURIComponent((e as never) || ('{}' as never))) ||
({} as Record<string, unknown>)
);
}),
references: spanReferences,
};
spanMap[span[1]] = spanObject;
});
for (const [, spanData] of Object.entries(spanMap)) {
if (spanData.references) {
createTarceRootSpan(spanData.references);
spanData.references.forEach(({ SpanId: parentSpanId }) => {
if (spanMap[parentSpanId]) {
spanData.isProcessed = true;
spanMap[parentSpanId].children.push(spanData);
2021-01-18 02:18:49 +05:30
}
});
}
}
for (const [spanId, spanData] of Object.entries(spanMap)) {
if (spanData.isProcessed) {
delete spanMap[spanId];
}
}
const spanTree: ITraceTree[] = [];
const missingSpanTree: ITraceTree[] = [];
const referencedTraceIds: string[] = Array.from(traceIdSet);
Object.keys(spanMap).forEach((spanId) => {
for (const traceId of referencedTraceIds) {
if (traceId.includes(spanId)) {
spanTree.push(spanMap[spanId]);
2021-01-18 02:18:49 +05:30
} else {
missingSpanTree.push(spanMap[spanId]);
2021-01-18 02:18:49 +05:30
}
}
});
2021-01-18 02:18:49 +05:30
return {
spanTree,
missingSpanTree,
};
2021-01-18 02:18:49 +05:30
};