@industry-theme/principal-view-panels 0.12.31 → 0.12.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/TraceTape.d.ts +44 -0
- package/dist/components/TraceTape.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/panels/TraceListPanel.d.ts.map +1 -1
- package/dist/panels.bundle.js +466 -21
- package/dist/panels.bundle.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Theme } from '@principal-ade/industry-theme';
|
|
2
|
+
import type { OtelSpanData } from '@principal-ai/principal-view-core';
|
|
3
|
+
import type { RegisteredTrace } from '../types/otel';
|
|
4
|
+
/**
|
|
5
|
+
* Color configuration for the tape
|
|
6
|
+
*/
|
|
7
|
+
interface TraceTapeColors {
|
|
8
|
+
line?: string;
|
|
9
|
+
scrubber?: string;
|
|
10
|
+
highlighted?: string;
|
|
11
|
+
background?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Props for the TraceTape component
|
|
15
|
+
*/
|
|
16
|
+
export interface TraceTapeProps {
|
|
17
|
+
/** Array of traces to display on the tape */
|
|
18
|
+
traces: RegisteredTrace[];
|
|
19
|
+
/** Theme for styling */
|
|
20
|
+
theme: Theme;
|
|
21
|
+
/** Currently highlighted span ID (controlled from parent) */
|
|
22
|
+
highlightedSpanId?: string;
|
|
23
|
+
/** Currently selected trace ID - its spans will glow */
|
|
24
|
+
selectedTraceId?: string;
|
|
25
|
+
/** Trace ID to focus/jump to (changes trigger scrubber movement) */
|
|
26
|
+
focusTraceId?: string | null;
|
|
27
|
+
/** Callback when user scrubs to a new span */
|
|
28
|
+
onSpanHighlight: (spanId: string | null, span: OtelSpanData | null) => void;
|
|
29
|
+
/** Height of the tape in pixels */
|
|
30
|
+
height?: number;
|
|
31
|
+
/** Whether the tape is interactive */
|
|
32
|
+
interactive?: boolean;
|
|
33
|
+
/** Color scheme configuration (overrides theme-based colors) */
|
|
34
|
+
colors?: TraceTapeColors;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* TraceTape - A horizontal timeline scrubber for navigating trace spans
|
|
38
|
+
*
|
|
39
|
+
* Displays all trace spans and events as vertical lines on a horizontal tape.
|
|
40
|
+
* Dragging the scrubber highlights the nearest span to the left of the cursor.
|
|
41
|
+
*/
|
|
42
|
+
export declare function TraceTape({ traces, theme, highlightedSpanId, selectedTraceId, focusTraceId, onSpanHighlight, height, interactive, colors, }: TraceTapeProps): import("react/jsx-runtime").JSX.Element;
|
|
43
|
+
export default TraceTape;
|
|
44
|
+
//# sourceMappingURL=TraceTape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TraceTape.d.ts","sourceRoot":"","sources":["../../src/components/TraceTape.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD;;GAEG;AACH,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,wBAAwB;IACxB,KAAK,EAAE,KAAK,CAAC;IACb,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,8CAA8C;IAC9C,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5E,mCAAmC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,gEAAgE;IAChE,MAAM,CAAC,EAAE,eAAe,CAAC;CAC1B;AAUD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,KAAK,EACL,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,eAAe,EACf,MAAW,EACX,WAAkB,EAClB,MAAW,GACZ,EAAE,cAAc,2CA8ahB;AAED,eAAe,SAAS,CAAC"}
|
|
@@ -2,4 +2,6 @@ export { TraceList } from './TraceList';
|
|
|
2
2
|
export type { TraceListProps } from './TraceList';
|
|
3
3
|
export { TraceDetails } from './TraceDetails';
|
|
4
4
|
export type { TraceDetailsProps, ScopeInfo } from './TraceDetails';
|
|
5
|
+
export { TraceTape } from './TraceTape';
|
|
6
|
+
export type { TraceTapeProps } from './TraceTape';
|
|
5
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TraceListPanel.d.ts","sourceRoot":"","sources":["../../src/panels/TraceListPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"TraceListPanel.d.ts","sourceRoot":"","sources":["../../src/panels/TraceListPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAE3D,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,UAAU,CAAC;AAgBzD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAurC7D,CAAC"}
|
package/dist/panels.bundle.js
CHANGED
|
@@ -86468,16 +86468,43 @@ const CustomNode = ({ data, selected: selected2, dragging }) => {
|
|
|
86468
86468
|
};
|
|
86469
86469
|
}
|
|
86470
86470
|
};
|
|
86471
|
+
const getBadgePosition = (position2) => {
|
|
86472
|
+
const isDiamondShape = typeDefinition.shape === "diamond";
|
|
86473
|
+
if (isDiamondShape) {
|
|
86474
|
+
switch (position2) {
|
|
86475
|
+
case "top-left":
|
|
86476
|
+
return { top: "50%", left: 0, transform: "translate(-50%, -50%)" };
|
|
86477
|
+
case "top-right":
|
|
86478
|
+
return { top: "50%", right: 0, transform: "translate(50%, -50%)" };
|
|
86479
|
+
case "left":
|
|
86480
|
+
return { top: "50%", left: 0, transform: "translate(-50%, -50%)" };
|
|
86481
|
+
case "right":
|
|
86482
|
+
return { top: "50%", right: 0, transform: "translate(50%, -50%)" };
|
|
86483
|
+
}
|
|
86484
|
+
}
|
|
86485
|
+
switch (position2) {
|
|
86486
|
+
case "top-left":
|
|
86487
|
+
return { top: -6, left: -6 };
|
|
86488
|
+
case "top-right":
|
|
86489
|
+
return { top: -6, right: -6 };
|
|
86490
|
+
case "left":
|
|
86491
|
+
return { top: -6, left: -6 };
|
|
86492
|
+
case "right":
|
|
86493
|
+
return { top: -6, right: -6 };
|
|
86494
|
+
}
|
|
86495
|
+
};
|
|
86471
86496
|
const renderSourcesBadge = () => {
|
|
86472
86497
|
const sources2 = nodeData == null ? void 0 : nodeData.sources;
|
|
86473
86498
|
if (!sources2 || sources2.length === 0)
|
|
86474
86499
|
return null;
|
|
86475
86500
|
const shapeStyles = getBadgeShapeStyles();
|
|
86501
|
+
const positionStyles = getBadgePosition("top-right");
|
|
86476
86502
|
return jsx("div", { style: {
|
|
86477
86503
|
position: "absolute",
|
|
86478
|
-
|
|
86479
|
-
right: -6,
|
|
86504
|
+
...positionStyles,
|
|
86480
86505
|
...shapeStyles,
|
|
86506
|
+
// Override transform if shape has rotation but we already have a position transform
|
|
86507
|
+
...typeDefinition.shape === "diamond" ? { transform: `${positionStyles.transform} rotate(45deg)` } : {},
|
|
86481
86508
|
backgroundColor: "#10b981",
|
|
86482
86509
|
color: "white",
|
|
86483
86510
|
fontSize: theme2.fontSizes[0],
|
|
@@ -86499,11 +86526,10 @@ const CustomNode = ({ data, selected: selected2, dragging }) => {
|
|
|
86499
86526
|
const isOutbound = direction === "outbound";
|
|
86500
86527
|
const directionIcon = isOutbound ? "↗" : "↙";
|
|
86501
86528
|
const directionTitle = isOutbound ? "Outbound boundary (calls external system)" : "Inbound boundary (called by external system)";
|
|
86529
|
+
const positionStyles = getBadgePosition(isOutbound ? "right" : "left");
|
|
86502
86530
|
return jsx("div", { style: {
|
|
86503
86531
|
position: "absolute",
|
|
86504
|
-
|
|
86505
|
-
// Inbound badge on left, outbound badge on right
|
|
86506
|
-
...isOutbound ? { right: -6 } : { left: -6 },
|
|
86532
|
+
...positionStyles,
|
|
86507
86533
|
width: 18,
|
|
86508
86534
|
height: 18,
|
|
86509
86535
|
borderRadius: "50%",
|
|
@@ -86542,11 +86568,13 @@ const CustomNode = ({ data, selected: selected2, dragging }) => {
|
|
|
86542
86568
|
implemented: "Implemented - Code exists"
|
|
86543
86569
|
};
|
|
86544
86570
|
const shapeStyles = getBadgeShapeStyles();
|
|
86571
|
+
const positionStyles = getBadgePosition("top-left");
|
|
86545
86572
|
return jsx("div", { style: {
|
|
86546
86573
|
position: "absolute",
|
|
86547
|
-
|
|
86548
|
-
left: -6,
|
|
86574
|
+
...positionStyles,
|
|
86549
86575
|
...shapeStyles,
|
|
86576
|
+
// Override transform if shape has rotation but we already have a position transform
|
|
86577
|
+
...typeDefinition.shape === "diamond" ? { transform: `${positionStyles.transform} rotate(45deg)` } : {},
|
|
86550
86578
|
backgroundColor: statusColors[status2],
|
|
86551
86579
|
color: "white",
|
|
86552
86580
|
fontSize: theme2.fontSizes[0],
|
|
@@ -100928,6 +100956,361 @@ const TraceList = ({
|
|
|
100928
100956
|
}
|
|
100929
100957
|
);
|
|
100930
100958
|
};
|
|
100959
|
+
function parseNanoTime(nanoStr) {
|
|
100960
|
+
const nanos = BigInt(nanoStr);
|
|
100961
|
+
return Number(nanos / BigInt(1e6));
|
|
100962
|
+
}
|
|
100963
|
+
function TraceTape({
|
|
100964
|
+
traces,
|
|
100965
|
+
theme: theme2,
|
|
100966
|
+
highlightedSpanId,
|
|
100967
|
+
selectedTraceId,
|
|
100968
|
+
focusTraceId,
|
|
100969
|
+
onSpanHighlight,
|
|
100970
|
+
height = 48,
|
|
100971
|
+
interactive = true,
|
|
100972
|
+
colors: colors2 = {}
|
|
100973
|
+
}) {
|
|
100974
|
+
var _a;
|
|
100975
|
+
const tapeRef = useRef(null);
|
|
100976
|
+
const [scrubberPercent, setScrubberPercent] = useState(null);
|
|
100977
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
100978
|
+
const prevFocusTraceIdRef = useRef(void 0);
|
|
100979
|
+
const resolvedColors = {
|
|
100980
|
+
line: theme2.colors.primary,
|
|
100981
|
+
scrubber: theme2.colors.accent || "#22d3ee",
|
|
100982
|
+
highlighted: theme2.colors.text,
|
|
100983
|
+
background: theme2.colors.backgroundSecondary,
|
|
100984
|
+
...colors2
|
|
100985
|
+
};
|
|
100986
|
+
const timeRange = useMemo(() => {
|
|
100987
|
+
if (traces.length === 0) return { min: 0, max: 0 };
|
|
100988
|
+
const allStartTimes = traces.map((t) => t.startTime);
|
|
100989
|
+
const allEndTimes = traces.map((t) => t.endTime);
|
|
100990
|
+
return {
|
|
100991
|
+
min: Math.min(...allStartTimes),
|
|
100992
|
+
max: Math.max(...allEndTimes)
|
|
100993
|
+
};
|
|
100994
|
+
}, [traces]);
|
|
100995
|
+
const spanIndexToPercent = useCallback((index2, total) => {
|
|
100996
|
+
if (total <= 1) return 50;
|
|
100997
|
+
const usableRange = 90;
|
|
100998
|
+
const startOffset = 5;
|
|
100999
|
+
return startOffset + index2 / (total - 1) * usableRange;
|
|
101000
|
+
}, []);
|
|
101001
|
+
const percentToSpanIndex = useCallback((percent, total) => {
|
|
101002
|
+
if (total <= 1) return 0;
|
|
101003
|
+
const usableRange = 90;
|
|
101004
|
+
const startOffset = 5;
|
|
101005
|
+
const normalizedPercent = Math.max(0, Math.min(100, percent));
|
|
101006
|
+
const index2 = Math.round((normalizedPercent - startOffset) / usableRange * (total - 1));
|
|
101007
|
+
return Math.max(0, Math.min(total - 1, index2));
|
|
101008
|
+
}, []);
|
|
101009
|
+
const spanMap = useMemo(() => {
|
|
101010
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
101011
|
+
traces.forEach((trace2) => {
|
|
101012
|
+
const spans = getSpansFromTrace(trace2);
|
|
101013
|
+
spans.forEach((span) => map2.set(span.spanId, span));
|
|
101014
|
+
});
|
|
101015
|
+
return map2;
|
|
101016
|
+
}, [traces]);
|
|
101017
|
+
const spanBars = useMemo(() => {
|
|
101018
|
+
const bars = [];
|
|
101019
|
+
traces.forEach((trace2) => {
|
|
101020
|
+
const spans = getSpansFromTrace(trace2);
|
|
101021
|
+
if (spans.length > 0) {
|
|
101022
|
+
let earliestSpanId = spans[0].spanId;
|
|
101023
|
+
let earliestTime = parseNanoTime(spans[0].startTimeUnixNano);
|
|
101024
|
+
spans.forEach((span) => {
|
|
101025
|
+
const startMs = parseNanoTime(span.startTimeUnixNano);
|
|
101026
|
+
const endMs = parseNanoTime(span.endTimeUnixNano);
|
|
101027
|
+
if (startMs < earliestTime) {
|
|
101028
|
+
earliestTime = startMs;
|
|
101029
|
+
earliestSpanId = span.spanId;
|
|
101030
|
+
}
|
|
101031
|
+
bars.push({
|
|
101032
|
+
id: span.spanId,
|
|
101033
|
+
spanId: span.spanId,
|
|
101034
|
+
spanName: span.name,
|
|
101035
|
+
startMs,
|
|
101036
|
+
endMs,
|
|
101037
|
+
isRoot: false,
|
|
101038
|
+
// Will be set below
|
|
101039
|
+
traceId: trace2.traceId
|
|
101040
|
+
});
|
|
101041
|
+
});
|
|
101042
|
+
const rootBar = bars.find((b) => b.spanId === earliestSpanId);
|
|
101043
|
+
if (rootBar) rootBar.isRoot = true;
|
|
101044
|
+
} else {
|
|
101045
|
+
bars.push({
|
|
101046
|
+
id: `trace-${trace2.traceId}`,
|
|
101047
|
+
spanId: `trace-${trace2.traceId}`,
|
|
101048
|
+
spanName: trace2.name,
|
|
101049
|
+
startMs: trace2.startTime,
|
|
101050
|
+
endMs: trace2.endTime,
|
|
101051
|
+
isRoot: true,
|
|
101052
|
+
traceId: trace2.traceId
|
|
101053
|
+
});
|
|
101054
|
+
}
|
|
101055
|
+
});
|
|
101056
|
+
bars.sort((a, b) => a.startMs - b.startMs);
|
|
101057
|
+
return bars;
|
|
101058
|
+
}, [traces]);
|
|
101059
|
+
const findSpanByIndex = useCallback(
|
|
101060
|
+
(index2) => {
|
|
101061
|
+
if (index2 < 0 || index2 >= spanBars.length) return null;
|
|
101062
|
+
const bar = spanBars[index2];
|
|
101063
|
+
return spanMap.get(bar.spanId) || null;
|
|
101064
|
+
},
|
|
101065
|
+
[spanBars, spanMap]
|
|
101066
|
+
);
|
|
101067
|
+
const getSpanBarByIndex = useCallback(
|
|
101068
|
+
(index2) => {
|
|
101069
|
+
if (index2 < 0 || index2 >= spanBars.length) return null;
|
|
101070
|
+
return spanBars[index2];
|
|
101071
|
+
},
|
|
101072
|
+
[spanBars]
|
|
101073
|
+
);
|
|
101074
|
+
const getRelativePercent = useCallback((event) => {
|
|
101075
|
+
var _a2, _b;
|
|
101076
|
+
if (!tapeRef.current) return 0;
|
|
101077
|
+
const rect = tapeRef.current.getBoundingClientRect();
|
|
101078
|
+
const clientX = "touches" in event ? ((_a2 = event.touches[0]) == null ? void 0 : _a2.clientX) ?? ((_b = event.changedTouches[0]) == null ? void 0 : _b.clientX) ?? 0 : event.clientX;
|
|
101079
|
+
const x = clientX - rect.left;
|
|
101080
|
+
const percent = x / rect.width * 100;
|
|
101081
|
+
return Math.max(0, Math.min(100, percent));
|
|
101082
|
+
}, []);
|
|
101083
|
+
const handlePointerDown2 = useCallback(
|
|
101084
|
+
(event) => {
|
|
101085
|
+
if (!interactive) return;
|
|
101086
|
+
event.preventDefault();
|
|
101087
|
+
setIsDragging(true);
|
|
101088
|
+
const percent = getRelativePercent(event.nativeEvent);
|
|
101089
|
+
const spanIndex = percentToSpanIndex(percent, spanBars.length);
|
|
101090
|
+
const snappedPercent = spanIndexToPercent(spanIndex, spanBars.length);
|
|
101091
|
+
setScrubberPercent(snappedPercent);
|
|
101092
|
+
const span = findSpanByIndex(spanIndex);
|
|
101093
|
+
const bar = getSpanBarByIndex(spanIndex);
|
|
101094
|
+
onSpanHighlight((span == null ? void 0 : span.spanId) || (bar == null ? void 0 : bar.spanId) || null, span);
|
|
101095
|
+
},
|
|
101096
|
+
[
|
|
101097
|
+
interactive,
|
|
101098
|
+
percentToSpanIndex,
|
|
101099
|
+
spanIndexToPercent,
|
|
101100
|
+
spanBars.length,
|
|
101101
|
+
findSpanByIndex,
|
|
101102
|
+
getSpanBarByIndex,
|
|
101103
|
+
onSpanHighlight,
|
|
101104
|
+
getRelativePercent
|
|
101105
|
+
]
|
|
101106
|
+
);
|
|
101107
|
+
const handlePointerMove2 = useCallback(
|
|
101108
|
+
(event) => {
|
|
101109
|
+
if (!isDragging || !tapeRef.current) return;
|
|
101110
|
+
event.preventDefault();
|
|
101111
|
+
const percent = getRelativePercent(event);
|
|
101112
|
+
const spanIndex = percentToSpanIndex(percent, spanBars.length);
|
|
101113
|
+
const snappedPercent = spanIndexToPercent(spanIndex, spanBars.length);
|
|
101114
|
+
setScrubberPercent(snappedPercent);
|
|
101115
|
+
const span = findSpanByIndex(spanIndex);
|
|
101116
|
+
const bar = getSpanBarByIndex(spanIndex);
|
|
101117
|
+
onSpanHighlight((span == null ? void 0 : span.spanId) || (bar == null ? void 0 : bar.spanId) || null, span);
|
|
101118
|
+
},
|
|
101119
|
+
[
|
|
101120
|
+
isDragging,
|
|
101121
|
+
percentToSpanIndex,
|
|
101122
|
+
spanIndexToPercent,
|
|
101123
|
+
spanBars.length,
|
|
101124
|
+
findSpanByIndex,
|
|
101125
|
+
getSpanBarByIndex,
|
|
101126
|
+
onSpanHighlight,
|
|
101127
|
+
getRelativePercent
|
|
101128
|
+
]
|
|
101129
|
+
);
|
|
101130
|
+
const handlePointerUp2 = useCallback(() => {
|
|
101131
|
+
setIsDragging(false);
|
|
101132
|
+
}, []);
|
|
101133
|
+
useEffect(() => {
|
|
101134
|
+
if (focusTraceId === prevFocusTraceIdRef.current) return;
|
|
101135
|
+
prevFocusTraceIdRef.current = focusTraceId;
|
|
101136
|
+
if (!focusTraceId) return;
|
|
101137
|
+
const spanIndex = spanBars.findIndex((bar) => bar.traceId === focusTraceId);
|
|
101138
|
+
if (spanIndex !== -1) {
|
|
101139
|
+
const snappedPercent = spanIndexToPercent(spanIndex, spanBars.length);
|
|
101140
|
+
setScrubberPercent(snappedPercent);
|
|
101141
|
+
}
|
|
101142
|
+
}, [focusTraceId, spanBars, spanIndexToPercent]);
|
|
101143
|
+
useEffect(() => {
|
|
101144
|
+
if (isDragging) {
|
|
101145
|
+
window.addEventListener("mousemove", handlePointerMove2);
|
|
101146
|
+
window.addEventListener("mouseup", handlePointerUp2);
|
|
101147
|
+
window.addEventListener("touchmove", handlePointerMove2, { passive: false });
|
|
101148
|
+
window.addEventListener("touchend", handlePointerUp2);
|
|
101149
|
+
}
|
|
101150
|
+
return () => {
|
|
101151
|
+
window.removeEventListener("mousemove", handlePointerMove2);
|
|
101152
|
+
window.removeEventListener("mouseup", handlePointerUp2);
|
|
101153
|
+
window.removeEventListener("touchmove", handlePointerMove2);
|
|
101154
|
+
window.removeEventListener("touchend", handlePointerUp2);
|
|
101155
|
+
};
|
|
101156
|
+
}, [isDragging, handlePointerMove2, handlePointerUp2]);
|
|
101157
|
+
const formatDuration = (ms) => {
|
|
101158
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
101159
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
101160
|
+
const seconds = totalSeconds % 60;
|
|
101161
|
+
const milliseconds = Math.floor(ms % 1e3);
|
|
101162
|
+
if (minutes > 0) {
|
|
101163
|
+
return `${minutes}:${String(seconds).padStart(2, "0")}.${String(milliseconds).padStart(3, "0")}`;
|
|
101164
|
+
}
|
|
101165
|
+
return `${seconds}.${String(milliseconds).padStart(3, "0")}`;
|
|
101166
|
+
};
|
|
101167
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
101168
|
+
/* @__PURE__ */ jsx(
|
|
101169
|
+
"div",
|
|
101170
|
+
{
|
|
101171
|
+
style: {
|
|
101172
|
+
fontSize: theme2.fontSizes[1],
|
|
101173
|
+
fontFamily: theme2.fonts.monospace,
|
|
101174
|
+
color: theme2.colors.textSecondary,
|
|
101175
|
+
whiteSpace: "nowrap",
|
|
101176
|
+
minWidth: "60px"
|
|
101177
|
+
},
|
|
101178
|
+
children: traces.length > 0 ? "0.000" : "--.---"
|
|
101179
|
+
}
|
|
101180
|
+
),
|
|
101181
|
+
/* @__PURE__ */ jsxs(
|
|
101182
|
+
"div",
|
|
101183
|
+
{
|
|
101184
|
+
ref: tapeRef,
|
|
101185
|
+
onMouseDown: handlePointerDown2,
|
|
101186
|
+
onTouchStart: handlePointerDown2,
|
|
101187
|
+
style: {
|
|
101188
|
+
position: "relative",
|
|
101189
|
+
flex: 1,
|
|
101190
|
+
height: `${height}px`,
|
|
101191
|
+
background: resolvedColors.background,
|
|
101192
|
+
borderRadius: theme2.radii[2],
|
|
101193
|
+
overflow: "visible",
|
|
101194
|
+
cursor: interactive ? "pointer" : "default",
|
|
101195
|
+
userSelect: "none",
|
|
101196
|
+
touchAction: "none"
|
|
101197
|
+
},
|
|
101198
|
+
children: [
|
|
101199
|
+
traces.length === 0 && /* @__PURE__ */ jsx(
|
|
101200
|
+
"div",
|
|
101201
|
+
{
|
|
101202
|
+
style: {
|
|
101203
|
+
position: "absolute",
|
|
101204
|
+
inset: 0,
|
|
101205
|
+
display: "flex",
|
|
101206
|
+
alignItems: "center",
|
|
101207
|
+
justifyContent: "center",
|
|
101208
|
+
color: theme2.colors.textMuted,
|
|
101209
|
+
fontSize: theme2.fontSizes[2],
|
|
101210
|
+
fontFamily: theme2.fonts.body
|
|
101211
|
+
},
|
|
101212
|
+
children: "No traces"
|
|
101213
|
+
}
|
|
101214
|
+
),
|
|
101215
|
+
spanBars.map((bar, index2) => {
|
|
101216
|
+
const percent = spanIndexToPercent(index2, spanBars.length);
|
|
101217
|
+
const isHighlighted = bar.spanId === highlightedSpanId;
|
|
101218
|
+
const isInSelectedTrace = bar.traceId === selectedTraceId;
|
|
101219
|
+
const topOffset = bar.isRoot ? "4px" : "50%";
|
|
101220
|
+
const bottomOffset = "4px";
|
|
101221
|
+
const traceColor = theme2.colors.accent || "#14b8a6";
|
|
101222
|
+
const spanColor = resolvedColors.line;
|
|
101223
|
+
const selectedTraceColor = theme2.colors.accent || "#5eead4";
|
|
101224
|
+
const selectedSpanColor = `${theme2.colors.primary}cc`;
|
|
101225
|
+
const getWidth = () => {
|
|
101226
|
+
if (isHighlighted) return "6px";
|
|
101227
|
+
if (isInSelectedTrace) return bar.isRoot ? "6px" : "4px";
|
|
101228
|
+
return bar.isRoot ? "4px" : "2px";
|
|
101229
|
+
};
|
|
101230
|
+
const getBackground = () => {
|
|
101231
|
+
if (isHighlighted) return resolvedColors.highlighted;
|
|
101232
|
+
if (isInSelectedTrace) return bar.isRoot ? selectedTraceColor : selectedSpanColor;
|
|
101233
|
+
return bar.isRoot ? traceColor : spanColor;
|
|
101234
|
+
};
|
|
101235
|
+
return /* @__PURE__ */ jsx(
|
|
101236
|
+
"div",
|
|
101237
|
+
{
|
|
101238
|
+
style: {
|
|
101239
|
+
position: "absolute",
|
|
101240
|
+
left: `${percent}%`,
|
|
101241
|
+
transform: "translateX(-50%)",
|
|
101242
|
+
top: topOffset,
|
|
101243
|
+
bottom: bottomOffset,
|
|
101244
|
+
width: getWidth(),
|
|
101245
|
+
background: getBackground(),
|
|
101246
|
+
opacity: isHighlighted ? 1 : isInSelectedTrace ? 1 : bar.isRoot ? 0.9 : 0.5,
|
|
101247
|
+
borderRadius: "2px",
|
|
101248
|
+
transition: "all 0.15s",
|
|
101249
|
+
pointerEvents: "none",
|
|
101250
|
+
boxShadow: isInSelectedTrace ? `0 0 8px 2px ${getBackground()}` : "none"
|
|
101251
|
+
},
|
|
101252
|
+
title: `${bar.isRoot ? "Trace: " : ""}${bar.spanName} (${(bar.endMs - bar.startMs).toFixed(1)}ms)`
|
|
101253
|
+
},
|
|
101254
|
+
bar.id
|
|
101255
|
+
);
|
|
101256
|
+
}),
|
|
101257
|
+
scrubberPercent !== null && /* @__PURE__ */ jsx(
|
|
101258
|
+
"div",
|
|
101259
|
+
{
|
|
101260
|
+
style: {
|
|
101261
|
+
position: "absolute",
|
|
101262
|
+
left: `${scrubberPercent}%`,
|
|
101263
|
+
top: 0,
|
|
101264
|
+
bottom: 0,
|
|
101265
|
+
width: "2px",
|
|
101266
|
+
marginLeft: "-1px",
|
|
101267
|
+
background: resolvedColors.scrubber,
|
|
101268
|
+
pointerEvents: "none",
|
|
101269
|
+
zIndex: 10
|
|
101270
|
+
},
|
|
101271
|
+
children: /* @__PURE__ */ jsx(
|
|
101272
|
+
"div",
|
|
101273
|
+
{
|
|
101274
|
+
style: {
|
|
101275
|
+
position: "absolute",
|
|
101276
|
+
top: "-24px",
|
|
101277
|
+
left: "50%",
|
|
101278
|
+
transform: "translateX(-50%)",
|
|
101279
|
+
fontSize: theme2.fontSizes[0],
|
|
101280
|
+
fontFamily: theme2.fonts.monospace,
|
|
101281
|
+
color: resolvedColors.scrubber,
|
|
101282
|
+
whiteSpace: "nowrap",
|
|
101283
|
+
background: theme2.colors.background,
|
|
101284
|
+
padding: "2px 6px",
|
|
101285
|
+
borderRadius: "3px",
|
|
101286
|
+
textTransform: "uppercase",
|
|
101287
|
+
letterSpacing: "0.5px",
|
|
101288
|
+
border: `1px solid ${theme2.colors.border}`
|
|
101289
|
+
},
|
|
101290
|
+
children: ((_a = spanBars[percentToSpanIndex(scrubberPercent, spanBars.length)]) == null ? void 0 : _a.isRoot) ? "trace" : "span"
|
|
101291
|
+
}
|
|
101292
|
+
)
|
|
101293
|
+
}
|
|
101294
|
+
)
|
|
101295
|
+
]
|
|
101296
|
+
}
|
|
101297
|
+
),
|
|
101298
|
+
/* @__PURE__ */ jsx(
|
|
101299
|
+
"div",
|
|
101300
|
+
{
|
|
101301
|
+
style: {
|
|
101302
|
+
fontSize: theme2.fontSizes[1],
|
|
101303
|
+
fontFamily: theme2.fonts.monospace,
|
|
101304
|
+
color: theme2.colors.textSecondary,
|
|
101305
|
+
whiteSpace: "nowrap",
|
|
101306
|
+
minWidth: "60px",
|
|
101307
|
+
textAlign: "right"
|
|
101308
|
+
},
|
|
101309
|
+
children: traces.length > 0 ? formatDuration(timeRange.max - timeRange.min) : "--.---"
|
|
101310
|
+
}
|
|
101311
|
+
)
|
|
101312
|
+
] });
|
|
101313
|
+
}
|
|
100931
101314
|
class PanelFileSystemAdapter {
|
|
100932
101315
|
constructor(options) {
|
|
100933
101316
|
this.fileContentCache = /* @__PURE__ */ new Map();
|
|
@@ -101158,6 +101541,8 @@ const TraceListPanel = ({
|
|
|
101158
101541
|
const [activeTab, setActiveTab] = useState("traces");
|
|
101159
101542
|
const [selectedSchematicNodeId, setSelectedSchematicNodeId] = useState(null);
|
|
101160
101543
|
const [workflowFilterMode, setWorkflowFilterMode] = useState("all");
|
|
101544
|
+
const [highlightedSpanId, setHighlightedSpanId] = useState();
|
|
101545
|
+
const [focusTraceId, setFocusTraceId] = useState(null);
|
|
101161
101546
|
const telemetrySlice = context2.telemetry;
|
|
101162
101547
|
const traces = React__default.useMemo(() => (telemetrySlice == null ? void 0 : telemetrySlice.data) || [], [telemetrySlice == null ? void 0 : telemetrySlice.data]);
|
|
101163
101548
|
const schematicsSlice = context2.schematics;
|
|
@@ -101389,6 +101774,39 @@ const TraceListPanel = ({
|
|
|
101389
101774
|
setResources((prev) => ({ ...prev, [key.trim()]: "" }));
|
|
101390
101775
|
}
|
|
101391
101776
|
};
|
|
101777
|
+
const findTraceForSpan = (spanId) => {
|
|
101778
|
+
var _a;
|
|
101779
|
+
if (spanId.startsWith("trace-")) {
|
|
101780
|
+
const traceId = spanId.slice(6);
|
|
101781
|
+
return traces.find((t) => t.traceId === traceId) || null;
|
|
101782
|
+
}
|
|
101783
|
+
for (const trace2 of traces) {
|
|
101784
|
+
if ((_a = trace2.otlpData) == null ? void 0 : _a.resourceSpans) {
|
|
101785
|
+
for (const resourceSpan of trace2.otlpData.resourceSpans) {
|
|
101786
|
+
for (const scopeSpan of resourceSpan.scopeSpans) {
|
|
101787
|
+
if (scopeSpan.spans.some((s2) => s2.spanId === spanId)) {
|
|
101788
|
+
return trace2;
|
|
101789
|
+
}
|
|
101790
|
+
}
|
|
101791
|
+
}
|
|
101792
|
+
}
|
|
101793
|
+
}
|
|
101794
|
+
return null;
|
|
101795
|
+
};
|
|
101796
|
+
const handleSpanHighlight = (spanId, _span) => {
|
|
101797
|
+
setHighlightedSpanId(spanId ?? void 0);
|
|
101798
|
+
setFocusTraceId(null);
|
|
101799
|
+
if (spanId) {
|
|
101800
|
+
const trace2 = findTraceForSpan(spanId);
|
|
101801
|
+
if (trace2) {
|
|
101802
|
+
setExpandedTraceIds((prev) => {
|
|
101803
|
+
const newSet = new Set(prev);
|
|
101804
|
+
newSet.add(trace2.traceId);
|
|
101805
|
+
return newSet;
|
|
101806
|
+
});
|
|
101807
|
+
}
|
|
101808
|
+
}
|
|
101809
|
+
};
|
|
101392
101810
|
const handleTraceClick = (trace2) => {
|
|
101393
101811
|
setExpandedTraceIds((prev) => {
|
|
101394
101812
|
const newSet = new Set(prev);
|
|
@@ -101399,6 +101817,7 @@ const TraceListPanel = ({
|
|
|
101399
101817
|
}
|
|
101400
101818
|
return newSet;
|
|
101401
101819
|
});
|
|
101820
|
+
setFocusTraceId(trace2.traceId);
|
|
101402
101821
|
};
|
|
101403
101822
|
const handleTraceSelect = (trace2) => {
|
|
101404
101823
|
if (events) {
|
|
@@ -101688,20 +102107,46 @@ const TraceListPanel = ({
|
|
|
101688
102107
|
]
|
|
101689
102108
|
}
|
|
101690
102109
|
),
|
|
101691
|
-
activeTab === "traces" ? /* @__PURE__ */
|
|
101692
|
-
|
|
101693
|
-
|
|
101694
|
-
|
|
101695
|
-
|
|
101696
|
-
|
|
101697
|
-
|
|
101698
|
-
|
|
101699
|
-
|
|
101700
|
-
|
|
101701
|
-
|
|
101702
|
-
|
|
101703
|
-
|
|
101704
|
-
|
|
102110
|
+
activeTab === "traces" ? /* @__PURE__ */ jsxs("div", { style: { flex: 1, overflow: "hidden", display: "flex", flexDirection: "column" }, children: [
|
|
102111
|
+
traces.length > 0 && /* @__PURE__ */ jsx(
|
|
102112
|
+
"div",
|
|
102113
|
+
{
|
|
102114
|
+
style: {
|
|
102115
|
+
padding: "16px 16px 8px 16px",
|
|
102116
|
+
paddingTop: "24px",
|
|
102117
|
+
// Extra space for scrubber label
|
|
102118
|
+
borderBottom: `1px solid ${theme2.colors.border}`,
|
|
102119
|
+
flexShrink: 0
|
|
102120
|
+
},
|
|
102121
|
+
children: /* @__PURE__ */ jsx(
|
|
102122
|
+
TraceTape,
|
|
102123
|
+
{
|
|
102124
|
+
traces,
|
|
102125
|
+
theme: theme2,
|
|
102126
|
+
highlightedSpanId,
|
|
102127
|
+
selectedTraceId: Array.from(expandedTraceIds)[0],
|
|
102128
|
+
focusTraceId,
|
|
102129
|
+
onSpanHighlight: handleSpanHighlight,
|
|
102130
|
+
height: 40
|
|
102131
|
+
}
|
|
102132
|
+
)
|
|
102133
|
+
}
|
|
102134
|
+
),
|
|
102135
|
+
/* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "auto" }, children: /* @__PURE__ */ jsx(
|
|
102136
|
+
TraceList,
|
|
102137
|
+
{
|
|
102138
|
+
traces,
|
|
102139
|
+
theme: theme2,
|
|
102140
|
+
onTraceClick: handleTraceClick,
|
|
102141
|
+
onTraceSelect: handleTraceSelect,
|
|
102142
|
+
onWorkflowClick: handleWorkflowClick,
|
|
102143
|
+
onRemoveTrace: handleRemoveTrace,
|
|
102144
|
+
onClearAll: handleClearAll,
|
|
102145
|
+
expandedTraceIds,
|
|
102146
|
+
emptyMessage: traces.length === 0 ? "No traces received yet. Waiting for telemetry data..." : void 0
|
|
102147
|
+
}
|
|
102148
|
+
) })
|
|
102149
|
+
] }) : activeTab === "configuration" && showConfigurationTab ? /* @__PURE__ */ jsx("div", { style: { flex: 1, padding: "16px", overflow: "auto" }, children: configLoading ? /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", height: "100%" }, children: /* @__PURE__ */ jsx("div", { style: { fontFamily: theme2.fonts.body, fontSize: theme2.fontSizes[1], color: theme2.colors.textSecondary }, children: "Loading resources..." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
101705
102150
|
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "16px" }, children: [
|
|
101706
102151
|
/* @__PURE__ */ jsx("h2", { style: { margin: "0 0 8px 0", fontFamily: theme2.fonts.heading, fontSize: theme2.fontSizes[3], fontWeight: theme2.fontWeights.semibold }, children: "Library Resources" }),
|
|
101707
102152
|
/* @__PURE__ */ jsx("p", { style: { margin: 0, fontFamily: theme2.fonts.body, fontSize: theme2.fontSizes[1], color: theme2.colors.textSecondary }, children: "Configure OpenTelemetry and other resources in library.yaml" })
|