@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":"ObservabilityApi.esm.js","sources":["../../src/api/ObservabilityApi.ts"],"sourcesContent":["import {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport {\n ResourceMetrics,\n HttpMetrics,\n MetricType,\n Trace,\n Span,\n SpanDetails,\n RCAReportSummary,\n RCAReportDetailed,\n AlertSummary,\n IncidentSummary,\n FinOpsReportSummary,\n FinOpsReportDetailed,\n} from '../types';\nimport { LogsResponse } from '../components/RuntimeLogs/types';\nimport { ObserverUrlCache } from './ObserverUrlCache';\n\nexport interface ObservabilityApi {\n getRuntimeLogs(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n limit?: number;\n startTime?: string;\n endTime?: string;\n logLevels?: string[];\n searchQuery?: string;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<LogsResponse>;\n\n getMetrics(\n environmentName: string,\n componentName: string,\n namespaceName: string,\n projectName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n step?: string;\n type?: MetricType;\n },\n ): Promise<ResourceMetrics | HttpMetrics>;\n\n getTraces(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n limit?: number;\n startTime?: string;\n endTime?: string;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<{\n traces: Trace[];\n total: number;\n tookMs: number;\n }>;\n\n getTraceSpans(\n traceId: string,\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n startTime?: string;\n endTime?: string;\n },\n ): Promise<{\n spans: Span[];\n total: number;\n tookMs: number;\n }>;\n\n getSpanDetails(\n traceId: string,\n spanId: string,\n namespaceName: string,\n environmentName: string,\n ): Promise<SpanDetails>;\n\n getRCAReports(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n status?: 'pending' | 'completed' | 'failed';\n limit?: number;\n },\n ): Promise<{\n reports: RCAReportSummary[];\n totalCount?: number;\n }>;\n\n getRCAReport(\n reportId: string,\n environmentName: string,\n namespaceName: string,\n ): Promise<RCAReportDetailed>;\n\n getIncidents(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n startTime?: string;\n endTime?: string;\n limit?: number;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<{\n incidents: IncidentSummary[];\n total: number;\n }>;\n\n getAlerts(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n limit?: number;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<{\n alerts: AlertSummary[];\n total: number;\n }>;\n\n updateIncidentStatus(\n incidentId: string,\n status: 'acknowledged' | 'resolved',\n namespaceName: string,\n environmentName: string,\n ): Promise<void>;\n\n getFinOpsReports(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n status?: 'pending' | 'completed' | 'failed';\n limit?: number;\n sort?: string;\n },\n ): Promise<{\n reports: FinOpsReportSummary[];\n totalCount?: number;\n }>;\n\n getFinOpsReport(\n reportId: string,\n environmentName: string,\n namespaceName: string,\n ): Promise<FinOpsReportDetailed>;\n}\n\nexport const observabilityApiRef = createApiRef<ObservabilityApi>({\n id: 'plugin.openchoreo-observability.service',\n});\n\nconst DIRECT_HEADER = { 'x-openchoreo-direct': 'true' };\n\nexport class ObservabilityClient implements ObservabilityApi {\n private readonly fetchApi: FetchApi;\n private readonly urlCache: ObserverUrlCache;\n\n constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) {\n this.fetchApi = options.fetchApi;\n this.urlCache = new ObserverUrlCache(options);\n }\n\n async getMetrics(\n environmentName: string,\n componentName: string,\n namespaceName: string,\n projectName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n step?: string;\n type?: MetricType;\n },\n ): Promise<ResourceMetrics | HttpMetrics> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const searchScope = {\n namespace: namespaceName,\n project: projectName,\n component: componentName,\n environment: environmentName,\n };\n\n const baseBody = {\n startTime:\n options?.startTime ?? new Date(Date.now() - 3600000).toISOString(),\n endTime: options?.endTime ?? new Date().toISOString(),\n searchScope,\n ...(options?.step ? { step: options.step } : {}),\n };\n\n const fetchOptions = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...DIRECT_HEADER },\n };\n\n const metricType = options?.type ?? 'resource';\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1/metrics/query`,\n {\n ...fetchOptions,\n body: JSON.stringify({ ...baseBody, metric: metricType }),\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('Observability is not configured for component')) {\n throw new Error('Observability is not enabled for this component');\n }\n throw new Error(\n error || `Failed to fetch metrics: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n switch (metricType) {\n case 'resource':\n return {\n cpuUsage: {\n cpuUsage: data.cpuUsage ?? [],\n cpuRequests: data.cpuRequests ?? [],\n cpuLimits: data.cpuLimits ?? [],\n },\n memoryUsage: {\n memoryUsage: data.memoryUsage ?? [],\n memoryRequests: data.memoryRequests ?? [],\n memoryLimits: data.memoryLimits ?? [],\n },\n };\n case 'http':\n return {\n networkThroughput: {\n requestCount: data.requestCount ?? [],\n successfulRequestCount: data.successfulRequestCount ?? [],\n unsuccessfulRequestCount: data.unsuccessfulRequestCount ?? [],\n },\n networkLatency: {\n meanLatency: data.meanLatency ?? [],\n latencyP50: data.latencyP50 ?? [],\n latencyP90: data.latencyP90 ?? [],\n latencyP99: data.latencyP99 ?? [],\n },\n };\n default:\n throw new Error(`Unsupported metric type: ${metricType}`);\n }\n }\n\n async getTraces(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n limit?: number;\n startTime?: string;\n endTime?: string;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<{\n traces: Trace[];\n total: number;\n tookMs: number;\n }> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1alpha1/traces/query`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...DIRECT_HEADER },\n body: JSON.stringify({\n startTime:\n options?.startTime ?? new Date(Date.now() - 3600000).toISOString(),\n endTime: options?.endTime ?? new Date().toISOString(),\n limit: options?.limit ?? 100,\n sortOrder: options?.sortOrder ?? 'desc',\n searchScope: {\n namespace: namespaceName,\n project: projectName,\n ...(componentName ? { component: componentName } : {}),\n environment: environmentName,\n },\n }),\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('Observability is not configured for component')) {\n throw new Error('Observability is not enabled for this component');\n }\n throw new Error(\n error || `Failed to fetch traces: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return {\n traces: (data.traces ?? []).map((t: any) => ({\n traceId: t.traceId ?? '',\n traceName: t.traceName,\n spanCount: t.spanCount ?? 0,\n rootSpanId: t.rootSpanId,\n rootSpanName: t.rootSpanName,\n rootSpanKind: t.rootSpanKind,\n startTime: t.startTime ?? '',\n endTime: t.endTime ?? '',\n durationNs: t.durationNs ?? 0,\n hasErrors: t.hasErrors ?? false,\n })),\n total: data.total ?? 0,\n tookMs: data.tookMs ?? 0,\n };\n }\n\n async getTraceSpans(\n traceId: string,\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n startTime?: string;\n endTime?: string;\n },\n ): Promise<{\n spans: Span[];\n total: number;\n tookMs: number;\n }> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1alpha1/traces/${encodeURIComponent(\n traceId,\n )}/spans/query`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...DIRECT_HEADER },\n body: JSON.stringify({\n startTime:\n options?.startTime ?? new Date(Date.now() - 3600000).toISOString(),\n endTime: options?.endTime ?? new Date().toISOString(),\n limit: 1000,\n sortOrder: 'asc',\n searchScope: {\n namespace: namespaceName,\n project: projectName,\n ...(componentName ? { component: componentName } : {}),\n environment: environmentName,\n },\n }),\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n throw new Error(\n error ||\n `Failed to fetch spans for trace ${traceId}: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return {\n spans: (data.spans ?? []).map((s: any) => ({\n spanId: s.spanId ?? '',\n spanName: s.spanName ?? '',\n spanKind: s.spanKind,\n startTime: s.startTime ?? '',\n endTime: s.endTime ?? '',\n durationNs: s.durationNs ?? 0,\n parentSpanId: s.parentSpanId,\n status: s.status,\n })),\n total: data.total ?? 0,\n tookMs: data.tookMs ?? 0,\n };\n }\n\n async getSpanDetails(\n traceId: string,\n spanId: string,\n namespaceName: string,\n environmentName: string,\n ): Promise<SpanDetails> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1alpha1/traces/${encodeURIComponent(\n traceId,\n )}/spans/${encodeURIComponent(spanId)}`,\n {\n headers: { ...DIRECT_HEADER },\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n throw new Error(\n error ||\n `Failed to fetch span details for span ${spanId}: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return {\n spanId: data.spanId ?? '',\n spanName: data.spanName ?? '',\n spanKind: data.spanKind,\n startTime: data.startTime ?? '',\n endTime: data.endTime ?? '',\n durationNs: data.durationNs ?? 0,\n parentSpanId: data.parentSpanId,\n attributes: data.attributes,\n resourceAttributes: data.resourceAttributes,\n };\n }\n\n async getRCAReports(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n status?: 'pending' | 'completed' | 'failed';\n limit?: number;\n },\n ): Promise<{\n reports: RCAReportSummary[];\n totalCount?: number;\n }> {\n const { rcaAgentUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n if (!rcaAgentUrl) {\n throw new Error('RCA service is not configured');\n }\n\n const url = new URL(`${rcaAgentUrl}/api/v1/rca-agent/reports`);\n url.searchParams.set('namespace', namespaceName);\n url.searchParams.set('project', projectName);\n url.searchParams.set('environment', environmentName);\n if (options?.startTime)\n url.searchParams.set('startTime', options.startTime);\n if (options?.endTime) url.searchParams.set('endTime', options.endTime);\n if (options?.status) url.searchParams.set('status', options.status);\n if (options?.limit !== undefined)\n url.searchParams.set('limit', String(options.limit));\n\n let response: Response;\n try {\n response = await this.fetchApi.fetch(url.toString(), {\n headers: { ...DIRECT_HEADER },\n });\n } catch (err) {\n throw new Error(\n `RCA service is unreachable: ${\n err instanceof Error ? err.message : err\n }`,\n );\n }\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('RCA service is not configured')) {\n throw new Error('RCA service is not configured');\n }\n if (error.includes('Observability is not configured for component')) {\n throw new Error('Observability is not enabled for this component');\n }\n throw new Error(\n error || `Failed to fetch RCA reports: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return {\n reports: data.reports || [],\n totalCount: data.totalCount,\n };\n }\n\n async getRCAReport(\n reportId: string,\n environmentName: string,\n namespaceName: string,\n ): Promise<RCAReportDetailed> {\n const { rcaAgentUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n if (!rcaAgentUrl) {\n throw new Error('RCA service is not configured');\n }\n\n const url = new URL(\n `${rcaAgentUrl}/api/v1/rca-agent/reports/${encodeURIComponent(reportId)}`,\n );\n\n let response: Response;\n try {\n response = await this.fetchApi.fetch(url.toString(), {\n headers: { ...DIRECT_HEADER },\n });\n } catch (err) {\n throw new Error(\n `RCA service is unreachable: ${\n err instanceof Error ? err.message : err\n }`,\n );\n }\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('RCA service is not configured')) {\n throw new Error('RCA service is not configured');\n }\n if (error.includes('RCA report not found')) {\n throw new Error('RCA report not found');\n }\n throw new Error(\n error || `Failed to fetch RCA report: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return data;\n }\n\n async getIncidents(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n startTime?: string;\n endTime?: string;\n limit?: number;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<{\n incidents: IncidentSummary[];\n total: number;\n }> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1alpha1/incidents/query`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...DIRECT_HEADER },\n body: JSON.stringify({\n startTime:\n options?.startTime ?? new Date(Date.now() - 3600000).toISOString(),\n endTime: options?.endTime ?? new Date().toISOString(),\n limit: options?.limit ?? 100,\n sortOrder: options?.sortOrder ?? 'desc',\n searchScope: {\n namespace: namespaceName,\n project: projectName,\n ...(componentName ? { component: componentName } : {}),\n environment: environmentName,\n },\n }),\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('Observability is not configured for component')) {\n throw new Error('Observability is not enabled for this component');\n }\n throw new Error(\n error || `Failed to fetch incidents: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n const validStatuses = ['active', 'acknowledged', 'resolved'];\n return {\n incidents: (data.incidents ?? [])\n .filter((i: any) => validStatuses.includes(i.status))\n .map(\n (i: any): IncidentSummary => ({\n incidentId: i.incidentId ?? '',\n alertId: i.alertId ?? '',\n status: i.status,\n description: i.description,\n notes: i.notes,\n timestamp: i.timestamp,\n triggeredAt: i.triggeredAt,\n acknowledgedAt: i.acknowledgedAt,\n resolvedAt: i.resolvedAt,\n incidentTriggerAiRca: i.incidentTriggerAiRca ?? false,\n incidentTriggerAiCostAnalysis:\n i.incidentTriggerAiCostAnalysis ?? false,\n projectName: i.labels?.projectName,\n componentName: i.labels?.componentName,\n environmentName: i.labels?.environmentName,\n namespaceName: i.labels?.namespaceName,\n }),\n ),\n total: data.total ?? 0,\n };\n }\n\n async getAlerts(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n limit?: number;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<{\n alerts: AlertSummary[];\n total: number;\n }> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1alpha1/alerts/query`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...DIRECT_HEADER },\n body: JSON.stringify({\n startTime:\n options?.startTime ?? new Date(Date.now() - 3600000).toISOString(),\n endTime: options?.endTime ?? new Date().toISOString(),\n limit: options?.limit ?? 100,\n sortOrder: options?.sortOrder ?? 'desc',\n searchScope: {\n namespace: namespaceName,\n project: projectName,\n component: componentName,\n environment: environmentName,\n },\n }),\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('Observability is not configured for component')) {\n throw new Error('Observability is not enabled for this component');\n }\n throw new Error(\n error || `Failed to fetch alerts: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n return {\n alerts: (data.alerts ?? []).map(\n (a: any): AlertSummary => ({\n timestamp: a.timestamp,\n alertId: a.alertId ?? '',\n alertValue: a.alertValue,\n ruleName: a.metadata?.alertRule?.name,\n ruleDescription: a.metadata?.alertRule?.description,\n severity: a.metadata?.alertRule?.severity,\n sourceType: a.metadata?.alertRule?.source?.type,\n sourceQuery: a.metadata?.alertRule?.source?.query,\n sourceMetric: a.metadata?.alertRule?.source?.metric,\n projectName: a.metadata?.labels?.projectName,\n componentName: a.metadata?.labels?.componentName,\n environmentName: a.metadata?.labels?.environmentName,\n namespaceName: a.metadata?.labels?.namespaceName,\n notificationChannels: a.notificationChannels ?? [],\n incidentEnabled: a.incidentEnabled ?? false,\n }),\n ),\n total: data.total ?? 0,\n };\n }\n\n async getRuntimeLogs(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n componentName?: string,\n options?: {\n limit?: number;\n startTime?: string;\n endTime?: string;\n logLevels?: string[];\n searchQuery?: string;\n sortOrder?: 'asc' | 'desc';\n },\n ): Promise<LogsResponse> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1/logs/query`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...DIRECT_HEADER },\n body: JSON.stringify({\n startTime:\n options?.startTime ||\n new Date(Date.now() - 60 * 60 * 1000).toISOString(),\n endTime: options?.endTime || new Date().toISOString(),\n limit: options?.limit || 100,\n sortOrder: options?.sortOrder || 'desc',\n ...(options?.logLevels &&\n options.logLevels.length > 0 && { logLevels: options.logLevels }),\n ...(options?.searchQuery && {\n searchPhrase: options.searchQuery,\n }),\n searchScope: {\n namespace: namespaceName,\n project: projectName,\n ...(componentName ? { component: componentName } : {}),\n environment: environmentName,\n },\n }),\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('Observability is not configured for component')) {\n throw new Error('Observability is not enabled for this component');\n }\n throw new Error(\n error ||\n `Failed to fetch runtime logs: ${response.status} ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return data;\n }\n\n async updateIncidentStatus(\n incidentId: string,\n status: 'acknowledged' | 'resolved',\n namespaceName: string,\n environmentName: string,\n ): Promise<void> {\n const { observerUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n const response = await this.fetchApi.fetch(\n `${observerUrl}/api/v1alpha1/incidents/${encodeURIComponent(incidentId)}`,\n {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json', ...DIRECT_HEADER },\n body: JSON.stringify({ status }),\n },\n );\n\n if (!response.ok) {\n const error = await this.parseError(response);\n throw new Error(\n error || `Failed to update incident: ${response.statusText}`,\n );\n }\n }\n\n async getFinOpsReports(\n namespaceName: string,\n projectName: string,\n environmentName: string,\n options?: {\n startTime?: string;\n endTime?: string;\n status?: 'pending' | 'completed' | 'failed';\n limit?: number;\n sort?: string;\n },\n ): Promise<{\n reports: FinOpsReportSummary[];\n totalCount?: number;\n }> {\n const { finopsAgentUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n if (!finopsAgentUrl) {\n throw new Error('FinOps service is not configured');\n }\n\n const url = new URL(`${finopsAgentUrl}/api/v1alpha1/reports`);\n url.searchParams.set('namespace', namespaceName);\n url.searchParams.set('project', projectName);\n url.searchParams.set('environment', environmentName);\n if (options?.startTime)\n url.searchParams.set('startTime', options.startTime);\n if (options?.endTime) url.searchParams.set('endTime', options.endTime);\n if (options?.status) url.searchParams.set('status', options.status);\n if (options?.limit !== undefined)\n url.searchParams.set('limit', String(options.limit));\n if (options?.sort) url.searchParams.set('sort', options.sort);\n\n let response: Response;\n try {\n response = await this.fetchApi.fetch(url.toString(), {\n headers: { ...DIRECT_HEADER },\n });\n } catch (err) {\n throw new Error(\n `FinOps service is unreachable: ${\n err instanceof Error ? err.message : err\n }`,\n );\n }\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('FinOps service is not configured')) {\n throw new Error('FinOps service is not configured');\n }\n if (error.includes('Observability is not configured for component')) {\n throw new Error('Observability is not enabled for this component');\n }\n throw new Error(\n error || `Failed to fetch FinOps reports: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return {\n reports: data.reports || [],\n totalCount: data.totalCount,\n };\n }\n\n async getFinOpsReport(\n reportId: string,\n environmentName: string,\n namespaceName: string,\n ): Promise<FinOpsReportDetailed> {\n const { finopsAgentUrl } = await this.urlCache.resolveUrls(\n namespaceName,\n environmentName,\n );\n\n if (!finopsAgentUrl) {\n throw new Error('FinOps service is not configured');\n }\n\n const url = new URL(\n `${finopsAgentUrl}/api/v1alpha1/reports/${encodeURIComponent(reportId)}`,\n );\n\n let response: Response;\n try {\n response = await this.fetchApi.fetch(url.toString(), {\n headers: { ...DIRECT_HEADER },\n });\n } catch (err) {\n throw new Error(\n `FinOps service is unreachable: ${\n err instanceof Error ? err.message : err\n }`,\n );\n }\n\n if (!response.ok) {\n const error = await this.parseError(response);\n if (error.includes('FinOps service is not configured')) {\n throw new Error('FinOps service is not configured');\n }\n if (error.includes('FinOps report not found')) {\n throw new Error('FinOps report not found');\n }\n throw new Error(\n error || `Failed to fetch FinOps report: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n return data;\n }\n\n private async parseError(response: Response): Promise<string> {\n try {\n const error = await response.json();\n return (\n error.error ||\n error.message ||\n `${response.status} ${response.statusText}`\n );\n } catch {\n return `${response.status} ${response.statusText}`;\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ const CACHE_TTL_MS = 5 * 60 * 1e3;
2
+ class ObserverUrlCache {
3
+ discoveryApi;
4
+ fetchApi;
5
+ cache = /* @__PURE__ */ new Map();
6
+ constructor(options) {
7
+ this.discoveryApi = options.discoveryApi;
8
+ this.fetchApi = options.fetchApi;
9
+ }
10
+ async resolveUrls(namespaceName, environmentName) {
11
+ const cacheKey = `${namespaceName}/${environmentName}`;
12
+ const cached = this.cache.get(cacheKey);
13
+ if (cached && Date.now() < cached.expiresAt) {
14
+ return {
15
+ observerUrl: cached.observerUrl,
16
+ rcaAgentUrl: cached.rcaAgentUrl,
17
+ finopsAgentUrl: cached.finopsAgentUrl
18
+ };
19
+ }
20
+ const baseUrl = await this.discoveryApi.getBaseUrl(
21
+ "openchoreo-observability-backend"
22
+ );
23
+ const url = new URL(`${baseUrl}/resolve-urls`);
24
+ url.searchParams.set("namespaceName", namespaceName);
25
+ url.searchParams.set("environmentName", environmentName);
26
+ const response = await this.fetchApi.fetch(url.toString());
27
+ if (!response.ok) {
28
+ let error;
29
+ try {
30
+ error = await response.json();
31
+ } catch {
32
+ throw new Error(
33
+ `Failed to resolve observer URLs: ${response.status} ${response.statusText}`
34
+ );
35
+ }
36
+ throw new Error(
37
+ error.error || `Failed to resolve observer URLs: ${response.statusText}`
38
+ );
39
+ }
40
+ const data = await response.json();
41
+ if (!data.observerUrl) {
42
+ throw new Error("Observability is not enabled for this component");
43
+ }
44
+ this.cache.set(cacheKey, {
45
+ observerUrl: data.observerUrl,
46
+ rcaAgentUrl: data.rcaAgentUrl,
47
+ finopsAgentUrl: data.finopsAgentUrl,
48
+ expiresAt: Date.now() + CACHE_TTL_MS
49
+ });
50
+ return {
51
+ observerUrl: data.observerUrl,
52
+ rcaAgentUrl: data.rcaAgentUrl,
53
+ finopsAgentUrl: data.finopsAgentUrl
54
+ };
55
+ }
56
+ }
57
+
58
+ export { ObserverUrlCache };
59
+ //# sourceMappingURL=ObserverUrlCache.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObserverUrlCache.esm.js","sources":["../../src/api/ObserverUrlCache.ts"],"sourcesContent":["import { DiscoveryApi, FetchApi } from '@backstage/core-plugin-api';\n\ninterface CachedUrls {\n observerUrl: string;\n rcaAgentUrl?: string;\n finopsAgentUrl?: string;\n expiresAt: number;\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\nexport class ObserverUrlCache {\n private readonly discoveryApi: DiscoveryApi;\n private readonly fetchApi: FetchApi;\n private readonly cache = new Map<string, CachedUrls>();\n\n constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) {\n this.discoveryApi = options.discoveryApi;\n this.fetchApi = options.fetchApi;\n }\n\n async resolveUrls(\n namespaceName: string,\n environmentName: string,\n ): Promise<{\n observerUrl: string;\n rcaAgentUrl?: string;\n finopsAgentUrl?: string;\n }> {\n const cacheKey = `${namespaceName}/${environmentName}`;\n const cached = this.cache.get(cacheKey);\n if (cached && Date.now() < cached.expiresAt) {\n return {\n observerUrl: cached.observerUrl,\n rcaAgentUrl: cached.rcaAgentUrl,\n finopsAgentUrl: cached.finopsAgentUrl,\n };\n }\n\n const baseUrl = await this.discoveryApi.getBaseUrl(\n 'openchoreo-observability-backend',\n );\n const url = new URL(`${baseUrl}/resolve-urls`);\n url.searchParams.set('namespaceName', namespaceName);\n url.searchParams.set('environmentName', environmentName);\n\n const response = await this.fetchApi.fetch(url.toString());\n\n if (!response.ok) {\n let error;\n try {\n error = await response.json();\n } catch {\n throw new Error(\n `Failed to resolve observer URLs: ${response.status} ${response.statusText}`,\n );\n }\n throw new Error(\n error.error ||\n `Failed to resolve observer URLs: ${response.statusText}`,\n );\n }\n\n const data = await response.json();\n\n if (!data.observerUrl) {\n throw new Error('Observability is not enabled for this component');\n }\n\n this.cache.set(cacheKey, {\n observerUrl: data.observerUrl,\n rcaAgentUrl: data.rcaAgentUrl,\n finopsAgentUrl: data.finopsAgentUrl,\n expiresAt: Date.now() + CACHE_TTL_MS,\n });\n\n return {\n observerUrl: data.observerUrl,\n rcaAgentUrl: data.rcaAgentUrl,\n finopsAgentUrl: data.finopsAgentUrl,\n };\n }\n}\n"],"names":[],"mappings":"AASA,MAAM,YAAA,GAAe,IAAI,EAAA,GAAK,GAAA;AAEvB,MAAM,gBAAA,CAAiB;AAAA,EACX,YAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA,uBAAY,GAAA,EAAwB;AAAA,EAErD,YAAY,OAAA,EAA6D;AACvE,IAAA,IAAA,CAAK,eAAe,OAAA,CAAQ,YAAA;AAC5B,IAAA,IAAA,CAAK,WAAW,OAAA,CAAQ,QAAA;AAAA,EAC1B;AAAA,EAEA,MAAM,WAAA,CACJ,aAAA,EACA,eAAA,EAKC;AACD,IAAA,MAAM,QAAA,GAAW,CAAA,EAAG,aAAa,CAAA,CAAA,EAAI,eAAe,CAAA,CAAA;AACpD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,QAAQ,CAAA;AACtC,IAAA,IAAI,MAAA,IAAU,IAAA,CAAK,GAAA,EAAI,GAAI,OAAO,SAAA,EAAW;AAC3C,MAAA,OAAO;AAAA,QACL,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,aAAa,MAAA,CAAO,WAAA;AAAA,QACpB,gBAAgB,MAAA,CAAO;AAAA,OACzB;AAAA,IACF;AAEA,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,YAAA,CAAa,UAAA;AAAA,MACtC;AAAA,KACF;AACA,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,CAAA,EAAG,OAAO,CAAA,aAAA,CAAe,CAAA;AAC7C,IAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,eAAA,EAAiB,aAAa,CAAA;AACnD,IAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,iBAAA,EAAmB,eAAe,CAAA;AAEvD,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,SAAS,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AAEzD,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,MAC9B,CAAA,CAAA,MAAQ;AACN,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,CAAA,iCAAA,EAAoC,QAAA,CAAS,MAAM,CAAA,CAAA,EAAI,SAAS,UAAU,CAAA;AAAA,SAC5E;AAAA,MACF;AACA,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,KAAA,CAAM,KAAA,IACJ,CAAA,iCAAA,EAAoC,QAAA,CAAS,UAAU,CAAA;AAAA,OAC3D;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AAEjC,IAAA,IAAI,CAAC,KAAK,WAAA,EAAa;AACrB,MAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,IACnE;AAEA,IAAA,IAAA,CAAK,KAAA,CAAM,IAAI,QAAA,EAAU;AAAA,MACvB,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,gBAAgB,IAAA,CAAK,cAAA;AAAA,MACrB,SAAA,EAAW,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,KACzB,CAAA;AAED,IAAA,OAAO;AAAA,MACL,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,aAAa,IAAA,CAAK,WAAA;AAAA,MAClB,gBAAgB,IAAA,CAAK;AAAA,KACvB;AAAA,EACF;AACF;;;;"}
@@ -0,0 +1,104 @@
1
+ import { createApiRef } from '@backstage/core-plugin-api';
2
+ import { ObserverUrlCache } from './ObserverUrlCache.esm.js';
3
+
4
+ const rcaAgentApiRef = createApiRef({
5
+ id: "plugin.openchoreo-rca-agent.service"
6
+ });
7
+ class RCAAgentClient {
8
+ fetchApi;
9
+ urlCache;
10
+ constructor(options) {
11
+ this.fetchApi = options.fetchApi;
12
+ this.urlCache = new ObserverUrlCache(options);
13
+ }
14
+ async streamRCAChat(request, routing, onEvent, signal) {
15
+ const { rcaAgentUrl } = await this.urlCache.resolveUrls(
16
+ routing.namespaceName,
17
+ routing.environmentName
18
+ );
19
+ if (!rcaAgentUrl) {
20
+ throw new Error("RCA service is not configured");
21
+ }
22
+ const response = await this.fetchApi.fetch(
23
+ `${rcaAgentUrl}/api/v1alpha1/rca-agent/chat`,
24
+ {
25
+ method: "POST",
26
+ body: JSON.stringify(request),
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ "x-openchoreo-direct": "true"
30
+ },
31
+ signal
32
+ }
33
+ );
34
+ if (!response.ok) {
35
+ const error = await response.json();
36
+ throw new Error(error.error || `RCA chat failed: ${response.statusText}`);
37
+ }
38
+ if (!response.body) {
39
+ throw new Error("No response body from RCA chat");
40
+ }
41
+ const reader = response.body.getReader();
42
+ const decoder = new TextDecoder();
43
+ let buffer = "";
44
+ try {
45
+ let done = false;
46
+ while (!done) {
47
+ const result = await reader.read();
48
+ done = result.done;
49
+ if (done) break;
50
+ const value = result.value;
51
+ buffer += decoder.decode(value, { stream: true });
52
+ const lines = buffer.split("\n");
53
+ buffer = lines.pop() || "";
54
+ for (const line of lines) {
55
+ if (line.trim()) {
56
+ try {
57
+ const event = JSON.parse(line);
58
+ onEvent(event);
59
+ } catch {
60
+ }
61
+ }
62
+ }
63
+ }
64
+ if (buffer.trim()) {
65
+ try {
66
+ const event = JSON.parse(buffer);
67
+ onEvent(event);
68
+ } catch {
69
+ }
70
+ }
71
+ } finally {
72
+ reader.releaseLock();
73
+ }
74
+ }
75
+ async updateActionStatuses(reportId, routing, update) {
76
+ const { rcaAgentUrl } = await this.urlCache.resolveUrls(
77
+ routing.namespaceName,
78
+ routing.environmentName
79
+ );
80
+ if (!rcaAgentUrl) {
81
+ throw new Error("RCA service is not configured");
82
+ }
83
+ const response = await this.fetchApi.fetch(
84
+ `${rcaAgentUrl}/api/v1/rca-agent/reports/${encodeURIComponent(reportId)}`,
85
+ {
86
+ method: "PUT",
87
+ body: JSON.stringify(update),
88
+ headers: {
89
+ "Content-Type": "application/json",
90
+ "x-openchoreo-direct": "true"
91
+ }
92
+ }
93
+ );
94
+ if (!response.ok) {
95
+ const error = await response.json();
96
+ throw new Error(
97
+ error.error || `Update report failed: ${response.statusText}`
98
+ );
99
+ }
100
+ }
101
+ }
102
+
103
+ export { RCAAgentClient, rcaAgentApiRef };
104
+ //# sourceMappingURL=RCAAgentApi.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RCAAgentApi.esm.js","sources":["../../src/api/RCAAgentApi.ts"],"sourcesContent":["import {\n createApiRef,\n DiscoveryApi,\n FetchApi,\n} from '@backstage/core-plugin-api';\nimport type { AIRCAAgentComponents } from '@openchoreo/backstage-plugin-common';\nimport { ObserverUrlCache } from './ObserverUrlCache';\n\nexport type ChatMessage = { role: string; content: string };\nexport type StreamEvent = AIRCAAgentComponents['schemas']['StreamEvent'];\nexport type RecommendedAction =\n AIRCAAgentComponents['schemas']['RecommendedAction'];\nexport type ResourceChange = AIRCAAgentComponents['schemas']['ResourceChange'];\nexport type EnvVarChange = AIRCAAgentComponents['schemas']['EnvVarChange'];\nexport type FileChange = AIRCAAgentComponents['schemas']['FileChange'];\nexport type FieldChange = AIRCAAgentComponents['schemas']['FieldChange'];\n\nexport interface ChatRoutingContext {\n namespaceName: string;\n environmentName: string;\n}\n\nexport interface ChatRequest {\n reportId: string;\n namespace: string;\n project: string;\n environment: string;\n messages: ChatMessage[];\n}\n\nexport interface RCAAgentApi {\n streamRCAChat(\n request: ChatRequest,\n routing: ChatRoutingContext,\n onEvent: (event: StreamEvent) => void,\n signal?: AbortSignal,\n ): Promise<void>;\n\n updateActionStatuses(\n reportId: string,\n routing: ChatRoutingContext,\n update: { appliedIndices?: number[]; dismissedIndices?: number[] },\n ): Promise<void>;\n}\n\nexport const rcaAgentApiRef = createApiRef<RCAAgentApi>({\n id: 'plugin.openchoreo-rca-agent.service',\n});\n\nexport class RCAAgentClient implements RCAAgentApi {\n private readonly fetchApi: FetchApi;\n private readonly urlCache: ObserverUrlCache;\n\n constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) {\n this.fetchApi = options.fetchApi;\n this.urlCache = new ObserverUrlCache(options);\n }\n\n async streamRCAChat(\n request: ChatRequest,\n routing: ChatRoutingContext,\n onEvent: (event: StreamEvent) => void,\n signal?: AbortSignal,\n ): Promise<void> {\n const { rcaAgentUrl } = await this.urlCache.resolveUrls(\n routing.namespaceName,\n routing.environmentName,\n );\n\n if (!rcaAgentUrl) {\n throw new Error('RCA service is not configured');\n }\n\n const response = await this.fetchApi.fetch(\n `${rcaAgentUrl}/api/v1alpha1/rca-agent/chat`,\n {\n method: 'POST',\n body: JSON.stringify(request),\n headers: {\n 'Content-Type': 'application/json',\n 'x-openchoreo-direct': 'true',\n },\n signal,\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error || `RCA chat failed: ${response.statusText}`);\n }\n\n if (!response.body) {\n throw new Error('No response body from RCA chat');\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n let done = false;\n while (!done) {\n const result = await reader.read();\n done = result.done;\n\n if (done) break;\n const value = result.value;\n\n // Decode chunk and add to buffer\n buffer += decoder.decode(value, { stream: true });\n\n // Split by newlines (NDJSON format)\n const lines = buffer.split('\\n');\n\n // Keep incomplete last line in buffer\n buffer = lines.pop() || '';\n\n // Process complete lines\n for (const line of lines) {\n if (line.trim()) {\n try {\n const event: StreamEvent = JSON.parse(line);\n onEvent(event);\n } catch {\n // Skip malformed JSON lines\n }\n }\n }\n }\n\n // Process any remaining buffer\n if (buffer.trim()) {\n try {\n const event: StreamEvent = JSON.parse(buffer);\n onEvent(event);\n } catch {\n // Skip malformed JSON\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n async updateActionStatuses(\n reportId: string,\n routing: ChatRoutingContext,\n update: { appliedIndices?: number[]; dismissedIndices?: number[] },\n ): Promise<void> {\n const { rcaAgentUrl } = await this.urlCache.resolveUrls(\n routing.namespaceName,\n routing.environmentName,\n );\n\n if (!rcaAgentUrl) {\n throw new Error('RCA service is not configured');\n }\n\n const response = await this.fetchApi.fetch(\n `${rcaAgentUrl}/api/v1/rca-agent/reports/${encodeURIComponent(reportId)}`,\n {\n method: 'PUT',\n body: JSON.stringify(update),\n headers: {\n 'Content-Type': 'application/json',\n 'x-openchoreo-direct': 'true',\n },\n },\n );\n\n if (!response.ok) {\n const error = await response.json();\n throw new Error(\n error.error || `Update report failed: ${response.statusText}`,\n );\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,203 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { TableRow, TableCell, Typography, Chip, Box, Tooltip, Button, Collapse } from '@material-ui/core';
4
+ import OpenInNewIcon from '@material-ui/icons/OpenInNew';
5
+ import { useLogEntryStyles } from '../RuntimeLogs/styles.esm.js';
6
+
7
+ const formatTimestamp = (ts) => {
8
+ if (!ts) return "\u2014";
9
+ try {
10
+ const d = new Date(ts);
11
+ return d.toLocaleString();
12
+ } catch {
13
+ return ts;
14
+ }
15
+ };
16
+ const getSeverityChipClass = (severity, classes) => {
17
+ switch (severity?.toLowerCase()) {
18
+ case "critical":
19
+ return classes.errorChip;
20
+ case "warning":
21
+ return classes.warnChip;
22
+ case "info":
23
+ return classes.infoChip;
24
+ default:
25
+ return classes.undefinedChip;
26
+ }
27
+ };
28
+ const AlertRow = ({
29
+ alert,
30
+ environmentName,
31
+ projectName,
32
+ componentName,
33
+ namespaceName,
34
+ onViewIncident,
35
+ onViewCostAnalysis
36
+ }) => {
37
+ const classes = useLogEntryStyles();
38
+ const [expanded, setExpanded] = useState(false);
39
+ const handleRowClick = () => {
40
+ setExpanded((prev) => !prev);
41
+ };
42
+ const handleViewIncidentClick = (event) => {
43
+ event.stopPropagation();
44
+ onViewIncident(alert);
45
+ };
46
+ const handleViewCostAnalysisClick = (event) => {
47
+ event.stopPropagation();
48
+ onViewCostAnalysis?.(alert);
49
+ };
50
+ const effectiveProject = alert.projectName || projectName || "\u2014";
51
+ const effectiveComponent = alert.componentName || componentName || "\u2014";
52
+ const effectiveEnvironment = alert.environmentName || environmentName || "\u2014";
53
+ const effectiveNamespace = alert.namespaceName || namespaceName || "\u2014";
54
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
55
+ /* @__PURE__ */ jsxs(
56
+ TableRow,
57
+ {
58
+ hover: true,
59
+ className: `${classes.logRow} ${expanded ? classes.expandedRow : ""}`,
60
+ onClick: handleRowClick,
61
+ children: [
62
+ /* @__PURE__ */ jsx(TableCell, { style: { fontSize: "0.75rem" }, children: formatTimestamp(alert.timestamp) }),
63
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { variant: "body2", noWrap: true, title: alert.ruleDescription, children: alert.ruleName || "\u2014" }) }),
64
+ /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
65
+ Chip,
66
+ {
67
+ size: "small",
68
+ label: (alert.severity || "info").toUpperCase(),
69
+ className: `${classes.logLevelChip} ${getSeverityChipClass(
70
+ alert.severity,
71
+ classes
72
+ )}`
73
+ }
74
+ ) }),
75
+ /* @__PURE__ */ jsx(TableCell, { style: { fontSize: "0.75rem" }, children: alert.sourceType || "\u2014" }),
76
+ /* @__PURE__ */ jsx(TableCell, { style: { fontSize: "0.75rem" }, children: /* @__PURE__ */ jsxs(
77
+ Box,
78
+ {
79
+ display: "flex",
80
+ alignItems: "center",
81
+ justifyContent: "space-between",
82
+ children: [
83
+ /* @__PURE__ */ jsx("span", { children: alert.alertValue ?? "\u2014" }),
84
+ /* @__PURE__ */ jsxs(Box, { display: "flex", style: { gap: 8 }, children: [
85
+ alert.incidentEnabled && /* @__PURE__ */ jsx(Tooltip, { title: "View associated incident in project Incidents tab", children: /* @__PURE__ */ jsx("span", { className: classes.hoverActionButton, children: /* @__PURE__ */ jsx(
86
+ Button,
87
+ {
88
+ size: "small",
89
+ startIcon: /* @__PURE__ */ jsx(OpenInNewIcon, { fontSize: "small" }),
90
+ onClick: handleViewIncidentClick,
91
+ style: { whiteSpace: "nowrap" },
92
+ children: "View incident"
93
+ }
94
+ ) }) }),
95
+ alert.sourceType === "metric" && alert.sourceMetric === "budget" && onViewCostAnalysis && /* @__PURE__ */ jsx(Tooltip, { title: "View cost analysis for this budget alert", children: /* @__PURE__ */ jsx("span", { className: classes.hoverActionButton, children: /* @__PURE__ */ jsx(
96
+ Button,
97
+ {
98
+ size: "small",
99
+ startIcon: /* @__PURE__ */ jsx(OpenInNewIcon, { fontSize: "small" }),
100
+ onClick: handleViewCostAnalysisClick,
101
+ style: { whiteSpace: "nowrap" },
102
+ children: "View cost analysis"
103
+ }
104
+ ) }) })
105
+ ] })
106
+ ]
107
+ }
108
+ ) })
109
+ ]
110
+ }
111
+ ),
112
+ expanded && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 5, style: { paddingBottom: 0, paddingTop: 0 }, children: /* @__PURE__ */ jsx(Collapse, { in: expanded, timeout: "auto", unmountOnExit: true, children: /* @__PURE__ */ jsxs(Box, { className: classes.expandedContent, children: [
113
+ /* @__PURE__ */ jsxs(
114
+ Box,
115
+ {
116
+ display: "flex",
117
+ alignItems: "center",
118
+ justifyContent: "space-between",
119
+ style: { marginBottom: 8 },
120
+ children: [
121
+ /* @__PURE__ */ jsx(Typography, { className: classes.expandedSectionTitle, children: "Alert details" }),
122
+ /* @__PURE__ */ jsxs(Box, { display: "flex", style: { gap: 8 }, children: [
123
+ alert.incidentEnabled && /* @__PURE__ */ jsx(Tooltip, { title: "View associated incident in project Incidents tab", children: /* @__PURE__ */ jsx(
124
+ Button,
125
+ {
126
+ size: "small",
127
+ variant: "outlined",
128
+ startIcon: /* @__PURE__ */ jsx(OpenInNewIcon, { fontSize: "small" }),
129
+ onClick: handleViewIncidentClick,
130
+ children: "View incident"
131
+ }
132
+ ) }),
133
+ alert.sourceType === "metric" && alert.sourceMetric === "budget" && onViewCostAnalysis && /* @__PURE__ */ jsx(Tooltip, { title: "View cost analysis for this budget alert", children: /* @__PURE__ */ jsx(
134
+ Button,
135
+ {
136
+ size: "small",
137
+ variant: "outlined",
138
+ startIcon: /* @__PURE__ */ jsx(OpenInNewIcon, { fontSize: "small" }),
139
+ onClick: handleViewCostAnalysisClick,
140
+ children: "View cost analysis"
141
+ }
142
+ ) })
143
+ ] })
144
+ ]
145
+ }
146
+ ),
147
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataBox, children: [
148
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataGrid, children: [
149
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
150
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Alert ID:" }),
151
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: alert.alertId || "\u2014" })
152
+ ] }),
153
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
154
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Project:" }),
155
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: effectiveProject })
156
+ ] }),
157
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
158
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Component:" }),
159
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: effectiveComponent })
160
+ ] }),
161
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
162
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Environment:" }),
163
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: effectiveEnvironment })
164
+ ] }),
165
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
166
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Namespace:" }),
167
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: effectiveNamespace })
168
+ ] }),
169
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
170
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Source Type:" }),
171
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: alert.sourceType || "\u2014" })
172
+ ] }),
173
+ alert.sourceType === "log" && alert.sourceQuery && /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
174
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Log Query:" }),
175
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: alert.sourceQuery })
176
+ ] }),
177
+ alert.sourceType === "metric" && alert.sourceMetric && /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
178
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Metric:" }),
179
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: alert.sourceMetric })
180
+ ] }),
181
+ alert.notificationChannels && alert.notificationChannels.length > 0 && /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
182
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Notification Channels:" }),
183
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: alert.notificationChannels.join(", ") })
184
+ ] })
185
+ ] }),
186
+ alert.ruleDescription && /* @__PURE__ */ jsxs(Box, { style: { marginTop: 12 }, children: [
187
+ /* @__PURE__ */ jsx(Typography, { className: classes.metadataTitle, children: "Rule description" }),
188
+ /* @__PURE__ */ jsx(
189
+ Typography,
190
+ {
191
+ variant: "body2",
192
+ className: classes.metadataValue,
193
+ children: alert.ruleDescription
194
+ }
195
+ )
196
+ ] })
197
+ ] })
198
+ ] }) }) }) })
199
+ ] });
200
+ };
201
+
202
+ export { AlertRow };
203
+ //# sourceMappingURL=AlertRow.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AlertRow.esm.js","sources":["../../../src/components/Alerts/AlertRow.tsx"],"sourcesContent":["import { FC, MouseEvent, useState } from 'react';\nimport {\n TableRow,\n TableCell,\n Typography,\n Box,\n Chip,\n Collapse,\n Button,\n Tooltip,\n} from '@material-ui/core';\nimport OpenInNewIcon from '@material-ui/icons/OpenInNew';\nimport type { AlertSummary } from '../../types';\nimport { useLogEntryStyles } from '../RuntimeLogs/styles';\n\ninterface AlertRowProps {\n alert: AlertSummary;\n environmentName?: string;\n projectName?: string;\n componentName?: string;\n namespaceName?: string;\n onViewIncident: (alert: AlertSummary) => void;\n onViewCostAnalysis?: (alert: AlertSummary) => void;\n}\n\nconst formatTimestamp = (ts?: string) => {\n if (!ts) return '—';\n try {\n const d = new Date(ts);\n return d.toLocaleString();\n } catch {\n return ts;\n }\n};\n\nconst getSeverityChipClass = (\n severity: string | undefined,\n classes: ReturnType<typeof useLogEntryStyles>,\n): string => {\n switch (severity?.toLowerCase()) {\n case 'critical':\n return classes.errorChip;\n case 'warning':\n return classes.warnChip;\n case 'info':\n return classes.infoChip;\n default:\n return classes.undefinedChip;\n }\n};\n\nexport const AlertRow: FC<AlertRowProps> = ({\n alert,\n environmentName,\n projectName,\n componentName,\n namespaceName,\n onViewIncident,\n onViewCostAnalysis,\n}) => {\n const classes = useLogEntryStyles();\n const [expanded, setExpanded] = useState(false);\n\n const handleRowClick = () => {\n setExpanded(prev => !prev);\n };\n\n const handleViewIncidentClick = (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n onViewIncident(alert);\n };\n\n const handleViewCostAnalysisClick = (\n event: MouseEvent<HTMLButtonElement>,\n ) => {\n event.stopPropagation();\n onViewCostAnalysis?.(alert);\n };\n\n const effectiveProject = alert.projectName || projectName || '—';\n const effectiveComponent = alert.componentName || componentName || '—';\n const effectiveEnvironment = alert.environmentName || environmentName || '—';\n const effectiveNamespace = alert.namespaceName || namespaceName || '—';\n\n return (\n <>\n <TableRow\n hover\n className={`${classes.logRow} ${expanded ? classes.expandedRow : ''}`}\n onClick={handleRowClick}\n >\n <TableCell style={{ fontSize: '0.75rem' }}>\n {formatTimestamp(alert.timestamp)}\n </TableCell>\n <TableCell>\n <Typography variant=\"body2\" noWrap title={alert.ruleDescription}>\n {alert.ruleName || '—'}\n </Typography>\n </TableCell>\n <TableCell>\n <Chip\n size=\"small\"\n label={(alert.severity || 'info').toUpperCase()}\n className={`${classes.logLevelChip} ${getSeverityChipClass(\n alert.severity,\n classes,\n )}`}\n />\n </TableCell>\n <TableCell style={{ fontSize: '0.75rem' }}>\n {alert.sourceType || '—'}\n </TableCell>\n <TableCell style={{ fontSize: '0.75rem' }}>\n <Box\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"space-between\"\n >\n <span>{alert.alertValue ?? '—'}</span>\n <Box display=\"flex\" style={{ gap: 8 }}>\n {alert.incidentEnabled && (\n <Tooltip title=\"View associated incident in project Incidents tab\">\n <span className={classes.hoverActionButton}>\n <Button\n size=\"small\"\n startIcon={<OpenInNewIcon fontSize=\"small\" />}\n onClick={handleViewIncidentClick}\n style={{ whiteSpace: 'nowrap' }}\n >\n View incident\n </Button>\n </span>\n </Tooltip>\n )}\n {alert.sourceType === 'metric' &&\n alert.sourceMetric === 'budget' &&\n onViewCostAnalysis && (\n <Tooltip title=\"View cost analysis for this budget alert\">\n <span className={classes.hoverActionButton}>\n <Button\n size=\"small\"\n startIcon={<OpenInNewIcon fontSize=\"small\" />}\n onClick={handleViewCostAnalysisClick}\n style={{ whiteSpace: 'nowrap' }}\n >\n View cost analysis\n </Button>\n </span>\n </Tooltip>\n )}\n </Box>\n </Box>\n </TableCell>\n </TableRow>\n\n {expanded && (\n <TableRow>\n <TableCell colSpan={5} style={{ paddingBottom: 0, paddingTop: 0 }}>\n <Collapse in={expanded} timeout=\"auto\" unmountOnExit>\n <Box className={classes.expandedContent}>\n <Box\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"space-between\"\n style={{ marginBottom: 8 }}\n >\n <Typography className={classes.expandedSectionTitle}>\n Alert details\n </Typography>\n <Box display=\"flex\" style={{ gap: 8 }}>\n {alert.incidentEnabled && (\n <Tooltip title=\"View associated incident in project Incidents tab\">\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<OpenInNewIcon fontSize=\"small\" />}\n onClick={handleViewIncidentClick}\n >\n View incident\n </Button>\n </Tooltip>\n )}\n {alert.sourceType === 'metric' &&\n alert.sourceMetric === 'budget' &&\n onViewCostAnalysis && (\n <Tooltip title=\"View cost analysis for this budget alert\">\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<OpenInNewIcon fontSize=\"small\" />}\n onClick={handleViewCostAnalysisClick}\n >\n View cost analysis\n </Button>\n </Tooltip>\n )}\n </Box>\n </Box>\n\n <Box className={classes.metadataBox}>\n <Box className={classes.metadataGrid}>\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Alert ID:</span>\n <span className={classes.metadataValue}>\n {alert.alertId || '—'}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Project:</span>\n <span className={classes.metadataValue}>\n {effectiveProject}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Component:</span>\n <span className={classes.metadataValue}>\n {effectiveComponent}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Environment:</span>\n <span className={classes.metadataValue}>\n {effectiveEnvironment}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Namespace:</span>\n <span className={classes.metadataValue}>\n {effectiveNamespace}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Source Type:</span>\n <span className={classes.metadataValue}>\n {alert.sourceType || '—'}\n </span>\n </Box>\n\n {alert.sourceType === 'log' && alert.sourceQuery && (\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Log Query:</span>\n <span className={classes.metadataValue}>\n {alert.sourceQuery}\n </span>\n </Box>\n )}\n\n {alert.sourceType === 'metric' && alert.sourceMetric && (\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Metric:</span>\n <span className={classes.metadataValue}>\n {alert.sourceMetric}\n </span>\n </Box>\n )}\n\n {alert.notificationChannels &&\n alert.notificationChannels.length > 0 && (\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Notification Channels:\n </span>\n <span className={classes.metadataValue}>\n {alert.notificationChannels.join(', ')}\n </span>\n </Box>\n )}\n </Box>\n\n {alert.ruleDescription && (\n <Box style={{ marginTop: 12 }}>\n <Typography className={classes.metadataTitle}>\n Rule description\n </Typography>\n <Typography\n variant=\"body2\"\n className={classes.metadataValue}\n >\n {alert.ruleDescription}\n </Typography>\n </Box>\n )}\n </Box>\n </Box>\n </Collapse>\n </TableCell>\n </TableRow>\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Typography, Tooltip, Button } from '@material-ui/core';
3
+ import Refresh from '@material-ui/icons/Refresh';
4
+ import ArrowUpward from '@material-ui/icons/ArrowUpward';
5
+ import ArrowDownward from '@material-ui/icons/ArrowDownward';
6
+ import { useLogsActionsStyles } from '../RuntimeLogs/styles.esm.js';
7
+
8
+ const formatDate = (date) => {
9
+ const day = String(date.getDate()).padStart(2, "0");
10
+ const month = String(date.getMonth() + 1).padStart(2, "0");
11
+ const year = date.getFullYear();
12
+ const hours = String(date.getHours()).padStart(2, "0");
13
+ const minutes = String(date.getMinutes()).padStart(2, "0");
14
+ const seconds = String(date.getSeconds()).padStart(2, "0");
15
+ return `${day}/${month}/${year}, ${hours}:${minutes}:${seconds}`;
16
+ };
17
+ const AlertsActions = ({
18
+ totalCount,
19
+ disabled,
20
+ onRefresh,
21
+ filters,
22
+ onFiltersChange,
23
+ lastUpdated
24
+ }) => {
25
+ const classes = useLogsActionsStyles();
26
+ const displayDate = lastUpdated || /* @__PURE__ */ new Date();
27
+ const effectiveSortOrder = filters.sortOrder || "desc";
28
+ const handleSortToggle = () => {
29
+ const newSortOrder = effectiveSortOrder === "desc" ? "asc" : "desc";
30
+ onFiltersChange({ sortOrder: newSortOrder });
31
+ };
32
+ return /* @__PURE__ */ jsxs(Box, { className: classes.statsContainer, children: [
33
+ /* @__PURE__ */ jsxs(Box, { children: [
34
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
35
+ "Total alerts: ",
36
+ totalCount
37
+ ] }),
38
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
39
+ "Last updated at: ",
40
+ formatDate(displayDate)
41
+ ] })
42
+ ] }),
43
+ /* @__PURE__ */ jsxs(Box, { className: classes.actionsContainer, children: [
44
+ /* @__PURE__ */ jsx(
45
+ Tooltip,
46
+ {
47
+ title: effectiveSortOrder === "desc" ? "Sort alerts by newest first" : "Sort alerts by oldest first",
48
+ children: /* @__PURE__ */ jsx(
49
+ Button,
50
+ {
51
+ variant: "outlined",
52
+ onClick: handleSortToggle,
53
+ disabled,
54
+ size: "small",
55
+ startIcon: effectiveSortOrder === "desc" ? /* @__PURE__ */ jsx(ArrowUpward, {}) : /* @__PURE__ */ jsx(ArrowDownward, {}),
56
+ children: effectiveSortOrder === "desc" ? "Newest First" : "Oldest First"
57
+ }
58
+ )
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsx(
62
+ Button,
63
+ {
64
+ variant: "outlined",
65
+ startIcon: /* @__PURE__ */ jsx(Refresh, {}),
66
+ onClick: onRefresh,
67
+ disabled,
68
+ size: "small",
69
+ children: "Refresh"
70
+ }
71
+ )
72
+ ] })
73
+ ] });
74
+ };
75
+
76
+ export { AlertsActions };
77
+ //# sourceMappingURL=AlertsActions.esm.js.map