@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,280 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useState, useEffect } from 'react';
|
|
3
|
+
import { makeStyles, TextField, InputAdornment, Popover, Box, Typography, FormHelperText, Button, MenuList, MenuItem } from '@material-ui/core';
|
|
4
|
+
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
|
|
5
|
+
import { MuiPickersUtilsProvider, KeyboardDatePicker, KeyboardTimePicker } from '@material-ui/pickers';
|
|
6
|
+
import DateFnsUtils from '@date-io/date-fns';
|
|
7
|
+
import { TIME_RANGE_OPTIONS } from '../../types.esm.js';
|
|
8
|
+
|
|
9
|
+
const HOUR_MS = 60 * 60 * 1e3;
|
|
10
|
+
const toDate = (iso) => {
|
|
11
|
+
if (!iso) return null;
|
|
12
|
+
const d = new Date(iso);
|
|
13
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
14
|
+
};
|
|
15
|
+
const mergeDate = (prev, picked) => {
|
|
16
|
+
if (!picked || Number.isNaN(picked.getTime())) return prev;
|
|
17
|
+
const base = prev ? new Date(prev) : new Date(picked);
|
|
18
|
+
base.setFullYear(picked.getFullYear(), picked.getMonth(), picked.getDate());
|
|
19
|
+
return base;
|
|
20
|
+
};
|
|
21
|
+
const mergeTime = (prev, picked) => {
|
|
22
|
+
if (!picked || Number.isNaN(picked.getTime())) return prev;
|
|
23
|
+
const base = prev ? new Date(prev) : new Date(picked);
|
|
24
|
+
base.setHours(picked.getHours(), picked.getMinutes(), picked.getSeconds(), 0);
|
|
25
|
+
return base;
|
|
26
|
+
};
|
|
27
|
+
const formatCustomLabel = (start, end) => {
|
|
28
|
+
if (!start || !end) return "Custom range";
|
|
29
|
+
const fmt = (iso) => new Date(iso).toLocaleString(void 0, {
|
|
30
|
+
day: "2-digit",
|
|
31
|
+
month: "short",
|
|
32
|
+
year: "numeric",
|
|
33
|
+
hour: "2-digit",
|
|
34
|
+
minute: "2-digit"
|
|
35
|
+
});
|
|
36
|
+
return `${fmt(start)} \u2013 ${fmt(end)}`;
|
|
37
|
+
};
|
|
38
|
+
const useStyles = makeStyles((theme) => ({
|
|
39
|
+
trigger: {
|
|
40
|
+
cursor: "pointer",
|
|
41
|
+
"& input": { cursor: "pointer" }
|
|
42
|
+
},
|
|
43
|
+
panel: {
|
|
44
|
+
display: "flex",
|
|
45
|
+
flexDirection: "row"
|
|
46
|
+
},
|
|
47
|
+
sidePanel: {
|
|
48
|
+
padding: theme.spacing(2),
|
|
49
|
+
width: 380,
|
|
50
|
+
borderRight: `1px solid ${theme.palette.divider}`
|
|
51
|
+
},
|
|
52
|
+
presetList: {
|
|
53
|
+
minWidth: 200,
|
|
54
|
+
padding: theme.spacing(1, 0)
|
|
55
|
+
},
|
|
56
|
+
panelTitle: {
|
|
57
|
+
fontWeight: 600,
|
|
58
|
+
marginBottom: theme.spacing(1)
|
|
59
|
+
},
|
|
60
|
+
fieldLabel: {
|
|
61
|
+
marginTop: theme.spacing(1.5),
|
|
62
|
+
marginBottom: theme.spacing(0.5)
|
|
63
|
+
},
|
|
64
|
+
fieldRow: {
|
|
65
|
+
display: "flex",
|
|
66
|
+
gap: theme.spacing(1),
|
|
67
|
+
"& > *": { flex: 1 }
|
|
68
|
+
},
|
|
69
|
+
actions: {
|
|
70
|
+
marginTop: theme.spacing(2),
|
|
71
|
+
display: "flex",
|
|
72
|
+
justifyContent: "flex-end",
|
|
73
|
+
gap: theme.spacing(1)
|
|
74
|
+
}
|
|
75
|
+
}));
|
|
76
|
+
const TimeRangeFilter = ({
|
|
77
|
+
value,
|
|
78
|
+
customStartTime,
|
|
79
|
+
customEndTime,
|
|
80
|
+
onChange,
|
|
81
|
+
disabled = false,
|
|
82
|
+
fullWidth = true
|
|
83
|
+
}) => {
|
|
84
|
+
const classes = useStyles();
|
|
85
|
+
const anchorRef = useRef(null);
|
|
86
|
+
const [open, setOpen] = useState(false);
|
|
87
|
+
const [showCustomPanel, setShowCustomPanel] = useState(false);
|
|
88
|
+
const [draftStart, setDraftStart] = useState(
|
|
89
|
+
toDate(customStartTime)
|
|
90
|
+
);
|
|
91
|
+
const [draftEnd, setDraftEnd] = useState(toDate(customEndTime));
|
|
92
|
+
const [error, setError] = useState(null);
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
setDraftStart(toDate(customStartTime));
|
|
95
|
+
setDraftEnd(toDate(customEndTime));
|
|
96
|
+
}, [customStartTime, customEndTime]);
|
|
97
|
+
const openDropdown = () => {
|
|
98
|
+
if (disabled) return;
|
|
99
|
+
setShowCustomPanel(value === "custom");
|
|
100
|
+
if (!draftStart || !draftEnd) {
|
|
101
|
+
const now = /* @__PURE__ */ new Date();
|
|
102
|
+
setDraftStart((prev) => prev ?? new Date(now.getTime() - HOUR_MS));
|
|
103
|
+
setDraftEnd((prev) => prev ?? now);
|
|
104
|
+
}
|
|
105
|
+
setOpen(true);
|
|
106
|
+
};
|
|
107
|
+
const close = () => {
|
|
108
|
+
setOpen(false);
|
|
109
|
+
setError(null);
|
|
110
|
+
};
|
|
111
|
+
const selectPreset = (preset) => {
|
|
112
|
+
if (preset === "custom") {
|
|
113
|
+
setShowCustomPanel(true);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
onChange({
|
|
117
|
+
timeRange: preset,
|
|
118
|
+
customStartTime: void 0,
|
|
119
|
+
customEndTime: void 0
|
|
120
|
+
});
|
|
121
|
+
close();
|
|
122
|
+
};
|
|
123
|
+
const handleApply = () => {
|
|
124
|
+
if (!draftStart || !draftEnd) {
|
|
125
|
+
setError("Select both a start and end time.");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (draftEnd.getTime() <= draftStart.getTime()) {
|
|
129
|
+
setError("End time must be after start time.");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
onChange({
|
|
133
|
+
timeRange: "custom",
|
|
134
|
+
customStartTime: draftStart.toISOString(),
|
|
135
|
+
customEndTime: draftEnd.toISOString()
|
|
136
|
+
});
|
|
137
|
+
close();
|
|
138
|
+
};
|
|
139
|
+
const triggerLabel = value === "custom" ? formatCustomLabel(customStartTime, customEndTime) : TIME_RANGE_OPTIONS.find((o) => o.value === value)?.label ?? "";
|
|
140
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
141
|
+
/* @__PURE__ */ jsx("div", { ref: anchorRef, children: /* @__PURE__ */ jsx(
|
|
142
|
+
TextField,
|
|
143
|
+
{
|
|
144
|
+
fullWidth,
|
|
145
|
+
disabled,
|
|
146
|
+
variant: "outlined",
|
|
147
|
+
label: "Time Range",
|
|
148
|
+
value: triggerLabel,
|
|
149
|
+
onClick: openDropdown,
|
|
150
|
+
InputLabelProps: { shrink: true },
|
|
151
|
+
InputProps: {
|
|
152
|
+
readOnly: true,
|
|
153
|
+
classes: { root: classes.trigger },
|
|
154
|
+
endAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "end", children: /* @__PURE__ */ jsx(ArrowDropDownIcon, {}) })
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
) }),
|
|
158
|
+
/* @__PURE__ */ jsxs(
|
|
159
|
+
Popover,
|
|
160
|
+
{
|
|
161
|
+
open,
|
|
162
|
+
anchorEl: anchorRef.current,
|
|
163
|
+
onClose: close,
|
|
164
|
+
anchorOrigin: { vertical: "bottom", horizontal: "right" },
|
|
165
|
+
transformOrigin: { vertical: "top", horizontal: "right" },
|
|
166
|
+
marginThreshold: 8,
|
|
167
|
+
PaperProps: { elevation: 3, className: classes.panel },
|
|
168
|
+
children: [
|
|
169
|
+
showCustomPanel && /* @__PURE__ */ jsxs(Box, { className: classes.sidePanel, children: [
|
|
170
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", className: classes.panelTitle, children: "Select date and time range" }),
|
|
171
|
+
/* @__PURE__ */ jsxs(MuiPickersUtilsProvider, { utils: DateFnsUtils, children: [
|
|
172
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: classes.fieldLabel, children: "Start from" }),
|
|
173
|
+
/* @__PURE__ */ jsxs(Box, { className: classes.fieldRow, children: [
|
|
174
|
+
/* @__PURE__ */ jsx(
|
|
175
|
+
KeyboardDatePicker,
|
|
176
|
+
{
|
|
177
|
+
value: draftStart,
|
|
178
|
+
onChange: (d) => {
|
|
179
|
+
setDraftStart((prev) => mergeDate(prev, d));
|
|
180
|
+
setError(null);
|
|
181
|
+
},
|
|
182
|
+
format: "dd MMM, yyyy",
|
|
183
|
+
inputVariant: "outlined",
|
|
184
|
+
size: "small",
|
|
185
|
+
variant: "inline",
|
|
186
|
+
autoOk: true,
|
|
187
|
+
maxDate: draftEnd || void 0
|
|
188
|
+
}
|
|
189
|
+
),
|
|
190
|
+
/* @__PURE__ */ jsx(
|
|
191
|
+
KeyboardTimePicker,
|
|
192
|
+
{
|
|
193
|
+
value: draftStart,
|
|
194
|
+
onChange: (d) => {
|
|
195
|
+
setDraftStart((prev) => mergeTime(prev, d));
|
|
196
|
+
setError(null);
|
|
197
|
+
},
|
|
198
|
+
ampm: false,
|
|
199
|
+
views: ["hours", "minutes", "seconds"],
|
|
200
|
+
format: "HH:mm:ss",
|
|
201
|
+
inputVariant: "outlined",
|
|
202
|
+
size: "small",
|
|
203
|
+
variant: "inline",
|
|
204
|
+
autoOk: true
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
] }),
|
|
208
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", className: classes.fieldLabel, children: "End on" }),
|
|
209
|
+
/* @__PURE__ */ jsxs(Box, { className: classes.fieldRow, children: [
|
|
210
|
+
/* @__PURE__ */ jsx(
|
|
211
|
+
KeyboardDatePicker,
|
|
212
|
+
{
|
|
213
|
+
value: draftEnd,
|
|
214
|
+
onChange: (d) => {
|
|
215
|
+
setDraftEnd((prev) => mergeDate(prev, d));
|
|
216
|
+
setError(null);
|
|
217
|
+
},
|
|
218
|
+
format: "dd MMM, yyyy",
|
|
219
|
+
inputVariant: "outlined",
|
|
220
|
+
size: "small",
|
|
221
|
+
variant: "inline",
|
|
222
|
+
autoOk: true,
|
|
223
|
+
minDate: draftStart || void 0,
|
|
224
|
+
disableFuture: true
|
|
225
|
+
}
|
|
226
|
+
),
|
|
227
|
+
/* @__PURE__ */ jsx(
|
|
228
|
+
KeyboardTimePicker,
|
|
229
|
+
{
|
|
230
|
+
value: draftEnd,
|
|
231
|
+
onChange: (d) => {
|
|
232
|
+
setDraftEnd((prev) => mergeTime(prev, d));
|
|
233
|
+
setError(null);
|
|
234
|
+
},
|
|
235
|
+
ampm: false,
|
|
236
|
+
views: ["hours", "minutes", "seconds"],
|
|
237
|
+
format: "HH:mm:ss",
|
|
238
|
+
inputVariant: "outlined",
|
|
239
|
+
size: "small",
|
|
240
|
+
variant: "inline",
|
|
241
|
+
autoOk: true
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
] })
|
|
245
|
+
] }),
|
|
246
|
+
error && /* @__PURE__ */ jsx(FormHelperText, { error: true, children: error }),
|
|
247
|
+
/* @__PURE__ */ jsxs(Box, { className: classes.actions, children: [
|
|
248
|
+
/* @__PURE__ */ jsx(Button, { onClick: close, size: "small", children: "Cancel" }),
|
|
249
|
+
/* @__PURE__ */ jsx(
|
|
250
|
+
Button,
|
|
251
|
+
{
|
|
252
|
+
onClick: handleApply,
|
|
253
|
+
size: "small",
|
|
254
|
+
variant: "contained",
|
|
255
|
+
color: "primary",
|
|
256
|
+
children: "Apply"
|
|
257
|
+
}
|
|
258
|
+
)
|
|
259
|
+
] })
|
|
260
|
+
] }),
|
|
261
|
+
/* @__PURE__ */ jsx(MenuList, { className: classes.presetList, disablePadding: true, children: TIME_RANGE_OPTIONS.map((option) => {
|
|
262
|
+
const isCustomActive = option.value === "custom" && showCustomPanel;
|
|
263
|
+
return /* @__PURE__ */ jsx(
|
|
264
|
+
MenuItem,
|
|
265
|
+
{
|
|
266
|
+
selected: option.value === value || isCustomActive,
|
|
267
|
+
onClick: () => selectPreset(option.value),
|
|
268
|
+
children: option.label
|
|
269
|
+
},
|
|
270
|
+
option.value
|
|
271
|
+
);
|
|
272
|
+
}) })
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
)
|
|
276
|
+
] });
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
export { TimeRangeFilter };
|
|
280
|
+
//# sourceMappingURL=TimeRangeFilter.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeRangeFilter.esm.js","sources":["../../../src/components/TimeRangeFilter/TimeRangeFilter.tsx"],"sourcesContent":["import { FC, useEffect, useRef, useState } from 'react';\nimport {\n Box,\n Button,\n FormHelperText,\n InputAdornment,\n MenuItem,\n MenuList,\n Popover,\n TextField,\n Typography,\n makeStyles,\n} from '@material-ui/core';\nimport ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';\nimport {\n KeyboardDatePicker,\n KeyboardTimePicker,\n MuiPickersUtilsProvider,\n} from '@material-ui/pickers';\nimport DateFnsUtils from '@date-io/date-fns';\nimport { TIME_RANGE_OPTIONS } from '../../types';\n\nconst HOUR_MS = 60 * 60 * 1000;\n\nconst toDate = (iso?: string): Date | null => {\n if (!iso) return null;\n const d = new Date(iso);\n return Number.isNaN(d.getTime()) ? null : d;\n};\n\n// Replace just the date portion of `prev` with the date from `picked`,\n// preserving the existing time-of-day.\nconst mergeDate = (prev: Date | null, picked: Date | null): Date | null => {\n if (!picked || Number.isNaN(picked.getTime())) return prev;\n const base = prev ? new Date(prev) : new Date(picked);\n base.setFullYear(picked.getFullYear(), picked.getMonth(), picked.getDate());\n return base;\n};\n\nconst mergeTime = (prev: Date | null, picked: Date | null): Date | null => {\n if (!picked || Number.isNaN(picked.getTime())) return prev;\n const base = prev ? new Date(prev) : new Date(picked);\n base.setHours(picked.getHours(), picked.getMinutes(), picked.getSeconds(), 0);\n return base;\n};\n\nconst formatCustomLabel = (start?: string, end?: string): string => {\n if (!start || !end) return 'Custom range';\n const fmt = (iso: string) =>\n new Date(iso).toLocaleString(undefined, {\n day: '2-digit',\n month: 'short',\n year: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n });\n return `${fmt(start)} – ${fmt(end)}`;\n};\n\nconst useStyles = makeStyles(theme => ({\n trigger: {\n cursor: 'pointer',\n '& input': { cursor: 'pointer' },\n },\n panel: {\n display: 'flex',\n flexDirection: 'row',\n },\n sidePanel: {\n padding: theme.spacing(2),\n width: 380,\n borderRight: `1px solid ${theme.palette.divider}`,\n },\n presetList: {\n minWidth: 200,\n padding: theme.spacing(1, 0),\n },\n panelTitle: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n },\n fieldLabel: {\n marginTop: theme.spacing(1.5),\n marginBottom: theme.spacing(0.5),\n },\n fieldRow: {\n display: 'flex',\n gap: theme.spacing(1),\n '& > *': { flex: 1 },\n },\n actions: {\n marginTop: theme.spacing(2),\n display: 'flex',\n justifyContent: 'flex-end',\n gap: theme.spacing(1),\n },\n}));\n\nexport interface TimeRangeFilterProps {\n value: string;\n customStartTime?: string;\n customEndTime?: string;\n onChange: (next: {\n timeRange: string;\n customStartTime?: string;\n customEndTime?: string;\n }) => void;\n disabled?: boolean;\n fullWidth?: boolean;\n}\n\nexport const TimeRangeFilter: FC<TimeRangeFilterProps> = ({\n value,\n customStartTime,\n customEndTime,\n onChange,\n disabled = false,\n fullWidth = true,\n}) => {\n const classes = useStyles();\n const anchorRef = useRef<HTMLDivElement | null>(null);\n const [open, setOpen] = useState(false);\n const [showCustomPanel, setShowCustomPanel] = useState(false);\n const [draftStart, setDraftStart] = useState<Date | null>(\n toDate(customStartTime),\n );\n const [draftEnd, setDraftEnd] = useState<Date | null>(toDate(customEndTime));\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n setDraftStart(toDate(customStartTime));\n setDraftEnd(toDate(customEndTime));\n }, [customStartTime, customEndTime]);\n\n const openDropdown = () => {\n if (disabled) return;\n setShowCustomPanel(value === 'custom');\n if (!draftStart || !draftEnd) {\n const now = new Date();\n setDraftStart(prev => prev ?? new Date(now.getTime() - HOUR_MS));\n setDraftEnd(prev => prev ?? now);\n }\n setOpen(true);\n };\n\n const close = () => {\n setOpen(false);\n setError(null);\n };\n\n const selectPreset = (preset: string) => {\n if (preset === 'custom') {\n setShowCustomPanel(true);\n return;\n }\n onChange({\n timeRange: preset,\n customStartTime: undefined,\n customEndTime: undefined,\n });\n close();\n };\n\n const handleApply = () => {\n if (!draftStart || !draftEnd) {\n setError('Select both a start and end time.');\n return;\n }\n if (draftEnd.getTime() <= draftStart.getTime()) {\n setError('End time must be after start time.');\n return;\n }\n onChange({\n timeRange: 'custom',\n customStartTime: draftStart.toISOString(),\n customEndTime: draftEnd.toISOString(),\n });\n close();\n };\n\n const triggerLabel =\n value === 'custom'\n ? formatCustomLabel(customStartTime, customEndTime)\n : TIME_RANGE_OPTIONS.find(o => o.value === value)?.label ?? '';\n\n return (\n <>\n <div ref={anchorRef}>\n <TextField\n fullWidth={fullWidth}\n disabled={disabled}\n variant=\"outlined\"\n label=\"Time Range\"\n value={triggerLabel}\n onClick={openDropdown}\n InputLabelProps={{ shrink: true }}\n InputProps={{\n readOnly: true,\n classes: { root: classes.trigger },\n endAdornment: (\n <InputAdornment position=\"end\">\n <ArrowDropDownIcon />\n </InputAdornment>\n ),\n }}\n />\n </div>\n <Popover\n open={open}\n anchorEl={anchorRef.current}\n onClose={close}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\n marginThreshold={8}\n PaperProps={{ elevation: 3, className: classes.panel }}\n >\n {showCustomPanel && (\n <Box className={classes.sidePanel}>\n <Typography variant=\"subtitle1\" className={classes.panelTitle}>\n Select date and time range\n </Typography>\n <MuiPickersUtilsProvider utils={DateFnsUtils}>\n <Typography variant=\"body2\" className={classes.fieldLabel}>\n Start from\n </Typography>\n <Box className={classes.fieldRow}>\n <KeyboardDatePicker\n value={draftStart}\n onChange={d => {\n setDraftStart(prev => mergeDate(prev, d));\n setError(null);\n }}\n format=\"dd MMM, yyyy\"\n inputVariant=\"outlined\"\n size=\"small\"\n variant=\"inline\"\n autoOk\n maxDate={draftEnd || undefined}\n />\n <KeyboardTimePicker\n value={draftStart}\n onChange={d => {\n setDraftStart(prev => mergeTime(prev, d));\n setError(null);\n }}\n ampm={false}\n views={['hours', 'minutes', 'seconds']}\n format=\"HH:mm:ss\"\n inputVariant=\"outlined\"\n size=\"small\"\n variant=\"inline\"\n autoOk\n />\n </Box>\n <Typography variant=\"body2\" className={classes.fieldLabel}>\n End on\n </Typography>\n <Box className={classes.fieldRow}>\n <KeyboardDatePicker\n value={draftEnd}\n onChange={d => {\n setDraftEnd(prev => mergeDate(prev, d));\n setError(null);\n }}\n format=\"dd MMM, yyyy\"\n inputVariant=\"outlined\"\n size=\"small\"\n variant=\"inline\"\n autoOk\n minDate={draftStart || undefined}\n disableFuture\n />\n <KeyboardTimePicker\n value={draftEnd}\n onChange={d => {\n setDraftEnd(prev => mergeTime(prev, d));\n setError(null);\n }}\n ampm={false}\n views={['hours', 'minutes', 'seconds']}\n format=\"HH:mm:ss\"\n inputVariant=\"outlined\"\n size=\"small\"\n variant=\"inline\"\n autoOk\n />\n </Box>\n </MuiPickersUtilsProvider>\n {error && <FormHelperText error>{error}</FormHelperText>}\n <Box className={classes.actions}>\n <Button onClick={close} size=\"small\">\n Cancel\n </Button>\n <Button\n onClick={handleApply}\n size=\"small\"\n variant=\"contained\"\n color=\"primary\"\n >\n Apply\n </Button>\n </Box>\n </Box>\n )}\n <MenuList className={classes.presetList} disablePadding>\n {TIME_RANGE_OPTIONS.map(option => {\n const isCustomActive = option.value === 'custom' && showCustomPanel;\n return (\n <MenuItem\n key={option.value}\n selected={option.value === value || isCustomActive}\n onClick={() => selectPreset(option.value)}\n >\n {option.label}\n </MenuItem>\n );\n })}\n </MenuList>\n </Popover>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { Box, Typography, Button } from '@material-ui/core';
|
|
4
|
+
import { TracesFilters } from './TracesFilters.esm.js';
|
|
5
|
+
import { TracesActions } from './TracesActions.esm.js';
|
|
6
|
+
import { TracesTable } from './TracesTable.esm.js';
|
|
7
|
+
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
8
|
+
import { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';
|
|
9
|
+
import '@backstage/core-plugin-api';
|
|
10
|
+
import { useGetEnvironmentsByNamespace } from '../../hooks/useGetEnvironmentsByNamespace.esm.js';
|
|
11
|
+
import { useUrlFilters } from '../../hooks/useUrlFilters.esm.js';
|
|
12
|
+
import '../../api/ObservabilityApi.esm.js';
|
|
13
|
+
import { useTracesPermission, ForbiddenState, calculateTimeRange } from '@openchoreo/backstage-plugin-react';
|
|
14
|
+
import { useTraces } from '../../hooks/useTraces.esm.js';
|
|
15
|
+
import { useTraceSpans } from '../../hooks/useTraceSpans.esm.js';
|
|
16
|
+
import { useSpanDetails } from '../../hooks/useSpanDetails.esm.js';
|
|
17
|
+
import { useGetComponentsByProject } from '../../hooks/useGetComponentsByProject.esm.js';
|
|
18
|
+
import 'react-router-dom';
|
|
19
|
+
import '../../utils/urlTimeRange.esm.js';
|
|
20
|
+
import '../../api/RCAAgentApi.esm.js';
|
|
21
|
+
import '../../api/FinOpsAgentApi.esm.js';
|
|
22
|
+
import { Progress } from '@backstage/core-components';
|
|
23
|
+
import { Alert } from '@material-ui/lab';
|
|
24
|
+
|
|
25
|
+
const ObservabilityTracesContent = () => {
|
|
26
|
+
const { entity } = useEntity();
|
|
27
|
+
const namespace = entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE] ?? "";
|
|
28
|
+
const projectName = entity.metadata.name;
|
|
29
|
+
const {
|
|
30
|
+
environments,
|
|
31
|
+
loading: environmentsLoading,
|
|
32
|
+
error: environmentsError
|
|
33
|
+
} = useGetEnvironmentsByNamespace(namespace, projectName);
|
|
34
|
+
const {
|
|
35
|
+
components,
|
|
36
|
+
loading: componentsLoading,
|
|
37
|
+
error: componentsError
|
|
38
|
+
} = useGetComponentsByProject(entity);
|
|
39
|
+
const { filters, updateFilters } = useUrlFilters({
|
|
40
|
+
environments
|
|
41
|
+
});
|
|
42
|
+
const {
|
|
43
|
+
canViewTraces: canViewTracesForEnv,
|
|
44
|
+
loading: envPermissionLoading,
|
|
45
|
+
deniedTooltip: envPermissionDenied,
|
|
46
|
+
permissionName: envPermissionName
|
|
47
|
+
} = useTracesPermission(filters.environment?.name);
|
|
48
|
+
const tracesFilters = canViewTracesForEnv && !envPermissionLoading ? filters : { ...filters, environment: void 0 };
|
|
49
|
+
const {
|
|
50
|
+
traces,
|
|
51
|
+
total,
|
|
52
|
+
loading: tracesLoading,
|
|
53
|
+
error: tracesError,
|
|
54
|
+
refresh
|
|
55
|
+
} = useTraces(tracesFilters, entity);
|
|
56
|
+
const selectedComponents = filters.components ?? [];
|
|
57
|
+
const componentName = selectedComponents.length === 1 ? selectedComponents[0] : void 0;
|
|
58
|
+
const { startTime, endTime } = filters.timeRange ? calculateTimeRange(filters.timeRange, {
|
|
59
|
+
startTime: filters.customStartTime,
|
|
60
|
+
endTime: filters.customEndTime
|
|
61
|
+
}) : { startTime: void 0, endTime: void 0 };
|
|
62
|
+
const traceSpans = useTraceSpans({
|
|
63
|
+
namespaceName: namespace,
|
|
64
|
+
projectName,
|
|
65
|
+
environmentName: filters.environment?.name ?? "",
|
|
66
|
+
componentName,
|
|
67
|
+
startTime,
|
|
68
|
+
endTime
|
|
69
|
+
});
|
|
70
|
+
const spanDetails = useSpanDetails({
|
|
71
|
+
namespaceName: namespace,
|
|
72
|
+
environmentName: filters.environment?.name ?? ""
|
|
73
|
+
});
|
|
74
|
+
const handleFiltersChange = useCallback(
|
|
75
|
+
(newFilters) => {
|
|
76
|
+
updateFilters(newFilters);
|
|
77
|
+
},
|
|
78
|
+
[updateFilters]
|
|
79
|
+
);
|
|
80
|
+
const handleRefresh = useCallback(() => {
|
|
81
|
+
refresh();
|
|
82
|
+
}, [refresh]);
|
|
83
|
+
if (componentsError) {
|
|
84
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
85
|
+
}
|
|
86
|
+
if (environmentsError) {
|
|
87
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
88
|
+
}
|
|
89
|
+
const renderError = (error) => {
|
|
90
|
+
const isObservabilityDisabled = error.includes(
|
|
91
|
+
"Observability is not enabled"
|
|
92
|
+
);
|
|
93
|
+
return /* @__PURE__ */ jsx(Box, { mt: 2, mb: 2, children: /* @__PURE__ */ jsxs(Alert, { severity: isObservabilityDisabled ? "info" : "error", children: [
|
|
94
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", children: isObservabilityDisabled ? "Observability is not enabled for this project in the current environment. Enable observability to view traces." : error }),
|
|
95
|
+
!isObservabilityDisabled && /* @__PURE__ */ jsx(Button, { onClick: handleRefresh, color: "inherit", size: "small", children: "Retry" })
|
|
96
|
+
] }) });
|
|
97
|
+
};
|
|
98
|
+
return /* @__PURE__ */ jsxs(Box, { children: [
|
|
99
|
+
tracesLoading && /* @__PURE__ */ jsx(Progress, {}),
|
|
100
|
+
!tracesLoading && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
101
|
+
/* @__PURE__ */ jsx(
|
|
102
|
+
TracesFilters,
|
|
103
|
+
{
|
|
104
|
+
filters,
|
|
105
|
+
onFiltersChange: handleFiltersChange,
|
|
106
|
+
environments,
|
|
107
|
+
environmentsLoading,
|
|
108
|
+
components,
|
|
109
|
+
componentsLoading
|
|
110
|
+
}
|
|
111
|
+
),
|
|
112
|
+
filters.environment && !envPermissionLoading && !canViewTracesForEnv && /* @__PURE__ */ jsx(
|
|
113
|
+
ForbiddenState,
|
|
114
|
+
{
|
|
115
|
+
message: envPermissionDenied,
|
|
116
|
+
permissionName: envPermissionName,
|
|
117
|
+
variant: "compact"
|
|
118
|
+
}
|
|
119
|
+
),
|
|
120
|
+
(canViewTracesForEnv || envPermissionLoading) && tracesError && renderError(tracesError),
|
|
121
|
+
(canViewTracesForEnv || envPermissionLoading) && /* @__PURE__ */ jsx(
|
|
122
|
+
TracesActions,
|
|
123
|
+
{
|
|
124
|
+
totalCount: total,
|
|
125
|
+
disabled: tracesLoading,
|
|
126
|
+
onRefresh: handleRefresh
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
(canViewTracesForEnv || envPermissionLoading) && /* @__PURE__ */ jsx(
|
|
130
|
+
TracesTable,
|
|
131
|
+
{
|
|
132
|
+
traces,
|
|
133
|
+
traceSpans,
|
|
134
|
+
spanDetails,
|
|
135
|
+
loading: tracesLoading || envPermissionLoading
|
|
136
|
+
}
|
|
137
|
+
)
|
|
138
|
+
] })
|
|
139
|
+
] });
|
|
140
|
+
};
|
|
141
|
+
const ObservabilityTracesPage = () => {
|
|
142
|
+
const {
|
|
143
|
+
canViewTraces,
|
|
144
|
+
loading: permissionLoading,
|
|
145
|
+
deniedTooltip,
|
|
146
|
+
permissionName
|
|
147
|
+
} = useTracesPermission();
|
|
148
|
+
if (permissionLoading) {
|
|
149
|
+
return /* @__PURE__ */ jsx(Progress, {});
|
|
150
|
+
}
|
|
151
|
+
if (!canViewTraces) {
|
|
152
|
+
return /* @__PURE__ */ jsx(
|
|
153
|
+
ForbiddenState,
|
|
154
|
+
{
|
|
155
|
+
message: deniedTooltip,
|
|
156
|
+
permissionName,
|
|
157
|
+
variant: "fullpage"
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
return /* @__PURE__ */ jsx(ObservabilityTracesContent, {});
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export { ObservabilityTracesPage };
|
|
165
|
+
//# sourceMappingURL=ObservabilityTracesPage.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObservabilityTracesPage.esm.js","sources":["../../../src/components/Traces/ObservabilityTracesPage.tsx"],"sourcesContent":["import { useCallback } from 'react';\nimport { Box, Button, Typography } from '@material-ui/core';\nimport { TracesFilters } from './TracesFilters';\nimport { TracesActions } from './TracesActions';\nimport { TracesTable } from './TracesTable';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';\nimport {\n useUrlFilters,\n useTraces,\n useGetEnvironmentsByNamespace,\n useGetComponentsByProject,\n} from '../../hooks';\nimport { useTraceSpans } from '../../hooks/useTraceSpans';\nimport { useSpanDetails } from '../../hooks/useSpanDetails';\nimport type { Filters } from '../../types';\nimport { Progress } from '@backstage/core-components';\nimport { Alert } from '@material-ui/lab';\nimport {\n useTracesPermission,\n ForbiddenState,\n calculateTimeRange,\n} from '@openchoreo/backstage-plugin-react';\n\nconst ObservabilityTracesContent = () => {\n const { entity } = useEntity();\n const namespace =\n entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE] ?? '';\n const projectName = entity.metadata.name as string;\n\n const {\n environments,\n loading: environmentsLoading,\n error: environmentsError,\n } = useGetEnvironmentsByNamespace(namespace, projectName);\n const {\n components,\n loading: componentsLoading,\n error: componentsError,\n } = useGetComponentsByProject(entity);\n\n const { filters, updateFilters } = useUrlFilters({\n environments,\n });\n\n // Per-environment permission (ABAC `resource.environment`) — gates the\n // traces content once an environment is selected. See openchoreo#3408.\n const {\n canViewTraces: canViewTracesForEnv,\n loading: envPermissionLoading,\n deniedTooltip: envPermissionDenied,\n permissionName: envPermissionName,\n } = useTracesPermission(filters.environment?.name);\n\n // Don't fire the backend query until the per-env permission resolves to\n // allow — otherwise a denied user produces a 403 we'd have to suppress.\n // useTraces guards on filters.environment internally, so clearing it\n // turns the hook into a no-op while keeping the same hook-call order.\n const tracesFilters: Filters =\n canViewTracesForEnv && !envPermissionLoading\n ? filters\n : ({ ...filters, environment: undefined } as unknown as Filters);\n const {\n traces,\n total,\n loading: tracesLoading,\n error: tracesError,\n refresh,\n } = useTraces(tracesFilters, entity);\n\n // Determine which component name to pass for span queries\n // (mirrors what useTraces does — single selection passes the name)\n const selectedComponents = filters.components ?? [];\n const componentName =\n selectedComponents.length === 1 ? selectedComponents[0] : undefined;\n\n const { startTime, endTime } = filters.timeRange\n ? calculateTimeRange(filters.timeRange, {\n startTime: filters.customStartTime,\n endTime: filters.customEndTime,\n })\n : { startTime: undefined, endTime: undefined };\n\n const traceSpans = useTraceSpans({\n namespaceName: namespace,\n projectName,\n environmentName: filters.environment?.name ?? '',\n componentName,\n startTime,\n endTime,\n });\n\n const spanDetails = useSpanDetails({\n namespaceName: namespace,\n environmentName: filters.environment?.name ?? '',\n });\n\n const handleFiltersChange = useCallback(\n (newFilters: Partial<typeof filters>) => {\n updateFilters(newFilters);\n },\n [updateFilters],\n );\n\n const handleRefresh = useCallback(() => {\n refresh();\n }, [refresh]);\n\n if (componentsError) {\n return <></>;\n }\n\n if (environmentsError) {\n return <></>;\n }\n\n const renderError = (error: string) => {\n const isObservabilityDisabled = error.includes(\n 'Observability is not enabled',\n );\n\n return (\n <Box mt={2} mb={2}>\n <Alert severity={isObservabilityDisabled ? 'info' : 'error'}>\n <Typography variant=\"body1\">\n {isObservabilityDisabled\n ? 'Observability is not enabled for this project in the current environment. Enable observability to view traces.'\n : error}\n </Typography>\n {!isObservabilityDisabled && (\n <Button onClick={handleRefresh} color=\"inherit\" size=\"small\">\n Retry\n </Button>\n )}\n </Alert>\n </Box>\n );\n };\n\n return (\n <Box>\n {tracesLoading && <Progress />}\n\n {!tracesLoading && (\n <>\n <TracesFilters\n filters={filters}\n onFiltersChange={handleFiltersChange}\n environments={environments}\n environmentsLoading={environmentsLoading}\n components={components}\n componentsLoading={componentsLoading}\n />\n\n {filters.environment &&\n !envPermissionLoading &&\n !canViewTracesForEnv && (\n <ForbiddenState\n message={envPermissionDenied}\n permissionName={envPermissionName}\n variant=\"compact\"\n />\n )}\n\n {(canViewTracesForEnv || envPermissionLoading) &&\n tracesError &&\n renderError(tracesError)}\n\n {(canViewTracesForEnv || envPermissionLoading) && (\n <TracesActions\n totalCount={total}\n disabled={tracesLoading}\n onRefresh={handleRefresh}\n />\n )}\n\n {(canViewTracesForEnv || envPermissionLoading) && (\n <TracesTable\n traces={traces}\n traceSpans={traceSpans}\n spanDetails={spanDetails}\n loading={tracesLoading || envPermissionLoading}\n />\n )}\n </>\n )}\n </Box>\n );\n};\n\nexport const ObservabilityTracesPage = () => {\n const {\n canViewTraces,\n loading: permissionLoading,\n deniedTooltip,\n permissionName,\n } = useTracesPermission();\n\n if (permissionLoading) {\n return <Progress />;\n }\n\n if (!canViewTraces) {\n return (\n <ForbiddenState\n message={deniedTooltip}\n permissionName={permissionName}\n variant=\"fullpage\"\n />\n );\n }\n\n return <ObservabilityTracesContent />;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Box, Typography, Button } from '@material-ui/core';
|
|
3
|
+
import Refresh from '@material-ui/icons/Refresh';
|
|
4
|
+
import { useTracesActionsStyles } from './styles.esm.js';
|
|
5
|
+
import { memo } from 'react';
|
|
6
|
+
|
|
7
|
+
const TracesActions = memo(
|
|
8
|
+
({ totalCount, disabled, onRefresh }) => {
|
|
9
|
+
const classes = useTracesActionsStyles();
|
|
10
|
+
return /* @__PURE__ */ jsxs(Box, { className: classes.statsContainer, children: [
|
|
11
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
12
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
|
|
13
|
+
"Total traces: ",
|
|
14
|
+
totalCount
|
|
15
|
+
] }),
|
|
16
|
+
/* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
|
|
17
|
+
"Last updated at: ",
|
|
18
|
+
(/* @__PURE__ */ new Date()).toLocaleString()
|
|
19
|
+
] })
|
|
20
|
+
] }),
|
|
21
|
+
/* @__PURE__ */ jsx(Box, { className: classes.actionsContainer, children: /* @__PURE__ */ jsx(
|
|
22
|
+
Button,
|
|
23
|
+
{
|
|
24
|
+
variant: "outlined",
|
|
25
|
+
startIcon: /* @__PURE__ */ jsx(Refresh, {}),
|
|
26
|
+
onClick: onRefresh,
|
|
27
|
+
disabled,
|
|
28
|
+
children: "Refresh"
|
|
29
|
+
}
|
|
30
|
+
) })
|
|
31
|
+
] });
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
TracesActions.displayName = "TracesActions";
|
|
35
|
+
|
|
36
|
+
export { TracesActions };
|
|
37
|
+
//# sourceMappingURL=TracesActions.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TracesActions.esm.js","sources":["../../../src/components/Traces/TracesActions.tsx"],"sourcesContent":["import { Box, Typography, Button } from '@material-ui/core';\nimport RefreshIcon from '@material-ui/icons/Refresh';\nimport { useTracesActionsStyles } from './styles';\nimport { memo } from 'react';\n\ninterface TracesActionsProps {\n totalCount: number;\n disabled: boolean;\n onRefresh: () => void;\n}\n\nexport const TracesActions = memo(\n ({ totalCount, disabled, onRefresh }: TracesActionsProps) => {\n const classes = useTracesActionsStyles();\n\n return (\n <Box className={classes.statsContainer}>\n <Box>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Total traces: {totalCount}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Last updated at: {new Date().toLocaleString()}\n </Typography>\n </Box>\n <Box className={classes.actionsContainer}>\n <Button\n variant=\"outlined\"\n startIcon={<RefreshIcon />}\n onClick={onRefresh}\n disabled={disabled}\n >\n Refresh\n </Button>\n {/* TODO: Add Auto Refresh Button, Sort Button and Download Button */}\n </Box>\n </Box>\n );\n },\n);\n\nTracesActions.displayName = 'TracesActions';\n"],"names":["RefreshIcon"],"mappings":";;;;;;AAWO,MAAM,aAAA,GAAgB,IAAA;AAAA,EAC3B,CAAC,EAAE,UAAA,EAAY,QAAA,EAAU,WAAU,KAA0B;AAC3D,IAAA,MAAM,UAAU,sBAAA,EAAuB;AAEvC,IAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,cAAA,EACtB,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,GAAA,EAAA,EACC,QAAA,EAAA;AAAA,wBAAA,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,KAAA,EAAM,eAAA,EAAgB,QAAA,EAAA;AAAA,UAAA,gBAAA;AAAA,UACjC;AAAA,SAAA,EACjB,CAAA;AAAA,wBACA,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,OAAM,eAAA,EAAgB,QAAA,EAAA;AAAA,UAAA,mBAAA;AAAA,UAAA,iBAC9B,IAAI,IAAA,EAAK,EAAE,cAAA;AAAe,SAAA,EAC9C;AAAA,OAAA,EACF,CAAA;AAAA,sBACA,GAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,gBAAA,EACtB,QAAA,kBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAQ,UAAA;AAAA,UACR,SAAA,sBAAYA,OAAA,EAAA,EAAY,CAAA;AAAA,UACxB,OAAA,EAAS,SAAA;AAAA,UACT,QAAA;AAAA,UACD,QAAA,EAAA;AAAA;AAAA,OAED,EAEF;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AACF;AAEA,aAAA,CAAc,WAAA,GAAc,eAAA;;;;"}
|