Compare commits

...

1 Commits

Author SHA1 Message Date
aks07
5ca7baca9f feat(frontend): add analytics events to span percentile flow
Instrument the span percentile widget with product analytics: panel
toggle, time-range change, resource-attributes selector toggle, and
attribute selection change. Events go through the existing
useTraceDetailLogEvent hook so view and traceId are injected.
2026-08-13 12:33:53 +05:30
3 changed files with 56 additions and 12 deletions

View File

@@ -42,7 +42,7 @@ function SpanPercentilePanel({
selectedTimeRange,
setSelectedTimeRange,
showResourceAttributesSelector,
setShowResourceAttributesSelector,
toggleResourceAttributesSelector,
resourceAttributesSearchQuery,
setResourceAttributesSearchQuery,
spanResourceAttributes,
@@ -72,9 +72,7 @@ function SpanPercentilePanel({
variant="link"
color="secondary"
size="icon"
onClick={(): void =>
setShowResourceAttributesSelector(!showResourceAttributesSelector)
}
onClick={toggleResourceAttributesSelector}
prefix={
showResourceAttributesSelector ? <Check size={16} /> : <Plus size={16} />
}

View File

@@ -8,6 +8,11 @@ import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import { USER_PREFERENCES } from 'constants/userPreferences';
import dayjs from 'dayjs';
import useClickOutside from 'hooks/useClickOutside';
import {
TraceDetailEventKeys,
TraceDetailEvents,
} from 'pages/TraceDetailsV3/events';
import { useTraceDetailLogEvent } from 'pages/TraceDetailsV3/hooks/useTraceDetailLogEvent';
import { SpanV3 } from 'types/api/trace/getTraceV3';
export interface IResourceAttribute {
@@ -37,7 +42,7 @@ export interface UseSpanPercentileReturn {
selectedTimeRange: number;
setSelectedTimeRange: (range: number) => void;
showResourceAttributesSelector: boolean;
setShowResourceAttributesSelector: (show: boolean) => void;
toggleResourceAttributesSelector: () => void;
resourceAttributesSearchQuery: string;
setResourceAttributesSearchQuery: (query: string) => void;
spanResourceAttributes: IResourceAttribute[];
@@ -76,6 +81,8 @@ function useSpanPercentile(selectedSpan: SpanV3): UseSpanPercentileReturn {
const resourceAttributesSelectorRef = useRef<HTMLDivElement | null>(null);
const logTraceEvent = useTraceDetailLogEvent('v3', selectedSpan.trace_id);
useClickOutside({
ref: resourceAttributesSelectorRef,
onClickOutside: () => {
@@ -257,6 +264,12 @@ function useSpanPercentile(selectedSpan: SpanV3): UseSpanPercentileReturn {
const handleResourceAttributeChange = useCallback(
(key: string, value: string, isSelected: boolean): void => {
logTraceEvent(TraceDetailEvents.SpanPercentileAttributeChanged, {
[TraceDetailEventKeys.SpanId]: selectedSpan.span_id,
[TraceDetailEventKeys.ResourceAttributeKey]: key,
[TraceDetailEventKeys.Selected]: isSelected,
});
updateSpanResourceAttributes((prev) =>
prev.map((attr) => (attr.key === key ? { ...attr, isSelected } : attr)),
);
@@ -271,7 +284,7 @@ function useSpanPercentile(selectedSpan: SpanV3): UseSpanPercentileReturn {
setShouldFetchData(true);
setShouldUpdateUserPreference(true);
},
[selectedResourceAttributes],
[selectedResourceAttributes, logTraceEvent, selectedSpan.span_id],
);
useEffect(() => {
@@ -293,12 +306,37 @@ function useSpanPercentile(selectedSpan: SpanV3): UseSpanPercentileReturn {
'ms',
);
const toggleOpen = useCallback(() => setIsOpen((prev) => !prev), []);
const toggleOpen = useCallback(() => {
const nextOpen = !isOpen;
setIsOpen(nextOpen);
logTraceEvent(TraceDetailEvents.SpanPercentileToggled, {
[TraceDetailEventKeys.SpanId]: selectedSpan.span_id,
[TraceDetailEventKeys.Open]: nextOpen,
[TraceDetailEventKeys.PercentileValue]: percentileValue,
});
}, [isOpen, logTraceEvent, selectedSpan.span_id, percentileValue]);
const handleTimeRangeChange = useCallback((range: number): void => {
setShouldFetchData(true);
setSelectedTimeRange(range);
}, []);
const toggleResourceAttributesSelector = useCallback(() => {
const nextOpen = !showResourceAttributesSelector;
setShowResourceAttributesSelector(nextOpen);
logTraceEvent(TraceDetailEvents.SpanPercentileAttributesSelectorToggled, {
[TraceDetailEventKeys.SpanId]: selectedSpan.span_id,
[TraceDetailEventKeys.Open]: nextOpen,
});
}, [showResourceAttributesSelector, logTraceEvent, selectedSpan.span_id]);
const handleTimeRangeChange = useCallback(
(range: number): void => {
logTraceEvent(TraceDetailEvents.SpanPercentileTimeRangeChanged, {
[TraceDetailEventKeys.SpanId]: selectedSpan.span_id,
[TraceDetailEventKeys.From]: selectedTimeRange,
[TraceDetailEventKeys.To]: range,
});
setShouldFetchData(true);
setSelectedTimeRange(range);
},
[logTraceEvent, selectedSpan.span_id, selectedTimeRange],
);
return {
isOpen,
@@ -312,7 +350,7 @@ function useSpanPercentile(selectedSpan: SpanV3): UseSpanPercentileReturn {
selectedTimeRange,
setSelectedTimeRange: handleTimeRangeChange,
showResourceAttributesSelector,
setShowResourceAttributesSelector,
toggleResourceAttributesSelector,
resourceAttributesSearchQuery,
setResourceAttributesSearchQuery,
spanResourceAttributes,

View File

@@ -8,6 +8,10 @@ export enum TraceDetailEvents {
SpanPanelTabChanged = 'Trace Detail: Span panel tab changed',
DownloadTriggered = 'Trace Detail: Download triggered',
DownloadCancelled = 'Trace Detail: Download cancelled',
SpanPercentileToggled = 'Trace Detail: Span percentile toggled',
SpanPercentileTimeRangeChanged = 'Trace Detail: Span percentile time range changed',
SpanPercentileAttributesSelectorToggled = 'Trace Detail: Span percentile attributes selector toggled',
SpanPercentileAttributeChanged = 'Trace Detail: Span percentile attribute changed',
}
export enum TraceDetailEventKeys {
@@ -36,6 +40,10 @@ export enum TraceDetailEventKeys {
SpanId = 'spanId',
// Download triggered (reuses TotalSpansCount for trace size)
Format = 'format',
// Span percentile (reuses Open, SpanId, From, To)
PercentileValue = 'percentileValue',
ResourceAttributeKey = 'resourceAttributeKey',
Selected = 'selected',
}
export type TraceDetailView = 'v2' | 'v3';