@openchoreo/backstage-plugin-openchoreo-observability 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +22 -0
  3. package/dist/api/FinOpsAgentApi.esm.js +43 -0
  4. package/dist/api/FinOpsAgentApi.esm.js.map +1 -0
  5. package/dist/api/ObservabilityApi.esm.js +568 -0
  6. package/dist/api/ObservabilityApi.esm.js.map +1 -0
  7. package/dist/api/ObserverUrlCache.esm.js +59 -0
  8. package/dist/api/ObserverUrlCache.esm.js.map +1 -0
  9. package/dist/api/RCAAgentApi.esm.js +104 -0
  10. package/dist/api/RCAAgentApi.esm.js.map +1 -0
  11. package/dist/components/Alerts/AlertRow.esm.js +203 -0
  12. package/dist/components/Alerts/AlertRow.esm.js.map +1 -0
  13. package/dist/components/Alerts/AlertsActions.esm.js +77 -0
  14. package/dist/components/Alerts/AlertsActions.esm.js.map +1 -0
  15. package/dist/components/Alerts/AlertsFilter.esm.js +95 -0
  16. package/dist/components/Alerts/AlertsFilter.esm.js.map +1 -0
  17. package/dist/components/Alerts/AlertsTable.esm.js +63 -0
  18. package/dist/components/Alerts/AlertsTable.esm.js.map +1 -0
  19. package/dist/components/Alerts/ObservabilityAlertsPage.esm.js +251 -0
  20. package/dist/components/Alerts/ObservabilityAlertsPage.esm.js.map +1 -0
  21. package/dist/components/Alerts/types.esm.js +4 -0
  22. package/dist/components/Alerts/types.esm.js.map +1 -0
  23. package/dist/components/CostAnalysis/CostAnalysisPage.esm.js +141 -0
  24. package/dist/components/CostAnalysis/CostAnalysisPage.esm.js.map +1 -0
  25. package/dist/components/CostAnalysis/CostAnalysisReport.esm.js +128 -0
  26. package/dist/components/CostAnalysis/CostAnalysisReport.esm.js.map +1 -0
  27. package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js +517 -0
  28. package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js.map +1 -0
  29. package/dist/components/CostAnalysis/CostAnalysisTable.esm.js +149 -0
  30. package/dist/components/CostAnalysis/CostAnalysisTable.esm.js.map +1 -0
  31. package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js +112 -0
  32. package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js.map +1 -0
  33. package/dist/components/CostAnalysis/index.esm.js +2 -0
  34. package/dist/components/CostAnalysis/index.esm.js.map +1 -0
  35. package/dist/components/Incidents/IncidentRow.esm.js +258 -0
  36. package/dist/components/Incidents/IncidentRow.esm.js.map +1 -0
  37. package/dist/components/Incidents/IncidentsActions.esm.js +77 -0
  38. package/dist/components/Incidents/IncidentsActions.esm.js.map +1 -0
  39. package/dist/components/Incidents/IncidentsFilter.esm.js +144 -0
  40. package/dist/components/Incidents/IncidentsFilter.esm.js.map +1 -0
  41. package/dist/components/Incidents/IncidentsTable.esm.js +68 -0
  42. package/dist/components/Incidents/IncidentsTable.esm.js.map +1 -0
  43. package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js +283 -0
  44. package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js.map +1 -0
  45. package/dist/components/Incidents/types.esm.js +8 -0
  46. package/dist/components/Incidents/types.esm.js.map +1 -0
  47. package/dist/components/Metrics/ChartTooltip.esm.js +53 -0
  48. package/dist/components/Metrics/ChartTooltip.esm.js.map +1 -0
  49. package/dist/components/Metrics/HTTPMetricsSection.esm.js +109 -0
  50. package/dist/components/Metrics/HTTPMetricsSection.esm.js.map +1 -0
  51. package/dist/components/Metrics/MetricGraphByComponent.esm.js +99 -0
  52. package/dist/components/Metrics/MetricGraphByComponent.esm.js.map +1 -0
  53. package/dist/components/Metrics/MetricsActions.esm.js +30 -0
  54. package/dist/components/Metrics/MetricsActions.esm.js.map +1 -0
  55. package/dist/components/Metrics/MetricsFilters.esm.js +49 -0
  56. package/dist/components/Metrics/MetricsFilters.esm.js.map +1 -0
  57. package/dist/components/Metrics/ObservabilityMetricsPage.esm.js +196 -0
  58. package/dist/components/Metrics/ObservabilityMetricsPage.esm.js.map +1 -0
  59. package/dist/components/Metrics/styles.esm.js +55 -0
  60. package/dist/components/Metrics/styles.esm.js.map +1 -0
  61. package/dist/components/Metrics/utils.esm.js +221 -0
  62. package/dist/components/Metrics/utils.esm.js.map +1 -0
  63. package/dist/components/RCA/RCAActions.esm.js +42 -0
  64. package/dist/components/RCA/RCAActions.esm.js.map +1 -0
  65. package/dist/components/RCA/RCAFilters.esm.js +100 -0
  66. package/dist/components/RCA/RCAFilters.esm.js.map +1 -0
  67. package/dist/components/RCA/RCAPage.esm.js +137 -0
  68. package/dist/components/RCA/RCAPage.esm.js.map +1 -0
  69. package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js +9 -0
  70. package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js.map +1 -0
  71. package/dist/components/RCA/RCAReport/FormattedText.esm.js +94 -0
  72. package/dist/components/RCA/RCAReport/FormattedText.esm.js.map +1 -0
  73. package/dist/components/RCA/RCAReport/RCAReportView.esm.js +308 -0
  74. package/dist/components/RCA/RCAReport/RCAReportView.esm.js.map +1 -0
  75. package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js +113 -0
  76. package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js.map +1 -0
  77. package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js +272 -0
  78. package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js.map +1 -0
  79. package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js +48 -0
  80. package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js.map +1 -0
  81. package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js +205 -0
  82. package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js.map +1 -0
  83. package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js +121 -0
  84. package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js.map +1 -0
  85. package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js +593 -0
  86. package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js.map +1 -0
  87. package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js +35 -0
  88. package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js.map +1 -0
  89. package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js +54 -0
  90. package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js.map +1 -0
  91. package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js +526 -0
  92. package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js.map +1 -0
  93. package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js +70 -0
  94. package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js.map +1 -0
  95. package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js +54 -0
  96. package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js.map +1 -0
  97. package/dist/components/RCA/RCAReport/styles.esm.js +467 -0
  98. package/dist/components/RCA/RCAReport/styles.esm.js.map +1 -0
  99. package/dist/components/RCA/RCAReport.esm.js +109 -0
  100. package/dist/components/RCA/RCAReport.esm.js.map +1 -0
  101. package/dist/components/RCA/RCATable.esm.js +140 -0
  102. package/dist/components/RCA/RCATable.esm.js.map +1 -0
  103. package/dist/components/RuntimeLogs/LogEntry.esm.js +182 -0
  104. package/dist/components/RuntimeLogs/LogEntry.esm.js.map +1 -0
  105. package/dist/components/RuntimeLogs/LogsActions.esm.js +106 -0
  106. package/dist/components/RuntimeLogs/LogsActions.esm.js.map +1 -0
  107. package/dist/components/RuntimeLogs/LogsFilter.esm.js +200 -0
  108. package/dist/components/RuntimeLogs/LogsFilter.esm.js.map +1 -0
  109. package/dist/components/RuntimeLogs/LogsTable.esm.js +91 -0
  110. package/dist/components/RuntimeLogs/LogsTable.esm.js.map +1 -0
  111. package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js +220 -0
  112. package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js.map +1 -0
  113. package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js +222 -0
  114. package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js.map +1 -0
  115. package/dist/components/RuntimeLogs/styles.esm.js +256 -0
  116. package/dist/components/RuntimeLogs/styles.esm.js.map +1 -0
  117. package/dist/components/RuntimeLogs/types.esm.js +16 -0
  118. package/dist/components/RuntimeLogs/types.esm.js.map +1 -0
  119. package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js +280 -0
  120. package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js.map +1 -0
  121. package/dist/components/Traces/ObservabilityTracesPage.esm.js +165 -0
  122. package/dist/components/Traces/ObservabilityTracesPage.esm.js.map +1 -0
  123. package/dist/components/Traces/TracesActions.esm.js +37 -0
  124. package/dist/components/Traces/TracesActions.esm.js.map +1 -0
  125. package/dist/components/Traces/TracesFilters.esm.js +121 -0
  126. package/dist/components/Traces/TracesFilters.esm.js.map +1 -0
  127. package/dist/components/Traces/TracesTable.esm.js +137 -0
  128. package/dist/components/Traces/TracesTable.esm.js.map +1 -0
  129. package/dist/components/Traces/WaterfallView.esm.js +567 -0
  130. package/dist/components/Traces/WaterfallView.esm.js.map +1 -0
  131. package/dist/components/Traces/styles.esm.js +198 -0
  132. package/dist/components/Traces/styles.esm.js.map +1 -0
  133. package/dist/components/Traces/utils.esm.js +19 -0
  134. package/dist/components/Traces/utils.esm.js.map +1 -0
  135. package/dist/hooks/useAutoSelectFirstEnvironment.esm.js +25 -0
  136. package/dist/hooks/useAutoSelectFirstEnvironment.esm.js.map +1 -0
  137. package/dist/hooks/useComponentAlerts.esm.js +80 -0
  138. package/dist/hooks/useComponentAlerts.esm.js.map +1 -0
  139. package/dist/hooks/useDataPlaneNetPolProvider.esm.js +55 -0
  140. package/dist/hooks/useDataPlaneNetPolProvider.esm.js.map +1 -0
  141. package/dist/hooks/useDebouncedSearch.esm.js +24 -0
  142. package/dist/hooks/useDebouncedSearch.esm.js.map +1 -0
  143. package/dist/hooks/useFilters.esm.js +29 -0
  144. package/dist/hooks/useFilters.esm.js.map +1 -0
  145. package/dist/hooks/useFinOpsReport.esm.js +66 -0
  146. package/dist/hooks/useFinOpsReport.esm.js.map +1 -0
  147. package/dist/hooks/useFinOpsReports.esm.js +70 -0
  148. package/dist/hooks/useFinOpsReports.esm.js.map +1 -0
  149. package/dist/hooks/useGetComponentsByProject.esm.js +57 -0
  150. package/dist/hooks/useGetComponentsByProject.esm.js.map +1 -0
  151. package/dist/hooks/useGetEnvironmentsByNamespace.esm.js +53 -0
  152. package/dist/hooks/useGetEnvironmentsByNamespace.esm.js.map +1 -0
  153. package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js +40 -0
  154. package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js.map +1 -0
  155. package/dist/hooks/useMetrics.esm.js +107 -0
  156. package/dist/hooks/useMetrics.esm.js.map +1 -0
  157. package/dist/hooks/useProjectIncidents.esm.js +111 -0
  158. package/dist/hooks/useProjectIncidents.esm.js.map +1 -0
  159. package/dist/hooks/useProjectRuntimeLogs.esm.js +185 -0
  160. package/dist/hooks/useProjectRuntimeLogs.esm.js.map +1 -0
  161. package/dist/hooks/useRCAReportByAlert.esm.js +54 -0
  162. package/dist/hooks/useRCAReportByAlert.esm.js.map +1 -0
  163. package/dist/hooks/useRCAReports.esm.js +75 -0
  164. package/dist/hooks/useRCAReports.esm.js.map +1 -0
  165. package/dist/hooks/useRuntimeLogs.esm.js +147 -0
  166. package/dist/hooks/useRuntimeLogs.esm.js.map +1 -0
  167. package/dist/hooks/useSpanDetails.esm.js +71 -0
  168. package/dist/hooks/useSpanDetails.esm.js.map +1 -0
  169. package/dist/hooks/useTraceSpans.esm.js +80 -0
  170. package/dist/hooks/useTraceSpans.esm.js.map +1 -0
  171. package/dist/hooks/useTraces.esm.js +112 -0
  172. package/dist/hooks/useTraces.esm.js.map +1 -0
  173. package/dist/hooks/useUpdateIncident.esm.js +50 -0
  174. package/dist/hooks/useUpdateIncident.esm.js.map +1 -0
  175. package/dist/hooks/useUrlFilters.esm.js +63 -0
  176. package/dist/hooks/useUrlFilters.esm.js.map +1 -0
  177. package/dist/hooks/useUrlFiltersForAlerts.esm.js +80 -0
  178. package/dist/hooks/useUrlFiltersForAlerts.esm.js.map +1 -0
  179. package/dist/hooks/useUrlFiltersForIncidents.esm.js +87 -0
  180. package/dist/hooks/useUrlFiltersForIncidents.esm.js.map +1 -0
  181. package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js +135 -0
  182. package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js.map +1 -0
  183. package/dist/index.d.ts +41 -0
  184. package/dist/index.esm.js +2 -0
  185. package/dist/index.esm.js.map +1 -0
  186. package/dist/plugin.esm.js +107 -0
  187. package/dist/plugin.esm.js.map +1 -0
  188. package/dist/routes.esm.js +8 -0
  189. package/dist/routes.esm.js.map +1 -0
  190. package/dist/types.esm.js +18 -0
  191. package/dist/types.esm.js.map +1 -0
  192. package/dist/utils/applyResourceChange.esm.js +79 -0
  193. package/dist/utils/applyResourceChange.esm.js.map +1 -0
  194. package/dist/utils/urlTimeRange.esm.js +52 -0
  195. package/dist/utils/urlTimeRange.esm.js.map +1 -0
  196. package/package.json +81 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CostAnalysisPage.esm.js","sources":["../../../src/components/CostAnalysis/CostAnalysisPage.tsx"],"sourcesContent":["import { useCallback, useMemo } from 'react';\nimport { Routes, Route } from 'react-router-dom';\nimport { Box, Typography, Button } from '@material-ui/core';\nimport { RCAFilters } from '../RCA/RCAFilters';\nimport { RCAActions } from '../RCA/RCAActions';\nimport { CostAnalysisTable } from './CostAnalysisTable';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';\nimport type { FinOpsReportSummary } from '../../types';\nimport {\n useUrlFilters,\n useGetEnvironmentsByNamespace,\n useFinOpsReports,\n} from '../../hooks';\nimport { Progress } from '@backstage/core-components';\nimport { Alert } from '@material-ui/lab';\nimport {\n useRcaPermission,\n ForbiddenState,\n} from '@openchoreo/backstage-plugin-react';\nimport { CostAnalysisReport } from './CostAnalysisReport';\nimport { EntityLinkContext } from '../RCA/RCAReport/EntityLinkContext';\n\nconst CostAnalysisListContent = () => {\n const { entity } = useEntity();\n const namespace = entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE];\n const projectName = entity.metadata.name;\n const namespaceValue = useMemo(\n () => ({ namespace: namespace || 'default' }),\n [namespace],\n );\n const {\n environments,\n loading: environmentsLoading,\n error: environmentsError,\n } = useGetEnvironmentsByNamespace(namespace, projectName);\n const { filters, updateFilters } = useUrlFilters({ environments });\n\n const {\n reports,\n loading: reportsLoading,\n error: reportsError,\n refresh,\n } = useFinOpsReports(filters, entity);\n\n const filteredReports = useMemo((): FinOpsReportSummary[] => {\n if (!filters.searchQuery) return reports;\n const q = filters.searchQuery.toLowerCase();\n return reports.filter(\n r =>\n (r.reportId || '').toLowerCase().includes(q) ||\n (r.component || '').toLowerCase().includes(q) ||\n (r.summary || '').toLowerCase().includes(q) ||\n (r.status || '').toLowerCase().includes(q),\n );\n }, [reports, filters.searchQuery]);\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 const renderError = (error: string) => {\n const isObservabilityDisabled = error.includes(\n 'Observability is not enabled',\n );\n const isFinOpsServiceDisabled = error.includes(\n 'FinOps service is not configured',\n );\n const isInfoAlert = isObservabilityDisabled || isFinOpsServiceDisabled;\n\n let errorMessage = error;\n if (isObservabilityDisabled) {\n errorMessage =\n 'Observability is not enabled for this environment. Enable observability and enable the FinOps agent.';\n } else if (isFinOpsServiceDisabled) {\n errorMessage =\n 'FinOps Agent is not configured. Enable it to view cost analysis reports.';\n }\n\n return (\n <Box mt={2} mb={2}>\n <Alert severity={isInfoAlert ? 'info' : 'error'}>\n <Typography variant=\"body1\">{errorMessage}</Typography>\n {!isInfoAlert && (\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 {reportsLoading && <Progress />}\n\n {!reportsLoading && (\n <>\n <RCAFilters\n filters={filters}\n onFiltersChange={handleFiltersChange}\n environments={environments}\n environmentsLoading={environmentsLoading}\n />\n\n {environmentsError && (\n <Box mt={2} mb={2}>\n <Alert severity=\"warning\">\n <Typography variant=\"body1\">\n Failed to load environments. Environment filtering may not be\n available.\n </Typography>\n </Alert>\n </Box>\n )}\n\n {reportsError && renderError(reportsError)}\n\n <RCAActions\n disabled={reportsLoading}\n onRefresh={handleRefresh}\n totalCount={filteredReports.length}\n />\n\n <EntityLinkContext.Provider value={namespaceValue}>\n <CostAnalysisTable\n reports={filteredReports}\n loading={reportsLoading}\n />\n </EntityLinkContext.Provider>\n </>\n )}\n </Box>\n );\n};\n\nconst CostAnalysisListView = () => {\n const {\n canViewRca,\n loading: permissionLoading,\n deniedTooltip,\n permissionName,\n } = useRcaPermission();\n\n if (permissionLoading) {\n return <Progress />;\n }\n\n if (!canViewRca) {\n return (\n <ForbiddenState\n message={deniedTooltip}\n permissionName={permissionName}\n variant=\"fullpage\"\n />\n );\n }\n\n return <CostAnalysisListContent />;\n};\n\nexport const CostAnalysisPage = () => {\n return (\n <Routes>\n <Route path=\"/\" element={<CostAnalysisListView />} />\n <Route path=\"/:reportId\" element={<CostAnalysisReport />} />\n </Routes>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,128 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { useParams, useNavigate } from 'react-router-dom';
4
+ import { Box, Typography } from '@material-ui/core';
5
+ import { Progress } from '@backstage/core-components';
6
+ import { Alert } from '@material-ui/lab';
7
+ import { useRcaPermission, ForbiddenState } from '@openchoreo/backstage-plugin-react';
8
+ import { useEntity } from '@backstage/plugin-catalog-react';
9
+ import { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';
10
+ import { useApi, discoveryApiRef } from '@backstage/core-plugin-api';
11
+ import { useGetEnvironmentsByNamespace } from '../../hooks/useGetEnvironmentsByNamespace.esm.js';
12
+ import { useFilters } from '../../hooks/useFilters.esm.js';
13
+ import '../../utils/urlTimeRange.esm.js';
14
+ import '../../api/ObservabilityApi.esm.js';
15
+ import { useFinOpsReport } from '../../hooks/useFinOpsReport.esm.js';
16
+ import '../../api/RCAAgentApi.esm.js';
17
+ import { finopsAgentApiRef } from '../../api/FinOpsAgentApi.esm.js';
18
+ import { CostAnalysisReportView } from './CostAnalysisReportView.esm.js';
19
+
20
+ const CostAnalysisReportContent = () => {
21
+ const { reportId } = useParams();
22
+ const navigate = useNavigate();
23
+ const { entity } = useEntity();
24
+ const { filters } = useFilters();
25
+ const namespace = entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE];
26
+ const projectName = entity.metadata.name;
27
+ const finopsAgentApi = useApi(finopsAgentApiRef);
28
+ const discoveryApi = useApi(discoveryApiRef);
29
+ const { environments } = useGetEnvironmentsByNamespace(
30
+ namespace,
31
+ projectName
32
+ );
33
+ const environment = filters.environment || environments[0];
34
+ const {
35
+ report: detailedReport,
36
+ loading,
37
+ error,
38
+ refresh
39
+ } = useFinOpsReport(reportId, environment?.name, entity);
40
+ const [backendBaseUrl, setBackendBaseUrl] = useState();
41
+ const [discoveryError, setDiscoveryError] = useState();
42
+ useEffect(() => {
43
+ discoveryApi.getBaseUrl("openchoreo-observability-backend").then(setBackendBaseUrl).catch((err) => {
44
+ console.error(
45
+ "Failed to discover openchoreo-observability-backend:",
46
+ err
47
+ );
48
+ setDiscoveryError(
49
+ err instanceof Error ? err.message : "Failed to connect to the observability backend."
50
+ );
51
+ });
52
+ }, [discoveryApi]);
53
+ if (loading) {
54
+ return /* @__PURE__ */ jsx(Progress, {});
55
+ }
56
+ if (error) {
57
+ let errorMessage = error;
58
+ let severity = "error";
59
+ if (error.includes("FinOps service is not configured")) {
60
+ errorMessage = "FinOps Agent is not configured. Enable it to view cost analysis reports.";
61
+ severity = "info";
62
+ } else if (error.includes("Observability is not enabled")) {
63
+ errorMessage = "Observability is not enabled for this environment. Enable observability and enable the FinOps agent.";
64
+ severity = "info";
65
+ }
66
+ return /* @__PURE__ */ jsx(Box, { mt: 2, mb: 2, children: /* @__PURE__ */ jsx(Alert, { severity, children: /* @__PURE__ */ jsx(Typography, { variant: "body1", children: errorMessage }) }) });
67
+ }
68
+ if (discoveryError) {
69
+ return /* @__PURE__ */ jsx(Box, { mt: 2, mb: 2, children: /* @__PURE__ */ jsx(Alert, { severity: "error", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", children: discoveryError }) }) });
70
+ }
71
+ if (!detailedReport) {
72
+ if (!reportId) {
73
+ return /* @__PURE__ */ jsx(Alert, { severity: "error", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", children: "Report ID is required" }) });
74
+ }
75
+ return null;
76
+ }
77
+ const handleBack = () => {
78
+ navigate(-1);
79
+ };
80
+ const componentName = detailedReport.report?.component;
81
+ const catalogNs = entity.metadata.namespace || "default";
82
+ const environmentName = environment?.name || detailedReport.environment;
83
+ const componentUrl = componentName ? `/catalog/${catalogNs}/component/${componentName}` : void 0;
84
+ const metricsUrl = componentName ? `/catalog/${catalogNs}/component/${componentName}/metrics${environmentName ? `?env=${environmentName}` : ""}` : void 0;
85
+ const chatContext = {
86
+ backendBaseUrl,
87
+ namespaceName: namespace || "",
88
+ environmentName: environmentName || "",
89
+ finopsAgentApi
90
+ };
91
+ return /* @__PURE__ */ jsx(
92
+ CostAnalysisReportView,
93
+ {
94
+ report: detailedReport,
95
+ reportId,
96
+ onBack: handleBack,
97
+ componentUrl,
98
+ metricsUrl,
99
+ chatContext,
100
+ onRecommendationApplied: refresh
101
+ }
102
+ );
103
+ };
104
+ const CostAnalysisReport = () => {
105
+ const {
106
+ canViewRca,
107
+ loading: permissionLoading,
108
+ deniedTooltip,
109
+ permissionName
110
+ } = useRcaPermission();
111
+ if (permissionLoading) {
112
+ return /* @__PURE__ */ jsx(Progress, {});
113
+ }
114
+ if (!canViewRca) {
115
+ return /* @__PURE__ */ jsx(
116
+ ForbiddenState,
117
+ {
118
+ message: deniedTooltip,
119
+ permissionName,
120
+ variant: "fullpage"
121
+ }
122
+ );
123
+ }
124
+ return /* @__PURE__ */ jsx(CostAnalysisReportContent, {});
125
+ };
126
+
127
+ export { CostAnalysisReport };
128
+ //# sourceMappingURL=CostAnalysisReport.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CostAnalysisReport.esm.js","sources":["../../../src/components/CostAnalysis/CostAnalysisReport.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { Box, Typography } from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { Alert } from '@material-ui/lab';\nimport {\n useRcaPermission,\n ForbiddenState,\n} from '@openchoreo/backstage-plugin-react';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport {\n useFinOpsReport,\n useFilters,\n useGetEnvironmentsByNamespace,\n} from '../../hooks';\nimport { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';\nimport { CostAnalysisReportView } from './CostAnalysisReportView';\nimport { useApi, discoveryApiRef } from '@backstage/core-plugin-api';\nimport { finopsAgentApiRef } from '../../api/FinOpsAgentApi';\n\nconst CostAnalysisReportContent = () => {\n const { reportId } = useParams<{ reportId?: string }>();\n const navigate = useNavigate();\n const { entity } = useEntity();\n const { filters } = useFilters();\n const namespace = entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE];\n const projectName = entity.metadata.name as string;\n const finopsAgentApi = useApi(finopsAgentApiRef);\n const discoveryApi = useApi(discoveryApiRef);\n\n // Get environments to ensure we have environment data\n const { environments } = useGetEnvironmentsByNamespace(\n namespace,\n projectName,\n );\n const environment = filters.environment || environments[0];\n\n const {\n report: detailedReport,\n loading,\n error,\n refresh,\n } = useFinOpsReport(reportId, environment?.name, entity);\n\n const [backendBaseUrl, setBackendBaseUrl] = useState<string | undefined>();\n const [discoveryError, setDiscoveryError] = useState<string | undefined>();\n useEffect(() => {\n discoveryApi\n .getBaseUrl('openchoreo-observability-backend')\n .then(setBackendBaseUrl)\n .catch((err: unknown) => {\n // eslint-disable-next-line no-console\n console.error(\n 'Failed to discover openchoreo-observability-backend:',\n err,\n );\n setDiscoveryError(\n err instanceof Error\n ? err.message\n : 'Failed to connect to the observability backend.',\n );\n });\n }, [discoveryApi]);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n let errorMessage = error;\n let severity: 'info' | 'error' = 'error';\n\n if (error.includes('FinOps service is not configured')) {\n errorMessage =\n 'FinOps Agent is not configured. Enable it to view cost analysis reports.';\n severity = 'info';\n } else if (error.includes('Observability is not enabled')) {\n errorMessage =\n 'Observability is not enabled for this environment. Enable observability and enable the FinOps agent.';\n severity = 'info';\n }\n\n return (\n <Box mt={2} mb={2}>\n <Alert severity={severity}>\n <Typography variant=\"body1\">{errorMessage}</Typography>\n </Alert>\n </Box>\n );\n }\n\n if (discoveryError) {\n return (\n <Box mt={2} mb={2}>\n <Alert severity=\"error\">\n <Typography variant=\"body1\">{discoveryError}</Typography>\n </Alert>\n </Box>\n );\n }\n\n if (!detailedReport) {\n if (!reportId) {\n return (\n <Alert severity=\"error\">\n <Typography variant=\"body1\">Report ID is required</Typography>\n </Alert>\n );\n }\n return null;\n }\n\n const handleBack = () => {\n navigate(-1);\n };\n\n const componentName = detailedReport.report?.component;\n const catalogNs = entity.metadata.namespace || 'default';\n const environmentName = environment?.name || detailedReport.environment;\n const componentUrl = componentName\n ? `/catalog/${catalogNs}/component/${componentName}`\n : undefined;\n const metricsUrl = componentName\n ? `/catalog/${catalogNs}/component/${componentName}/metrics${\n environmentName ? `?env=${environmentName}` : ''\n }`\n : undefined;\n\n const chatContext = {\n backendBaseUrl,\n namespaceName: namespace || '',\n environmentName: environmentName || '',\n finopsAgentApi,\n };\n\n return (\n <CostAnalysisReportView\n report={detailedReport}\n reportId={reportId!}\n onBack={handleBack}\n componentUrl={componentUrl}\n metricsUrl={metricsUrl}\n chatContext={chatContext}\n onRecommendationApplied={refresh}\n />\n );\n};\n\nexport const CostAnalysisReport = () => {\n const {\n canViewRca,\n loading: permissionLoading,\n deniedTooltip,\n permissionName,\n } = useRcaPermission();\n\n if (permissionLoading) {\n return <Progress />;\n }\n\n if (!canViewRca) {\n return (\n <ForbiddenState\n message={deniedTooltip}\n permissionName={permissionName}\n variant=\"fullpage\"\n />\n );\n }\n\n return <CostAnalysisReportContent />;\n};\n"],"names":[],"mappings":"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"}