@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.
- package/CHANGELOG.md +5 -0
- package/README.md +22 -0
- package/dist/api/FinOpsAgentApi.esm.js +43 -0
- package/dist/api/FinOpsAgentApi.esm.js.map +1 -0
- package/dist/api/ObservabilityApi.esm.js +568 -0
- package/dist/api/ObservabilityApi.esm.js.map +1 -0
- package/dist/api/ObserverUrlCache.esm.js +59 -0
- package/dist/api/ObserverUrlCache.esm.js.map +1 -0
- package/dist/api/RCAAgentApi.esm.js +104 -0
- package/dist/api/RCAAgentApi.esm.js.map +1 -0
- package/dist/components/Alerts/AlertRow.esm.js +203 -0
- package/dist/components/Alerts/AlertRow.esm.js.map +1 -0
- package/dist/components/Alerts/AlertsActions.esm.js +77 -0
- package/dist/components/Alerts/AlertsActions.esm.js.map +1 -0
- package/dist/components/Alerts/AlertsFilter.esm.js +95 -0
- package/dist/components/Alerts/AlertsFilter.esm.js.map +1 -0
- package/dist/components/Alerts/AlertsTable.esm.js +63 -0
- package/dist/components/Alerts/AlertsTable.esm.js.map +1 -0
- package/dist/components/Alerts/ObservabilityAlertsPage.esm.js +251 -0
- package/dist/components/Alerts/ObservabilityAlertsPage.esm.js.map +1 -0
- package/dist/components/Alerts/types.esm.js +4 -0
- package/dist/components/Alerts/types.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisPage.esm.js +141 -0
- package/dist/components/CostAnalysis/CostAnalysisPage.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisReport.esm.js +128 -0
- package/dist/components/CostAnalysis/CostAnalysisReport.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js +517 -0
- package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisTable.esm.js +149 -0
- package/dist/components/CostAnalysis/CostAnalysisTable.esm.js.map +1 -0
- package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js +112 -0
- package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js.map +1 -0
- package/dist/components/CostAnalysis/index.esm.js +2 -0
- package/dist/components/CostAnalysis/index.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentRow.esm.js +258 -0
- package/dist/components/Incidents/IncidentRow.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentsActions.esm.js +77 -0
- package/dist/components/Incidents/IncidentsActions.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentsFilter.esm.js +144 -0
- package/dist/components/Incidents/IncidentsFilter.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentsTable.esm.js +68 -0
- package/dist/components/Incidents/IncidentsTable.esm.js.map +1 -0
- package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js +283 -0
- package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js.map +1 -0
- package/dist/components/Incidents/types.esm.js +8 -0
- package/dist/components/Incidents/types.esm.js.map +1 -0
- package/dist/components/Metrics/ChartTooltip.esm.js +53 -0
- package/dist/components/Metrics/ChartTooltip.esm.js.map +1 -0
- package/dist/components/Metrics/HTTPMetricsSection.esm.js +109 -0
- package/dist/components/Metrics/HTTPMetricsSection.esm.js.map +1 -0
- package/dist/components/Metrics/MetricGraphByComponent.esm.js +99 -0
- package/dist/components/Metrics/MetricGraphByComponent.esm.js.map +1 -0
- package/dist/components/Metrics/MetricsActions.esm.js +30 -0
- package/dist/components/Metrics/MetricsActions.esm.js.map +1 -0
- package/dist/components/Metrics/MetricsFilters.esm.js +49 -0
- package/dist/components/Metrics/MetricsFilters.esm.js.map +1 -0
- package/dist/components/Metrics/ObservabilityMetricsPage.esm.js +196 -0
- package/dist/components/Metrics/ObservabilityMetricsPage.esm.js.map +1 -0
- package/dist/components/Metrics/styles.esm.js +55 -0
- package/dist/components/Metrics/styles.esm.js.map +1 -0
- package/dist/components/Metrics/utils.esm.js +221 -0
- package/dist/components/Metrics/utils.esm.js.map +1 -0
- package/dist/components/RCA/RCAActions.esm.js +42 -0
- package/dist/components/RCA/RCAActions.esm.js.map +1 -0
- package/dist/components/RCA/RCAFilters.esm.js +100 -0
- package/dist/components/RCA/RCAFilters.esm.js.map +1 -0
- package/dist/components/RCA/RCAPage.esm.js +137 -0
- package/dist/components/RCA/RCAPage.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js +9 -0
- package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/FormattedText.esm.js +94 -0
- package/dist/components/RCA/RCAReport/FormattedText.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/RCAReportView.esm.js +308 -0
- package/dist/components/RCA/RCAReport/RCAReportView.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js +113 -0
- package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js +272 -0
- package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js +48 -0
- package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js +205 -0
- package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js +121 -0
- package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js +593 -0
- package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js +35 -0
- package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js +54 -0
- package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js +526 -0
- package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js +70 -0
- package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js +54 -0
- package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/styles.esm.js +467 -0
- package/dist/components/RCA/RCAReport/styles.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport.esm.js +109 -0
- package/dist/components/RCA/RCAReport.esm.js.map +1 -0
- package/dist/components/RCA/RCATable.esm.js +140 -0
- package/dist/components/RCA/RCATable.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogEntry.esm.js +182 -0
- package/dist/components/RuntimeLogs/LogEntry.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogsActions.esm.js +106 -0
- package/dist/components/RuntimeLogs/LogsActions.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogsFilter.esm.js +200 -0
- package/dist/components/RuntimeLogs/LogsFilter.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogsTable.esm.js +91 -0
- package/dist/components/RuntimeLogs/LogsTable.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js +220 -0
- package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js +222 -0
- package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/styles.esm.js +256 -0
- package/dist/components/RuntimeLogs/styles.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/types.esm.js +16 -0
- package/dist/components/RuntimeLogs/types.esm.js.map +1 -0
- package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js +280 -0
- package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js.map +1 -0
- package/dist/components/Traces/ObservabilityTracesPage.esm.js +165 -0
- package/dist/components/Traces/ObservabilityTracesPage.esm.js.map +1 -0
- package/dist/components/Traces/TracesActions.esm.js +37 -0
- package/dist/components/Traces/TracesActions.esm.js.map +1 -0
- package/dist/components/Traces/TracesFilters.esm.js +121 -0
- package/dist/components/Traces/TracesFilters.esm.js.map +1 -0
- package/dist/components/Traces/TracesTable.esm.js +137 -0
- package/dist/components/Traces/TracesTable.esm.js.map +1 -0
- package/dist/components/Traces/WaterfallView.esm.js +567 -0
- package/dist/components/Traces/WaterfallView.esm.js.map +1 -0
- package/dist/components/Traces/styles.esm.js +198 -0
- package/dist/components/Traces/styles.esm.js.map +1 -0
- package/dist/components/Traces/utils.esm.js +19 -0
- package/dist/components/Traces/utils.esm.js.map +1 -0
- package/dist/hooks/useAutoSelectFirstEnvironment.esm.js +25 -0
- package/dist/hooks/useAutoSelectFirstEnvironment.esm.js.map +1 -0
- package/dist/hooks/useComponentAlerts.esm.js +80 -0
- package/dist/hooks/useComponentAlerts.esm.js.map +1 -0
- package/dist/hooks/useDataPlaneNetPolProvider.esm.js +55 -0
- package/dist/hooks/useDataPlaneNetPolProvider.esm.js.map +1 -0
- package/dist/hooks/useDebouncedSearch.esm.js +24 -0
- package/dist/hooks/useDebouncedSearch.esm.js.map +1 -0
- package/dist/hooks/useFilters.esm.js +29 -0
- package/dist/hooks/useFilters.esm.js.map +1 -0
- package/dist/hooks/useFinOpsReport.esm.js +66 -0
- package/dist/hooks/useFinOpsReport.esm.js.map +1 -0
- package/dist/hooks/useFinOpsReports.esm.js +70 -0
- package/dist/hooks/useFinOpsReports.esm.js.map +1 -0
- package/dist/hooks/useGetComponentsByProject.esm.js +57 -0
- package/dist/hooks/useGetComponentsByProject.esm.js.map +1 -0
- package/dist/hooks/useGetEnvironmentsByNamespace.esm.js +53 -0
- package/dist/hooks/useGetEnvironmentsByNamespace.esm.js.map +1 -0
- package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js +40 -0
- package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js.map +1 -0
- package/dist/hooks/useMetrics.esm.js +107 -0
- package/dist/hooks/useMetrics.esm.js.map +1 -0
- package/dist/hooks/useProjectIncidents.esm.js +111 -0
- package/dist/hooks/useProjectIncidents.esm.js.map +1 -0
- package/dist/hooks/useProjectRuntimeLogs.esm.js +185 -0
- package/dist/hooks/useProjectRuntimeLogs.esm.js.map +1 -0
- package/dist/hooks/useRCAReportByAlert.esm.js +54 -0
- package/dist/hooks/useRCAReportByAlert.esm.js.map +1 -0
- package/dist/hooks/useRCAReports.esm.js +75 -0
- package/dist/hooks/useRCAReports.esm.js.map +1 -0
- package/dist/hooks/useRuntimeLogs.esm.js +147 -0
- package/dist/hooks/useRuntimeLogs.esm.js.map +1 -0
- package/dist/hooks/useSpanDetails.esm.js +71 -0
- package/dist/hooks/useSpanDetails.esm.js.map +1 -0
- package/dist/hooks/useTraceSpans.esm.js +80 -0
- package/dist/hooks/useTraceSpans.esm.js.map +1 -0
- package/dist/hooks/useTraces.esm.js +112 -0
- package/dist/hooks/useTraces.esm.js.map +1 -0
- package/dist/hooks/useUpdateIncident.esm.js +50 -0
- package/dist/hooks/useUpdateIncident.esm.js.map +1 -0
- package/dist/hooks/useUrlFilters.esm.js +63 -0
- package/dist/hooks/useUrlFilters.esm.js.map +1 -0
- package/dist/hooks/useUrlFiltersForAlerts.esm.js +80 -0
- package/dist/hooks/useUrlFiltersForAlerts.esm.js.map +1 -0
- package/dist/hooks/useUrlFiltersForIncidents.esm.js +87 -0
- package/dist/hooks/useUrlFiltersForIncidents.esm.js.map +1 -0
- package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js +135 -0
- package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/plugin.esm.js +107 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +8 -0
- package/dist/routes.esm.js.map +1 -0
- package/dist/types.esm.js +18 -0
- package/dist/types.esm.js.map +1 -0
- package/dist/utils/applyResourceChange.esm.js +79 -0
- package/dist/utils/applyResourceChange.esm.js.map +1 -0
- package/dist/utils/urlTimeRange.esm.js +52 -0
- package/dist/utils/urlTimeRange.esm.js.map +1 -0
- 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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"}
|