@flanksource/clicky-ui 0.3.56 → 0.3.57

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.
Files changed (141) hide show
  1. package/dist/components/ErrorWrapper.cjs +15 -4
  2. package/dist/components/ErrorWrapper.cjs.map +1 -1
  3. package/dist/components/ErrorWrapper.d.ts +7 -0
  4. package/dist/components/ErrorWrapper.d.ts.map +1 -1
  5. package/dist/components/ErrorWrapper.js +15 -4
  6. package/dist/components/ErrorWrapper.js.map +1 -1
  7. package/dist/data/ai/PromptCatalog/PromptLayerStrip.cjs +6 -3
  8. package/dist/data/ai/PromptCatalog/PromptLayerStrip.cjs.map +1 -1
  9. package/dist/data/ai/PromptCatalog/PromptLayerStrip.js +6 -3
  10. package/dist/data/ai/PromptCatalog/PromptLayerStrip.js.map +1 -1
  11. package/dist/data/ai/PromptCatalog/PromptPage.cjs +2 -1
  12. package/dist/data/ai/PromptCatalog/PromptPage.cjs.map +1 -1
  13. package/dist/data/ai/PromptCatalog/PromptPage.d.ts.map +1 -1
  14. package/dist/data/ai/PromptCatalog/PromptPage.js +2 -1
  15. package/dist/data/ai/PromptCatalog/PromptPage.js.map +1 -1
  16. package/dist/data/ai/PromptCatalog/PromptPageHeader.cjs +9 -6
  17. package/dist/data/ai/PromptCatalog/PromptPageHeader.cjs.map +1 -1
  18. package/dist/data/ai/PromptCatalog/PromptPageHeader.d.ts.map +1 -1
  19. package/dist/data/ai/PromptCatalog/PromptPageHeader.js +9 -6
  20. package/dist/data/ai/PromptCatalog/PromptPageHeader.js.map +1 -1
  21. package/dist/data/ai/PromptCatalog/PromptPageSaveBar.cjs +3 -3
  22. package/dist/data/ai/PromptCatalog/PromptPageSaveBar.cjs.map +1 -1
  23. package/dist/data/ai/PromptCatalog/PromptPageSaveBar.d.ts +2 -1
  24. package/dist/data/ai/PromptCatalog/PromptPageSaveBar.d.ts.map +1 -1
  25. package/dist/data/ai/PromptCatalog/PromptPageSaveBar.js +3 -3
  26. package/dist/data/ai/PromptCatalog/PromptPageSaveBar.js.map +1 -1
  27. package/dist/data/ai/PromptCatalog/prompt-page-model.cjs +4 -3
  28. package/dist/data/ai/PromptCatalog/prompt-page-model.cjs.map +1 -1
  29. package/dist/data/ai/PromptCatalog/prompt-page-model.d.ts +1 -1
  30. package/dist/data/ai/PromptCatalog/prompt-page-model.d.ts.map +1 -1
  31. package/dist/data/ai/PromptCatalog/prompt-page-model.js +4 -3
  32. package/dist/data/ai/PromptCatalog/prompt-page-model.js.map +1 -1
  33. package/dist/data/ai/PromptCatalog/types.d.ts +1 -0
  34. package/dist/data/ai/PromptCatalog/types.d.ts.map +1 -1
  35. package/dist/data/traces/index.d.ts +7 -0
  36. package/dist/data/traces/index.d.ts.map +1 -1
  37. package/dist/data/traces/otel/OperationList.cjs +64 -0
  38. package/dist/data/traces/otel/OperationList.cjs.map +1 -0
  39. package/dist/data/traces/otel/OperationList.d.ts +10 -0
  40. package/dist/data/traces/otel/OperationList.d.ts.map +1 -0
  41. package/dist/data/traces/otel/OperationList.js +64 -0
  42. package/dist/data/traces/otel/OperationList.js.map +1 -0
  43. package/dist/data/traces/otel/OtelTraceDetail.cjs +781 -0
  44. package/dist/data/traces/otel/OtelTraceDetail.cjs.map +1 -0
  45. package/dist/data/traces/otel/OtelTraceDetail.d.ts +7 -0
  46. package/dist/data/traces/otel/OtelTraceDetail.d.ts.map +1 -0
  47. package/dist/data/traces/otel/OtelTraceDetail.js +781 -0
  48. package/dist/data/traces/otel/OtelTraceDetail.js.map +1 -0
  49. package/dist/data/traces/otel/OtelTraceSearch.cjs +145 -0
  50. package/dist/data/traces/otel/OtelTraceSearch.cjs.map +1 -0
  51. package/dist/data/traces/otel/OtelTraceSearch.d.ts +16 -0
  52. package/dist/data/traces/otel/OtelTraceSearch.d.ts.map +1 -0
  53. package/dist/data/traces/otel/OtelTraceSearch.js +145 -0
  54. package/dist/data/traces/otel/OtelTraceSearch.js.map +1 -0
  55. package/dist/data/traces/otel/OtelTraceTable.cjs +47 -0
  56. package/dist/data/traces/otel/OtelTraceTable.cjs.map +1 -0
  57. package/dist/data/traces/otel/OtelTraceTable.d.ts +12 -0
  58. package/dist/data/traces/otel/OtelTraceTable.d.ts.map +1 -0
  59. package/dist/data/traces/otel/OtelTraceTable.js +47 -0
  60. package/dist/data/traces/otel/OtelTraceTable.js.map +1 -0
  61. package/dist/data/traces/otel/QueryBar.cjs +158 -0
  62. package/dist/data/traces/otel/QueryBar.cjs.map +1 -0
  63. package/dist/data/traces/otel/QueryBar.d.ts +12 -0
  64. package/dist/data/traces/otel/QueryBar.d.ts.map +1 -0
  65. package/dist/data/traces/otel/QueryBar.js +158 -0
  66. package/dist/data/traces/otel/QueryBar.js.map +1 -0
  67. package/dist/data/traces/otel/SpanCards.cjs +264 -0
  68. package/dist/data/traces/otel/SpanCards.cjs.map +1 -0
  69. package/dist/data/traces/otel/SpanCards.d.ts +17 -0
  70. package/dist/data/traces/otel/SpanCards.d.ts.map +1 -0
  71. package/dist/data/traces/otel/SpanCards.js +261 -0
  72. package/dist/data/traces/otel/SpanCards.js.map +1 -0
  73. package/dist/data/traces/otel/SpanCategory.cjs +18 -0
  74. package/dist/data/traces/otel/SpanCategory.cjs.map +1 -0
  75. package/dist/data/traces/otel/SpanCategory.d.ts +7 -0
  76. package/dist/data/traces/otel/SpanCategory.d.ts.map +1 -0
  77. package/dist/data/traces/otel/SpanCategory.js +18 -0
  78. package/dist/data/traces/otel/SpanCategory.js.map +1 -0
  79. package/dist/data/traces/otel/TraceResults.cjs +195 -0
  80. package/dist/data/traces/otel/TraceResults.cjs.map +1 -0
  81. package/dist/data/traces/otel/TraceResults.d.ts +19 -0
  82. package/dist/data/traces/otel/TraceResults.d.ts.map +1 -0
  83. package/dist/data/traces/otel/TraceResults.js +193 -0
  84. package/dist/data/traces/otel/TraceResults.js.map +1 -0
  85. package/dist/data/traces/otel/api.cjs +36 -0
  86. package/dist/data/traces/otel/api.cjs.map +1 -0
  87. package/dist/data/traces/otel/api.d.ts +87 -0
  88. package/dist/data/traces/otel/api.d.ts.map +1 -0
  89. package/dist/data/traces/otel/api.js +33 -0
  90. package/dist/data/traces/otel/api.js.map +1 -0
  91. package/dist/data/traces/otel/fixtures.d.ts +4 -0
  92. package/dist/data/traces/otel/fixtures.d.ts.map +1 -0
  93. package/dist/data/traces/otel/metrics.cjs +7 -0
  94. package/dist/data/traces/otel/metrics.cjs.map +1 -0
  95. package/dist/data/traces/otel/metrics.d.ts +2 -0
  96. package/dist/data/traces/otel/metrics.d.ts.map +1 -0
  97. package/dist/data/traces/otel/metrics.js +7 -0
  98. package/dist/data/traces/otel/metrics.js.map +1 -0
  99. package/dist/data/traces/otel/model.cjs +167 -0
  100. package/dist/data/traces/otel/model.cjs.map +1 -0
  101. package/dist/data/traces/otel/model.d.ts +81 -0
  102. package/dist/data/traces/otel/model.d.ts.map +1 -0
  103. package/dist/data/traces/otel/model.js +154 -0
  104. package/dist/data/traces/otel/model.js.map +1 -0
  105. package/dist/data/traces/otel/query.cjs +90 -0
  106. package/dist/data/traces/otel/query.cjs.map +1 -0
  107. package/dist/data/traces/otel/query.d.ts +20 -0
  108. package/dist/data/traces/otel/query.d.ts.map +1 -0
  109. package/dist/data/traces/otel/query.js +86 -0
  110. package/dist/data/traces/otel/query.js.map +1 -0
  111. package/dist/data/traces/otel/result-model.cjs +25 -0
  112. package/dist/data/traces/otel/result-model.cjs.map +1 -0
  113. package/dist/data/traces/otel/result-model.d.ts +5 -0
  114. package/dist/data/traces/otel/result-model.d.ts.map +1 -0
  115. package/dist/data/traces/otel/result-model.js +24 -0
  116. package/dist/data/traces/otel/result-model.js.map +1 -0
  117. package/dist/data/traces/otel/source.cjs +11 -0
  118. package/dist/data/traces/otel/source.cjs.map +1 -0
  119. package/dist/data/traces/otel/source.d.ts +5 -0
  120. package/dist/data/traces/otel/source.d.ts.map +1 -0
  121. package/dist/data/traces/otel/source.js +10 -0
  122. package/dist/data/traces/otel/source.js.map +1 -0
  123. package/dist/data/traces/otel/span-traces.cjs +39 -0
  124. package/dist/data/traces/otel/span-traces.cjs.map +1 -0
  125. package/dist/data/traces/otel/span-traces.d.ts +3 -0
  126. package/dist/data/traces/otel/span-traces.d.ts.map +1 -0
  127. package/dist/data/traces/otel/span-traces.js +39 -0
  128. package/dist/data/traces/otel/span-traces.js.map +1 -0
  129. package/dist/data/version-info.cjs +3 -3
  130. package/dist/data/version-info.js +3 -3
  131. package/dist/data.cjs +11 -0
  132. package/dist/data.js +6 -1
  133. package/dist/index.cjs +11 -0
  134. package/dist/index.js +6 -1
  135. package/dist/profiles/editor/profileEditorSections.cjs +4 -0
  136. package/dist/profiles/editor/profileEditorSections.cjs.map +1 -1
  137. package/dist/profiles/editor/profileEditorSections.d.ts.map +1 -1
  138. package/dist/profiles/editor/profileEditorSections.js +4 -0
  139. package/dist/profiles/editor/profileEditorSections.js.map +1 -1
  140. package/dist/styles.css +1 -1
  141. package/package.json +1 -1
@@ -0,0 +1,19 @@
1
+ import { DataTableProps } from '../../DataTable.js';
2
+ import { SearchResult, Summary } from './api.js';
3
+ export declare function ResultSummary({ result }: {
4
+ result: SearchResult;
5
+ }): import("react").JSX.Element;
6
+ /** Each trace by when it started and how long it took, dot size by span count. */
7
+ export declare function Scatter({ traces, onOpen }: {
8
+ traces: Summary[];
9
+ onOpen: (id: string) => void;
10
+ }): import("react").JSX.Element;
11
+ /** The traces, newest first: what ran, when, how long against the slowest, and its span count. */
12
+ export declare function ResultTable({ traces, href, onOpen, now, tableProps }: {
13
+ traces: Summary[];
14
+ href: (id: string) => string;
15
+ onOpen: (id: string) => void;
16
+ now: number;
17
+ tableProps?: Pick<DataTableProps<Summary>, "externalFilters" | "externalSearch" | "externalTimeRange" | "pagination" | "infinite" | "loading">;
18
+ }): import("react").JSX.Element;
19
+ //# sourceMappingURL=TraceResults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TraceResults.d.ts","sourceRoot":"","sources":["../../../../src/data/traces/otel/TraceResults.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmC,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAY,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,OAAO,CAAC;AAMlE,wBAAgB,aAAa,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,+BAUjE;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,+BAgD9F;AAED,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,UAAe,EAAE,EAAE;IAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAC;IAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC,CAAA;CAAE,+BAkDzT"}
@@ -0,0 +1,193 @@
1
+ import { Badge } from "../../Badge.js";
2
+ import { DataTable } from "../../DataTable.js";
3
+ import { duration } from "./api.js";
4
+ import { shortOperation } from "./query.js";
5
+ import { ago, niceStep } from "./result-model.js";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ // src/data/traces/otel/TraceResults.tsx
8
+ var startMs = (trace) => Date.parse(trace.startedAt);
9
+ var clock = (ms) => new Date(ms).toLocaleTimeString([], {
10
+ hour: "2-digit",
11
+ minute: "2-digit",
12
+ second: "2-digit"
13
+ });
14
+ function ResultSummary({ result }) {
15
+ const shown = result.traces.length;
16
+ return /* @__PURE__ */ jsxs("p", {
17
+ className: "text-sm text-muted-foreground",
18
+ children: [
19
+ /* @__PURE__ */ jsx("span", {
20
+ className: "font-medium text-foreground",
21
+ children: shown
22
+ }),
23
+ " ",
24
+ shown === 1 ? "trace" : "traces",
25
+ shown < result.total ? /* @__PURE__ */ jsxs(Fragment, { children: [
26
+ " · the ",
27
+ shown,
28
+ " newest of ",
29
+ result.total.toLocaleString(),
30
+ ". Narrow the window or operation to see older ones"
31
+ ] }) : /* @__PURE__ */ jsx(Fragment, { children: " · all in the window" })
32
+ ]
33
+ });
34
+ }
35
+ /** Each trace by when it started and how long it took, dot size by span count. */
36
+ function Scatter({ traces, onOpen }) {
37
+ const starts = traces.map(startMs);
38
+ const t0 = Math.min(...starts);
39
+ const span = Math.max(...starts) - t0;
40
+ const slowest = Math.max(...traces.map((trace) => trace.durationMs)) || 1;
41
+ const step = niceStep(slowest, 4);
42
+ const top = Math.ceil(slowest * 1.05 / step) * step;
43
+ const yTicks = Array.from({ length: Math.round(top / step) + 1 }, (_, i) => i * step);
44
+ const xTicks = span === 0 ? [.5] : [
45
+ 0,
46
+ .25,
47
+ .5,
48
+ .75,
49
+ 1
50
+ ];
51
+ const x = (ms) => span === 0 ? .5 : (ms - t0) / span;
52
+ return /* @__PURE__ */ jsxs("figure", {
53
+ className: "rounded-lg border border-border p-density-2",
54
+ "aria-label": "Duration over time",
55
+ children: [
56
+ /* @__PURE__ */ jsxs("figcaption", {
57
+ className: "mb-1 flex items-center gap-3 text-xs text-muted-foreground",
58
+ children: [/* @__PURE__ */ jsx("span", {
59
+ className: "font-medium text-foreground",
60
+ children: "Duration over time"
61
+ }), /* @__PURE__ */ jsx("span", { children: "dot size = span count · click to open" })]
62
+ }),
63
+ /* @__PURE__ */ jsxs("div", {
64
+ className: "relative ml-[4.5rem] mr-2 mt-3.5 h-[180px]",
65
+ children: [yTicks.map((y) => /* @__PURE__ */ jsx("div", {
66
+ className: "absolute inset-x-0 border-t border-border/60",
67
+ style: { bottom: `${y / top * 100}%` },
68
+ children: /* @__PURE__ */ jsx("span", {
69
+ className: "absolute right-full -translate-y-1/2 whitespace-nowrap pr-1.5 text-xs tabular-nums text-muted-foreground",
70
+ children: y === 0 ? "0" : duration(y)
71
+ })
72
+ }, y)), traces.map((trace) => {
73
+ const size = 6 + Math.log2(trace.spanCount) * 1.6;
74
+ const label = `${shortOperation(trace.operation)}, ${duration(trace.durationMs)}, ${trace.spanCount} spans at ${clock(startMs(trace))}`;
75
+ return /* @__PURE__ */ jsx("button", {
76
+ type: "button",
77
+ "aria-label": label,
78
+ title: label,
79
+ onClick: () => onOpen(trace.traceId),
80
+ className: `absolute -translate-x-1/2 translate-y-1/2 rounded-full opacity-75 hover:ring-2 hover:ring-ring ${trace.errors > 0 ? "bg-destructive" : trace.spanCount > 1 ? "bg-primary" : "bg-muted-foreground"}`,
81
+ style: {
82
+ left: `${x(startMs(trace)) * 100}%`,
83
+ bottom: `${trace.durationMs / top * 100}%`,
84
+ width: size,
85
+ height: size
86
+ }
87
+ }, trace.traceId);
88
+ })]
89
+ }),
90
+ /* @__PURE__ */ jsx("div", {
91
+ className: "relative ml-[4.5rem] mr-2 mt-1 h-4 text-xs tabular-nums text-muted-foreground",
92
+ children: xTicks.map((fraction, i) => /* @__PURE__ */ jsx("span", {
93
+ className: `absolute whitespace-nowrap ${xTicks.length > 1 && i === 0 ? "" : xTicks.length > 1 && i === xTicks.length - 1 ? "-translate-x-full" : "-translate-x-1/2"}`,
94
+ style: { left: `${fraction * 100}%` },
95
+ children: clock(t0 + fraction * span)
96
+ }, fraction))
97
+ })
98
+ ]
99
+ });
100
+ }
101
+ /** The traces, newest first: what ran, when, how long against the slowest, and its span count. */
102
+ function ResultTable({ traces, href, onOpen, now, tableProps = {} }) {
103
+ const slowest = Math.max(1, ...traces.map((trace) => trace.durationMs));
104
+ const columns = [
105
+ {
106
+ key: "operation",
107
+ label: "Trace",
108
+ grow: true,
109
+ minWidth: 320,
110
+ render: (_, trace) => /* @__PURE__ */ jsxs("span", {
111
+ className: "flex min-w-0 items-center gap-2",
112
+ title: trace.operation,
113
+ children: [
114
+ /* @__PURE__ */ jsx("span", {
115
+ className: "shrink-0 font-medium",
116
+ children: shortOperation(trace.operation) || trace.traceId
117
+ }),
118
+ /* @__PURE__ */ jsx("code", {
119
+ className: "text-xs text-muted-foreground",
120
+ children: trace.traceId.slice(0, 8)
121
+ }),
122
+ trace.services.length > 1 && /* @__PURE__ */ jsx("span", {
123
+ className: "truncate text-xs text-muted-foreground",
124
+ children: trace.services.join(" → ")
125
+ }),
126
+ trace.errors > 0 && /* @__PURE__ */ jsxs(Badge, {
127
+ size: "sm",
128
+ tone: "danger",
129
+ variant: "soft",
130
+ children: [
131
+ trace.errors,
132
+ " ",
133
+ trace.errors === 1 ? "error" : "errors"
134
+ ]
135
+ })
136
+ ]
137
+ })
138
+ },
139
+ {
140
+ key: "startedAt",
141
+ label: "Started",
142
+ render: (_, trace) => /* @__PURE__ */ jsxs("span", {
143
+ className: "whitespace-nowrap tabular-nums",
144
+ children: [
145
+ clock(startMs(trace)),
146
+ " ",
147
+ /* @__PURE__ */ jsx("span", {
148
+ className: "text-muted-foreground",
149
+ children: ago(now - startMs(trace))
150
+ })
151
+ ]
152
+ })
153
+ },
154
+ {
155
+ key: "durationMs",
156
+ label: "Duration",
157
+ render: (_, trace) => /* @__PURE__ */ jsxs("span", {
158
+ className: "flex items-center gap-2",
159
+ children: [/* @__PURE__ */ jsx("span", {
160
+ className: "relative h-1.5 w-24 rounded-full bg-muted",
161
+ children: /* @__PURE__ */ jsx("span", {
162
+ className: "absolute inset-y-0 left-0 rounded-full bg-primary",
163
+ style: { width: `${trace.durationMs / slowest * 100}%` }
164
+ })
165
+ }), /* @__PURE__ */ jsx("span", {
166
+ className: "tabular-nums",
167
+ children: duration(trace.durationMs)
168
+ })]
169
+ })
170
+ },
171
+ {
172
+ key: "spanCount",
173
+ label: "Spans",
174
+ align: "right"
175
+ }
176
+ ];
177
+ return /* @__PURE__ */ jsx("div", {
178
+ className: "flex h-[28rem] min-h-0 flex-col",
179
+ children: /* @__PURE__ */ jsx(DataTable, {
180
+ ...tableProps,
181
+ data: traces,
182
+ columns,
183
+ getRowId: (trace) => trace.traceId,
184
+ autoFilter: false,
185
+ getRowHref: (trace) => href(trace.traceId),
186
+ onRowClick: (trace) => onOpen(trace.traceId),
187
+ emptyMessage: "No traces match. Widen the time range, clear the duration or attribute filters, or show single-span traces."
188
+ })
189
+ });
190
+ }
191
+ export { ResultSummary, ResultTable, Scatter };
192
+
193
+ //# sourceMappingURL=TraceResults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TraceResults.js","names":["_Fragment"],"sources":["../../../../src/data/traces/otel/TraceResults.tsx"],"sourcesContent":["import { ago, niceStep } from \"./result-model\";\nimport { Badge } from \"../../Badge\";\nimport { DataTable, type DataTableColumn, type DataTableProps } from \"../../DataTable\";\nimport { duration, type SearchResult, type Summary } from \"./api\";\nimport { shortOperation } from \"./query\";\n\nconst startMs = (trace: Summary) => Date.parse(trace.startedAt);\nconst clock = (ms: number) => new Date(ms).toLocaleTimeString([], { hour: \"2-digit\", minute: \"2-digit\", second: \"2-digit\" });\n\nexport function ResultSummary({ result }: { result: SearchResult }) {\n const shown = result.traces.length;\n return (\n <p className=\"text-sm text-muted-foreground\">\n <span className=\"font-medium text-foreground\">{shown}</span> {shown === 1 ? \"trace\" : \"traces\"}\n {shown < result.total\n ? <> · the {shown} newest of {result.total.toLocaleString()}. Narrow the window or operation to see older ones</>\n : <> · all in the window</>}\n </p>\n );\n}\n\n/** Each trace by when it started and how long it took, dot size by span count. */\nexport function Scatter({ traces, onOpen }: { traces: Summary[]; onOpen: (id: string) => void }) {\n const starts = traces.map(startMs);\n const t0 = Math.min(...starts);\n const span = Math.max(...starts) - t0;\n const slowest = Math.max(...traces.map(trace => trace.durationMs)) || 1;\n const step = niceStep(slowest, 4);\n const top = Math.ceil((slowest * 1.05) / step) * step;\n const yTicks = Array.from({ length: Math.round(top / step) + 1 }, (_, i) => i * step);\n // Traces that all started together sit mid-axis under one tick.\n const xTicks = span === 0 ? [0.5] : [0, 0.25, 0.5, 0.75, 1];\n const x = (ms: number) => (span === 0 ? 0.5 : (ms - t0) / span);\n return (\n <figure className=\"rounded-lg border border-border p-density-2\" aria-label=\"Duration over time\">\n <figcaption className=\"mb-1 flex items-center gap-3 text-xs text-muted-foreground\">\n <span className=\"font-medium text-foreground\">Duration over time</span>\n <span>dot size = span count · click to open</span>\n </figcaption>\n <div className=\"relative ml-[4.5rem] mr-2 mt-3.5 h-[180px]\">\n {yTicks.map(y => (\n <div key={y} className=\"absolute inset-x-0 border-t border-border/60\" style={{ bottom: `${(y / top) * 100}%` }}>\n <span className=\"absolute right-full -translate-y-1/2 whitespace-nowrap pr-1.5 text-xs tabular-nums text-muted-foreground\">{y === 0 ? \"0\" : duration(y)}</span>\n </div>\n ))}\n {traces.map(trace => {\n const size = 6 + Math.log2(trace.spanCount) * 1.6;\n const label = `${shortOperation(trace.operation)}, ${duration(trace.durationMs)}, ${trace.spanCount} spans at ${clock(startMs(trace))}`;\n return (\n <button\n key={trace.traceId}\n type=\"button\"\n aria-label={label}\n title={label}\n onClick={() => onOpen(trace.traceId)}\n className={`absolute -translate-x-1/2 translate-y-1/2 rounded-full opacity-75 hover:ring-2 hover:ring-ring ${trace.errors > 0 ? \"bg-destructive\" : trace.spanCount > 1 ? \"bg-primary\" : \"bg-muted-foreground\"}`}\n style={{ left: `${x(startMs(trace)) * 100}%`, bottom: `${(trace.durationMs / top) * 100}%`, width: size, height: size }}\n />\n );\n })}\n </div>\n <div className=\"relative ml-[4.5rem] mr-2 mt-1 h-4 text-xs tabular-nums text-muted-foreground\">\n {xTicks.map((fraction, i) => (\n <span key={fraction} className={`absolute whitespace-nowrap ${xTicks.length > 1 && i === 0 ? \"\" : xTicks.length > 1 && i === xTicks.length - 1 ? \"-translate-x-full\" : \"-translate-x-1/2\"}`} style={{ left: `${fraction * 100}%` }}>\n {clock(t0 + fraction * span)}\n </span>\n ))}\n </div>\n </figure>\n );\n}\n\n/** The traces, newest first: what ran, when, how long against the slowest, and its span count. */\nexport function ResultTable({ traces, href, onOpen, now, tableProps = {} }: { traces: Summary[]; href: (id: string) => string; onOpen: (id: string) => void; now: number; tableProps?: Pick<DataTableProps<Summary>, \"externalFilters\" | \"externalSearch\" | \"externalTimeRange\" | \"pagination\" | \"infinite\" | \"loading\"> }) {\n const slowest = Math.max(1, ...traces.map(trace => trace.durationMs));\n const columns: DataTableColumn<Summary>[] = [\n {\n key: \"operation\",\n label: \"Trace\",\n grow: true,\n minWidth: 320,\n render: (_, trace) => (\n <span className=\"flex min-w-0 items-center gap-2\" title={trace.operation}>\n <span className=\"shrink-0 font-medium\">{shortOperation(trace.operation) || trace.traceId}</span>\n <code className=\"text-xs text-muted-foreground\">{trace.traceId.slice(0, 8)}</code>\n {trace.services.length > 1 && <span className=\"truncate text-xs text-muted-foreground\">{trace.services.join(\" → \")}</span>}\n {trace.errors > 0 && <Badge size=\"sm\" tone=\"danger\" variant=\"soft\">{trace.errors} {trace.errors === 1 ? \"error\" : \"errors\"}</Badge>}\n </span>\n ),\n },\n {\n key: \"startedAt\",\n label: \"Started\",\n render: (_, trace) => <span className=\"whitespace-nowrap tabular-nums\">{clock(startMs(trace))} <span className=\"text-muted-foreground\">{ago(now - startMs(trace))}</span></span>,\n },\n {\n key: \"durationMs\",\n label: \"Duration\",\n render: (_, trace) => (\n <span className=\"flex items-center gap-2\">\n <span className=\"relative h-1.5 w-24 rounded-full bg-muted\">\n <span className=\"absolute inset-y-0 left-0 rounded-full bg-primary\" style={{ width: `${(trace.durationMs / slowest) * 100}%` }} />\n </span>\n <span className=\"tabular-nums\">{duration(trace.durationMs)}</span>\n </span>\n ),\n },\n { key: \"spanCount\", label: \"Spans\", align: \"right\" },\n ];\n return (\n <div className=\"flex h-[28rem] min-h-0 flex-col\">\n <DataTable\n {...tableProps}\n data={traces}\n columns={columns}\n getRowId={trace => trace.traceId}\n autoFilter={false}\n getRowHref={trace => href(trace.traceId)}\n onRowClick={trace => onOpen(trace.traceId)}\n emptyMessage=\"No traces match. Widen the time range, clear the duration or attribute filters, or show single-span traces.\"\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ // src/data/traces/otel/api.ts
2
+ var MODE_FILTERS = [
3
+ "services",
4
+ "operations",
5
+ "statuses",
6
+ "attributes"
7
+ ];
8
+ function searchParams(value) {
9
+ const params = new URLSearchParams();
10
+ for (const [key, item] of Object.entries(value)) if (item !== void 0 && item !== null && item !== "" && !(typeof item === "object" && Object.keys(item).length === 0)) params.set(key, typeof item === "object" ? JSON.stringify(item) : String(item));
11
+ return params;
12
+ }
13
+ function parseModes(key, text) {
14
+ const value = JSON.parse(text);
15
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.values(value).some((mode) => mode !== "include" && mode !== "exclude")) throw new Error(`${key} must be a JSON object of values to include or exclude`);
16
+ return value;
17
+ }
18
+ function readSearchValues(params = new URLSearchParams(window.location.search)) {
19
+ const result = {};
20
+ for (const [key, value] of params) {
21
+ if (key === "span") continue;
22
+ if (MODE_FILTERS.includes(key)) result[key] = parseModes(key, value);
23
+ else if (key === "limit" || key === "minSpans") {
24
+ if (!/^\d+$/.test(value)) throw new Error(`${key} must be a whole number, not ${JSON.stringify(value)}`);
25
+ result[key] = Number(value);
26
+ } else result[key] = value;
27
+ }
28
+ return result;
29
+ }
30
+ var duration = (ms) => ms >= 1e3 ? `${(ms / 1e3).toFixed(2)} s` : ms >= 10 ? `${ms.toFixed(0)} ms` : ms >= 1 ? `${ms.toFixed(1)} ms` : `${(ms * 1e3).toFixed(0)} µs`;
31
+ exports.MODE_FILTERS = MODE_FILTERS;
32
+ exports.duration = duration;
33
+ exports.readSearchValues = readSearchValues;
34
+ exports.searchParams = searchParams;
35
+
36
+ //# sourceMappingURL=api.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.cjs","names":[],"sources":["../../../../src/data/traces/otel/api.ts"],"sourcesContent":["import type { JsonSchemaObject } from \"../../../components\";\n\nexport type Span = {\n traceId: string;\n spanId: string;\n parentId?: string;\n service: string;\n operation: string;\n kind?: string;\n startedAt: string;\n durationMs: number;\n status: string;\n attributes?: Record<string, unknown>;\n resource?: Record<string, unknown>;\n otlp?: Record<string, unknown>;\n};\nexport type Summary = {\n traceId: string;\n service: string;\n operation: string;\n startedAt: string;\n durationMs: number;\n spanCount: number;\n errors: number;\n services: string[];\n};\nexport interface Trace {\n summary: Summary;\n spans: Span[];\n missingParents: string[];\n}\n/** The traces of one root operation in the window (tracequery.OperationStats). */\nexport interface OperationStats {\n operation: string;\n count: number;\n singleSpan?: boolean;\n p50Ms: number;\n p95Ms: number;\n}\nexport interface SearchResult {\n traces: Summary[];\n total: number;\n services: string[];\n /** Every filter but the operation and span-count ones applied, by root operation. */\n rootOperations: OperationStats[];\n /** key=value suggestions from those traces' root spans, most frequent first. */\n attributes: { value: string; count: number }[];\n}\nexport interface Source {\n id: string;\n name: string;\n type: string;\n}\n/** A filter's values, each included or excluded (tracequery.Modes). */\nexport type Modes = Record<string, \"include\" | \"exclude\">;\nexport const MODE_FILTERS = [\"services\", \"operations\", \"statuses\", \"attributes\"] as const;\nexport type ModeFilter = (typeof MODE_FILTERS)[number];\nexport type SearchValues = Record<string, unknown> & {\n source?: string | undefined;\n run?: string | undefined;\n index?: string | undefined;\n format?: string | undefined;\n services?: Modes | undefined;\n /** Root operations. */\n operations?: Modes | undefined;\n statuses?: Modes | undefined;\n /** key, key=value or key=prefix* expressions. */\n attributes?: Modes | undefined;\n minSpans?: number | undefined;\n traceId?: string | undefined;\n lookback?: string | undefined;\n from?: string | undefined;\n until?: string | undefined;\n minDuration?: string | undefined;\n maxDuration?: string | undefined;\n limit?: number | undefined;\n};\nexport interface SearchForm {\n schema: JsonSchemaObject;\n defaults: SearchValues;\n}\nexport function searchParams(value: SearchValues): URLSearchParams {\n const params = new URLSearchParams();\n for (const [key, item] of Object.entries(value))\n if (\n item !== undefined && item !== null && item !== \"\" &&\n !(typeof item === \"object\" && Object.keys(item).length === 0)\n )\n params.set(\n key,\n typeof item === \"object\" ? JSON.stringify(item) : String(item),\n );\n return params;\n}\n\nfunction parseModes(key: string, text: string): Modes {\n const value: unknown = JSON.parse(text);\n if (!value || typeof value !== \"object\" || Array.isArray(value) || Object.values(value).some(mode => mode !== \"include\" && mode !== \"exclude\"))\n throw new Error(`${key} must be a JSON object of values to include or exclude`);\n return value as Modes;\n}\n\nexport function readSearchValues(params: URLSearchParams = new URLSearchParams(window.location.search)): SearchValues {\n const result: SearchValues = {};\n for (const [key, value] of params) {\n if (key === \"span\") continue;\n if ((MODE_FILTERS as readonly string[]).includes(key)) result[key] = parseModes(key, value);\n else if (key === \"limit\" || key === \"minSpans\") {\n if (!/^\\d+$/.test(value)) throw new Error(`${key} must be a whole number, not ${JSON.stringify(value)}`);\n result[key] = Number(value);\n } else result[key] = value;\n }\n return result;\n}\n\nexport const duration = (ms: number) =>\n ms >= 1000\n ? `${(ms / 1000).toFixed(2)} s`\n : ms >= 10\n ? `${ms.toFixed(0)} ms`\n : ms >= 1\n ? `${ms.toFixed(1)} ms`\n : `${(ms * 1000).toFixed(0)} µs`;\n"],"mappings":";AAuDA,IAAa,eAAe;CAAC;CAAY;CAAc;CAAY;AAAY;AA0B/E,SAAgB,aAAa,OAAsC;CACjE,MAAM,SAAS,IAAI,gBAAgB;CACnC,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,KAAK,GAC5C,IACE,SAAS,KAAA,KAAa,SAAS,QAAQ,SAAS,MAChD,EAAE,OAAO,SAAS,YAAY,OAAO,KAAK,IAAI,CAAC,CAAC,WAAW,IAE3D,OAAO,IACL,KACA,OAAO,SAAS,WAAW,KAAK,UAAU,IAAI,IAAI,OAAO,IAAI,CAC/D;CACJ,OAAO;AACT;AAEA,SAAS,WAAW,KAAa,MAAqB;CACpD,MAAM,QAAiB,KAAK,MAAM,IAAI;CACtC,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,KAAK,OAAO,OAAO,KAAK,CAAC,CAAC,MAAK,SAAQ,SAAS,aAAa,SAAS,SAAS,GAC3I,MAAM,IAAI,MAAM,GAAG,IAAI,uDAAuD;CAChF,OAAO;AACT;AAEA,SAAgB,iBAAiB,SAA0B,IAAI,gBAAgB,OAAO,SAAS,MAAM,GAAiB;CACpH,MAAM,SAAuB,CAAC;CAC9B,KAAK,MAAM,CAAC,KAAK,UAAU,QAAQ;EACjC,IAAI,QAAQ,QAAQ;EACpB,IAAK,aAAmC,SAAS,GAAG,GAAG,OAAO,OAAO,WAAW,KAAK,KAAK;OACrF,IAAI,QAAQ,WAAW,QAAQ,YAAY;GAC9C,IAAI,CAAC,QAAQ,KAAK,KAAK,GAAG,MAAM,IAAI,MAAM,GAAG,IAAI,+BAA+B,KAAK,UAAU,KAAK,GAAG;GACvG,OAAO,OAAO,OAAO,KAAK;EAC5B,OAAO,OAAO,OAAO;CACvB;CACA,OAAO;AACT;AAEA,IAAa,YAAY,OACvB,MAAM,MACF,IAAI,KAAK,IAAA,CAAM,QAAQ,CAAC,EAAE,MAC1B,MAAM,KACJ,GAAG,GAAG,QAAQ,CAAC,EAAE,OACjB,MAAM,IACJ,GAAG,GAAG,QAAQ,CAAC,EAAE,OACjB,IAAI,KAAK,IAAA,CAAM,QAAQ,CAAC,EAAE"}
@@ -0,0 +1,87 @@
1
+ import { JsonSchemaObject } from '../../../components.js';
2
+ export type Span = {
3
+ traceId: string;
4
+ spanId: string;
5
+ parentId?: string;
6
+ service: string;
7
+ operation: string;
8
+ kind?: string;
9
+ startedAt: string;
10
+ durationMs: number;
11
+ status: string;
12
+ attributes?: Record<string, unknown>;
13
+ resource?: Record<string, unknown>;
14
+ otlp?: Record<string, unknown>;
15
+ };
16
+ export type Summary = {
17
+ traceId: string;
18
+ service: string;
19
+ operation: string;
20
+ startedAt: string;
21
+ durationMs: number;
22
+ spanCount: number;
23
+ errors: number;
24
+ services: string[];
25
+ };
26
+ export interface Trace {
27
+ summary: Summary;
28
+ spans: Span[];
29
+ missingParents: string[];
30
+ }
31
+ /** The traces of one root operation in the window (tracequery.OperationStats). */
32
+ export interface OperationStats {
33
+ operation: string;
34
+ count: number;
35
+ singleSpan?: boolean;
36
+ p50Ms: number;
37
+ p95Ms: number;
38
+ }
39
+ export interface SearchResult {
40
+ traces: Summary[];
41
+ total: number;
42
+ services: string[];
43
+ /** Every filter but the operation and span-count ones applied, by root operation. */
44
+ rootOperations: OperationStats[];
45
+ /** key=value suggestions from those traces' root spans, most frequent first. */
46
+ attributes: {
47
+ value: string;
48
+ count: number;
49
+ }[];
50
+ }
51
+ export interface Source {
52
+ id: string;
53
+ name: string;
54
+ type: string;
55
+ }
56
+ /** A filter's values, each included or excluded (tracequery.Modes). */
57
+ export type Modes = Record<string, "include" | "exclude">;
58
+ export declare const MODE_FILTERS: readonly ["services", "operations", "statuses", "attributes"];
59
+ export type ModeFilter = (typeof MODE_FILTERS)[number];
60
+ export type SearchValues = Record<string, unknown> & {
61
+ source?: string | undefined;
62
+ run?: string | undefined;
63
+ index?: string | undefined;
64
+ format?: string | undefined;
65
+ services?: Modes | undefined;
66
+ /** Root operations. */
67
+ operations?: Modes | undefined;
68
+ statuses?: Modes | undefined;
69
+ /** key, key=value or key=prefix* expressions. */
70
+ attributes?: Modes | undefined;
71
+ minSpans?: number | undefined;
72
+ traceId?: string | undefined;
73
+ lookback?: string | undefined;
74
+ from?: string | undefined;
75
+ until?: string | undefined;
76
+ minDuration?: string | undefined;
77
+ maxDuration?: string | undefined;
78
+ limit?: number | undefined;
79
+ };
80
+ export interface SearchForm {
81
+ schema: JsonSchemaObject;
82
+ defaults: SearchValues;
83
+ }
84
+ export declare function searchParams(value: SearchValues): URLSearchParams;
85
+ export declare function readSearchValues(params?: URLSearchParams): SearchValues;
86
+ export declare const duration: (ms: number) => string;
87
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/data/traces/otel/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ // src/data/traces/otel/api.ts
2
+ var MODE_FILTERS = [
3
+ "services",
4
+ "operations",
5
+ "statuses",
6
+ "attributes"
7
+ ];
8
+ function searchParams(value) {
9
+ const params = new URLSearchParams();
10
+ for (const [key, item] of Object.entries(value)) if (item !== void 0 && item !== null && item !== "" && !(typeof item === "object" && Object.keys(item).length === 0)) params.set(key, typeof item === "object" ? JSON.stringify(item) : String(item));
11
+ return params;
12
+ }
13
+ function parseModes(key, text) {
14
+ const value = JSON.parse(text);
15
+ if (!value || typeof value !== "object" || Array.isArray(value) || Object.values(value).some((mode) => mode !== "include" && mode !== "exclude")) throw new Error(`${key} must be a JSON object of values to include or exclude`);
16
+ return value;
17
+ }
18
+ function readSearchValues(params = new URLSearchParams(window.location.search)) {
19
+ const result = {};
20
+ for (const [key, value] of params) {
21
+ if (key === "span") continue;
22
+ if (MODE_FILTERS.includes(key)) result[key] = parseModes(key, value);
23
+ else if (key === "limit" || key === "minSpans") {
24
+ if (!/^\d+$/.test(value)) throw new Error(`${key} must be a whole number, not ${JSON.stringify(value)}`);
25
+ result[key] = Number(value);
26
+ } else result[key] = value;
27
+ }
28
+ return result;
29
+ }
30
+ var duration = (ms) => ms >= 1e3 ? `${(ms / 1e3).toFixed(2)} s` : ms >= 10 ? `${ms.toFixed(0)} ms` : ms >= 1 ? `${ms.toFixed(1)} ms` : `${(ms * 1e3).toFixed(0)} µs`;
31
+ export { MODE_FILTERS, duration, readSearchValues, searchParams };
32
+
33
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","names":[],"sources":["../../../../src/data/traces/otel/api.ts"],"sourcesContent":["import type { JsonSchemaObject } from \"../../../components\";\n\nexport type Span = {\n traceId: string;\n spanId: string;\n parentId?: string;\n service: string;\n operation: string;\n kind?: string;\n startedAt: string;\n durationMs: number;\n status: string;\n attributes?: Record<string, unknown>;\n resource?: Record<string, unknown>;\n otlp?: Record<string, unknown>;\n};\nexport type Summary = {\n traceId: string;\n service: string;\n operation: string;\n startedAt: string;\n durationMs: number;\n spanCount: number;\n errors: number;\n services: string[];\n};\nexport interface Trace {\n summary: Summary;\n spans: Span[];\n missingParents: string[];\n}\n/** The traces of one root operation in the window (tracequery.OperationStats). */\nexport interface OperationStats {\n operation: string;\n count: number;\n singleSpan?: boolean;\n p50Ms: number;\n p95Ms: number;\n}\nexport interface SearchResult {\n traces: Summary[];\n total: number;\n services: string[];\n /** Every filter but the operation and span-count ones applied, by root operation. */\n rootOperations: OperationStats[];\n /** key=value suggestions from those traces' root spans, most frequent first. */\n attributes: { value: string; count: number }[];\n}\nexport interface Source {\n id: string;\n name: string;\n type: string;\n}\n/** A filter's values, each included or excluded (tracequery.Modes). */\nexport type Modes = Record<string, \"include\" | \"exclude\">;\nexport const MODE_FILTERS = [\"services\", \"operations\", \"statuses\", \"attributes\"] as const;\nexport type ModeFilter = (typeof MODE_FILTERS)[number];\nexport type SearchValues = Record<string, unknown> & {\n source?: string | undefined;\n run?: string | undefined;\n index?: string | undefined;\n format?: string | undefined;\n services?: Modes | undefined;\n /** Root operations. */\n operations?: Modes | undefined;\n statuses?: Modes | undefined;\n /** key, key=value or key=prefix* expressions. */\n attributes?: Modes | undefined;\n minSpans?: number | undefined;\n traceId?: string | undefined;\n lookback?: string | undefined;\n from?: string | undefined;\n until?: string | undefined;\n minDuration?: string | undefined;\n maxDuration?: string | undefined;\n limit?: number | undefined;\n};\nexport interface SearchForm {\n schema: JsonSchemaObject;\n defaults: SearchValues;\n}\nexport function searchParams(value: SearchValues): URLSearchParams {\n const params = new URLSearchParams();\n for (const [key, item] of Object.entries(value))\n if (\n item !== undefined && item !== null && item !== \"\" &&\n !(typeof item === \"object\" && Object.keys(item).length === 0)\n )\n params.set(\n key,\n typeof item === \"object\" ? JSON.stringify(item) : String(item),\n );\n return params;\n}\n\nfunction parseModes(key: string, text: string): Modes {\n const value: unknown = JSON.parse(text);\n if (!value || typeof value !== \"object\" || Array.isArray(value) || Object.values(value).some(mode => mode !== \"include\" && mode !== \"exclude\"))\n throw new Error(`${key} must be a JSON object of values to include or exclude`);\n return value as Modes;\n}\n\nexport function readSearchValues(params: URLSearchParams = new URLSearchParams(window.location.search)): SearchValues {\n const result: SearchValues = {};\n for (const [key, value] of params) {\n if (key === \"span\") continue;\n if ((MODE_FILTERS as readonly string[]).includes(key)) result[key] = parseModes(key, value);\n else if (key === \"limit\" || key === \"minSpans\") {\n if (!/^\\d+$/.test(value)) throw new Error(`${key} must be a whole number, not ${JSON.stringify(value)}`);\n result[key] = Number(value);\n } else result[key] = value;\n }\n return result;\n}\n\nexport const duration = (ms: number) =>\n ms >= 1000\n ? `${(ms / 1000).toFixed(2)} s`\n : ms >= 10\n ? `${ms.toFixed(0)} ms`\n : ms >= 1\n ? `${ms.toFixed(1)} ms`\n : `${(ms * 1000).toFixed(0)} µs`;\n"],"mappings":";AAuDA,IAAa,eAAe;CAAC;CAAY;CAAc;CAAY;AAAY;AA0B/E,SAAgB,aAAa,OAAsC;CACjE,MAAM,SAAS,IAAI,gBAAgB;CACnC,KAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,KAAK,GAC5C,IACE,SAAS,KAAA,KAAa,SAAS,QAAQ,SAAS,MAChD,EAAE,OAAO,SAAS,YAAY,OAAO,KAAK,IAAI,CAAC,CAAC,WAAW,IAE3D,OAAO,IACL,KACA,OAAO,SAAS,WAAW,KAAK,UAAU,IAAI,IAAI,OAAO,IAAI,CAC/D;CACJ,OAAO;AACT;AAEA,SAAS,WAAW,KAAa,MAAqB;CACpD,MAAM,QAAiB,KAAK,MAAM,IAAI;CACtC,IAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,KAAK,OAAO,OAAO,KAAK,CAAC,CAAC,MAAK,SAAQ,SAAS,aAAa,SAAS,SAAS,GAC3I,MAAM,IAAI,MAAM,GAAG,IAAI,uDAAuD;CAChF,OAAO;AACT;AAEA,SAAgB,iBAAiB,SAA0B,IAAI,gBAAgB,OAAO,SAAS,MAAM,GAAiB;CACpH,MAAM,SAAuB,CAAC;CAC9B,KAAK,MAAM,CAAC,KAAK,UAAU,QAAQ;EACjC,IAAI,QAAQ,QAAQ;EACpB,IAAK,aAAmC,SAAS,GAAG,GAAG,OAAO,OAAO,WAAW,KAAK,KAAK;OACrF,IAAI,QAAQ,WAAW,QAAQ,YAAY;GAC9C,IAAI,CAAC,QAAQ,KAAK,KAAK,GAAG,MAAM,IAAI,MAAM,GAAG,IAAI,+BAA+B,KAAK,UAAU,KAAK,GAAG;GACvG,OAAO,OAAO,OAAO,KAAK;EAC5B,OAAO,OAAO,OAAO;CACvB;CACA,OAAO;AACT;AAEA,IAAa,YAAY,OACvB,MAAM,MACF,IAAI,KAAK,IAAA,CAAM,QAAQ,CAAC,EAAE,MAC1B,MAAM,KACJ,GAAG,GAAG,QAAQ,CAAC,EAAE,OACjB,MAAM,IACJ,GAAG,GAAG,QAAQ,CAAC,EAAE,OACjB,IAAI,KAAK,IAAA,CAAM,QAAQ,CAAC,EAAE"}
@@ -0,0 +1,4 @@
1
+ import { Trace, SearchResult } from './api.js';
2
+ export declare const traceExample: Trace;
3
+ export declare const searchExample: SearchResult;
4
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../../../src/data/traces/otel/fixtures.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAEjD,eAAO,MAAM,YAAY,EAAE,KAQ1B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,YAG3B,CAAC"}
@@ -0,0 +1,7 @@
1
+ // src/data/traces/otel/metrics.ts
2
+ function metric(value, format = (value) => value.toLocaleString()) {
3
+ return value === void 0 ? "—" : format(value);
4
+ }
5
+ exports.metric = metric;
6
+
7
+ //# sourceMappingURL=metrics.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.cjs","names":[],"sources":["../../../../src/data/traces/otel/metrics.ts"],"sourcesContent":["export function metric(value: number | undefined, format: (value: number) => string = value => value.toLocaleString()): string {\n return value === undefined ? \"—\" : format(value);\n}\n"],"mappings":";AAAA,SAAgB,OAAO,OAA2B,UAAoC,UAAS,MAAM,eAAe,GAAW;CAC7H,OAAO,UAAU,KAAA,IAAY,MAAM,OAAO,KAAK;AACjD"}
@@ -0,0 +1,2 @@
1
+ export declare function metric(value: number | undefined, format?: (value: number) => string): string;
2
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../../src/data/traces/otel/metrics.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,MAAM,GAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAwC,GAAG,MAAM,CAE7H"}
@@ -0,0 +1,7 @@
1
+ // src/data/traces/otel/metrics.ts
2
+ function metric(value, format = (value) => value.toLocaleString()) {
3
+ return value === void 0 ? "—" : format(value);
4
+ }
5
+ export { metric };
6
+
7
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","names":[],"sources":["../../../../src/data/traces/otel/metrics.ts"],"sourcesContent":["export function metric(value: number | undefined, format: (value: number) => string = value => value.toLocaleString()): string {\n return value === undefined ? \"—\" : format(value);\n}\n"],"mappings":";AAAA,SAAgB,OAAO,OAA2B,UAAoC,UAAS,MAAM,eAAe,GAAW;CAC7H,OAAO,UAAU,KAAA,IAAY,MAAM,OAAO,KAAK;AACjD"}
@@ -0,0 +1,167 @@
1
+ // src/data/traces/otel/model.ts
2
+ var CATEGORY_LABEL = {
3
+ agent: "Agent",
4
+ llm: "LLM",
5
+ db: "Database",
6
+ other: "Other"
7
+ };
8
+ /** Shared theme colors for the four span categories. */
9
+ var CATEGORY_COLOR = {
10
+ agent: "var(--primary)",
11
+ llm: "var(--fs-prereq-500)",
12
+ db: "var(--fs-info)",
13
+ other: "var(--muted-foreground)"
14
+ };
15
+ function category(span) {
16
+ const op = span.attributes?.["gen_ai.operation.name"];
17
+ if (op === "invoke_agent") return "agent";
18
+ if (op === "chat" || op === "text_completion" || op === "embeddings") return "llm";
19
+ if (span.attributes?.["db.system"] !== void 0) return "db";
20
+ return "other";
21
+ }
22
+ var isError = (span) => ["error", "2"].includes(span.status.toLowerCase());
23
+ /** `invoke_agent /abs/path/.captain/prompts/jira/x.prompt` → `invoke_agent jira/x.prompt`. */
24
+ var shortOperation = (op) => op.replace(/ \/\S*\/prompts\//, " ");
25
+ /** RFC3339 with up to nanosecond fraction → epoch microseconds (Date.parse keeps only ms). */
26
+ function micros(iso) {
27
+ const match = /^(.*?)(?:\.(\d+))?(Z|[+-]\d{2}:\d{2})$/.exec(iso);
28
+ if (!match) throw new Error(`unexpected timestamp ${iso}`);
29
+ const seconds = Date.parse(`${match[1]}${match[3]}`);
30
+ if (!Number.isFinite(seconds)) throw new Error(`unexpected timestamp ${iso}`);
31
+ return seconds * 1e3 + Number((match[2] ?? "").padEnd(6, "0").slice(0, 6));
32
+ }
33
+ var duration = (ms) => ms >= 1e3 ? `${(ms / 1e3).toFixed(2)} s` : ms >= 10 ? `${ms.toFixed(0)} ms` : ms >= 1 ? `${ms.toFixed(1)} ms` : `${(ms * 1e3).toFixed(0)} µs`;
34
+ function indexTrace(trace) {
35
+ const byId = new Map(trace.spans.map((span) => [span.spanId, span]));
36
+ if (byId.size !== trace.spans.length) throw new Error("duplicate span ids");
37
+ for (const span of trace.spans) {
38
+ const seen = /* @__PURE__ */ new Set();
39
+ for (let current = span; current; current = current.parentId ? byId.get(current.parentId) : void 0) {
40
+ if (seen.has(current.spanId)) throw new Error("span parent cycle");
41
+ seen.add(current.spanId);
42
+ }
43
+ }
44
+ const children = /* @__PURE__ */ new Map();
45
+ const roots = [];
46
+ for (const span of trace.spans) if (span.parentId && byId.has(span.parentId)) children.set(span.parentId, [...children.get(span.parentId) ?? [], span]);
47
+ else roots.push(span);
48
+ const order = (a, b) => micros(a.startedAt) - micros(b.startedAt) || a.spanId.localeCompare(b.spanId);
49
+ roots.sort(order);
50
+ for (const list of children.values()) list.sort(order);
51
+ const t0 = micros(trace.summary.startedAt);
52
+ return {
53
+ byId,
54
+ children,
55
+ roots,
56
+ offsetMs: (span) => (micros(span.startedAt) - t0) / 1e3,
57
+ totalMs: trace.summary.durationMs
58
+ };
59
+ }
60
+ /**
61
+ * Depth-first rows. With `group`, every run of ≥ GROUP_MIN consecutive leaf DB
62
+ * siblings becomes one group row; `expanded` opens a group, `collapsed` closes
63
+ * a span. `visible`, when set, keeps only those spans (callers include ancestors).
64
+ */
65
+ function buildRows(index, opts) {
66
+ const rows = [];
67
+ const walk = (siblings, depth) => {
68
+ const shown = opts.visible ? siblings.filter((span) => opts.visible.has(span.spanId)) : siblings;
69
+ let i = 0;
70
+ while (i < shown.length) {
71
+ let j = i;
72
+ const groupable = (span) => opts.group && category(span) === "db" && !index.children.has(span.spanId);
73
+ while (j < shown.length && groupable(shown[j])) j++;
74
+ if (j - i >= 3) {
75
+ const spans = shown.slice(i, j);
76
+ const id = `group:${spans[0].spanId}`;
77
+ rows.push({
78
+ type: "group",
79
+ id,
80
+ depth,
81
+ spans
82
+ });
83
+ if (opts.expanded.has(id)) for (const span of spans) rows.push({
84
+ type: "span",
85
+ id: span.spanId,
86
+ depth: depth + 1,
87
+ span,
88
+ childCount: 0
89
+ });
90
+ i = j;
91
+ continue;
92
+ }
93
+ const span = shown[i];
94
+ const kids = index.children.get(span.spanId) ?? [];
95
+ rows.push({
96
+ type: "span",
97
+ id: span.spanId,
98
+ depth,
99
+ span,
100
+ childCount: kids.length
101
+ });
102
+ if (!opts.collapsed.has(span.spanId)) walk(kids, depth + 1);
103
+ i++;
104
+ }
105
+ };
106
+ walk(index.roots, 0);
107
+ return rows;
108
+ }
109
+ function withAncestors(index, ids) {
110
+ const out = /* @__PURE__ */ new Set();
111
+ for (const id of ids) for (let span = index.byId.get(id); span && !out.has(span.spanId); span = span.parentId ? index.byId.get(span.parentId) : void 0) out.add(span.spanId);
112
+ return out;
113
+ }
114
+ /** Spans that run entirely inside a sibling agent span yet hang off the shared parent — usually lost context propagation. */
115
+ function misparented(index) {
116
+ const out = /* @__PURE__ */ new Map();
117
+ for (const siblings of [index.roots, ...index.children.values()]) {
118
+ const agents = siblings.filter((span) => category(span) === "agent");
119
+ for (const span of siblings) {
120
+ const start = index.offsetMs(span);
121
+ const host = agents.find((agent) => agent !== span && start >= index.offsetMs(agent) && start + span.durationMs <= index.offsetMs(agent) + agent.durationMs);
122
+ if (host) out.set(span.spanId, host);
123
+ }
124
+ }
125
+ return out;
126
+ }
127
+ /** Wall time of `span` not covered by any direct child. */
128
+ function selfTimeMs(index, span) {
129
+ const start = index.offsetMs(span);
130
+ const finish = start + span.durationMs;
131
+ const intervals = (index.children.get(span.spanId) ?? []).map((child) => [Math.max(start, index.offsetMs(child)), Math.min(finish, index.offsetMs(child) + child.durationMs)]).filter(([s, e]) => e > s).sort((a, b) => a[0] - b[0]);
132
+ let covered = 0;
133
+ let end = -Infinity;
134
+ for (const [s, e] of intervals) {
135
+ if (e <= end) continue;
136
+ covered += e - Math.max(s, end);
137
+ end = e;
138
+ }
139
+ return span.durationMs - covered;
140
+ }
141
+ var num = (value) => value === void 0 ? void 0 : Number(value);
142
+ function niceStep(totalMs, ticks = 6) {
143
+ const raw = totalMs / ticks;
144
+ const pow = 10 ** Math.floor(Math.log10(raw));
145
+ return [
146
+ 1,
147
+ 2,
148
+ 5,
149
+ 10
150
+ ].map((m) => m * pow).find((step) => step >= raw);
151
+ }
152
+ exports.CATEGORY_COLOR = CATEGORY_COLOR;
153
+ exports.CATEGORY_LABEL = CATEGORY_LABEL;
154
+ exports.buildRows = buildRows;
155
+ exports.category = category;
156
+ exports.duration = duration;
157
+ exports.indexTrace = indexTrace;
158
+ exports.isError = isError;
159
+ exports.micros = micros;
160
+ exports.misparented = misparented;
161
+ exports.niceStep = niceStep;
162
+ exports.num = num;
163
+ exports.selfTimeMs = selfTimeMs;
164
+ exports.shortOperation = shortOperation;
165
+ exports.withAncestors = withAncestors;
166
+
167
+ //# sourceMappingURL=model.cjs.map