diff --git a/frontend/src/container/GantChart/SpanName/index.tsx b/frontend/src/container/GantChart/SpanName/index.tsx
index 47d58c3e5c..7f536624b9 100644
--- a/frontend/src/container/GantChart/SpanName/index.tsx
+++ b/frontend/src/container/GantChart/SpanName/index.tsx
@@ -10,7 +10,7 @@ function SpanNameComponent({
{name}
- {serviceName}
+ {serviceName}
);
diff --git a/frontend/src/container/GantChart/SpanName/styles.ts b/frontend/src/container/GantChart/SpanName/styles.ts
index 642e28f639..abd41dc54e 100644
--- a/frontend/src/container/GantChart/SpanName/styles.ts
+++ b/frontend/src/container/GantChart/SpanName/styles.ts
@@ -9,7 +9,7 @@ export const Span = styled(Typography.Paragraph)`
}
`;
-export const Service = styled(Typography)`
+export const Service = styled(Typography.Paragraph)`
&&& {
color: #acacac;
font-size: 0.75rem;
diff --git a/frontend/src/container/GantChart/Trace/styles.ts b/frontend/src/container/GantChart/Trace/styles.ts
index 7710e77b5b..a85eec454c 100644
--- a/frontend/src/container/GantChart/Trace/styles.ts
+++ b/frontend/src/container/GantChart/Trace/styles.ts
@@ -41,8 +41,9 @@ export const CardContainer = styled.li<{ isMissing?: boolean }>`
width: 100%;
cursor: pointer;
border-radius: 0.25rem;
+ z-index: 2;
${({ isMissing }): string =>
- isMissing ? `border: 1px dashed ${volcano[6]};` : ''}
+ isMissing ? `border: 1px dashed ${volcano[6]} !important;` : ''}
`;
interface Props {
diff --git a/frontend/src/container/TraceDetail/Missingtrace.tsx b/frontend/src/container/TraceDetail/Missingtrace.tsx
index b203f05f68..eb0620a4ed 100644
--- a/frontend/src/container/TraceDetail/Missingtrace.tsx
+++ b/frontend/src/container/TraceDetail/Missingtrace.tsx
@@ -28,11 +28,10 @@ function MissingSpansMessage(): JSX.Element {
justifyContent: 'center',
alignItems: 'center',
margin: '1rem 0',
+ fontSize: '0.8rem',
}}
>
- {' '}
+ {' '}
This trace has missing spans
diff --git a/frontend/src/types/api/trace/getTraceItem.ts b/frontend/src/types/api/trace/getTraceItem.ts
index a653823821..4b12d15b2f 100644
--- a/frontend/src/types/api/trace/getTraceItem.ts
+++ b/frontend/src/types/api/trace/getTraceItem.ts
@@ -18,10 +18,10 @@ export type Span = [
string,
string,
string,
- string | string[],
- string | string[],
- string | string[],
- Record[],
+ string[],
+ string[],
+ string[],
+ string[],
boolean,
];
diff --git a/frontend/src/utils/__tests__/__snapshots__/spanToTree.test.ts.snap b/frontend/src/utils/__tests__/__snapshots__/spanToTree.test.ts.snap
new file mode 100644
index 0000000000..2c2ab402e2
--- /dev/null
+++ b/frontend/src/utils/__tests__/__snapshots__/spanToTree.test.ts.snap
@@ -0,0 +1,211 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`utils/spanToTree should return a single tree on valid trace data 1`] = `
+Object {
+ "missingSpanTree": Array [],
+ "spanTree": Array [
+ Object {
+ "children": Array [
+ Object {
+ "children": Array [
+ Object {
+ "children": Array [],
+ "event": Array [
+ Object {
+ "attributeMap": Object {
+ "event": "HTTP request received S3",
+ "level": "info",
+ "method": "GET",
+ "url": "/dispatch?customer=392&nonse=0.015296363321630757",
+ },
+ "timeUnixNano": 1657275433246142000,
+ },
+ ],
+ "hasError": false,
+ "id": "span_3",
+ "isProcessed": true,
+ "name": "HTTP GET SPAN 3",
+ "references": Array [
+ Object {
+ "RefType": "CHILD_OF",
+ "SpanId": "span_2",
+ "TraceId": "0000000000000000span_1",
+ },
+ ],
+ "serviceColour": "",
+ "serviceName": "frontend",
+ "startTime": 1657275433246,
+ "tags": Array [
+ Object {
+ "key": "host.name.span3",
+ "value": "span_3",
+ },
+ ],
+ "time": 683273000,
+ "value": 683273000,
+ },
+ ],
+ "event": Array [
+ Object {
+ "attributeMap": Object {
+ "event": "HTTP request received S2",
+ "level": "info",
+ "method": "GET",
+ "url": "/dispatch?customer=392&nonse=0.015296363321630757",
+ },
+ "timeUnixNano": 1657275433246142000,
+ },
+ ],
+ "hasError": false,
+ "id": "span_2",
+ "isProcessed": true,
+ "name": "HTTP GET SPAN 2",
+ "references": Array [
+ Object {
+ "RefType": "CHILD_OF",
+ "SpanId": "span_1",
+ "TraceId": "0000000000000000span_1",
+ },
+ ],
+ "serviceColour": "",
+ "serviceName": "frontend",
+ "startTime": 1657275433246,
+ "tags": Array [
+ Object {
+ "key": "host.name.span2",
+ "value": "span_2",
+ },
+ ],
+ "time": 683273000,
+ "value": 683273000,
+ },
+ ],
+ "event": Array [
+ Object {
+ "attributeMap": Object {
+ "event": "HTTP request received S1",
+ "level": "info",
+ "method": "GET",
+ "url": "/dispatch?customer=392&nonse=0.015296363321630757",
+ },
+ "timeUnixNano": 1657275433246142000,
+ },
+ ],
+ "hasError": false,
+ "id": "span_1",
+ "name": "HTTP GET SPAN 1",
+ "references": Array [
+ Object {
+ "RefType": "CHILD_OF",
+ "SpanId": "",
+ "TraceId": "0000000000000000span_1",
+ },
+ ],
+ "serviceColour": "",
+ "serviceName": "frontend",
+ "startTime": 1657275433246,
+ "tags": Array [
+ Object {
+ "key": "host.name.span1",
+ "value": "span_1",
+ },
+ ],
+ "time": 683273000,
+ "value": 683273000,
+ },
+ ],
+}
+`;
+
+exports[`utils/spanToTree should return a single tree on valid trace data 2`] = `
+Object {
+ "missingSpanTree": Array [
+ Object {
+ "children": Array [
+ Object {
+ "children": Array [],
+ "event": Array [
+ Object {
+ "attributeMap": Object {
+ "event": "HTTP request received S3",
+ "level": "info",
+ "method": "GET",
+ "url": "/dispatch?customer=392&nonse=0.015296363321630757",
+ },
+ "timeUnixNano": 1657275433246142000,
+ },
+ ],
+ "hasError": false,
+ "id": "span_3",
+ "isProcessed": true,
+ "name": "HTTP GET SPAN 3",
+ "references": Array [
+ Object {
+ "RefType": "CHILD_OF",
+ "SpanId": "span_2",
+ "TraceId": "0000000000000000span_1",
+ },
+ ],
+ "serviceColour": "",
+ "serviceName": "frontend",
+ "startTime": 1657275433246,
+ "tags": Array [
+ Object {
+ "key": "host.name.span3",
+ "value": "span_3",
+ },
+ ],
+ "time": 683273000,
+ "value": 683273000,
+ },
+ ],
+ "id": "span_2",
+ "isMissing": true,
+ "name": "Missing Span (span_2)",
+ "serviceColour": "",
+ "serviceName": "",
+ "startTime": null,
+ "tags": Array [],
+ "time": null,
+ "value": null,
+ },
+ ],
+ "spanTree": Array [
+ Object {
+ "children": Array [],
+ "event": Array [
+ Object {
+ "attributeMap": Object {
+ "event": "HTTP request received S1",
+ "level": "info",
+ "method": "GET",
+ "url": "/dispatch?customer=392&nonse=0.015296363321630757",
+ },
+ "timeUnixNano": 1657275433246142000,
+ },
+ ],
+ "hasError": false,
+ "id": "span_1",
+ "name": "HTTP GET SPAN 1",
+ "references": Array [
+ Object {
+ "RefType": "CHILD_OF",
+ "SpanId": "",
+ "TraceId": "0000000000000000span_1",
+ },
+ ],
+ "serviceColour": "",
+ "serviceName": "frontend",
+ "startTime": 1657275433246,
+ "tags": Array [
+ Object {
+ "key": "host.name.span1",
+ "value": "span_1",
+ },
+ ],
+ "time": 683273000,
+ "value": 683273000,
+ },
+ ],
+}
+`;
diff --git a/frontend/src/utils/__tests__/spanToTree.test.ts b/frontend/src/utils/__tests__/spanToTree.test.ts
new file mode 100644
index 0000000000..4cf7a20fb4
--- /dev/null
+++ b/frontend/src/utils/__tests__/spanToTree.test.ts
@@ -0,0 +1,21 @@
+import { TraceData } from '../fixtures/TraceData';
+import { spanToTreeUtil } from '../spanToTree';
+
+describe('utils/spanToTree', () => {
+ test('should return a single tree on valid trace data', () => {
+ const spanTree = spanToTreeUtil(TraceData);
+ expect(spanTree.spanTree.length).toBe(1);
+ expect(spanTree.missingSpanTree.length).toBe(0);
+ expect(spanTree).toMatchSnapshot();
+ });
+ test('should return a single tree on valid trace data', () => {
+ const MissingTraceData = [...TraceData];
+ MissingTraceData.splice(1, 1);
+
+ const spanTree = spanToTreeUtil(MissingTraceData);
+
+ expect(spanTree.spanTree.length).toBe(1);
+ expect(spanTree.missingSpanTree.length).toBe(1);
+ expect(spanTree).toMatchSnapshot();
+ });
+});
diff --git a/frontend/src/utils/fixtures/TraceData.ts b/frontend/src/utils/fixtures/TraceData.ts
new file mode 100644
index 0000000000..289e91e949
--- /dev/null
+++ b/frontend/src/utils/fixtures/TraceData.ts
@@ -0,0 +1,52 @@
+import { Span } from 'types/api/trace/getTraceItem';
+
+export const TraceData: Span[] = [
+ [
+ 1657275433246,
+ 'span_1',
+ '0000000000000000span_1',
+ 'frontend',
+ 'HTTP GET SPAN 1',
+ '2',
+ '683273000',
+ ['host.name.span1'],
+ ['span_1'],
+ ['{TraceId=0000000000000000span_1, SpanId=, RefType=CHILD_OF}'],
+ [
+ '{"timeUnixNano":1657275433246142000,"attributeMap":{"event":"HTTP request received S1","level":"info","method":"GET","url":"/dispatch?customer=392\\u0026nonse=0.015296363321630757"}}',
+ ],
+ false,
+ ],
+ [
+ 1657275433246,
+ 'span_2',
+ '0000000000000000span_1',
+ 'frontend',
+ 'HTTP GET SPAN 2',
+ '2',
+ '683273000',
+ ['host.name.span2'],
+ ['span_2'],
+ ['{TraceId=0000000000000000span_1, SpanId=span_1, RefType=CHILD_OF}'],
+ [
+ '{"timeUnixNano":1657275433246142000,"attributeMap":{"event":"HTTP request received S2","level":"info","method":"GET","url":"/dispatch?customer=392\\u0026nonse=0.015296363321630757"}}',
+ ],
+ false,
+ ],
+ [
+ 1657275433246,
+ 'span_3',
+ '0000000000000000span_1',
+ 'frontend',
+ 'HTTP GET SPAN 3',
+ '2',
+ '683273000',
+ ['host.name.span3'],
+ ['span_3'],
+ ['{TraceId=0000000000000000span_1, SpanId=span_2, RefType=CHILD_OF}'],
+ [
+ '{"timeUnixNano":1657275433246142000,"attributeMap":{"event":"HTTP request received S3","level":"info","method":"GET","url":"/dispatch?customer=392\\u0026nonse=0.015296363321630757"}}',
+ ],
+ false,
+ ],
+];
diff --git a/frontend/src/utils/spanToTree.ts b/frontend/src/utils/spanToTree.ts
index 115c4c111a..142df3dec8 100644
--- a/frontend/src/utils/spanToTree.ts
+++ b/frontend/src/utils/spanToTree.ts
@@ -109,6 +109,12 @@ export const spanToTreeUtil = (inputSpanList: Span[]): ITraceForest => {
const missingSpanTree: ITraceTree[] = [];
const referencedTraceIds: string[] = Array.from(traceIdSet);
Object.keys(spanMap).forEach((spanId) => {
+ const isRoot = spanMap[spanId].references?.some((refs) => refs.SpanId === '');
+ if (isRoot) {
+ spanTree.push(spanMap[spanId]);
+ return;
+ }
+
for (const traceId of referencedTraceIds) {
if (traceId.includes(spanId)) {
spanTree.push(spanMap[spanId]);