@openchoreo/backstage-plugin-openchoreo-observability 1.1.0

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 (196) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +22 -0
  3. package/dist/api/FinOpsAgentApi.esm.js +43 -0
  4. package/dist/api/FinOpsAgentApi.esm.js.map +1 -0
  5. package/dist/api/ObservabilityApi.esm.js +568 -0
  6. package/dist/api/ObservabilityApi.esm.js.map +1 -0
  7. package/dist/api/ObserverUrlCache.esm.js +59 -0
  8. package/dist/api/ObserverUrlCache.esm.js.map +1 -0
  9. package/dist/api/RCAAgentApi.esm.js +104 -0
  10. package/dist/api/RCAAgentApi.esm.js.map +1 -0
  11. package/dist/components/Alerts/AlertRow.esm.js +203 -0
  12. package/dist/components/Alerts/AlertRow.esm.js.map +1 -0
  13. package/dist/components/Alerts/AlertsActions.esm.js +77 -0
  14. package/dist/components/Alerts/AlertsActions.esm.js.map +1 -0
  15. package/dist/components/Alerts/AlertsFilter.esm.js +95 -0
  16. package/dist/components/Alerts/AlertsFilter.esm.js.map +1 -0
  17. package/dist/components/Alerts/AlertsTable.esm.js +63 -0
  18. package/dist/components/Alerts/AlertsTable.esm.js.map +1 -0
  19. package/dist/components/Alerts/ObservabilityAlertsPage.esm.js +251 -0
  20. package/dist/components/Alerts/ObservabilityAlertsPage.esm.js.map +1 -0
  21. package/dist/components/Alerts/types.esm.js +4 -0
  22. package/dist/components/Alerts/types.esm.js.map +1 -0
  23. package/dist/components/CostAnalysis/CostAnalysisPage.esm.js +141 -0
  24. package/dist/components/CostAnalysis/CostAnalysisPage.esm.js.map +1 -0
  25. package/dist/components/CostAnalysis/CostAnalysisReport.esm.js +128 -0
  26. package/dist/components/CostAnalysis/CostAnalysisReport.esm.js.map +1 -0
  27. package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js +517 -0
  28. package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js.map +1 -0
  29. package/dist/components/CostAnalysis/CostAnalysisTable.esm.js +149 -0
  30. package/dist/components/CostAnalysis/CostAnalysisTable.esm.js.map +1 -0
  31. package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js +112 -0
  32. package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js.map +1 -0
  33. package/dist/components/CostAnalysis/index.esm.js +2 -0
  34. package/dist/components/CostAnalysis/index.esm.js.map +1 -0
  35. package/dist/components/Incidents/IncidentRow.esm.js +258 -0
  36. package/dist/components/Incidents/IncidentRow.esm.js.map +1 -0
  37. package/dist/components/Incidents/IncidentsActions.esm.js +77 -0
  38. package/dist/components/Incidents/IncidentsActions.esm.js.map +1 -0
  39. package/dist/components/Incidents/IncidentsFilter.esm.js +144 -0
  40. package/dist/components/Incidents/IncidentsFilter.esm.js.map +1 -0
  41. package/dist/components/Incidents/IncidentsTable.esm.js +68 -0
  42. package/dist/components/Incidents/IncidentsTable.esm.js.map +1 -0
  43. package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js +283 -0
  44. package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js.map +1 -0
  45. package/dist/components/Incidents/types.esm.js +8 -0
  46. package/dist/components/Incidents/types.esm.js.map +1 -0
  47. package/dist/components/Metrics/ChartTooltip.esm.js +53 -0
  48. package/dist/components/Metrics/ChartTooltip.esm.js.map +1 -0
  49. package/dist/components/Metrics/HTTPMetricsSection.esm.js +109 -0
  50. package/dist/components/Metrics/HTTPMetricsSection.esm.js.map +1 -0
  51. package/dist/components/Metrics/MetricGraphByComponent.esm.js +99 -0
  52. package/dist/components/Metrics/MetricGraphByComponent.esm.js.map +1 -0
  53. package/dist/components/Metrics/MetricsActions.esm.js +30 -0
  54. package/dist/components/Metrics/MetricsActions.esm.js.map +1 -0
  55. package/dist/components/Metrics/MetricsFilters.esm.js +49 -0
  56. package/dist/components/Metrics/MetricsFilters.esm.js.map +1 -0
  57. package/dist/components/Metrics/ObservabilityMetricsPage.esm.js +196 -0
  58. package/dist/components/Metrics/ObservabilityMetricsPage.esm.js.map +1 -0
  59. package/dist/components/Metrics/styles.esm.js +55 -0
  60. package/dist/components/Metrics/styles.esm.js.map +1 -0
  61. package/dist/components/Metrics/utils.esm.js +221 -0
  62. package/dist/components/Metrics/utils.esm.js.map +1 -0
  63. package/dist/components/RCA/RCAActions.esm.js +42 -0
  64. package/dist/components/RCA/RCAActions.esm.js.map +1 -0
  65. package/dist/components/RCA/RCAFilters.esm.js +100 -0
  66. package/dist/components/RCA/RCAFilters.esm.js.map +1 -0
  67. package/dist/components/RCA/RCAPage.esm.js +137 -0
  68. package/dist/components/RCA/RCAPage.esm.js.map +1 -0
  69. package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js +9 -0
  70. package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js.map +1 -0
  71. package/dist/components/RCA/RCAReport/FormattedText.esm.js +94 -0
  72. package/dist/components/RCA/RCAReport/FormattedText.esm.js.map +1 -0
  73. package/dist/components/RCA/RCAReport/RCAReportView.esm.js +308 -0
  74. package/dist/components/RCA/RCAReport/RCAReportView.esm.js.map +1 -0
  75. package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js +113 -0
  76. package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js.map +1 -0
  77. package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js +272 -0
  78. package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js.map +1 -0
  79. package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js +48 -0
  80. package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js.map +1 -0
  81. package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js +205 -0
  82. package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js.map +1 -0
  83. package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js +121 -0
  84. package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js.map +1 -0
  85. package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js +593 -0
  86. package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js.map +1 -0
  87. package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js +35 -0
  88. package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js.map +1 -0
  89. package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js +54 -0
  90. package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js.map +1 -0
  91. package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js +526 -0
  92. package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js.map +1 -0
  93. package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js +70 -0
  94. package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js.map +1 -0
  95. package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js +54 -0
  96. package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js.map +1 -0
  97. package/dist/components/RCA/RCAReport/styles.esm.js +467 -0
  98. package/dist/components/RCA/RCAReport/styles.esm.js.map +1 -0
  99. package/dist/components/RCA/RCAReport.esm.js +109 -0
  100. package/dist/components/RCA/RCAReport.esm.js.map +1 -0
  101. package/dist/components/RCA/RCATable.esm.js +140 -0
  102. package/dist/components/RCA/RCATable.esm.js.map +1 -0
  103. package/dist/components/RuntimeLogs/LogEntry.esm.js +182 -0
  104. package/dist/components/RuntimeLogs/LogEntry.esm.js.map +1 -0
  105. package/dist/components/RuntimeLogs/LogsActions.esm.js +106 -0
  106. package/dist/components/RuntimeLogs/LogsActions.esm.js.map +1 -0
  107. package/dist/components/RuntimeLogs/LogsFilter.esm.js +200 -0
  108. package/dist/components/RuntimeLogs/LogsFilter.esm.js.map +1 -0
  109. package/dist/components/RuntimeLogs/LogsTable.esm.js +91 -0
  110. package/dist/components/RuntimeLogs/LogsTable.esm.js.map +1 -0
  111. package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js +220 -0
  112. package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js.map +1 -0
  113. package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js +222 -0
  114. package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js.map +1 -0
  115. package/dist/components/RuntimeLogs/styles.esm.js +256 -0
  116. package/dist/components/RuntimeLogs/styles.esm.js.map +1 -0
  117. package/dist/components/RuntimeLogs/types.esm.js +16 -0
  118. package/dist/components/RuntimeLogs/types.esm.js.map +1 -0
  119. package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js +280 -0
  120. package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js.map +1 -0
  121. package/dist/components/Traces/ObservabilityTracesPage.esm.js +165 -0
  122. package/dist/components/Traces/ObservabilityTracesPage.esm.js.map +1 -0
  123. package/dist/components/Traces/TracesActions.esm.js +37 -0
  124. package/dist/components/Traces/TracesActions.esm.js.map +1 -0
  125. package/dist/components/Traces/TracesFilters.esm.js +121 -0
  126. package/dist/components/Traces/TracesFilters.esm.js.map +1 -0
  127. package/dist/components/Traces/TracesTable.esm.js +137 -0
  128. package/dist/components/Traces/TracesTable.esm.js.map +1 -0
  129. package/dist/components/Traces/WaterfallView.esm.js +567 -0
  130. package/dist/components/Traces/WaterfallView.esm.js.map +1 -0
  131. package/dist/components/Traces/styles.esm.js +198 -0
  132. package/dist/components/Traces/styles.esm.js.map +1 -0
  133. package/dist/components/Traces/utils.esm.js +19 -0
  134. package/dist/components/Traces/utils.esm.js.map +1 -0
  135. package/dist/hooks/useAutoSelectFirstEnvironment.esm.js +25 -0
  136. package/dist/hooks/useAutoSelectFirstEnvironment.esm.js.map +1 -0
  137. package/dist/hooks/useComponentAlerts.esm.js +80 -0
  138. package/dist/hooks/useComponentAlerts.esm.js.map +1 -0
  139. package/dist/hooks/useDataPlaneNetPolProvider.esm.js +55 -0
  140. package/dist/hooks/useDataPlaneNetPolProvider.esm.js.map +1 -0
  141. package/dist/hooks/useDebouncedSearch.esm.js +24 -0
  142. package/dist/hooks/useDebouncedSearch.esm.js.map +1 -0
  143. package/dist/hooks/useFilters.esm.js +29 -0
  144. package/dist/hooks/useFilters.esm.js.map +1 -0
  145. package/dist/hooks/useFinOpsReport.esm.js +66 -0
  146. package/dist/hooks/useFinOpsReport.esm.js.map +1 -0
  147. package/dist/hooks/useFinOpsReports.esm.js +70 -0
  148. package/dist/hooks/useFinOpsReports.esm.js.map +1 -0
  149. package/dist/hooks/useGetComponentsByProject.esm.js +57 -0
  150. package/dist/hooks/useGetComponentsByProject.esm.js.map +1 -0
  151. package/dist/hooks/useGetEnvironmentsByNamespace.esm.js +53 -0
  152. package/dist/hooks/useGetEnvironmentsByNamespace.esm.js.map +1 -0
  153. package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js +40 -0
  154. package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js.map +1 -0
  155. package/dist/hooks/useMetrics.esm.js +107 -0
  156. package/dist/hooks/useMetrics.esm.js.map +1 -0
  157. package/dist/hooks/useProjectIncidents.esm.js +111 -0
  158. package/dist/hooks/useProjectIncidents.esm.js.map +1 -0
  159. package/dist/hooks/useProjectRuntimeLogs.esm.js +185 -0
  160. package/dist/hooks/useProjectRuntimeLogs.esm.js.map +1 -0
  161. package/dist/hooks/useRCAReportByAlert.esm.js +54 -0
  162. package/dist/hooks/useRCAReportByAlert.esm.js.map +1 -0
  163. package/dist/hooks/useRCAReports.esm.js +75 -0
  164. package/dist/hooks/useRCAReports.esm.js.map +1 -0
  165. package/dist/hooks/useRuntimeLogs.esm.js +147 -0
  166. package/dist/hooks/useRuntimeLogs.esm.js.map +1 -0
  167. package/dist/hooks/useSpanDetails.esm.js +71 -0
  168. package/dist/hooks/useSpanDetails.esm.js.map +1 -0
  169. package/dist/hooks/useTraceSpans.esm.js +80 -0
  170. package/dist/hooks/useTraceSpans.esm.js.map +1 -0
  171. package/dist/hooks/useTraces.esm.js +112 -0
  172. package/dist/hooks/useTraces.esm.js.map +1 -0
  173. package/dist/hooks/useUpdateIncident.esm.js +50 -0
  174. package/dist/hooks/useUpdateIncident.esm.js.map +1 -0
  175. package/dist/hooks/useUrlFilters.esm.js +63 -0
  176. package/dist/hooks/useUrlFilters.esm.js.map +1 -0
  177. package/dist/hooks/useUrlFiltersForAlerts.esm.js +80 -0
  178. package/dist/hooks/useUrlFiltersForAlerts.esm.js.map +1 -0
  179. package/dist/hooks/useUrlFiltersForIncidents.esm.js +87 -0
  180. package/dist/hooks/useUrlFiltersForIncidents.esm.js.map +1 -0
  181. package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js +135 -0
  182. package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js.map +1 -0
  183. package/dist/index.d.ts +41 -0
  184. package/dist/index.esm.js +2 -0
  185. package/dist/index.esm.js.map +1 -0
  186. package/dist/plugin.esm.js +107 -0
  187. package/dist/plugin.esm.js.map +1 -0
  188. package/dist/routes.esm.js +8 -0
  189. package/dist/routes.esm.js.map +1 -0
  190. package/dist/types.esm.js +18 -0
  191. package/dist/types.esm.js.map +1 -0
  192. package/dist/utils/applyResourceChange.esm.js +79 -0
  193. package/dist/utils/applyResourceChange.esm.js.map +1 -0
  194. package/dist/utils/urlTimeRange.esm.js +52 -0
  195. package/dist/utils/urlTimeRange.esm.js.map +1 -0
  196. package/package.json +81 -0
@@ -0,0 +1,567 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { useState, useMemo } from 'react';
3
+ import { useTheme, Box, Typography, IconButton, Tooltip, Divider, CircularProgress } from '@material-ui/core';
4
+ import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
5
+ import ExpandLessIcon from '@material-ui/icons/ExpandLess';
6
+ import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
7
+ import { useWaterfallStyles } from './styles.esm.js';
8
+ import { parseRfc3339NanoToNanoseconds, formatDuration, formatTimeFromString } from './utils.esm.js';
9
+
10
+ function flattenObject(obj, prefix = "") {
11
+ const rows = [];
12
+ for (const [k, v] of Object.entries(obj)) {
13
+ const fullKey = prefix ? `${prefix}.${k}` : k;
14
+ if (v !== null && typeof v === "object" && !Array.isArray(v)) {
15
+ rows.push(...flattenObject(v, fullKey));
16
+ } else {
17
+ rows.push({ key: fullKey, value: String(v ?? "") });
18
+ }
19
+ }
20
+ return rows;
21
+ }
22
+ const AttributeSection = ({ label, data }) => {
23
+ const theme = useTheme();
24
+ if (!data || Object.keys(data).length === 0) return null;
25
+ const rows = flattenObject(data);
26
+ return /* @__PURE__ */ jsxs(Box, { mb: 2, children: [
27
+ /* @__PURE__ */ jsx(
28
+ Typography,
29
+ {
30
+ variant: "caption",
31
+ style: {
32
+ fontSize: "0.65rem",
33
+ fontWeight: 700,
34
+ display: "block",
35
+ marginBottom: 4,
36
+ color: theme.palette.text.secondary,
37
+ textTransform: "uppercase",
38
+ letterSpacing: "0.05em"
39
+ },
40
+ children: label
41
+ }
42
+ ),
43
+ rows.map(({ key, value }) => /* @__PURE__ */ jsxs(Box, { display: "flex", style: { gap: 8, marginBottom: 2 }, children: [
44
+ /* @__PURE__ */ jsx(
45
+ Typography,
46
+ {
47
+ variant: "caption",
48
+ style: {
49
+ fontSize: "0.7rem",
50
+ fontFamily: "monospace",
51
+ fontWeight: 600,
52
+ minWidth: 220,
53
+ flexShrink: 0,
54
+ wordBreak: "break-all"
55
+ },
56
+ children: key
57
+ }
58
+ ),
59
+ /* @__PURE__ */ jsx(
60
+ Typography,
61
+ {
62
+ variant: "caption",
63
+ style: {
64
+ fontSize: "0.7rem",
65
+ fontFamily: "monospace",
66
+ wordBreak: "break-word"
67
+ },
68
+ children: value
69
+ }
70
+ )
71
+ ] }, key))
72
+ ] });
73
+ };
74
+ const SpanDetailsPanel = ({ details, traceId }) => {
75
+ const theme = useTheme();
76
+ const coreFields = [
77
+ { label: "Trace ID", value: traceId },
78
+ { label: "Span ID", value: details.spanId },
79
+ { label: "Span Name", value: details.spanName },
80
+ ...details.spanKind ? [{ label: "Span Kind", value: details.spanKind }] : [],
81
+ ...details.parentSpanId ? [{ label: "Parent Span ID", value: details.parentSpanId }] : [],
82
+ { label: "Start Time", value: formatTimeFromString(details.startTime) },
83
+ { label: "End Time", value: formatTimeFromString(details.endTime) },
84
+ { label: "Duration", value: formatDuration(details.durationNs) }
85
+ ];
86
+ let statusColor = "#94A3B8";
87
+ if (details.status === "error") {
88
+ statusColor = "#EF4444";
89
+ } else if (details.status === "ok") {
90
+ statusColor = "#10B981";
91
+ }
92
+ return /* @__PURE__ */ jsxs(Box, { children: [
93
+ /* @__PURE__ */ jsxs(Box, { mb: 2, children: [
94
+ /* @__PURE__ */ jsx(
95
+ Typography,
96
+ {
97
+ variant: "caption",
98
+ style: {
99
+ fontSize: "0.65rem",
100
+ fontWeight: 700,
101
+ display: "block",
102
+ marginBottom: 4,
103
+ color: theme.palette.text.secondary,
104
+ textTransform: "uppercase",
105
+ letterSpacing: "0.05em"
106
+ },
107
+ children: "Span Info"
108
+ }
109
+ ),
110
+ coreFields.map(({ label, value }) => /* @__PURE__ */ jsxs(Box, { display: "flex", style: { gap: 8, marginBottom: 2 }, children: [
111
+ /* @__PURE__ */ jsx(
112
+ Typography,
113
+ {
114
+ variant: "caption",
115
+ style: {
116
+ fontSize: "0.7rem",
117
+ fontFamily: "monospace",
118
+ fontWeight: 600,
119
+ minWidth: 220,
120
+ flexShrink: 0
121
+ },
122
+ children: label
123
+ }
124
+ ),
125
+ /* @__PURE__ */ jsx(
126
+ Typography,
127
+ {
128
+ variant: "caption",
129
+ style: {
130
+ fontSize: "0.7rem",
131
+ fontFamily: "monospace",
132
+ wordBreak: "break-all"
133
+ },
134
+ children: value
135
+ }
136
+ )
137
+ ] }, label)),
138
+ details.status && /* @__PURE__ */ jsxs(Box, { display: "flex", style: { gap: 8, marginBottom: 2 }, children: [
139
+ /* @__PURE__ */ jsx(
140
+ Typography,
141
+ {
142
+ variant: "caption",
143
+ style: {
144
+ fontSize: "0.7rem",
145
+ fontFamily: "monospace",
146
+ fontWeight: 600,
147
+ minWidth: 220,
148
+ flexShrink: 0
149
+ },
150
+ children: "Status"
151
+ }
152
+ ),
153
+ /* @__PURE__ */ jsx(
154
+ Typography,
155
+ {
156
+ variant: "caption",
157
+ style: {
158
+ fontSize: "0.7rem",
159
+ fontFamily: "monospace",
160
+ fontWeight: 600,
161
+ color: statusColor
162
+ },
163
+ children: details.status
164
+ }
165
+ )
166
+ ] })
167
+ ] }),
168
+ /* @__PURE__ */ jsx(AttributeSection, { label: "Attributes", data: details.attributes }),
169
+ /* @__PURE__ */ jsx(
170
+ AttributeSection,
171
+ {
172
+ label: "Resource Attributes",
173
+ data: details.resourceAttributes
174
+ }
175
+ )
176
+ ] });
177
+ };
178
+ const WaterfallView = ({
179
+ traceId,
180
+ spans,
181
+ spanDetails
182
+ }) => {
183
+ const classes = useWaterfallStyles();
184
+ const theme = useTheme();
185
+ const [collapsedSpans, setCollapsedSpans] = useState(/* @__PURE__ */ new Set());
186
+ const [selectedSpanId, setSelectedSpanId] = useState(null);
187
+ const getSpanColor = (spanName, depth, status) => {
188
+ if (status === "error") return "#FCA5A5";
189
+ const colors = [
190
+ "#93C5FD",
191
+ // blue-300
192
+ "#CBD5E1",
193
+ // slate-300
194
+ "#C4B5FD",
195
+ // violet-300
196
+ "#6EE7B7",
197
+ // emerald-300
198
+ "#67E8F9"
199
+ // cyan-300
200
+ ];
201
+ if (depth === 0) return colors[0];
202
+ if (depth === 1) return colors[1];
203
+ let hash = 0;
204
+ for (let i = 0; i < spanName.length; i++) {
205
+ hash = spanName.charCodeAt(i) + ((hash << 5) - hash);
206
+ }
207
+ return colors[Math.abs(hash) % colors.length];
208
+ };
209
+ const { spanTree, minTime, timeRange } = useMemo(() => {
210
+ if (!spans || spans.length === 0) {
211
+ return { spanTree: [], minTime: 0, timeRange: 0 };
212
+ }
213
+ const times = spans.flatMap((span) => [
214
+ parseRfc3339NanoToNanoseconds(span.startTime),
215
+ parseRfc3339NanoToNanoseconds(span.endTime)
216
+ ]);
217
+ const min = Math.min(...times);
218
+ const max = Math.max(...times);
219
+ const range = max - min || 1;
220
+ const spanMap = /* @__PURE__ */ new Map();
221
+ const rootSpans = [];
222
+ spans.forEach((span) => {
223
+ spanMap.set(span.spanId, { ...span, depth: 0, children: [] });
224
+ });
225
+ spans.forEach((span) => {
226
+ const spanWithDepth = spanMap.get(span.spanId);
227
+ if (span.parentSpanId && spanMap.has(span.parentSpanId)) {
228
+ const parent = spanMap.get(span.parentSpanId);
229
+ parent.children.push(spanWithDepth);
230
+ spanWithDepth.depth = parent.depth + 1;
231
+ } else {
232
+ rootSpans.push(spanWithDepth);
233
+ }
234
+ });
235
+ if (rootSpans.length === 0) {
236
+ const sortedSpans = [...spans].sort((a, b) => {
237
+ const aStart = parseRfc3339NanoToNanoseconds(a.startTime);
238
+ const bStart = parseRfc3339NanoToNanoseconds(b.startTime);
239
+ return aStart - bStart;
240
+ });
241
+ if (sortedSpans.length > 0) {
242
+ const rootSpan = spanMap.get(sortedSpans[0].spanId);
243
+ rootSpans.push(rootSpan);
244
+ rootSpan.depth = 0;
245
+ sortedSpans.slice(1).forEach((span) => {
246
+ const spanWithDepth = spanMap.get(span.spanId);
247
+ const spanStart = parseRfc3339NanoToNanoseconds(span.startTime);
248
+ const spanEnd = parseRfc3339NanoToNanoseconds(span.endTime);
249
+ let parent = null;
250
+ let maxDepth = -1;
251
+ sortedSpans.slice(0, sortedSpans.indexOf(span)).forEach((prevSpan) => {
252
+ const prevSpanWithDepth = spanMap.get(prevSpan.spanId);
253
+ if (!prevSpanWithDepth) return;
254
+ const prevStart = parseRfc3339NanoToNanoseconds(prevSpan.startTime);
255
+ const prevEnd = parseRfc3339NanoToNanoseconds(prevSpan.endTime);
256
+ if (spanStart >= prevStart && spanEnd <= prevEnd && prevSpanWithDepth.depth > maxDepth) {
257
+ parent = prevSpanWithDepth;
258
+ maxDepth = prevSpanWithDepth.depth;
259
+ }
260
+ });
261
+ if (parent) {
262
+ const parentSpan = parent;
263
+ parentSpan.children.push(spanWithDepth);
264
+ spanWithDepth.depth = parentSpan.depth + 1;
265
+ } else {
266
+ rootSpans.push(spanWithDepth);
267
+ spanWithDepth.depth = 0;
268
+ }
269
+ });
270
+ }
271
+ }
272
+ return { spanTree: rootSpans, minTime: min, timeRange: range };
273
+ }, [spans]);
274
+ const visibleSpans = useMemo(() => {
275
+ const getVisibleSpans = (nodes) => {
276
+ const result = [];
277
+ nodes.forEach((node) => {
278
+ result.push(node);
279
+ if (!collapsedSpans.has(node.spanId)) {
280
+ result.push(...getVisibleSpans(node.children));
281
+ }
282
+ });
283
+ return result;
284
+ };
285
+ return getVisibleSpans(spanTree);
286
+ }, [spanTree, collapsedSpans]);
287
+ const toggleCollapse = (spanId) => {
288
+ setCollapsedSpans((prev) => {
289
+ const newSet = new Set(prev);
290
+ if (newSet.has(spanId)) {
291
+ newSet.delete(spanId);
292
+ } else {
293
+ newSet.add(spanId);
294
+ }
295
+ return newSet;
296
+ });
297
+ };
298
+ const handleSpanClick = (spanId) => {
299
+ if (selectedSpanId === spanId) {
300
+ setSelectedSpanId(null);
301
+ return;
302
+ }
303
+ setSelectedSpanId(spanId);
304
+ spanDetails.fetchSpanDetails(traceId, spanId);
305
+ };
306
+ if (spanTree.length === 0) {
307
+ return /* @__PURE__ */ jsx(Box, { className: classes.container, children: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "No spans available for this trace" }) });
308
+ }
309
+ const calculatePosition = (startTime) => {
310
+ const time = parseRfc3339NanoToNanoseconds(startTime);
311
+ return (time - minTime) / timeRange * 100;
312
+ };
313
+ const calculateWidth = (startTime, endTime) => {
314
+ const start = parseRfc3339NanoToNanoseconds(startTime);
315
+ const end = parseRfc3339NanoToNanoseconds(endTime);
316
+ const duration = end - start;
317
+ return duration / timeRange * 100;
318
+ };
319
+ const selectedSpan = selectedSpanId ? visibleSpans.find((s) => s.spanId === selectedSpanId) : null;
320
+ const selectedDetails = selectedSpanId ? spanDetails.getDetails(traceId, selectedSpanId) : null;
321
+ const detailsLoading = selectedSpanId ? spanDetails.isLoading(traceId, selectedSpanId) : false;
322
+ const detailsError = selectedSpanId ? spanDetails.getError(traceId, selectedSpanId) : null;
323
+ return /* @__PURE__ */ jsxs(Box, { className: classes.container, children: [
324
+ /* @__PURE__ */ jsxs(Typography, { variant: "subtitle2", gutterBottom: true, children: [
325
+ "Trace ID: ",
326
+ traceId
327
+ ] }),
328
+ /* @__PURE__ */ jsx(Box, { className: classes.timeline, children: visibleSpans.map((span) => {
329
+ const left = calculatePosition(span.startTime);
330
+ const width = Math.max(
331
+ calculateWidth(span.startTime, span.endTime),
332
+ 0.5
333
+ );
334
+ const color = getSpanColor(span.spanName, span.depth, span.status);
335
+ const indent = span.depth * 20;
336
+ const hasChildren = span.children.length > 0;
337
+ const isCollapsed = collapsedSpans.has(span.spanId);
338
+ const isSelected = selectedSpanId === span.spanId;
339
+ return /* @__PURE__ */ jsxs(Box, { className: classes.spanRow, children: [
340
+ /* @__PURE__ */ jsxs(
341
+ Box,
342
+ {
343
+ className: classes.spanLabel,
344
+ style: { paddingLeft: `${indent}px` },
345
+ children: [
346
+ hasChildren && /* @__PURE__ */ jsx(
347
+ IconButton,
348
+ {
349
+ size: "small",
350
+ className: classes.collapseButton,
351
+ onClick: () => toggleCollapse(span.spanId),
352
+ children: isCollapsed ? /* @__PURE__ */ jsx(ExpandMoreIcon, {}) : /* @__PURE__ */ jsx(ExpandLessIcon, {})
353
+ }
354
+ ),
355
+ !hasChildren && /* @__PURE__ */ jsx(Box, { style: { width: "20px" } }),
356
+ span.status === "error" && /* @__PURE__ */ jsx(Tooltip, { title: "Span error", children: /* @__PURE__ */ jsx(ErrorOutlineIcon, { className: classes.spanErrorIcon }) }),
357
+ /* @__PURE__ */ jsx(
358
+ Box,
359
+ {
360
+ style: {
361
+ overflow: "hidden",
362
+ textOverflow: "ellipsis",
363
+ whiteSpace: "nowrap",
364
+ flex: 1
365
+ },
366
+ title: span.spanName,
367
+ children: span.spanName
368
+ }
369
+ )
370
+ ]
371
+ }
372
+ ),
373
+ /* @__PURE__ */ jsx(Box, { className: classes.spanBarContainer, children: /* @__PURE__ */ jsx(
374
+ Tooltip,
375
+ {
376
+ title: /* @__PURE__ */ jsxs(Box, { className: classes.tooltipContent, children: [
377
+ /* @__PURE__ */ jsx(Box, { className: classes.tooltipRow, children: /* @__PURE__ */ jsx(
378
+ Typography,
379
+ {
380
+ variant: "subtitle2",
381
+ component: "span",
382
+ style: {
383
+ fontWeight: 600,
384
+ color: "inherit",
385
+ marginBottom: 8
386
+ },
387
+ children: span.spanName
388
+ }
389
+ ) }),
390
+ /* @__PURE__ */ jsx(Divider, { style: { marginBottom: 8, marginTop: 4 } }),
391
+ /* @__PURE__ */ jsxs(Box, { className: classes.tooltipRow, children: [
392
+ /* @__PURE__ */ jsx(
393
+ Typography,
394
+ {
395
+ variant: "caption",
396
+ component: "span",
397
+ className: classes.tooltipLabel,
398
+ children: "Span ID:"
399
+ }
400
+ ),
401
+ /* @__PURE__ */ jsx(
402
+ Typography,
403
+ {
404
+ variant: "caption",
405
+ style: {
406
+ fontFamily: "monospace",
407
+ wordBreak: "break-word",
408
+ overflowWrap: "break-word",
409
+ flex: 1,
410
+ minWidth: 0
411
+ },
412
+ children: span.spanId
413
+ }
414
+ )
415
+ ] }),
416
+ span.spanKind && /* @__PURE__ */ jsxs(Box, { className: classes.tooltipRow, children: [
417
+ /* @__PURE__ */ jsx(
418
+ Typography,
419
+ {
420
+ variant: "caption",
421
+ component: "span",
422
+ className: classes.tooltipLabel,
423
+ children: "Kind:"
424
+ }
425
+ ),
426
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", children: span.spanKind })
427
+ ] }),
428
+ /* @__PURE__ */ jsxs(Box, { className: classes.tooltipRow, children: [
429
+ /* @__PURE__ */ jsx(
430
+ Typography,
431
+ {
432
+ variant: "caption",
433
+ component: "span",
434
+ className: classes.tooltipLabel,
435
+ children: "Start Time:"
436
+ }
437
+ ),
438
+ /* @__PURE__ */ jsx(
439
+ Typography,
440
+ {
441
+ variant: "caption",
442
+ style: {
443
+ fontFamily: "monospace",
444
+ fontSize: "0.7rem",
445
+ wordBreak: "break-word",
446
+ overflowWrap: "break-word",
447
+ flex: 1,
448
+ minWidth: 0
449
+ },
450
+ children: formatTimeFromString(span.startTime)
451
+ }
452
+ )
453
+ ] }),
454
+ /* @__PURE__ */ jsxs(Box, { className: classes.tooltipRow, children: [
455
+ /* @__PURE__ */ jsx(
456
+ Typography,
457
+ {
458
+ variant: "caption",
459
+ component: "span",
460
+ className: classes.tooltipLabel,
461
+ children: "End Time:"
462
+ }
463
+ ),
464
+ /* @__PURE__ */ jsx(
465
+ Typography,
466
+ {
467
+ variant: "caption",
468
+ style: {
469
+ fontFamily: "monospace",
470
+ fontSize: "0.7rem",
471
+ wordBreak: "break-word",
472
+ overflowWrap: "break-word",
473
+ flex: 1,
474
+ minWidth: 0
475
+ },
476
+ children: formatTimeFromString(span.endTime)
477
+ }
478
+ )
479
+ ] }),
480
+ /* @__PURE__ */ jsxs(Box, { className: classes.tooltipRow, children: [
481
+ /* @__PURE__ */ jsx(
482
+ Typography,
483
+ {
484
+ variant: "caption",
485
+ component: "span",
486
+ className: classes.tooltipLabel,
487
+ children: "Duration:"
488
+ }
489
+ ),
490
+ /* @__PURE__ */ jsx(
491
+ Typography,
492
+ {
493
+ variant: "caption",
494
+ style: { fontWeight: 500 },
495
+ children: formatDuration(span.durationNs)
496
+ }
497
+ )
498
+ ] }),
499
+ span.status && /* @__PURE__ */ jsxs(Box, { className: classes.tooltipRow, children: [
500
+ /* @__PURE__ */ jsx(
501
+ Typography,
502
+ {
503
+ variant: "caption",
504
+ component: "span",
505
+ className: classes.tooltipLabel,
506
+ children: "Status:"
507
+ }
508
+ ),
509
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", children: span.status })
510
+ ] })
511
+ ] }),
512
+ arrow: true,
513
+ placement: "top",
514
+ enterDelay: 200,
515
+ leaveDelay: 100,
516
+ children: /* @__PURE__ */ jsx(
517
+ Box,
518
+ {
519
+ className: classes.spanBar,
520
+ style: {
521
+ left: `${left}%`,
522
+ width: `${width}%`,
523
+ backgroundColor: color,
524
+ outline: isSelected ? `2px solid ${theme.palette.primary.main}` : void 0
525
+ },
526
+ onClick: () => handleSpanClick(span.spanId),
527
+ children: width > 5 && formatDuration(span.durationNs)
528
+ }
529
+ )
530
+ }
531
+ ) })
532
+ ] }, span.spanId);
533
+ }) }),
534
+ selectedSpanId && /* @__PURE__ */ jsxs(
535
+ Box,
536
+ {
537
+ mt: 2,
538
+ p: 2,
539
+ style: {
540
+ border: `1px solid ${theme.palette.divider}`,
541
+ borderRadius: 4,
542
+ backgroundColor: theme.palette.background.paper
543
+ },
544
+ children: [
545
+ /* @__PURE__ */ jsxs(Typography, { variant: "subtitle2", gutterBottom: true, children: [
546
+ "Span Details",
547
+ selectedSpan ? `: ${selectedSpan.spanName}` : ""
548
+ ] }),
549
+ /* @__PURE__ */ jsx(Divider, { style: { marginBottom: 8 } }),
550
+ detailsLoading && /* @__PURE__ */ jsxs(Box, { display: "flex", alignItems: "center", style: { gap: 8 }, children: [
551
+ /* @__PURE__ */ jsx(CircularProgress, { size: 16 }),
552
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "Loading span details..." })
553
+ ] }),
554
+ detailsError && /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "error", children: [
555
+ "Failed to load span details: ",
556
+ detailsError
557
+ ] }),
558
+ selectedDetails && !detailsLoading && /* @__PURE__ */ jsx(SpanDetailsPanel, { details: selectedDetails, traceId }),
559
+ !detailsLoading && !detailsError && !selectedDetails && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "Click a span bar to view its details." })
560
+ ]
561
+ }
562
+ )
563
+ ] });
564
+ };
565
+
566
+ export { WaterfallView };
567
+ //# sourceMappingURL=WaterfallView.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WaterfallView.esm.js","sources":["../../../src/components/Traces/WaterfallView.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport {\n Box,\n Typography,\n Tooltip,\n IconButton,\n Divider,\n useTheme,\n CircularProgress,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport ExpandLessIcon from '@material-ui/icons/ExpandLess';\nimport ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';\nimport { useWaterfallStyles } from './styles';\nimport { Span, SpanDetails } from '../../types';\nimport {\n parseRfc3339NanoToNanoseconds,\n formatDuration,\n formatTimeFromString,\n} from './utils';\n\ninterface SpanDetailsHook {\n fetchSpanDetails: (traceId: string, spanId: string) => Promise<void>;\n getDetails: (traceId: string, spanId: string) => SpanDetails | undefined;\n isLoading: (traceId: string, spanId: string) => boolean;\n getError: (traceId: string, spanId: string) => string | undefined;\n}\n\ninterface WaterfallViewProps {\n traceId: string;\n spans: Span[];\n spanDetails: SpanDetailsHook;\n}\n\ninterface SpanWithDepth extends Span {\n depth: number;\n children: SpanWithDepth[];\n}\n\n/** Flatten a nested object into dot-separated key: value rows. */\nfunction flattenObject(\n obj: Record<string, unknown>,\n prefix = '',\n): Array<{ key: string; value: string }> {\n const rows: Array<{ key: string; value: string }> = [];\n for (const [k, v] of Object.entries(obj)) {\n const fullKey = prefix ? `${prefix}.${k}` : k;\n if (v !== null && typeof v === 'object' && !Array.isArray(v)) {\n rows.push(...flattenObject(v as Record<string, unknown>, fullKey));\n } else {\n rows.push({ key: fullKey, value: String(v ?? '') });\n }\n }\n return rows;\n}\n\ninterface AttributeSectionProps {\n label: string;\n data: Record<string, unknown> | undefined;\n}\n\nconst AttributeSection = ({ label, data }: AttributeSectionProps) => {\n const theme = useTheme();\n if (!data || Object.keys(data).length === 0) return null;\n const rows = flattenObject(data);\n return (\n <Box mb={2}>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.65rem',\n fontWeight: 700,\n display: 'block',\n marginBottom: 4,\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}\n >\n {label}\n </Typography>\n {rows.map(({ key, value }) => (\n <Box key={key} display=\"flex\" style={{ gap: 8, marginBottom: 2 }}>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.7rem',\n fontFamily: 'monospace',\n fontWeight: 600,\n minWidth: 220,\n flexShrink: 0,\n wordBreak: 'break-all',\n }}\n >\n {key}\n </Typography>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.7rem',\n fontFamily: 'monospace',\n wordBreak: 'break-word',\n }}\n >\n {value}\n </Typography>\n </Box>\n ))}\n </Box>\n );\n};\n\ninterface SpanDetailsPanelProps {\n details: SpanDetails;\n traceId: string;\n}\n\nconst SpanDetailsPanel = ({ details, traceId }: SpanDetailsPanelProps) => {\n const theme = useTheme();\n const coreFields: Array<{ label: string; value: string }> = [\n { label: 'Trace ID', value: traceId },\n { label: 'Span ID', value: details.spanId },\n { label: 'Span Name', value: details.spanName },\n ...(details.spanKind\n ? [{ label: 'Span Kind', value: details.spanKind }]\n : []),\n ...(details.parentSpanId\n ? [{ label: 'Parent Span ID', value: details.parentSpanId }]\n : []),\n { label: 'Start Time', value: formatTimeFromString(details.startTime) },\n { label: 'End Time', value: formatTimeFromString(details.endTime) },\n { label: 'Duration', value: formatDuration(details.durationNs) },\n ];\n\n let statusColor = '#94A3B8';\n if (details.status === 'error') {\n statusColor = '#EF4444';\n } else if (details.status === 'ok') {\n statusColor = '#10B981';\n }\n\n return (\n <Box>\n {/* Core span fields */}\n <Box mb={2}>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.65rem',\n fontWeight: 700,\n display: 'block',\n marginBottom: 4,\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }}\n >\n Span Info\n </Typography>\n {coreFields.map(({ label, value }) => (\n <Box key={label} display=\"flex\" style={{ gap: 8, marginBottom: 2 }}>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.7rem',\n fontFamily: 'monospace',\n fontWeight: 600,\n minWidth: 220,\n flexShrink: 0,\n }}\n >\n {label}\n </Typography>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.7rem',\n fontFamily: 'monospace',\n wordBreak: 'break-all',\n }}\n >\n {value}\n </Typography>\n </Box>\n ))}\n {details.status && (\n <Box display=\"flex\" style={{ gap: 8, marginBottom: 2 }}>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.7rem',\n fontFamily: 'monospace',\n fontWeight: 600,\n minWidth: 220,\n flexShrink: 0,\n }}\n >\n Status\n </Typography>\n <Typography\n variant=\"caption\"\n style={{\n fontSize: '0.7rem',\n fontFamily: 'monospace',\n fontWeight: 600,\n color: statusColor,\n }}\n >\n {details.status}\n </Typography>\n </Box>\n )}\n </Box>\n\n <AttributeSection label=\"Attributes\" data={details.attributes} />\n <AttributeSection\n label=\"Resource Attributes\"\n data={details.resourceAttributes}\n />\n </Box>\n );\n};\n\nexport const WaterfallView = ({\n traceId,\n spans,\n spanDetails,\n}: WaterfallViewProps) => {\n const classes = useWaterfallStyles();\n const theme = useTheme();\n const [collapsedSpans, setCollapsedSpans] = useState<Set<string>>(new Set());\n const [selectedSpanId, setSelectedSpanId] = useState<string | null>(null);\n\n // Color palette for different span types\n const getSpanColor = (\n spanName: string,\n depth: number,\n status?: string,\n ): string => {\n if (status === 'error') return '#FCA5A5'; // light red\n\n const colors = [\n '#93C5FD', // blue-300\n '#CBD5E1', // slate-300\n '#C4B5FD', // violet-300\n '#6EE7B7', // emerald-300\n '#67E8F9', // cyan-300\n ];\n\n if (depth === 0) return colors[0];\n if (depth === 1) return colors[1];\n\n let hash = 0;\n for (let i = 0; i < spanName.length; i++) {\n hash = spanName.charCodeAt(i) + ((hash << 5) - hash);\n }\n return colors[Math.abs(hash) % colors.length];\n };\n\n const { spanTree, minTime, timeRange } = useMemo(() => {\n if (!spans || spans.length === 0) {\n return { spanTree: [], minTime: 0, timeRange: 0 };\n }\n\n const times = spans.flatMap(span => [\n parseRfc3339NanoToNanoseconds(span.startTime),\n parseRfc3339NanoToNanoseconds(span.endTime),\n ]);\n\n const min = Math.min(...times);\n const max = Math.max(...times);\n const range = max - min || 1;\n\n const spanMap = new Map<string, SpanWithDepth>();\n const rootSpans: SpanWithDepth[] = [];\n\n spans.forEach(span => {\n spanMap.set(span.spanId, { ...span, depth: 0, children: [] });\n });\n\n spans.forEach(span => {\n const spanWithDepth = spanMap.get(span.spanId)!;\n\n if (span.parentSpanId && spanMap.has(span.parentSpanId)) {\n const parent = spanMap.get(span.parentSpanId)!;\n parent.children.push(spanWithDepth);\n spanWithDepth.depth = parent.depth + 1;\n } else {\n rootSpans.push(spanWithDepth);\n }\n });\n\n if (rootSpans.length === 0) {\n const sortedSpans = [...spans].sort((a, b) => {\n const aStart = parseRfc3339NanoToNanoseconds(a.startTime);\n const bStart = parseRfc3339NanoToNanoseconds(b.startTime);\n return aStart - bStart;\n });\n\n if (sortedSpans.length > 0) {\n const rootSpan = spanMap.get(sortedSpans[0].spanId)!;\n rootSpans.push(rootSpan);\n rootSpan.depth = 0;\n\n sortedSpans.slice(1).forEach(span => {\n const spanWithDepth = spanMap.get(span.spanId)!;\n const spanStart = parseRfc3339NanoToNanoseconds(span.startTime);\n const spanEnd = parseRfc3339NanoToNanoseconds(span.endTime);\n\n let parent: SpanWithDepth | null = null;\n let maxDepth = -1;\n\n sortedSpans.slice(0, sortedSpans.indexOf(span)).forEach(prevSpan => {\n const prevSpanWithDepth = spanMap.get(prevSpan.spanId);\n if (!prevSpanWithDepth) return;\n\n const prevStart = parseRfc3339NanoToNanoseconds(prevSpan.startTime);\n const prevEnd = parseRfc3339NanoToNanoseconds(prevSpan.endTime);\n\n if (\n spanStart >= prevStart &&\n spanEnd <= prevEnd &&\n prevSpanWithDepth.depth > maxDepth\n ) {\n parent = prevSpanWithDepth;\n maxDepth = prevSpanWithDepth.depth;\n }\n });\n\n if (parent) {\n const parentSpan = parent as SpanWithDepth;\n parentSpan.children.push(spanWithDepth);\n spanWithDepth.depth = parentSpan.depth + 1;\n } else {\n rootSpans.push(spanWithDepth);\n spanWithDepth.depth = 0;\n }\n });\n }\n }\n\n return { spanTree: rootSpans, minTime: min, timeRange: range };\n }, [spans]);\n\n const visibleSpans = useMemo(() => {\n const getVisibleSpans = (nodes: SpanWithDepth[]): SpanWithDepth[] => {\n const result: SpanWithDepth[] = [];\n nodes.forEach((node: SpanWithDepth) => {\n result.push(node);\n if (!collapsedSpans.has(node.spanId)) {\n result.push(...getVisibleSpans(node.children));\n }\n });\n return result;\n };\n return getVisibleSpans(spanTree);\n }, [spanTree, collapsedSpans]);\n\n const toggleCollapse = (spanId: string) => {\n setCollapsedSpans(prev => {\n const newSet = new Set(prev);\n if (newSet.has(spanId)) {\n newSet.delete(spanId);\n } else {\n newSet.add(spanId);\n }\n return newSet;\n });\n };\n\n const handleSpanClick = (spanId: string) => {\n if (selectedSpanId === spanId) {\n setSelectedSpanId(null);\n return;\n }\n setSelectedSpanId(spanId);\n spanDetails.fetchSpanDetails(traceId, spanId);\n };\n\n if (spanTree.length === 0) {\n return (\n <Box className={classes.container}>\n <Typography variant=\"body2\" color=\"textSecondary\">\n No spans available for this trace\n </Typography>\n </Box>\n );\n }\n\n const calculatePosition = (startTime: string): number => {\n const time = parseRfc3339NanoToNanoseconds(startTime);\n return ((time - minTime) / timeRange) * 100;\n };\n\n const calculateWidth = (startTime: string, endTime: string): number => {\n const start = parseRfc3339NanoToNanoseconds(startTime);\n const end = parseRfc3339NanoToNanoseconds(endTime);\n const duration = end - start;\n return (duration / timeRange) * 100;\n };\n\n const selectedSpan = selectedSpanId\n ? visibleSpans.find(s => s.spanId === selectedSpanId)\n : null;\n const selectedDetails = selectedSpanId\n ? spanDetails.getDetails(traceId, selectedSpanId)\n : null;\n const detailsLoading = selectedSpanId\n ? spanDetails.isLoading(traceId, selectedSpanId)\n : false;\n const detailsError = selectedSpanId\n ? spanDetails.getError(traceId, selectedSpanId)\n : null;\n\n return (\n <Box className={classes.container}>\n <Typography variant=\"subtitle2\" gutterBottom>\n Trace ID: {traceId}\n </Typography>\n <Box className={classes.timeline}>\n {visibleSpans.map(span => {\n const left = calculatePosition(span.startTime);\n const width = Math.max(\n calculateWidth(span.startTime, span.endTime),\n 0.5,\n );\n const color = getSpanColor(span.spanName, span.depth, span.status);\n const indent = span.depth * 20;\n const hasChildren = span.children.length > 0;\n const isCollapsed = collapsedSpans.has(span.spanId);\n const isSelected = selectedSpanId === span.spanId;\n\n return (\n <Box key={span.spanId} className={classes.spanRow}>\n <Box\n className={classes.spanLabel}\n style={{ paddingLeft: `${indent}px` }}\n >\n {hasChildren && (\n <IconButton\n size=\"small\"\n className={classes.collapseButton}\n onClick={() => toggleCollapse(span.spanId)}\n >\n {isCollapsed ? <ExpandMoreIcon /> : <ExpandLessIcon />}\n </IconButton>\n )}\n {!hasChildren && <Box style={{ width: '20px' }} />}\n {span.status === 'error' && (\n <Tooltip title=\"Span error\">\n <ErrorOutlineIcon className={classes.spanErrorIcon} />\n </Tooltip>\n )}\n <Box\n style={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n flex: 1,\n }}\n title={span.spanName}\n >\n {span.spanName}\n </Box>\n </Box>\n <Box className={classes.spanBarContainer}>\n <Tooltip\n title={\n <Box className={classes.tooltipContent}>\n <Box className={classes.tooltipRow}>\n <Typography\n variant=\"subtitle2\"\n component=\"span\"\n style={{\n fontWeight: 600,\n color: 'inherit',\n marginBottom: 8,\n }}\n >\n {span.spanName}\n </Typography>\n </Box>\n <Divider style={{ marginBottom: 8, marginTop: 4 }} />\n <Box className={classes.tooltipRow}>\n <Typography\n variant=\"caption\"\n component=\"span\"\n className={classes.tooltipLabel}\n >\n Span ID:\n </Typography>\n <Typography\n variant=\"caption\"\n style={{\n fontFamily: 'monospace',\n wordBreak: 'break-word',\n overflowWrap: 'break-word',\n flex: 1,\n minWidth: 0,\n }}\n >\n {span.spanId}\n </Typography>\n </Box>\n {span.spanKind && (\n <Box className={classes.tooltipRow}>\n <Typography\n variant=\"caption\"\n component=\"span\"\n className={classes.tooltipLabel}\n >\n Kind:\n </Typography>\n <Typography variant=\"caption\">\n {span.spanKind}\n </Typography>\n </Box>\n )}\n <Box className={classes.tooltipRow}>\n <Typography\n variant=\"caption\"\n component=\"span\"\n className={classes.tooltipLabel}\n >\n Start Time:\n </Typography>\n <Typography\n variant=\"caption\"\n style={{\n fontFamily: 'monospace',\n fontSize: '0.7rem',\n wordBreak: 'break-word',\n overflowWrap: 'break-word',\n flex: 1,\n minWidth: 0,\n }}\n >\n {formatTimeFromString(span.startTime)}\n </Typography>\n </Box>\n <Box className={classes.tooltipRow}>\n <Typography\n variant=\"caption\"\n component=\"span\"\n className={classes.tooltipLabel}\n >\n End Time:\n </Typography>\n <Typography\n variant=\"caption\"\n style={{\n fontFamily: 'monospace',\n fontSize: '0.7rem',\n wordBreak: 'break-word',\n overflowWrap: 'break-word',\n flex: 1,\n minWidth: 0,\n }}\n >\n {formatTimeFromString(span.endTime)}\n </Typography>\n </Box>\n <Box className={classes.tooltipRow}>\n <Typography\n variant=\"caption\"\n component=\"span\"\n className={classes.tooltipLabel}\n >\n Duration:\n </Typography>\n <Typography\n variant=\"caption\"\n style={{ fontWeight: 500 }}\n >\n {formatDuration(span.durationNs)}\n </Typography>\n </Box>\n {span.status && (\n <Box className={classes.tooltipRow}>\n <Typography\n variant=\"caption\"\n component=\"span\"\n className={classes.tooltipLabel}\n >\n Status:\n </Typography>\n <Typography variant=\"caption\">\n {span.status}\n </Typography>\n </Box>\n )}\n </Box>\n }\n arrow\n placement=\"top\"\n enterDelay={200}\n leaveDelay={100}\n >\n <Box\n className={classes.spanBar}\n style={{\n left: `${left}%`,\n width: `${width}%`,\n backgroundColor: color,\n outline: isSelected\n ? `2px solid ${theme.palette.primary.main}`\n : undefined,\n }}\n onClick={() => handleSpanClick(span.spanId)}\n >\n {width > 5 && formatDuration(span.durationNs)}\n </Box>\n </Tooltip>\n </Box>\n </Box>\n );\n })}\n </Box>\n\n {/* Span details panel — shown when a span bar is clicked */}\n {selectedSpanId && (\n <Box\n mt={2}\n p={2}\n style={{\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: 4,\n backgroundColor: theme.palette.background.paper,\n }}\n >\n <Typography variant=\"subtitle2\" gutterBottom>\n Span Details{selectedSpan ? `: ${selectedSpan.spanName}` : ''}\n </Typography>\n <Divider style={{ marginBottom: 8 }} />\n\n {detailsLoading && (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <CircularProgress size={16} />\n <Typography variant=\"body2\" color=\"textSecondary\">\n Loading span details...\n </Typography>\n </Box>\n )}\n\n {detailsError && (\n <Typography variant=\"body2\" color=\"error\">\n Failed to load span details: {detailsError}\n </Typography>\n )}\n\n {selectedDetails && !detailsLoading && (\n <SpanDetailsPanel details={selectedDetails} traceId={traceId} />\n )}\n\n {!detailsLoading && !detailsError && !selectedDetails && (\n <Typography variant=\"body2\" color=\"textSecondary\">\n Click a span bar to view its details.\n </Typography>\n )}\n </Box>\n )}\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}