mirror of
https://github.com/SigNoz/signoz.git
synced 2026-04-10 06:00:19 +01:00
Compare commits
2 Commits
feat/json-
...
feat/trace
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
420d405e8a | ||
|
|
e543776efc |
44
frontend/src/api/trace/getTraceV3.tsx
Normal file
44
frontend/src/api/trace/getTraceV3.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import { ApiV3Instance as axios } from 'api';
|
||||
import { omit } from 'lodash-es';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
GetTraceV3PayloadProps,
|
||||
GetTraceV3SuccessResponse,
|
||||
} from 'types/api/trace/getTraceV3';
|
||||
|
||||
const getTraceV3 = async (
|
||||
props: GetTraceV3PayloadProps,
|
||||
): Promise<SuccessResponse<GetTraceV3SuccessResponse> | ErrorResponse> => {
|
||||
let uncollapsedSpans = [...props.uncollapsedSpans];
|
||||
if (!props.isSelectedSpanIDUnCollapsed) {
|
||||
uncollapsedSpans = uncollapsedSpans.filter(
|
||||
(node) => node !== props.selectedSpanId,
|
||||
);
|
||||
}
|
||||
const postData: GetTraceV3PayloadProps = {
|
||||
...props,
|
||||
uncollapsedSpans,
|
||||
};
|
||||
const response = await axios.post<GetTraceV3SuccessResponse>(
|
||||
`/traces/${props.traceId}/waterfall`,
|
||||
omit(postData, 'traceId'),
|
||||
);
|
||||
|
||||
// V3 API wraps response in { status, data }
|
||||
const rawPayload = (response.data as any).data || response.data;
|
||||
|
||||
// Derive serviceName from resources for backward compatibility
|
||||
const spans = (rawPayload.spans || []).map((span: any) => ({
|
||||
...span,
|
||||
serviceName: span.serviceName || span.resources?.['service.name'] || '',
|
||||
}));
|
||||
|
||||
return {
|
||||
statusCode: 200,
|
||||
error: null,
|
||||
message: 'Success',
|
||||
payload: { ...rawPayload, spans },
|
||||
};
|
||||
};
|
||||
|
||||
export default getTraceV3;
|
||||
@@ -37,4 +37,5 @@ export enum LOCALSTORAGE {
|
||||
SHOW_FREQUENCY_CHART = 'SHOW_FREQUENCY_CHART',
|
||||
DISSMISSED_COST_METER_INFO = 'DISMISSED_COST_METER_INFO',
|
||||
DISMISSED_API_KEYS_DEPRECATION_BANNER = 'DISMISSED_API_KEYS_DEPRECATION_BANNER',
|
||||
TRACE_DETAILS_SPAN_DETAILS_POSITION = 'TRACE_DETAILS_SPAN_DETAILS_POSITION',
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ export const REACT_QUERY_KEY = {
|
||||
UPDATE_ALERT_RULE: 'UPDATE_ALERT_RULE',
|
||||
GET_ACTIVE_LICENSE_V3: 'GET_ACTIVE_LICENSE_V3',
|
||||
GET_TRACE_V2_WATERFALL: 'GET_TRACE_V2_WATERFALL',
|
||||
GET_TRACE_V3_WATERFALL: 'GET_TRACE_V3_WATERFALL',
|
||||
GET_TRACE_V2_FLAMEGRAPH: 'GET_TRACE_V2_FLAMEGRAPH',
|
||||
GET_POD_LIST: 'GET_POD_LIST',
|
||||
GET_NODE_LIST: 'GET_NODE_LIST',
|
||||
|
||||
@@ -677,6 +677,18 @@ function NewWidget({
|
||||
queryType: currentQuery.queryType,
|
||||
isNewPanel,
|
||||
dataSource: currentQuery?.builder?.queryData?.[0]?.dataSource,
|
||||
...(currentQuery.queryType === EQueryType.CLICKHOUSE && {
|
||||
clickhouseQueryCount: currentQuery.clickhouse_sql.length,
|
||||
clickhouseQueries: currentQuery.clickhouse_sql.map((q) => ({
|
||||
name: q.name,
|
||||
query: (q.query ?? '')
|
||||
.replace(/--[^\n]*/g, '') // strip line comments
|
||||
.replace(/\/\*[\s\S]*?\*\//g, '') // strip block comments
|
||||
.replace(/'(?:[^'\\]|\\.|'')*'/g, "'?'") // replace single-quoted strings (handles \' and '' escapes)
|
||||
.replace(/\b\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/g, '?'), // replace numeric literals (int, float, scientific)
|
||||
disabled: q.disabled,
|
||||
})),
|
||||
}),
|
||||
});
|
||||
setSaveModal(true);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MouseEventHandler, useCallback } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
import { useNotifications } from 'hooks/useNotifications';
|
||||
import { toast } from '@signozhq/sonner';
|
||||
import useUrlQuery from 'hooks/useUrlQuery';
|
||||
import { Span } from 'types/api/trace/getTraceV2';
|
||||
|
||||
@@ -11,7 +11,6 @@ export const useCopySpanLink = (
|
||||
const urlQuery = useUrlQuery();
|
||||
const { pathname } = useLocation();
|
||||
const [, setCopy] = useCopyToClipboard();
|
||||
const { notifications } = useNotifications();
|
||||
|
||||
const onSpanCopy: MouseEventHandler<HTMLElement> = useCallback(
|
||||
(event) => {
|
||||
@@ -31,11 +30,12 @@ export const useCopySpanLink = (
|
||||
const link = `${window.location.origin}${pathname}?${urlQuery.toString()}`;
|
||||
|
||||
setCopy(link);
|
||||
notifications.success({
|
||||
message: 'Copied to clipboard',
|
||||
toast.success('Copied to clipboard', {
|
||||
richColors: true,
|
||||
position: 'top-right',
|
||||
});
|
||||
},
|
||||
[span, urlQuery, pathname, setCopy, notifications],
|
||||
[span, urlQuery, pathname, setCopy],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
29
frontend/src/hooks/trace/useGetTraceV3.tsx
Normal file
29
frontend/src/hooks/trace/useGetTraceV3.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { useQuery, UseQueryResult } from 'react-query';
|
||||
import getTraceV3 from 'api/trace/getTraceV3';
|
||||
import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
|
||||
import { ErrorResponse, SuccessResponse } from 'types/api';
|
||||
import {
|
||||
GetTraceV3PayloadProps,
|
||||
GetTraceV3SuccessResponse,
|
||||
} from 'types/api/trace/getTraceV3';
|
||||
|
||||
const useGetTraceV3 = (props: GetTraceV3PayloadProps): UseTraceV3 =>
|
||||
useQuery({
|
||||
queryFn: () => getTraceV3(props),
|
||||
queryKey: [
|
||||
REACT_QUERY_KEY.GET_TRACE_V3_WATERFALL,
|
||||
props.traceId,
|
||||
props.selectedSpanId,
|
||||
props.isSelectedSpanIDUnCollapsed,
|
||||
],
|
||||
enabled: !!props.traceId,
|
||||
keepPreviousData: true,
|
||||
refetchOnWindowFocus: false,
|
||||
});
|
||||
|
||||
type UseTraceV3 = UseQueryResult<
|
||||
SuccessResponse<GetTraceV3SuccessResponse> | ErrorResponse,
|
||||
unknown
|
||||
>;
|
||||
|
||||
export default useGetTraceV3;
|
||||
@@ -4,7 +4,8 @@ export interface TraceDetailFlamegraphURLProps {
|
||||
|
||||
export interface GetTraceFlamegraphPayloadProps {
|
||||
traceId: string;
|
||||
selectedSpanId: string;
|
||||
selectedSpanId?: string;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
|
||||
@@ -37,6 +37,23 @@ export interface Span {
|
||||
hasSibling: boolean;
|
||||
subTreeNodeCount: number;
|
||||
level: number;
|
||||
// V2 API format fields
|
||||
attributes_string?: Record<string, string>;
|
||||
attributes_number?: Record<string, number>;
|
||||
attributes_bool?: Record<string, boolean>;
|
||||
resources_string?: Record<string, string>;
|
||||
// V3 API format fields
|
||||
attributes?: Record<string, string>;
|
||||
resources?: Record<string, string>;
|
||||
http_method?: string;
|
||||
http_url?: string;
|
||||
http_host?: string;
|
||||
db_name?: string;
|
||||
db_operation?: string;
|
||||
external_http_method?: string;
|
||||
external_http_url?: string;
|
||||
response_status_code?: string;
|
||||
is_remote?: string;
|
||||
}
|
||||
|
||||
export interface GetTraceV2SuccessResponse {
|
||||
|
||||
14
frontend/src/types/api/trace/getTraceV3.ts
Normal file
14
frontend/src/types/api/trace/getTraceV3.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface GetTraceV3PayloadProps {
|
||||
traceId: string;
|
||||
selectedSpanId: string;
|
||||
uncollapsedSpans: string[];
|
||||
isSelectedSpanIDUnCollapsed: boolean;
|
||||
}
|
||||
|
||||
// Re-export shared types from V2 until V3 response diverges
|
||||
export type {
|
||||
Event,
|
||||
GetTraceV2SuccessResponse as GetTraceV3SuccessResponse,
|
||||
Span,
|
||||
TraceDetailV2URLProps as TraceDetailV3URLProps,
|
||||
} from './getTraceV2';
|
||||
Reference in New Issue
Block a user