@oneuptime/common 11.0.0 → 11.0.2

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 (357) hide show
  1. package/Models/DatabaseModels/Alert.ts +110 -0
  2. package/Models/DatabaseModels/CephCluster.ts +964 -0
  3. package/Models/DatabaseModels/CephClusterLabelRule.ts +514 -0
  4. package/Models/DatabaseModels/CephClusterOwnerRule.ts +596 -0
  5. package/Models/DatabaseModels/CephClusterOwnerTeam.ts +487 -0
  6. package/Models/DatabaseModels/CephClusterOwnerUser.ts +486 -0
  7. package/Models/DatabaseModels/CephResource.ts +809 -0
  8. package/Models/DatabaseModels/Host.ts +64 -0
  9. package/Models/DatabaseModels/Incident.ts +110 -0
  10. package/Models/DatabaseModels/Index.ts +24 -0
  11. package/Models/DatabaseModels/ProxmoxCluster.ts +943 -0
  12. package/Models/DatabaseModels/ProxmoxClusterLabelRule.ts +514 -0
  13. package/Models/DatabaseModels/ProxmoxClusterOwnerRule.ts +596 -0
  14. package/Models/DatabaseModels/ProxmoxClusterOwnerTeam.ts +487 -0
  15. package/Models/DatabaseModels/ProxmoxClusterOwnerUser.ts +486 -0
  16. package/Models/DatabaseModels/ProxmoxResource.ts +726 -0
  17. package/Models/DatabaseModels/ScheduledMaintenance.ts +110 -0
  18. package/Server/API/BillingInvoiceAPI.ts +47 -7
  19. package/Server/API/CephResourceAPI.ts +134 -0
  20. package/Server/API/DashboardAPI.ts +46 -0
  21. package/Server/API/ProjectAPI.ts +15 -0
  22. package/Server/API/ProxmoxResourceAPI.ts +132 -0
  23. package/Server/API/ResellerPlanAPI.ts +17 -0
  24. package/Server/Infrastructure/GlobalCache.ts +8 -2
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.ts +163 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.ts +211 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.ts +590 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.ts +64 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  30. package/Server/Infrastructure/Redis.ts +40 -12
  31. package/Server/Services/AnalyticsDatabaseService.ts +1 -1
  32. package/Server/Services/BillingService.ts +109 -21
  33. package/Server/Services/CephClusterLabelRuleEngineService.ts +200 -0
  34. package/Server/Services/CephClusterLabelRuleService.ts +14 -0
  35. package/Server/Services/CephClusterOwnerRuleEngineService.ts +218 -0
  36. package/Server/Services/CephClusterOwnerRuleService.ts +14 -0
  37. package/Server/Services/CephClusterOwnerTeamService.ts +10 -0
  38. package/Server/Services/CephClusterOwnerUserService.ts +10 -0
  39. package/Server/Services/CephClusterService.ts +401 -0
  40. package/Server/Services/CephResourceService.ts +383 -0
  41. package/Server/Services/CloudResourceService.ts +11 -3
  42. package/Server/Services/DockerHostService.ts +11 -3
  43. package/Server/Services/ExceptionAggregationService.ts +2 -0
  44. package/Server/Services/HostService.ts +11 -3
  45. package/Server/Services/Index.ts +24 -0
  46. package/Server/Services/KubernetesClusterService.ts +11 -3
  47. package/Server/Services/LogAggregationService.ts +2 -0
  48. package/Server/Services/MetricAggregationService.ts +2 -0
  49. package/Server/Services/OpenTelemetryIngestService.ts +36 -0
  50. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +204 -0
  51. package/Server/Services/ProxmoxClusterLabelRuleService.ts +14 -0
  52. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +222 -0
  53. package/Server/Services/ProxmoxClusterOwnerRuleService.ts +14 -0
  54. package/Server/Services/ProxmoxClusterOwnerTeamService.ts +10 -0
  55. package/Server/Services/ProxmoxClusterOwnerUserService.ts +10 -0
  56. package/Server/Services/ProxmoxClusterService.ts +382 -0
  57. package/Server/Services/ProxmoxResourceService.ts +404 -0
  58. package/Server/Services/RumApplicationService.ts +11 -3
  59. package/Server/Services/ServerlessFunctionService.ts +11 -3
  60. package/Server/Services/TelemetryUsageBillingService.ts +41 -3
  61. package/Server/Services/TraceAggregationService.ts +2 -0
  62. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +8 -23
  63. package/Server/Utils/Monitor/MonitorAlert.ts +45 -0
  64. package/Server/Utils/Monitor/MonitorClusterContext.ts +129 -0
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +344 -4
  66. package/Server/Utils/Monitor/MonitorIncident.ts +130 -7
  67. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +39 -6
  68. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +3 -1
  69. package/Server/Utils/Monitor/SeriesResourceLabels.ts +33 -0
  70. package/Server/Utils/Profiling.ts +37 -2
  71. package/Server/Utils/Telemetry/EntityRegistry.ts +4 -0
  72. package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +1096 -0
  73. package/Server/Utils/Telemetry/TelemetryEntity.ts +85 -0
  74. package/Server/Utils/Telemetry.ts +8 -19
  75. package/Tests/Server/API/BillingInvoiceAPI.test.ts +194 -0
  76. package/Tests/Server/API/ProjectAPI.test.ts +91 -0
  77. package/Tests/Server/API/ResellerPlanAPI.test.ts +207 -0
  78. package/Tests/Server/Infrastructure/GlobalCache.test.ts +100 -0
  79. package/Tests/Server/Services/BillingService.test.ts +323 -0
  80. package/Tests/Server/Services/CephResourceService.test.ts +264 -0
  81. package/Tests/Server/Services/ProxmoxResourceService.test.ts +326 -0
  82. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +322 -0
  83. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +13 -0
  84. package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +879 -0
  85. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +196 -0
  86. package/Tests/Types/Monitor/CephAlertTemplates.test.ts +1231 -0
  87. package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +732 -0
  88. package/Tests/Utils/ModelImportExport.test.ts +366 -0
  89. package/Tests/Utils/Telemetry/EntityRelationship.test.ts +49 -0
  90. package/Tests/Utils/Telemetry/HeartbeatAvailability.test.ts +423 -0
  91. package/Types/BaseDatabase/AggregationIntervalUtil.ts +74 -0
  92. package/Types/Dashboard/DashboardComponentType.ts +4 -0
  93. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +2 -0
  94. package/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.ts +15 -0
  95. package/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.ts +14 -0
  96. package/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.ts +17 -0
  97. package/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.ts +16 -0
  98. package/Types/Dashboard/DashboardTemplates.ts +446 -0
  99. package/Types/Icon/IconProp.ts +2 -0
  100. package/Types/Monitor/CephAlertTemplates.ts +1647 -0
  101. package/Types/Monitor/CephMetricCatalog.ts +409 -0
  102. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +44 -0
  103. package/Types/Monitor/MonitorStep.ts +64 -0
  104. package/Types/Monitor/MonitorStepCephMonitor.ts +57 -0
  105. package/Types/Monitor/MonitorStepProxmoxMonitor.ts +81 -0
  106. package/Types/Monitor/MonitorType.ts +29 -1
  107. package/Types/Monitor/ProxmoxAlertTemplates.ts +899 -0
  108. package/Types/Monitor/ProxmoxMetricCatalog.ts +382 -0
  109. package/Types/Permission.ts +464 -0
  110. package/Types/Telemetry/EntityType.ts +11 -0
  111. package/Types/Telemetry/ServiceType.ts +2 -0
  112. package/UI/Components/Icon/Icon.tsx +84 -0
  113. package/UI/Components/ImportExport/ExportModelCard.tsx +90 -0
  114. package/UI/Components/ImportExport/ImportModelsModal.tsx +239 -0
  115. package/UI/Components/ModelTable/ModelTable.tsx +294 -143
  116. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +9 -5
  117. package/UI/Utils/ModelImportExport.ts +207 -0
  118. package/UI/Utils/Telemetry/Telemetry.ts +16 -21
  119. package/UI/Utils/TelemetryService.ts +7 -3
  120. package/Utils/Dashboard/Components/DashboardCephOsdListComponent.ts +63 -0
  121. package/Utils/Dashboard/Components/DashboardCephPoolListComponent.ts +32 -0
  122. package/Utils/Dashboard/Components/DashboardCephResourceListShared.ts +61 -0
  123. package/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.ts +69 -0
  124. package/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.ts +55 -0
  125. package/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.ts +61 -0
  126. package/Utils/Dashboard/Components/Index.ts +28 -0
  127. package/Utils/ModelImportExport.ts +369 -0
  128. package/Utils/Telemetry/EntityKey.ts +35 -0
  129. package/Utils/Telemetry/EntityRelationship.ts +6 -0
  130. package/Utils/Telemetry/HeartbeatAvailability.ts +262 -0
  131. package/build/dist/Models/DatabaseModels/Alert.js +108 -0
  132. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  133. package/build/dist/Models/DatabaseModels/CephCluster.js +992 -0
  134. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -0
  135. package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js +522 -0
  136. package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js.map +1 -0
  137. package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js +603 -0
  138. package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js.map +1 -0
  139. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js +503 -0
  140. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js.map +1 -0
  141. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js +502 -0
  142. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js.map +1 -0
  143. package/build/dist/Models/DatabaseModels/CephResource.js +846 -0
  144. package/build/dist/Models/DatabaseModels/CephResource.js.map +1 -0
  145. package/build/dist/Models/DatabaseModels/Host.js +63 -0
  146. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  147. package/build/dist/Models/DatabaseModels/Incident.js +108 -0
  148. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  149. package/build/dist/Models/DatabaseModels/Index.js +24 -0
  150. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  151. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +967 -0
  152. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -0
  153. package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js +522 -0
  154. package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js.map +1 -0
  155. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js +603 -0
  156. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js.map +1 -0
  157. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js +503 -0
  158. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js.map +1 -0
  159. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js +502 -0
  160. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js.map +1 -0
  161. package/build/dist/Models/DatabaseModels/ProxmoxResource.js +761 -0
  162. package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -0
  163. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +108 -0
  164. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  165. package/build/dist/Server/API/BillingInvoiceAPI.js +35 -5
  166. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  167. package/build/dist/Server/API/CephResourceAPI.js +98 -0
  168. package/build/dist/Server/API/CephResourceAPI.js.map +1 -0
  169. package/build/dist/Server/API/DashboardAPI.js +46 -0
  170. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  171. package/build/dist/Server/API/ProjectAPI.js +11 -0
  172. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  173. package/build/dist/Server/API/ProxmoxResourceAPI.js +95 -0
  174. package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -0
  175. package/build/dist/Server/API/ResellerPlanAPI.js +17 -3
  176. package/build/dist/Server/API/ResellerPlanAPI.js.map +1 -1
  177. package/build/dist/Server/Infrastructure/GlobalCache.js +7 -2
  178. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  179. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js +76 -0
  180. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js.map +1 -0
  181. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js +108 -0
  182. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js.map +1 -0
  183. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js +253 -0
  184. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js.map +1 -0
  185. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js +43 -0
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js.map +1 -0
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  188. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  189. package/build/dist/Server/Infrastructure/Redis.js +31 -8
  190. package/build/dist/Server/Infrastructure/Redis.js.map +1 -1
  191. package/build/dist/Server/Services/AnalyticsDatabaseService.js +1 -1
  192. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  193. package/build/dist/Server/Services/BillingService.js +85 -23
  194. package/build/dist/Server/Services/BillingService.js.map +1 -1
  195. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +166 -0
  196. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -0
  197. package/build/dist/Server/Services/CephClusterLabelRuleService.js +13 -0
  198. package/build/dist/Server/Services/CephClusterLabelRuleService.js.map +1 -0
  199. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +186 -0
  200. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -0
  201. package/build/dist/Server/Services/CephClusterOwnerRuleService.js +13 -0
  202. package/build/dist/Server/Services/CephClusterOwnerRuleService.js.map +1 -0
  203. package/build/dist/Server/Services/CephClusterOwnerTeamService.js +9 -0
  204. package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -0
  205. package/build/dist/Server/Services/CephClusterOwnerUserService.js +9 -0
  206. package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -0
  207. package/build/dist/Server/Services/CephClusterService.js +353 -0
  208. package/build/dist/Server/Services/CephClusterService.js.map +1 -0
  209. package/build/dist/Server/Services/CephResourceService.js +257 -0
  210. package/build/dist/Server/Services/CephResourceService.js.map +1 -0
  211. package/build/dist/Server/Services/CloudResourceService.js +10 -2
  212. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  213. package/build/dist/Server/Services/DockerHostService.js +10 -2
  214. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  215. package/build/dist/Server/Services/ExceptionAggregationService.js +2 -0
  216. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  217. package/build/dist/Server/Services/HostService.js +10 -2
  218. package/build/dist/Server/Services/HostService.js.map +1 -1
  219. package/build/dist/Server/Services/Index.js +24 -0
  220. package/build/dist/Server/Services/Index.js.map +1 -1
  221. package/build/dist/Server/Services/KubernetesClusterService.js +10 -2
  222. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  223. package/build/dist/Server/Services/LogAggregationService.js +2 -0
  224. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  225. package/build/dist/Server/Services/MetricAggregationService.js +2 -0
  226. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  227. package/build/dist/Server/Services/OpenTelemetryIngestService.js +37 -7
  228. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  229. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +166 -0
  230. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -0
  231. package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js +13 -0
  232. package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js.map +1 -0
  233. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +186 -0
  234. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -0
  235. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js +13 -0
  236. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js.map +1 -0
  237. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +9 -0
  238. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -0
  239. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +9 -0
  240. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -0
  241. package/build/dist/Server/Services/ProxmoxClusterService.js +337 -0
  242. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -0
  243. package/build/dist/Server/Services/ProxmoxResourceService.js +285 -0
  244. package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -0
  245. package/build/dist/Server/Services/RumApplicationService.js +10 -2
  246. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  247. package/build/dist/Server/Services/ServerlessFunctionService.js +10 -2
  248. package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
  249. package/build/dist/Server/Services/TelemetryUsageBillingService.js +30 -3
  250. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  251. package/build/dist/Server/Services/TraceAggregationService.js +2 -0
  252. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  253. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +8 -25
  254. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  255. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +36 -0
  256. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  257. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +90 -0
  258. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -0
  259. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +228 -4
  260. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  261. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +103 -8
  262. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  263. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +23 -6
  264. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  265. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +3 -1
  266. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  267. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +23 -0
  268. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  269. package/build/dist/Server/Utils/Profiling.js +24 -3
  270. package/build/dist/Server/Utils/Profiling.js.map +1 -1
  271. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -0
  272. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  273. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +854 -0
  274. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -0
  275. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +62 -0
  276. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  277. package/build/dist/Server/Utils/Telemetry.js +8 -10
  278. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  279. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +69 -0
  280. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -0
  281. package/build/dist/Types/Dashboard/DashboardComponentType.js +4 -0
  282. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  283. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +2 -0
  284. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  285. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js +2 -0
  286. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js.map +1 -0
  287. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js +2 -0
  288. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js.map +1 -0
  289. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js +2 -0
  290. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js.map +1 -0
  291. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js +2 -0
  292. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js.map +1 -0
  293. package/build/dist/Types/Dashboard/DashboardTemplates.js +394 -0
  294. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  295. package/build/dist/Types/Icon/IconProp.js +2 -0
  296. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  297. package/build/dist/Types/Monitor/CephAlertTemplates.js +1379 -0
  298. package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -0
  299. package/build/dist/Types/Monitor/CephMetricCatalog.js +353 -0
  300. package/build/dist/Types/Monitor/CephMetricCatalog.js.map +1 -0
  301. package/build/dist/Types/Monitor/MonitorStep.js +46 -0
  302. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  303. package/build/dist/Types/Monitor/MonitorStepCephMonitor.js +34 -0
  304. package/build/dist/Types/Monitor/MonitorStepCephMonitor.js.map +1 -0
  305. package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js +36 -0
  306. package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js.map +1 -0
  307. package/build/dist/Types/Monitor/MonitorType.js +27 -1
  308. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  309. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +743 -0
  310. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -0
  311. package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js +320 -0
  312. package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js.map +1 -0
  313. package/build/dist/Types/Permission.js +408 -0
  314. package/build/dist/Types/Permission.js.map +1 -1
  315. package/build/dist/Types/Telemetry/EntityType.js +11 -0
  316. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  317. package/build/dist/Types/Telemetry/ServiceType.js +2 -0
  318. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  319. package/build/dist/UI/Components/Icon/Icon.js +33 -0
  320. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  321. package/build/dist/UI/Components/ImportExport/ExportModelCard.js +50 -0
  322. package/build/dist/UI/Components/ImportExport/ExportModelCard.js.map +1 -0
  323. package/build/dist/UI/Components/ImportExport/ImportModelsModal.js +115 -0
  324. package/build/dist/UI/Components/ImportExport/ImportModelsModal.js.map +1 -0
  325. package/build/dist/UI/Components/ModelTable/ModelTable.js +166 -74
  326. package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
  327. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +5 -1
  328. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  329. package/build/dist/UI/Utils/ModelImportExport.js +142 -0
  330. package/build/dist/UI/Utils/ModelImportExport.js.map +1 -0
  331. package/build/dist/UI/Utils/Telemetry/Telemetry.js +11 -10
  332. package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
  333. package/build/dist/UI/Utils/TelemetryService.js +5 -2
  334. package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
  335. package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js +50 -0
  336. package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js.map +1 -0
  337. package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js +27 -0
  338. package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js.map +1 -0
  339. package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js +46 -0
  340. package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js.map +1 -0
  341. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js +55 -0
  342. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js.map +1 -0
  343. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js +42 -0
  344. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js.map +1 -0
  345. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js +46 -0
  346. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js.map +1 -0
  347. package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
  348. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  349. package/build/dist/Utils/ModelImportExport.js +257 -0
  350. package/build/dist/Utils/ModelImportExport.js.map +1 -0
  351. package/build/dist/Utils/Telemetry/EntityKey.js +27 -0
  352. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  353. package/build/dist/Utils/Telemetry/EntityRelationship.js +3 -0
  354. package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
  355. package/build/dist/Utils/Telemetry/HeartbeatAvailability.js +174 -0
  356. package/build/dist/Utils/Telemetry/HeartbeatAvailability.js.map +1 -0
  357. package/package.json +29 -21
@@ -0,0 +1,129 @@
1
+ import CephCluster from "../../../Models/DatabaseModels/CephCluster";
2
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
3
+ import ProxmoxCluster from "../../../Models/DatabaseModels/ProxmoxCluster";
4
+ import MonitorStep from "../../../Types/Monitor/MonitorStep";
5
+ import MonitorType from "../../../Types/Monitor/MonitorType";
6
+ import CephClusterService from "../../Services/CephClusterService";
7
+ import ProxmoxClusterService from "../../Services/ProxmoxClusterService";
8
+ import QueryHelper from "../../Types/Database/QueryHelper";
9
+ import logger from "../Logger";
10
+
11
+ /*
12
+ * WI-11 contract: incidents/alerts created by Proxmox/Ceph monitors must
13
+ * be attached to the cluster they monitor — the per-cluster Activity
14
+ * pages and SideMenu badge counts query `proxmoxClusters` /
15
+ * `cephClusters` on Incident/Alert. Series labels cannot supply this
16
+ * identity: the shipped templates group by datapoint labels (`id`,
17
+ * `ceph_daemon`, `pool_id`), and ungrouped templates (e.g.
18
+ * ceph-health-error) have no series at all. The deterministic source is
19
+ * the monitor step config, which always carries `clusterIdentifier`
20
+ * (validated as required by MonitorStep), so the incident/alert creation
21
+ * paths resolve the cluster row from it once per evaluation.
22
+ */
23
+ export interface MonitorClusterContext {
24
+ proxmoxClusterIds: Array<string>;
25
+ cephClusterIds: Array<string>;
26
+ }
27
+
28
+ export default class MonitorClusterContextUtil {
29
+ /*
30
+ * Resolve the Proxmox/Ceph cluster rows referenced by the monitor's
31
+ * step configs. Lookup-only — row creation belongs to ingest
32
+ * discovery (findOrCreateByName); a monitor pointing at a cluster
33
+ * that never sent data simply links nothing. The lookup is
34
+ * case-insensitive and project-scoped, matching the ingest contract
35
+ * (the agent-stamped name and the user-typed step identifier may
36
+ * differ only by case). Returns empty arrays for every other monitor
37
+ * type without touching the database.
38
+ */
39
+ public static async resolveClusterContextForMonitor(input: {
40
+ monitor: Monitor;
41
+ }): Promise<MonitorClusterContext> {
42
+ const context: MonitorClusterContext = {
43
+ proxmoxClusterIds: [],
44
+ cephClusterIds: [],
45
+ };
46
+
47
+ const monitorType: MonitorType | undefined = input.monitor.monitorType;
48
+
49
+ if (
50
+ monitorType !== MonitorType.Proxmox &&
51
+ monitorType !== MonitorType.Ceph
52
+ ) {
53
+ return context;
54
+ }
55
+
56
+ if (!input.monitor.projectId) {
57
+ return context;
58
+ }
59
+
60
+ const monitorSteps: Array<MonitorStep> =
61
+ input.monitor.monitorSteps?.data?.monitorStepsInstanceArray || [];
62
+
63
+ const clusterIdentifiers: Set<string> = new Set<string>();
64
+
65
+ for (const monitorStep of monitorSteps) {
66
+ const clusterIdentifier: string | undefined =
67
+ monitorType === MonitorType.Proxmox
68
+ ? monitorStep.data?.proxmoxMonitor?.clusterIdentifier
69
+ : monitorStep.data?.cephMonitor?.clusterIdentifier;
70
+
71
+ if (clusterIdentifier && clusterIdentifier.trim().length > 0) {
72
+ clusterIdentifiers.add(clusterIdentifier.trim());
73
+ }
74
+ }
75
+
76
+ /*
77
+ * Cluster linking is best-effort context — a lookup failure must
78
+ * never block incident/alert creation, so errors are logged and
79
+ * swallowed per identifier.
80
+ */
81
+ for (const clusterIdentifier of clusterIdentifiers) {
82
+ try {
83
+ if (monitorType === MonitorType.Proxmox) {
84
+ const proxmoxCluster: ProxmoxCluster | null =
85
+ await ProxmoxClusterService.findOneBy({
86
+ query: {
87
+ projectId: input.monitor.projectId,
88
+ name: QueryHelper.findWithSameText(clusterIdentifier),
89
+ },
90
+ select: {
91
+ _id: true,
92
+ },
93
+ props: {
94
+ isRoot: true,
95
+ },
96
+ });
97
+
98
+ if (proxmoxCluster?._id) {
99
+ context.proxmoxClusterIds.push(String(proxmoxCluster._id));
100
+ }
101
+ } else {
102
+ const cephCluster: CephCluster | null =
103
+ await CephClusterService.findOneBy({
104
+ query: {
105
+ projectId: input.monitor.projectId,
106
+ name: QueryHelper.findWithSameText(clusterIdentifier),
107
+ },
108
+ select: {
109
+ _id: true,
110
+ },
111
+ props: {
112
+ isRoot: true,
113
+ },
114
+ });
115
+
116
+ if (cephCluster?._id) {
117
+ context.cephClusterIds.push(String(cephCluster._id));
118
+ }
119
+ }
120
+ } catch (err) {
121
+ logger.error(
122
+ `Failed to resolve ${monitorType} cluster "${clusterIdentifier}" for monitor ${input.monitor.id?.toString()}: ${err}`,
123
+ );
124
+ }
125
+ }
126
+
127
+ return context;
128
+ }
129
+ }
@@ -54,6 +54,10 @@ import { DashboardClientUrl } from "../../EnvironmentConfig";
54
54
  import MetricMonitorResponse, {
55
55
  KubernetesAffectedResource,
56
56
  KubernetesResourceBreakdown,
57
+ ProxmoxAffectedResource,
58
+ ProxmoxResourceBreakdown,
59
+ CephAffectedResource,
60
+ CephResourceBreakdown,
57
61
  } from "../../../Types/Monitor/MetricMonitor/MetricMonitorResponse";
58
62
  import MetricSeriesResult from "../../../Types/Monitor/MetricMonitor/MetricSeriesResult";
59
63
  import MetricCriteriaContext, {
@@ -62,6 +66,8 @@ import MetricCriteriaContext, {
62
66
  MetricComponentValue,
63
67
  } from "../../../Types/Monitor/MetricMonitor/MetricCriteriaContext";
64
68
  import MonitorStepDockerMonitor from "../../../Types/Monitor/MonitorStepDockerMonitor";
69
+ import MonitorStepProxmoxMonitor from "../../../Types/Monitor/MonitorStepProxmoxMonitor";
70
+ import MonitorStepCephMonitor from "../../../Types/Monitor/MonitorStepCephMonitor";
65
71
 
66
72
  export default class MonitorCriteriaEvaluator {
67
73
  public static async processMonitorStep(input: {
@@ -214,8 +220,8 @@ ${contextBlock}
214
220
  }
215
221
 
216
222
  /**
217
- * For metric-backed monitors (Metrics/Kubernetes/Docker) with
218
- * per-series aggregated results, re-evaluate the matched criteria
223
+ * For metric-backed monitors (Metrics/Kubernetes/Docker/Proxmox/Ceph)
224
+ * with per-series aggregated results, re-evaluate the matched criteria
219
225
  * once per series and return one entry per series that breached.
220
226
  * Returns an empty array when the monitor is not series-aware or
221
227
  * no series matched — the caller falls back to the single-incident
@@ -230,7 +236,9 @@ ${contextBlock}
230
236
  if (
231
237
  input.monitor.monitorType !== MonitorType.Metrics &&
232
238
  input.monitor.monitorType !== MonitorType.Kubernetes &&
233
- input.monitor.monitorType !== MonitorType.Docker
239
+ input.monitor.monitorType !== MonitorType.Docker &&
240
+ input.monitor.monitorType !== MonitorType.Proxmox &&
241
+ input.monitor.monitorType !== MonitorType.Ceph
234
242
  ) {
235
243
  return [];
236
244
  }
@@ -676,7 +684,9 @@ ${contextBlock}
676
684
  if (
677
685
  input.monitor.monitorType === MonitorType.Metrics ||
678
686
  input.monitor.monitorType === MonitorType.Kubernetes ||
679
- input.monitor.monitorType === MonitorType.Docker
687
+ input.monitor.monitorType === MonitorType.Docker ||
688
+ input.monitor.monitorType === MonitorType.Proxmox ||
689
+ input.monitor.monitorType === MonitorType.Ceph
680
690
  ) {
681
691
  const metricMonitorResult: string | null =
682
692
  await MetricMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
@@ -809,6 +819,16 @@ ${contextBlock}
809
819
  return MonitorCriteriaEvaluator.buildDockerRootCauseContext(input);
810
820
  }
811
821
 
822
+ // Handle Proxmox monitors with resource context
823
+ if (input.monitor.monitorType === MonitorType.Proxmox) {
824
+ return MonitorCriteriaEvaluator.buildProxmoxRootCauseContext(input);
825
+ }
826
+
827
+ // Handle Ceph monitors with resource context
828
+ if (input.monitor.monitorType === MonitorType.Ceph) {
829
+ return MonitorCriteriaEvaluator.buildCephRootCauseContext(input);
830
+ }
831
+
812
832
  // Handle generic Metric monitors with metric identity + breaching series
813
833
  if (
814
834
  input.monitor.monitorType === MonitorType.Metrics &&
@@ -1573,6 +1593,326 @@ ${contextBlock}
1573
1593
  return sections.length > 0 ? sections.join("\n") : null;
1574
1594
  }
1575
1595
 
1596
+ private static buildProxmoxRootCauseContext(input: {
1597
+ dataToProcess: DataToProcess;
1598
+ monitorStep: MonitorStep;
1599
+ monitor: Monitor;
1600
+ }): string | null {
1601
+ const metricResponse: MetricMonitorResponse =
1602
+ input.dataToProcess as MetricMonitorResponse;
1603
+
1604
+ const breakdown: ProxmoxResourceBreakdown | undefined =
1605
+ metricResponse.proxmoxResourceBreakdown;
1606
+
1607
+ const sections: Array<string> = [];
1608
+
1609
+ // Proxmox cluster context
1610
+ const proxmoxMonitor: MonitorStepProxmoxMonitor | undefined =
1611
+ input.monitorStep.data?.proxmoxMonitor;
1612
+
1613
+ if (proxmoxMonitor || breakdown) {
1614
+ const clusterDetails: Array<string> = [];
1615
+ clusterDetails.push(
1616
+ `- Cluster: ${breakdown?.clusterName || proxmoxMonitor?.clusterIdentifier || "Unknown"}`,
1617
+ );
1618
+
1619
+ if (breakdown) {
1620
+ clusterDetails.push(
1621
+ `- Metric: ${breakdown.metricFriendlyName} (\`${breakdown.metricName}\`)`,
1622
+ );
1623
+ } else if (
1624
+ proxmoxMonitor &&
1625
+ proxmoxMonitor.metricViewConfig?.queryConfigs?.length > 0 &&
1626
+ proxmoxMonitor.metricViewConfig.queryConfigs[0]
1627
+ ) {
1628
+ const metricName: string = proxmoxMonitor.metricViewConfig
1629
+ .queryConfigs[0].metricQueryData?.filterData?.metricName as string;
1630
+ if (metricName) {
1631
+ clusterDetails.push(`- Metric: \`${metricName}\``);
1632
+ }
1633
+ }
1634
+
1635
+ if (proxmoxMonitor?.resourceFilters?.scope) {
1636
+ clusterDetails.push(
1637
+ `- Scope Filter: ${proxmoxMonitor.resourceFilters.scope}`,
1638
+ );
1639
+ }
1640
+
1641
+ if (proxmoxMonitor?.resourceFilters?.pveId) {
1642
+ clusterDetails.push(
1643
+ `- Resource ID Filter: ${proxmoxMonitor.resourceFilters.pveId}`,
1644
+ );
1645
+ }
1646
+
1647
+ if (proxmoxMonitor?.resourceFilters?.nodeName) {
1648
+ clusterDetails.push(
1649
+ `- Node Filter: ${proxmoxMonitor.resourceFilters.nodeName}`,
1650
+ );
1651
+ }
1652
+
1653
+ if (proxmoxMonitor?.resourceFilters?.guestId) {
1654
+ clusterDetails.push(
1655
+ `- Guest ID Filter: ${proxmoxMonitor.resourceFilters.guestId}`,
1656
+ );
1657
+ }
1658
+
1659
+ sections.push(
1660
+ `**Proxmox Cluster Details**\n${clusterDetails.join("\n")}`,
1661
+ );
1662
+ }
1663
+
1664
+ // Affected resources (Resource / Type / Node / Value)
1665
+ let renderedBreakdownTable: boolean = false;
1666
+
1667
+ if (breakdown && breakdown.affectedResources.length > 0) {
1668
+ /*
1669
+ * K8s-parity render: drop zero-value rows, worst (highest)
1670
+ * first, top 10. Note that for availability metrics (pve_up)
1671
+ * zero-valued rows ARE the down resources — those still drive
1672
+ * alerting through the per-series criteria evaluation; this
1673
+ * table is supplementary context only.
1674
+ */
1675
+ const sortedResources: Array<ProxmoxAffectedResource> = [
1676
+ ...breakdown.affectedResources,
1677
+ ]
1678
+ .filter((r: ProxmoxAffectedResource) => {
1679
+ return r.metricValue > 0;
1680
+ })
1681
+ .sort((a: ProxmoxAffectedResource, b: ProxmoxAffectedResource) => {
1682
+ return b.metricValue - a.metricValue;
1683
+ });
1684
+
1685
+ /*
1686
+ * Skip the table when no row carries any identity label
1687
+ * (cluster-wide series) — it would add nothing.
1688
+ */
1689
+ const hasIdentity: boolean = sortedResources.some(
1690
+ (r: ProxmoxAffectedResource) => {
1691
+ return r.resourceId || r.resourceName || r.nodeName;
1692
+ },
1693
+ );
1694
+
1695
+ if (sortedResources.length > 0 && hasIdentity) {
1696
+ const resourcesToShow: Array<ProxmoxAffectedResource> =
1697
+ sortedResources.slice(0, 10);
1698
+
1699
+ const resourceLines: Array<string> = [];
1700
+ resourceLines.push(`| Resource | Type | Node | Value |`);
1701
+ resourceLines.push(`| --- | --- | --- | --- |`);
1702
+
1703
+ for (const resource of resourcesToShow) {
1704
+ let resourceCell: string = "-";
1705
+ if (resource.resourceName && resource.resourceId) {
1706
+ resourceCell = `\`${resource.resourceName}\` (\`${resource.resourceId}\`)`;
1707
+ } else if (resource.resourceId) {
1708
+ resourceCell = `\`${resource.resourceId}\``;
1709
+ } else if (resource.resourceName) {
1710
+ resourceCell = `\`${resource.resourceName}\``;
1711
+ }
1712
+
1713
+ const typeCell: string =
1714
+ resource.resourceType || resource.scope || "-";
1715
+ const nodeCell: string = resource.nodeName
1716
+ ? `\`${resource.nodeName}\``
1717
+ : "-";
1718
+
1719
+ resourceLines.push(
1720
+ `| ${resourceCell} | ${typeCell} | ${nodeCell} | **${resource.metricValue}** |`,
1721
+ );
1722
+ }
1723
+
1724
+ if (sortedResources.length > 10) {
1725
+ resourceLines.push(
1726
+ `\n*... and ${sortedResources.length - 10} more affected resources*`,
1727
+ );
1728
+ }
1729
+
1730
+ sections.push(
1731
+ `\n\n**Affected Resources** (${sortedResources.length} total)\n\n${resourceLines.join("\n")}`,
1732
+ );
1733
+ renderedBreakdownTable = true;
1734
+ }
1735
+ }
1736
+
1737
+ // Metric results summary (fallback context when no table rendered)
1738
+ if (
1739
+ !renderedBreakdownTable &&
1740
+ metricResponse.metricResult &&
1741
+ metricResponse.metricResult.length > 0
1742
+ ) {
1743
+ const resultDetails: Array<string> = [];
1744
+
1745
+ for (const result of metricResponse.metricResult) {
1746
+ if (result.data && result.data.length > 0) {
1747
+ resultDetails.push(
1748
+ `- ${result.data.length} metric data point(s) returned`,
1749
+ );
1750
+ }
1751
+ }
1752
+
1753
+ if (resultDetails.length > 0) {
1754
+ sections.push(`\n\n**Metric Summary**\n${resultDetails.join("\n")}`);
1755
+ }
1756
+ }
1757
+
1758
+ return sections.length > 0 ? sections.join("\n") : null;
1759
+ }
1760
+
1761
+ private static buildCephRootCauseContext(input: {
1762
+ dataToProcess: DataToProcess;
1763
+ monitorStep: MonitorStep;
1764
+ monitor: Monitor;
1765
+ }): string | null {
1766
+ const metricResponse: MetricMonitorResponse =
1767
+ input.dataToProcess as MetricMonitorResponse;
1768
+
1769
+ const breakdown: CephResourceBreakdown | undefined =
1770
+ metricResponse.cephResourceBreakdown;
1771
+
1772
+ const sections: Array<string> = [];
1773
+
1774
+ // Ceph cluster context
1775
+ const cephMonitor: MonitorStepCephMonitor | undefined =
1776
+ input.monitorStep.data?.cephMonitor;
1777
+
1778
+ if (cephMonitor || breakdown) {
1779
+ const clusterDetails: Array<string> = [];
1780
+ clusterDetails.push(
1781
+ `- Cluster: ${breakdown?.clusterName || cephMonitor?.clusterIdentifier || "Unknown"}`,
1782
+ );
1783
+
1784
+ if (breakdown) {
1785
+ clusterDetails.push(
1786
+ `- Metric: ${breakdown.metricFriendlyName} (\`${breakdown.metricName}\`)`,
1787
+ );
1788
+ } else if (
1789
+ cephMonitor &&
1790
+ cephMonitor.metricViewConfig?.queryConfigs?.length > 0 &&
1791
+ cephMonitor.metricViewConfig.queryConfigs[0]
1792
+ ) {
1793
+ const metricName: string = cephMonitor.metricViewConfig.queryConfigs[0]
1794
+ .metricQueryData?.filterData?.metricName as string;
1795
+ if (metricName) {
1796
+ clusterDetails.push(`- Metric: \`${metricName}\``);
1797
+ }
1798
+ }
1799
+
1800
+ if (cephMonitor?.resourceFilters?.osdId) {
1801
+ clusterDetails.push(
1802
+ `- OSD Filter: ${cephMonitor.resourceFilters.osdId}`,
1803
+ );
1804
+ }
1805
+
1806
+ if (cephMonitor?.resourceFilters?.poolId) {
1807
+ clusterDetails.push(
1808
+ `- Pool ID Filter: ${cephMonitor.resourceFilters.poolId}`,
1809
+ );
1810
+ }
1811
+
1812
+ sections.push(`**Ceph Cluster Details**\n${clusterDetails.join("\n")}`);
1813
+ }
1814
+
1815
+ // Affected resources (Daemon / Pool / Host / Value)
1816
+ let renderedBreakdownTable: boolean = false;
1817
+
1818
+ if (breakdown && breakdown.affectedResources.length > 0) {
1819
+ /*
1820
+ * K8s-parity render: drop zero-value rows, worst (highest)
1821
+ * first, top 10. Note that for availability metrics
1822
+ * (ceph_osd_up / ceph_osd_in / ceph_mon_quorum_status)
1823
+ * zero-valued rows ARE the down resources — those still drive
1824
+ * alerting through the per-series criteria evaluation; this
1825
+ * table is supplementary context only.
1826
+ */
1827
+ const sortedResources: Array<CephAffectedResource> = [
1828
+ ...breakdown.affectedResources,
1829
+ ]
1830
+ .filter((r: CephAffectedResource) => {
1831
+ return r.metricValue > 0;
1832
+ })
1833
+ .sort((a: CephAffectedResource, b: CephAffectedResource) => {
1834
+ return b.metricValue - a.metricValue;
1835
+ });
1836
+
1837
+ /*
1838
+ * Skip the table when no row carries any identity label
1839
+ * (cluster-wide series like ceph_health_status) — it would add
1840
+ * nothing.
1841
+ */
1842
+ const hasIdentity: boolean = sortedResources.some(
1843
+ (r: CephAffectedResource) => {
1844
+ return r.daemon || r.poolId || r.poolName || r.hostname;
1845
+ },
1846
+ );
1847
+
1848
+ if (sortedResources.length > 0 && hasIdentity) {
1849
+ const resourcesToShow: Array<CephAffectedResource> =
1850
+ sortedResources.slice(0, 10);
1851
+
1852
+ const resourceLines: Array<string> = [];
1853
+ resourceLines.push(`| Daemon | Pool | Host | Value |`);
1854
+ resourceLines.push(`| --- | --- | --- | --- |`);
1855
+
1856
+ for (const resource of resourcesToShow) {
1857
+ const daemonCell: string = resource.daemon
1858
+ ? `\`${resource.daemon}\``
1859
+ : "-";
1860
+
1861
+ let poolCell: string = "-";
1862
+ if (resource.poolName && resource.poolId) {
1863
+ poolCell = `\`${resource.poolName}\` (\`${resource.poolId}\`)`;
1864
+ } else if (resource.poolName) {
1865
+ poolCell = `\`${resource.poolName}\``;
1866
+ } else if (resource.poolId) {
1867
+ poolCell = `\`${resource.poolId}\``;
1868
+ }
1869
+
1870
+ const hostCell: string = resource.hostname
1871
+ ? `\`${resource.hostname}\``
1872
+ : "-";
1873
+
1874
+ resourceLines.push(
1875
+ `| ${daemonCell} | ${poolCell} | ${hostCell} | **${resource.metricValue}** |`,
1876
+ );
1877
+ }
1878
+
1879
+ if (sortedResources.length > 10) {
1880
+ resourceLines.push(
1881
+ `\n*... and ${sortedResources.length - 10} more affected resources*`,
1882
+ );
1883
+ }
1884
+
1885
+ sections.push(
1886
+ `\n\n**Affected Resources** (${sortedResources.length} total)\n\n${resourceLines.join("\n")}`,
1887
+ );
1888
+ renderedBreakdownTable = true;
1889
+ }
1890
+ }
1891
+
1892
+ // Metric results summary (fallback context when no table rendered)
1893
+ if (
1894
+ !renderedBreakdownTable &&
1895
+ metricResponse.metricResult &&
1896
+ metricResponse.metricResult.length > 0
1897
+ ) {
1898
+ const resultDetails: Array<string> = [];
1899
+
1900
+ for (const result of metricResponse.metricResult) {
1901
+ if (result.data && result.data.length > 0) {
1902
+ resultDetails.push(
1903
+ `- ${result.data.length} metric data point(s) returned`,
1904
+ );
1905
+ }
1906
+ }
1907
+
1908
+ if (resultDetails.length > 0) {
1909
+ sections.push(`\n\n**Metric Summary**\n${resultDetails.join("\n")}`);
1910
+ }
1911
+ }
1912
+
1913
+ return sections.length > 0 ? sections.join("\n") : null;
1914
+ }
1915
+
1576
1916
  private static buildKubernetesRootCauseAnalysis(input: {
1577
1917
  breakdown: KubernetesResourceBreakdown;
1578
1918
  topResource: KubernetesAffectedResource;