Skip to content

Commit

Permalink
TraceView - Optimization of queries (#2349)
Browse files Browse the repository at this point in the history
* optimize trace veiw removing queries

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* fix date format

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* update app cypress for rounding

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* address comments

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* fix jaeger tree span and overview

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* match old behavior for jaeger, if an error is present display it in overview

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* update test to reflect error in jaeger trace

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* address comments

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* add cypress test for jaeger tree view

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* add fallback value for latency

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* fix sorting on span table

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* add back total use effect

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* status code of 2 indicates error

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* address comments

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* add sorting support to jaeger span table

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* address comments, refactor sorting

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* fix flaky cypress test

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* combine adding sort, and sorting action

Signed-off-by: Adam Tackett <tackadam@amazon.com>

* fix jaeger sorting for errors, fix gantt chart error override from text

Signed-off-by: Adam Tackett <tackadam@amazon.com>

---------

Signed-off-by: Adam Tackett <tackadam@amazon.com>
Co-authored-by: Adam Tackett <tackadam@amazon.com>
  • Loading branch information
TackAdam and Adam Tackett authored Feb 12, 2025
1 parent 5703582 commit 36311f5
Show file tree
Hide file tree
Showing 20 changed files with 1,552 additions and 759 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ describe('Viewing application', () => {
cy.get('[title="03f9c770db5ee2f1caac0afc36db49ba"]').click();
cy.get('[data-test-subj="traceDetailFlyoutTitle"]').should('be.visible');
cy.get('[data-test-subj="traceDetailFlyout"]').within(($flyout) => {
cy.get('[data-test-subj="LatencyDescriptionList"]').should('contain', '224.99');
cy.get('[data-test-subj="LatencyDescriptionList"]').should('contain', '225.00');
});
cy.get('[data-test-subj="euiFlyoutCloseButton"]').click();
cy.get('[data-test-subj="traceDetailFlyout"]').should('not.exist');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,4 +282,21 @@ describe('Testing switch mode to jaeger', () => {
cy.contains('Time spent by service').should('exist');
cy.get("[data-test-subj='span-gantt-chart-panel']").should('exist');
});

it('Checks tree view for specific traceId in Jaeger mode', () => {
cy.contains('15b0b4004a651c4c').click();
cy.get('[data-test-subj="globalLoadingIndicator"]').should('not.exist');

cy.get('.euiButtonGroup').contains('Tree view').click();
cy.get("[data-test-subj='treeExpandAll']").should('exist');
cy.get("[data-test-subj='treeCollapseAll']").should('exist');

// Waiting time for render to complete
cy.get("[data-test-subj='treeExpandAll']").click();
cy.get("[data-test-subj='treeCollapseAll']").click();

cy.get("[data-test-subj='treeViewExpandArrow']").should('have.length', 1);
cy.get("[data-test-subj='treeExpandAll']").click();
cy.get("[data-test-subj='treeViewExpandArrow']").should('have.length.greaterThan', 1);
});
});

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import { HttpStart } from '../../../../../../../src/core/public';
import { TraceAnalyticsMode } from '../../../../../common/types/trace_analytics';
import { ServiceBreakdownPanel } from '../../../trace_analytics/components/traces/service_breakdown_panel';
import { SpanDetailPanel } from '../../../trace_analytics/components/traces/span_detail_panel';
import {
handlePayloadRequest,
handleServicesPieChartRequest,
handleTraceViewRequest,
} from '../../../trace_analytics/requests/traces_request_handler';
import { handlePayloadRequest } from '../../../trace_analytics/requests/traces_request_handler';
import { getListItem } from '../../helpers/utils';
import {
getOverviewFields,
getServiceBreakdownData,
} from '../../../trace_analytics/components/traces/trace_view_helpers';

interface TraceDetailRenderProps {
traceId: string;
Expand Down Expand Up @@ -78,6 +78,7 @@ export const TraceDetailRender = ({
mode={mode}
dataSourceMDSId={dataSourceMDSId}
isApplicationFlyout={true}
payloadData={payloadData}
/>
<EuiSpacer size="xs" />
<EuiHorizontalRule margin="s" />
Expand All @@ -95,10 +96,29 @@ export const TraceDetailRender = ({
}, [traceId, fields, serviceBreakdownData, colorMap, payloadData]);

useEffect(() => {
handleTraceViewRequest(traceId, http, fields, setFields, mode);
handleServicesPieChartRequest(traceId, http, setServiceBreakdownData, setColorMap, mode);
handlePayloadRequest(traceId, http, payloadData, setPayloadData, mode);
}, [traceId]);

useEffect(() => {
if (!payloadData) return;

try {
const parsedPayload = JSON.parse(payloadData);
const overview = getOverviewFields(parsedPayload, mode);
if (overview) {
setFields(overview);
}

const {
serviceBreakdownData: queryServiceBreakdownData,
colorMap: queryColorMap,
} = getServiceBreakdownData(parsedPayload, mode);
setServiceBreakdownData(queryServiceBreakdownData);
setColorMap(queryColorMap);
} catch (error) {
console.error('Error processing payloadData:', error);
}
}, [payloadData, mode]);

return renderContent;
};
61 changes: 61 additions & 0 deletions public/components/trace_analytics/components/common/constants.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

// Conversion factor for nanoseconds to milliseconds
export const NANOS_TO_MS = 1e6;

export const MILI_TO_SEC = 1000;

export const pieChartColors = [
'#7492e7',
'#c33d69',
'#2ea597',
'#8456ce',
'#e07941',
'#3759ce',
'#ce567c',
'#9469d6',
'#4066df',
'#da7596',
];

export interface Span {
traceId: string;
spanId: string;
traceState: string;
parentSpanId: string;
name: string;
kind: string;
startTime: string;
endTime: string;
durationInNanos: number;
serviceName: string;
events: any[];
links: any[];
droppedAttributesCount: number;
droppedEventsCount: number;
droppedLinksCount: number;
traceGroup: string;
traceGroupFields: {
endTime: string;
durationInNanos: number;
statusCode: number;
};
status: {
code: number;
};
instrumentationLibrary: {
name: string;
version: string;
};
}

export interface ParsedHit {
_index: string;
_id: string;
_score: number;
_source: Span;
sort?: any[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { FieldCapResponse } from '../../../common/types';
import { serviceMapColorPalette } from './color_palette';
import { FilterType } from './filters/filters';
import { ServiceObject } from './plots/service_map';
import { NANOS_TO_MS, ParsedHit } from './constants';

const missingJaegerTracesConfigurationMessage = `The indices required for trace analytics (${JAEGER_INDEX_NAME} and ${JAEGER_SERVICE_INDEX_NAME}) do not exist or you do not have permission to access them.`;

Expand Down Expand Up @@ -615,3 +616,39 @@ export const generateServiceUrl = (

return url;
};

/*
* Parse an ISO timestamp with up to nanosecond precision.
* For example, "2025-01-28T03:12:37.293990144Z" will be converted
* to a number representing the total nanoseconds since the Unix epoch.
*/
export function parseIsoToNano(iso: string): number {
const match = iso.match(/^(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})(?:\.(\d+))?Z$/);
if (!match) {
throw new Error(`Invalid ISO timestamp: ${iso}`);
}
// Parse the base part using Date.parse (which gives ms)
const baseMs = new Date(match[1] + 'Z').getTime();
// Get the fractional part (if any), pad to 9 digits for nanosecond precision
let fraction = match[2] || '0';
fraction = fraction.padEnd(9, '0'); // ensure it has 9 digits
return baseMs * NANOS_TO_MS + Number(fraction);
}

export const parseHits = (payloadData: string): ParsedHit[] => {
try {
const parsed = JSON.parse(payloadData);
let hits: ParsedHit[] = [];

if (parsed.hits && Array.isArray(parsed.hits.hits)) {
hits = parsed.hits.hits;
} else if (Array.isArray(parsed)) {
hits = parsed;
}

return hits;
} catch (error) {
console.error('Error processing payloadData:', error);
return [];
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ exports[`Service breakdown panel component renders service breakdown panel 1`] =
data={
Array [
Object {
"hoverinfo": "label+percent",
"hovertemplate": "%{label}<br>%{value:.2f}%<extra></extra>",
"labels": Array [
"inventory",
Expand Down Expand Up @@ -177,6 +178,7 @@ exports[`Service breakdown panel component renders service breakdown panel 1`] =
data={
Array [
Object {
"hoverinfo": "label+percent",
"hovertemplate": "%{label}<br>%{value:.2f}%<extra></extra>",
"labels": Array [
"inventory",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
<EuiFlexItem>
<PanelTitle
title="Spans"
totalItems={0.5}
totalItems={0}
/>
</EuiFlexItem>
<EuiFlexItem
Expand All @@ -42,7 +42,6 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
>
<EuiButtonGroup
idSelected="timeline"
isDisabled={false}
legend="Select view of spans"
onChange={[Function]}
options={
Expand Down Expand Up @@ -74,26 +73,7 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
grow={false}
>
<Plt
data={
Array [
Object {
"hoverinfo": "none",
"marker": Object {
"color": "#fff",
},
"orientation": "h",
"showlegend": false,
"type": "bar",
"width": 0.4,
"x": Array [
10,
],
"y": Array [
"service1",
],
},
]
}
data={Array []}
layout={
Object {
"dragmode": "select",
Expand All @@ -116,7 +96,7 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
},
"type": "rect",
"x0": 0,
"x1": 22,
"x1": 0,
"xref": "x",
"y0": 0,
"y1": 1,
Expand All @@ -128,7 +108,7 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
"color": "#91989c",
"range": Array [
0,
22,
0,
],
"showline": true,
"side": "top",
Expand All @@ -153,31 +133,10 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
}
>
<Plt
data={
Array [
Object {
"hoverinfo": "none",
"marker": Object {
"color": "#fff",
},
"orientation": "h",
"showlegend": false,
"text": "10.00 ms",
"textposition": "outside",
"type": "bar",
"width": 0.4,
"x": Array [
10,
],
"y": Array [
"service1",
],
},
]
}
data={Array []}
layout={
Object {
"height": 85,
"height": 60,
"margin": Object {
"b": 30,
"l": 150,
Expand All @@ -191,7 +150,7 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
"color": "#91989c",
"range": Array [
0,
22,
0,
],
"showline": true,
"side": "top",
Expand All @@ -200,12 +159,8 @@ exports[`SpanDetailPanel component renders correctly with default props 1`] = `
"yaxis": Object {
"fixedrange": true,
"showgrid": false,
"ticktext": Array [
"",
],
"tickvals": Array [
"service1",
],
"ticktext": Array [],
"tickvals": Array [],
},
}
}
Expand Down
Loading

0 comments on commit 36311f5

Please sign in to comment.