@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,423 @@
1
+ import AggregatedModel from "../../../Types/BaseDatabase/AggregatedModel";
2
+ import HeartbeatAvailabilityUtil, {
3
+ HEARTBEAT_INGEST_LAG_MS,
4
+ HeartbeatAvailabilityResult,
5
+ } from "../../../Utils/Telemetry/HeartbeatAvailability";
6
+ import { describe, expect, test } from "@jest/globals";
7
+
8
+ const MINUTE: number = 60_000;
9
+
10
+ /*
11
+ * All scenarios use a fixed wall clock and a 30-minute window ending
12
+ * at `now` — the Host overview page's default — unless stated
13
+ * otherwise. The server grid for a <=3h window is 1-minute buckets
14
+ * aligned to minute boundaries, so rows are minute-aligned here too.
15
+ */
16
+ const NOW: Date = new Date("2026-06-13T10:30:30.000Z");
17
+ const WINDOW_START: Date = new Date(NOW.getTime() - 30 * MINUTE);
18
+
19
+ function row(timestamp: Date, count: number = 2): AggregatedModel {
20
+ return { timestamp, value: count } as AggregatedModel;
21
+ }
22
+
23
+ function minuteRows(
24
+ from: Date,
25
+ minutes: Array<number>,
26
+ ): Array<AggregatedModel> {
27
+ const base: number = Math.floor(from.getTime() / MINUTE) * MINUTE;
28
+ return minutes.map((m: number): AggregatedModel => {
29
+ return row(new Date(base + m * MINUTE));
30
+ });
31
+ }
32
+
33
+ function build(
34
+ heartbeatData: Array<AggregatedModel>,
35
+ windowStart: Date = WINDOW_START,
36
+ windowEnd: Date = NOW,
37
+ now: Date = NOW,
38
+ ): HeartbeatAvailabilityResult {
39
+ return HeartbeatAvailabilityUtil.buildAvailabilitySeries({
40
+ heartbeatData,
41
+ windowStart,
42
+ windowEnd,
43
+ now,
44
+ });
45
+ }
46
+
47
+ function downPoints(result: HeartbeatAvailabilityResult): Array<number> {
48
+ return result.points
49
+ .filter((p: { x: Date; y: number }) => {
50
+ return p.y === 0;
51
+ })
52
+ .map((p: { x: Date; y: number }) => {
53
+ return p.x.getTime();
54
+ });
55
+ }
56
+
57
+ describe("HeartbeatAvailabilityUtil.buildAvailabilitySeries", () => {
58
+ test("healthy host with a heartbeat in every complete bucket is 100% with no down points", () => {
59
+ /*
60
+ * Window start 10:00:30 → first complete bucket is 10:01. Evaluable
61
+ * end is 10:29:30 (now - lag) → last evaluable-complete bucket is
62
+ * 10:28. Provide rows for every minute bucket in range.
63
+ */
64
+ const rows: Array<AggregatedModel> = minuteRows(
65
+ WINDOW_START,
66
+ Array.from({ length: 31 }, (_: unknown, i: number) => {
67
+ return i;
68
+ }),
69
+ );
70
+ const result: HeartbeatAvailabilityResult = build(rows);
71
+ expect(result.uptimePercent).toBe(100);
72
+ expect(downPoints(result)).toHaveLength(0);
73
+ expect(result.points.length).toBeGreaterThan(25);
74
+ });
75
+
76
+ test("silent in-progress trailing bucket is excluded, not rendered as down", () => {
77
+ /*
78
+ * Rows for every bucket EXCEPT the in-progress one (10:30) and the
79
+ * lag-shadowed one (10:29). The old implementation rendered those
80
+ * as 0% and the uptime badge flapped to ~96% on every refresh.
81
+ */
82
+ const rows: Array<AggregatedModel> = minuteRows(
83
+ WINDOW_START,
84
+ Array.from({ length: 29 }, (_: unknown, i: number) => {
85
+ return i;
86
+ }),
87
+ );
88
+ const result: HeartbeatAvailabilityResult = build(rows);
89
+ expect(result.uptimePercent).toBe(100);
90
+ expect(downPoints(result)).toHaveLength(0);
91
+ });
92
+
93
+ test("present in-progress trailing bucket still proves UP", () => {
94
+ const allMinutes: Array<number> = Array.from(
95
+ { length: 31 },
96
+ (_: unknown, i: number) => {
97
+ return i;
98
+ },
99
+ );
100
+ const rows: Array<AggregatedModel> = minuteRows(WINDOW_START, allMinutes);
101
+ const withPartial: HeartbeatAvailabilityResult = build(rows);
102
+ const withoutPartial: HeartbeatAvailabilityResult = build(
103
+ rows.slice(0, -2),
104
+ );
105
+ // The two partial-bucket rows add points to the series.
106
+ expect(withPartial.points.length).toBeGreaterThan(
107
+ withoutPartial.points.length,
108
+ );
109
+ expect(withPartial.uptimePercent).toBe(100);
110
+ });
111
+
112
+ test("a single missing bucket (export jitter) is bridged to UP", () => {
113
+ const minutes: Array<number> = Array.from(
114
+ { length: 31 },
115
+ (_: unknown, i: number) => {
116
+ return i;
117
+ },
118
+ ).filter((m: number) => {
119
+ return m !== 15;
120
+ });
121
+ const result: HeartbeatAvailabilityResult = build(
122
+ minuteRows(WINDOW_START, minutes),
123
+ );
124
+ expect(result.uptimePercent).toBe(100);
125
+ expect(downPoints(result)).toHaveLength(0);
126
+ });
127
+
128
+ test("two consecutive missing buckets render as downtime", () => {
129
+ const minutes: Array<number> = Array.from(
130
+ { length: 31 },
131
+ (_: unknown, i: number) => {
132
+ return i;
133
+ },
134
+ ).filter((m: number) => {
135
+ return m !== 15 && m !== 16;
136
+ });
137
+ const result: HeartbeatAvailabilityResult = build(
138
+ minuteRows(WINDOW_START, minutes),
139
+ );
140
+ expect(downPoints(result)).toHaveLength(2);
141
+ expect(result.uptimePercent).not.toBeNull();
142
+ expect(result.uptimePercent!).toBeLessThan(100);
143
+ });
144
+
145
+ test("a long outage in the middle of the window is fully reported", () => {
146
+ // Up 10:01-10:10, silent 10:11-10:20, up again 10:21-10:28.
147
+ const minutes: Array<number> = Array.from(
148
+ { length: 31 },
149
+ (_: unknown, i: number) => {
150
+ return i;
151
+ },
152
+ ).filter((m: number) => {
153
+ return m <= 10 || m >= 21;
154
+ });
155
+ const result: HeartbeatAvailabilityResult = build(
156
+ minuteRows(WINDOW_START, minutes),
157
+ );
158
+ expect(downPoints(result)).toHaveLength(10);
159
+ });
160
+
161
+ test("host completely silent for the whole window reports ~0%", () => {
162
+ const result: HeartbeatAvailabilityResult = build([]);
163
+ expect(result.uptimePercent).toBe(0);
164
+ expect(result.points.length).toBeGreaterThan(25);
165
+ expect(
166
+ result.points.every((p: { x: Date; y: number }) => {
167
+ return p.y === 0;
168
+ }),
169
+ ).toBe(true);
170
+ });
171
+
172
+ test("queue-lag scenario: bucket sizing comes from the window, not from data gaps", () => {
173
+ /*
174
+ * Heartbeats with a 2-minute hole (ingest backlog collapsed two
175
+ * batches into one minute). The old smallest-gap inference could
176
+ * derive a wrong bucket size from patterns like this and knock
177
+ * genuine rows off the reconstructed grid; with the canonical
178
+ * window-derived size the present rows all stay on-grid.
179
+ */
180
+ const minutes: Array<number> = [
181
+ 1, 2, 3, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28,
182
+ ];
183
+ const result: HeartbeatAvailabilityResult = build(
184
+ minuteRows(WINDOW_START, minutes),
185
+ );
186
+ /*
187
+ * Every provided row lands on the grid as UP (alternating gaps are
188
+ * all single-bucket → bridged), and minute 5's neighbors 4 and 6
189
+ * bridge it too.
190
+ */
191
+ expect(result.uptimePercent).toBe(100);
192
+ });
193
+
194
+ test("rows snapped within half a bucket of a slot still register", () => {
195
+ /*
196
+ * Simulate a serialization offset: every row shifted +20s off the
197
+ * minute boundary. Exact-match would lose all of them.
198
+ */
199
+ const base: number =
200
+ Math.floor(WINDOW_START.getTime() / MINUTE) * MINUTE + 20_000;
201
+ const rows: Array<AggregatedModel> = Array.from(
202
+ { length: 31 },
203
+ (_: unknown, i: number): AggregatedModel => {
204
+ return row(new Date(base + i * MINUTE));
205
+ },
206
+ );
207
+ const result: HeartbeatAvailabilityResult = build(rows);
208
+ expect(result.uptimePercent).toBe(100);
209
+ expect(downPoints(result)).toHaveLength(0);
210
+ });
211
+
212
+ test("historical window (end far in the past) has no lag exclusion", () => {
213
+ const windowEnd: Date = new Date(NOW.getTime() - 24 * 60 * MINUTE);
214
+ const windowStart: Date = new Date(windowEnd.getTime() - 30 * MINUTE);
215
+ const minutes: Array<number> = Array.from(
216
+ { length: 31 },
217
+ (_: unknown, i: number) => {
218
+ return i;
219
+ },
220
+ ).filter((m: number) => {
221
+ /*
222
+ * Silent for the final three buckets of the window — a real
223
+ * outage at the window's edge must not be masked by lag logic
224
+ * because the window closed long ago.
225
+ */
226
+ return m < 28;
227
+ });
228
+ const result: HeartbeatAvailabilityResult = build(
229
+ minuteRows(windowStart, minutes),
230
+ windowStart,
231
+ windowEnd,
232
+ NOW,
233
+ );
234
+ expect(downPoints(result).length).toBeGreaterThanOrEqual(2);
235
+ });
236
+
237
+ test("hour buckets are used for windows over 3 hours", () => {
238
+ const windowEnd: Date = NOW;
239
+ const windowStart: Date = new Date(NOW.getTime() - 24 * 60 * MINUTE);
240
+ const hourMs: number = 60 * MINUTE;
241
+ const base: number = Math.floor(windowStart.getTime() / hourMs) * hourMs;
242
+ const rows: Array<AggregatedModel> = Array.from(
243
+ { length: 25 },
244
+ (_: unknown, i: number): AggregatedModel => {
245
+ return row(new Date(base + i * hourMs));
246
+ },
247
+ );
248
+ const result: HeartbeatAvailabilityResult = build(
249
+ rows,
250
+ windowStart,
251
+ windowEnd,
252
+ NOW,
253
+ );
254
+ expect(result.uptimePercent).toBe(100);
255
+ // ~24 hour buckets, not ~1440 minute buckets.
256
+ expect(result.points.length).toBeLessThanOrEqual(26);
257
+ });
258
+
259
+ test("returns null uptime when nothing is evaluable", () => {
260
+ /*
261
+ * Window entirely inside the lag shadow: started one lag-width
262
+ * ago and ends now, with no heartbeat rows.
263
+ */
264
+ const windowStart: Date = new Date(NOW.getTime() - HEARTBEAT_INGEST_LAG_MS);
265
+ const result: HeartbeatAvailabilityResult = build(
266
+ [],
267
+ windowStart,
268
+ NOW,
269
+ NOW,
270
+ );
271
+ expect(result.uptimePercent).toBeNull();
272
+ expect(result.points).toHaveLength(0);
273
+ });
274
+
275
+ test("invalid window returns empty result", () => {
276
+ const result: HeartbeatAvailabilityResult = build([], NOW, NOW, NOW);
277
+ expect(result.uptimePercent).toBeNull();
278
+ expect(result.points).toHaveLength(0);
279
+ });
280
+
281
+ test("rows with zero count are ignored", () => {
282
+ const zeroRows: Array<AggregatedModel> = minuteRows(
283
+ WINDOW_START,
284
+ Array.from({ length: 31 }, (_: unknown, i: number) => {
285
+ return i;
286
+ }),
287
+ ).map((r: AggregatedModel): AggregatedModel => {
288
+ return { ...r, value: 0 } as AggregatedModel;
289
+ });
290
+ const result: HeartbeatAvailabilityResult = build(zeroRows);
291
+ expect(result.uptimePercent).toBe(0);
292
+ });
293
+
294
+ test("reads MV-aliased `time` field when `timestamp` is absent", () => {
295
+ const base: number = Math.floor(WINDOW_START.getTime() / MINUTE) * MINUTE;
296
+ const rows: Array<AggregatedModel> = Array.from(
297
+ { length: 31 },
298
+ (_: unknown, i: number): AggregatedModel => {
299
+ return {
300
+ time: new Date(base + i * MINUTE).toISOString(),
301
+ value: 1,
302
+ } as unknown as AggregatedModel;
303
+ },
304
+ );
305
+ const result: HeartbeatAvailabilityResult = build(rows);
306
+ expect(result.uptimePercent).toBe(100);
307
+ });
308
+
309
+ test("no bridging at Day buckets: one fully missing day is real downtime", () => {
310
+ /*
311
+ * 10-day window → Day buckets. A whole day of silence is dozens
312
+ * of missed heartbeats — bridging it away (as the Minute-grid
313
+ * hysteresis would) must not happen at coarse widths.
314
+ */
315
+ const DAY: number = 24 * 60 * MINUTE;
316
+ const windowStart: Date = new Date(NOW.getTime() - 10 * DAY);
317
+ const base: number = Math.floor(windowStart.getTime() / DAY) * DAY;
318
+ const rows: Array<AggregatedModel> = Array.from(
319
+ { length: 11 },
320
+ (_: unknown, i: number): AggregatedModel => {
321
+ return row(new Date(base + i * DAY));
322
+ },
323
+ ).filter((_: AggregatedModel, i: number) => {
324
+ // Day index 5 is mid-window with up neighbors on both sides.
325
+ return i !== 5;
326
+ });
327
+ const result: HeartbeatAvailabilityResult = build(
328
+ rows,
329
+ windowStart,
330
+ NOW,
331
+ NOW,
332
+ );
333
+ expect(downPoints(result)).toHaveLength(1);
334
+ expect(result.uptimePercent).not.toBeNull();
335
+ expect(result.uptimePercent!).toBeLessThan(100);
336
+ });
337
+
338
+ test("jitter miss in the first complete bucket bridges off the excluded leading bucket", () => {
339
+ /*
340
+ * The leading partial bucket can never return a row (the query
341
+ * filters time >= windowStart), so the first complete bucket has
342
+ * no up neighbor on its left. A single jitter miss there must
343
+ * still bridge — otherwise every missed beat produces a ~1-minute
344
+ * false-down dip as it transits this position on the sliding
345
+ * auto-refresh window.
346
+ */
347
+ const minutes: Array<number> = Array.from(
348
+ { length: 29 },
349
+ (_: unknown, i: number) => {
350
+ return i + 2;
351
+ },
352
+ );
353
+ const result: HeartbeatAvailabilityResult = build(
354
+ minuteRows(WINDOW_START, minutes),
355
+ );
356
+ expect(downPoints(result)).toHaveLength(0);
357
+ expect(result.uptimePercent).toBe(100);
358
+ });
359
+
360
+ test("jitter miss adjacent to the trailing lag shadow bridges off its single up neighbor", () => {
361
+ /*
362
+ * Rows for minutes 1-27; miss at 28; 29/30 still in the ingest
363
+ * queue (excluded). The miss has up on the left and unknown on the
364
+ * right — bridge, don't flap.
365
+ */
366
+ const minutes: Array<number> = Array.from(
367
+ { length: 27 },
368
+ (_: unknown, i: number) => {
369
+ return i + 1;
370
+ },
371
+ );
372
+ const result: HeartbeatAvailabilityResult = build(
373
+ minuteRows(WINDOW_START, minutes),
374
+ );
375
+ expect(downPoints(result)).toHaveLength(0);
376
+ expect(result.uptimePercent).toBe(100);
377
+ });
378
+
379
+ test("a silent bucket with no up witness on either side stays down", () => {
380
+ /*
381
+ * 2-minute window ending now with no rows: the single evaluable
382
+ * bucket sits between the excluded leading and trailing buckets.
383
+ * Excluded neighbors are wildcards, not witnesses — with no up
384
+ * neighbor at all the bucket must render down.
385
+ */
386
+ const windowStart: Date = new Date(NOW.getTime() - 2 * MINUTE);
387
+ const result: HeartbeatAvailabilityResult = build(
388
+ [],
389
+ windowStart,
390
+ NOW,
391
+ NOW,
392
+ );
393
+ expect(result.uptimePercent).toBe(0);
394
+ expect(downPoints(result).length).toBeGreaterThanOrEqual(1);
395
+ });
396
+
397
+ test("bucket-aligned window start: first-bucket jitter miss still bridges", () => {
398
+ /*
399
+ * When windowStart lands exactly on a bucket boundary the grid has
400
+ * no excluded leading slot — the first slot's left neighbor is
401
+ * simply out of grid. Out-of-grid must count as a wildcard (like
402
+ * excluded), so a single jitter miss in slot 0 with an up
403
+ * right-neighbor bridges instead of rendering a false down.
404
+ */
405
+ const windowStart: Date = new Date(
406
+ Math.floor((NOW.getTime() - 30 * MINUTE) / MINUTE) * MINUTE,
407
+ );
408
+ const minutes: Array<number> = Array.from(
409
+ { length: 30 },
410
+ (_: unknown, i: number) => {
411
+ return i + 1;
412
+ },
413
+ );
414
+ const result: HeartbeatAvailabilityResult = build(
415
+ minuteRows(windowStart, minutes),
416
+ windowStart,
417
+ NOW,
418
+ NOW,
419
+ );
420
+ expect(downPoints(result)).toHaveLength(0);
421
+ expect(result.uptimePercent).toBe(100);
422
+ });
423
+ });
@@ -0,0 +1,74 @@
1
+ import AggregationInterval from "./AggregationInterval";
2
+ import OneUptimeDate from "../Date";
3
+
4
+ /*
5
+ * Single source of truth for "which time-bucket size does the
6
+ * analytics aggregate API use for a given query window". The server
7
+ * statement generator (AggregateUtil in
8
+ * Common/Server/Types/AnalyticsDatabase/AggregateBy.ts) delegates
9
+ * here when compiling `toStartOfInterval(...)`, and browser code that
10
+ * needs to reconstruct the server's bucket grid client-side (e.g. the
11
+ * heartbeat availability charts, which must synthesize the empty
12
+ * buckets ClickHouse never returns rows for) imports the same
13
+ * function — so the two sides can never drift apart.
14
+ */
15
+ export class AggregationIntervalUtil {
16
+ public static getAggregationIntervalForWindow(data: {
17
+ startDate: Date;
18
+ endDate: Date;
19
+ }): AggregationInterval {
20
+ const startDate: Date = OneUptimeDate.fromString(data.startDate);
21
+ const endDate: Date = OneUptimeDate.fromString(data.endDate);
22
+
23
+ const diff: number = endDate.getTime() - startDate.getTime();
24
+
25
+ if (diff <= 1000 * 60 * 60 * 3) {
26
+ // if less than 3 hours, then get minute precision
27
+ return AggregationInterval.Minute;
28
+ } else if (diff <= 1000 * 60 * 60 * 24 * 7) {
29
+ // 7 days
30
+ return AggregationInterval.Hour;
31
+ } else if (diff <= 1000 * 60 * 60 * 24 * 7 * 6) {
32
+ // 6 weeks
33
+ return AggregationInterval.Day;
34
+ } else if (diff <= 1000 * 60 * 60 * 24 * 30 * 6) {
35
+ // 6 months
36
+ return AggregationInterval.Week;
37
+ } else if (diff <= 1000 * 60 * 60 * 24 * 365 * 6) {
38
+ // 6 years
39
+ return AggregationInterval.Month;
40
+ }
41
+ return AggregationInterval.Year;
42
+ }
43
+
44
+ /*
45
+ * Nominal bucket width in milliseconds. Month and Year are
46
+ * calendar-variable in ClickHouse (`toStartOfInterval` snaps to
47
+ * calendar boundaries), so their values here are approximations —
48
+ * callers that walk a fixed-step grid at those widths must match
49
+ * rows to grid slots with tolerance (nearest slot), not by exact
50
+ * timestamp equality.
51
+ */
52
+ public static getAggregationIntervalMs(
53
+ interval: AggregationInterval,
54
+ ): number {
55
+ switch (interval) {
56
+ case AggregationInterval.Minute:
57
+ return 1000 * 60;
58
+ case AggregationInterval.Hour:
59
+ return 1000 * 60 * 60;
60
+ case AggregationInterval.Day:
61
+ return 1000 * 60 * 60 * 24;
62
+ case AggregationInterval.Week:
63
+ return 1000 * 60 * 60 * 24 * 7;
64
+ case AggregationInterval.Month:
65
+ return 1000 * 60 * 60 * 24 * 30;
66
+ case AggregationInterval.Year:
67
+ return 1000 * 60 * 60 * 24 * 365;
68
+ default:
69
+ return 1000 * 60;
70
+ }
71
+ }
72
+ }
73
+
74
+ export default AggregationIntervalUtil;
@@ -24,6 +24,10 @@ enum DashboardComponentType {
24
24
  DockerNetworkList = `DockerNetworkList`,
25
25
  DockerVolumeList = `DockerVolumeList`,
26
26
  HostList = `HostList`,
27
+ ProxmoxNodeList = `ProxmoxNodeList`,
28
+ ProxmoxGuestList = `ProxmoxGuestList`,
29
+ CephOsdList = `CephOsdList`,
30
+ CephPoolList = `CephPoolList`,
27
31
  }
28
32
 
29
33
  export default DashboardComponentType;
@@ -30,6 +30,8 @@ export enum EntityFilterModelType {
30
30
  Label = "Label",
31
31
  KubernetesCluster = "KubernetesCluster",
32
32
  DockerHost = "DockerHost",
33
+ ProxmoxCluster = "ProxmoxCluster",
34
+ CephCluster = "CephCluster",
33
35
  }
34
36
 
35
37
  export interface ComponentArgumentSection {
@@ -0,0 +1,15 @@
1
+ import ObjectID from "../../ObjectID";
2
+ import DashboardComponentType from "../DashboardComponentType";
3
+ import BaseComponent from "./DashboardBaseComponent";
4
+
5
+ export default interface DashboardCephOsdListComponent extends BaseComponent {
6
+ componentType: DashboardComponentType.CephOsdList;
7
+ componentId: ObjectID;
8
+ arguments: {
9
+ title?: string | undefined;
10
+ maxRows?: number | undefined;
11
+ viewMode?: "list" | "honeycomb" | undefined;
12
+ cephClusterIds?: Array<string> | undefined;
13
+ stateFilter?: string | undefined;
14
+ };
15
+ }
@@ -0,0 +1,14 @@
1
+ import ObjectID from "../../ObjectID";
2
+ import DashboardComponentType from "../DashboardComponentType";
3
+ import BaseComponent from "./DashboardBaseComponent";
4
+
5
+ export default interface DashboardCephPoolListComponent extends BaseComponent {
6
+ componentType: DashboardComponentType.CephPoolList;
7
+ componentId: ObjectID;
8
+ arguments: {
9
+ title?: string | undefined;
10
+ maxRows?: number | undefined;
11
+ viewMode?: "list" | "honeycomb" | undefined;
12
+ cephClusterIds?: Array<string> | undefined;
13
+ };
14
+ }
@@ -0,0 +1,17 @@
1
+ import ObjectID from "../../ObjectID";
2
+ import DashboardComponentType from "../DashboardComponentType";
3
+ import BaseComponent from "./DashboardBaseComponent";
4
+
5
+ export default interface DashboardProxmoxGuestListComponent
6
+ extends BaseComponent {
7
+ componentType: DashboardComponentType.ProxmoxGuestList;
8
+ componentId: ObjectID;
9
+ arguments: {
10
+ title?: string | undefined;
11
+ maxRows?: number | undefined;
12
+ viewMode?: "list" | "honeycomb" | undefined;
13
+ proxmoxClusterIds?: Array<string> | undefined;
14
+ guestTypeFilter?: string | undefined;
15
+ statusFilter?: string | undefined;
16
+ };
17
+ }
@@ -0,0 +1,16 @@
1
+ import ObjectID from "../../ObjectID";
2
+ import DashboardComponentType from "../DashboardComponentType";
3
+ import BaseComponent from "./DashboardBaseComponent";
4
+
5
+ export default interface DashboardProxmoxNodeListComponent
6
+ extends BaseComponent {
7
+ componentType: DashboardComponentType.ProxmoxNodeList;
8
+ componentId: ObjectID;
9
+ arguments: {
10
+ title?: string | undefined;
11
+ maxRows?: number | undefined;
12
+ viewMode?: "list" | "honeycomb" | undefined;
13
+ proxmoxClusterIds?: Array<string> | undefined;
14
+ statusFilter?: string | undefined;
15
+ };
16
+ }