@oneuptime/common 11.0.1 → 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.
- package/Models/DatabaseModels/Alert.ts +110 -0
- package/Models/DatabaseModels/CephCluster.ts +964 -0
- package/Models/DatabaseModels/CephClusterLabelRule.ts +514 -0
- package/Models/DatabaseModels/CephClusterOwnerRule.ts +596 -0
- package/Models/DatabaseModels/CephClusterOwnerTeam.ts +487 -0
- package/Models/DatabaseModels/CephClusterOwnerUser.ts +486 -0
- package/Models/DatabaseModels/CephResource.ts +809 -0
- package/Models/DatabaseModels/Host.ts +64 -0
- package/Models/DatabaseModels/Incident.ts +110 -0
- package/Models/DatabaseModels/Index.ts +24 -0
- package/Models/DatabaseModels/ProxmoxCluster.ts +943 -0
- package/Models/DatabaseModels/ProxmoxClusterLabelRule.ts +514 -0
- package/Models/DatabaseModels/ProxmoxClusterOwnerRule.ts +596 -0
- package/Models/DatabaseModels/ProxmoxClusterOwnerTeam.ts +487 -0
- package/Models/DatabaseModels/ProxmoxClusterOwnerUser.ts +486 -0
- package/Models/DatabaseModels/ProxmoxResource.ts +726 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +110 -0
- package/Server/API/BillingInvoiceAPI.ts +47 -7
- package/Server/API/CephResourceAPI.ts +134 -0
- package/Server/API/DashboardAPI.ts +46 -0
- package/Server/API/ProjectAPI.ts +15 -0
- package/Server/API/ProxmoxResourceAPI.ts +132 -0
- package/Server/API/ResellerPlanAPI.ts +17 -0
- package/Server/Infrastructure/GlobalCache.ts +8 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.ts +163 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.ts +211 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.ts +590 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.ts +64 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Infrastructure/Redis.ts +40 -12
- package/Server/Services/AnalyticsDatabaseService.ts +1 -1
- package/Server/Services/BillingService.ts +109 -21
- package/Server/Services/CephClusterLabelRuleEngineService.ts +200 -0
- package/Server/Services/CephClusterLabelRuleService.ts +14 -0
- package/Server/Services/CephClusterOwnerRuleEngineService.ts +218 -0
- package/Server/Services/CephClusterOwnerRuleService.ts +14 -0
- package/Server/Services/CephClusterOwnerTeamService.ts +10 -0
- package/Server/Services/CephClusterOwnerUserService.ts +10 -0
- package/Server/Services/CephClusterService.ts +401 -0
- package/Server/Services/CephResourceService.ts +383 -0
- package/Server/Services/CloudResourceService.ts +11 -3
- package/Server/Services/DockerHostService.ts +11 -3
- package/Server/Services/ExceptionAggregationService.ts +2 -0
- package/Server/Services/HostService.ts +11 -3
- package/Server/Services/Index.ts +24 -0
- package/Server/Services/KubernetesClusterService.ts +11 -3
- package/Server/Services/LogAggregationService.ts +2 -0
- package/Server/Services/MetricAggregationService.ts +2 -0
- package/Server/Services/OpenTelemetryIngestService.ts +36 -0
- package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +204 -0
- package/Server/Services/ProxmoxClusterLabelRuleService.ts +14 -0
- package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +222 -0
- package/Server/Services/ProxmoxClusterOwnerRuleService.ts +14 -0
- package/Server/Services/ProxmoxClusterOwnerTeamService.ts +10 -0
- package/Server/Services/ProxmoxClusterOwnerUserService.ts +10 -0
- package/Server/Services/ProxmoxClusterService.ts +382 -0
- package/Server/Services/ProxmoxResourceService.ts +404 -0
- package/Server/Services/RumApplicationService.ts +11 -3
- package/Server/Services/ServerlessFunctionService.ts +11 -3
- package/Server/Services/TelemetryUsageBillingService.ts +41 -3
- package/Server/Services/TraceAggregationService.ts +2 -0
- package/Server/Types/AnalyticsDatabase/AggregateBy.ts +8 -23
- package/Server/Utils/Monitor/MonitorAlert.ts +45 -0
- package/Server/Utils/Monitor/MonitorClusterContext.ts +129 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +344 -4
- package/Server/Utils/Monitor/MonitorIncident.ts +130 -7
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +39 -6
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +3 -1
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +33 -0
- package/Server/Utils/Profiling.ts +37 -2
- package/Server/Utils/Telemetry/EntityRegistry.ts +4 -0
- package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +1096 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +85 -0
- package/Server/Utils/Telemetry.ts +8 -19
- package/Tests/Server/API/BillingInvoiceAPI.test.ts +194 -0
- package/Tests/Server/API/ProjectAPI.test.ts +91 -0
- package/Tests/Server/API/ResellerPlanAPI.test.ts +207 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +100 -0
- package/Tests/Server/Services/BillingService.test.ts +323 -0
- package/Tests/Server/Services/CephResourceService.test.ts +264 -0
- package/Tests/Server/Services/ProxmoxResourceService.test.ts +326 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +322 -0
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +13 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +879 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +196 -0
- package/Tests/Types/Monitor/CephAlertTemplates.test.ts +1231 -0
- package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +732 -0
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +49 -0
- package/Tests/Utils/Telemetry/HeartbeatAvailability.test.ts +423 -0
- package/Types/BaseDatabase/AggregationIntervalUtil.ts +74 -0
- package/Types/Dashboard/DashboardComponentType.ts +4 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +2 -0
- package/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.ts +15 -0
- package/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.ts +14 -0
- package/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.ts +17 -0
- package/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.ts +16 -0
- package/Types/Dashboard/DashboardTemplates.ts +446 -0
- package/Types/Icon/IconProp.ts +2 -0
- package/Types/Monitor/CephAlertTemplates.ts +1647 -0
- package/Types/Monitor/CephMetricCatalog.ts +409 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +44 -0
- package/Types/Monitor/MonitorStep.ts +64 -0
- package/Types/Monitor/MonitorStepCephMonitor.ts +57 -0
- package/Types/Monitor/MonitorStepProxmoxMonitor.ts +81 -0
- package/Types/Monitor/MonitorType.ts +29 -1
- package/Types/Monitor/ProxmoxAlertTemplates.ts +899 -0
- package/Types/Monitor/ProxmoxMetricCatalog.ts +382 -0
- package/Types/Permission.ts +464 -0
- package/Types/Telemetry/EntityType.ts +11 -0
- package/Types/Telemetry/ServiceType.ts +2 -0
- package/UI/Components/Icon/Icon.tsx +84 -0
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +9 -5
- package/UI/Utils/Telemetry/Telemetry.ts +16 -21
- package/UI/Utils/TelemetryService.ts +7 -3
- package/Utils/Dashboard/Components/DashboardCephOsdListComponent.ts +63 -0
- package/Utils/Dashboard/Components/DashboardCephPoolListComponent.ts +32 -0
- package/Utils/Dashboard/Components/DashboardCephResourceListShared.ts +61 -0
- package/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.ts +69 -0
- package/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.ts +55 -0
- package/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.ts +61 -0
- package/Utils/Dashboard/Components/Index.ts +28 -0
- package/Utils/Telemetry/EntityKey.ts +35 -0
- package/Utils/Telemetry/EntityRelationship.ts +6 -0
- package/Utils/Telemetry/HeartbeatAvailability.ts +262 -0
- package/build/dist/Models/DatabaseModels/Alert.js +108 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +992 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -0
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js +503 -0
- package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js +502 -0
- package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/CephResource.js +846 -0
- package/build/dist/Models/DatabaseModels/CephResource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Host.js +63 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +108 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +24 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +967 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js +503 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js +502 -0
- package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js +761 -0
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +108 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Server/API/BillingInvoiceAPI.js +35 -5
- package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
- package/build/dist/Server/API/CephResourceAPI.js +98 -0
- package/build/dist/Server/API/CephResourceAPI.js.map +1 -0
- package/build/dist/Server/API/DashboardAPI.js +46 -0
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +11 -0
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/ProxmoxResourceAPI.js +95 -0
- package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -0
- package/build/dist/Server/API/ResellerPlanAPI.js +17 -3
- package/build/dist/Server/API/ResellerPlanAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +7 -2
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js +76 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js +108 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js +253 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js +43 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Redis.js +31 -8
- package/build/dist/Server/Infrastructure/Redis.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +85 -23
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +166 -0
- package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterLabelRuleService.js +13 -0
- package/build/dist/Server/Services/CephClusterLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +186 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/CephClusterOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterOwnerUserService.js +9 -0
- package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/CephClusterService.js +353 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -0
- package/build/dist/Server/Services/CephResourceService.js +257 -0
- package/build/dist/Server/Services/CephResourceService.js.map +1 -0
- package/build/dist/Server/Services/CloudResourceService.js +10 -2
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +10 -2
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +2 -0
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +10 -2
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +24 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +10 -2
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +2 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +2 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +37 -7
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +166 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js +13 -0
- package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +186 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +9 -0
- package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js +337 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -0
- package/build/dist/Server/Services/ProxmoxResourceService.js +285 -0
- package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -0
- package/build/dist/Server/Services/RumApplicationService.js +10 -2
- package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionService.js +10 -2
- package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +30 -3
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +2 -0
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +8 -25
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +36 -0
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +90 -0
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +228 -4
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +103 -8
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +23 -6
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +3 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +23 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Profiling.js +24 -3
- package/build/dist/Server/Utils/Profiling.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +854 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +62 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +8 -10
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +69 -0
- package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +4 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +394 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Icon/IconProp.js +2 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Monitor/CephAlertTemplates.js +1379 -0
- package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/CephMetricCatalog.js +353 -0
- package/build/dist/Types/Monitor/CephMetricCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStep.js +46 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepCephMonitor.js +34 -0
- package/build/dist/Types/Monitor/MonitorStepCephMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js +36 -0
- package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +27 -1
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +743 -0
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js +320 -0
- package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js.map +1 -0
- package/build/dist/Types/Permission.js +408 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +11 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +2 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +33 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +5 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/Telemetry.js +11 -10
- package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +5 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js +50 -0
- package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js +27 -0
- package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js +46 -0
- package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js +55 -0
- package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js +42 -0
- package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js +46 -0
- package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityKey.js +27 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +3 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/build/dist/Utils/Telemetry/HeartbeatAvailability.js +174 -0
- package/build/dist/Utils/Telemetry/HeartbeatAvailability.js.map +1 -0
- package/package.json +29 -21
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
import DatabaseService from "./DatabaseService";
|
|
2
|
+
import Model from "../../Models/DatabaseModels/ProxmoxResource";
|
|
3
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
4
|
+
import ObjectID from "../../Types/ObjectID";
|
|
5
|
+
import OneUptimeDate from "../../Types/Date";
|
|
6
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
7
|
+
import logger from "../Utils/Logger";
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* ------------------------------------------------------------------
|
|
11
|
+
* ProxmoxResourceService
|
|
12
|
+
*
|
|
13
|
+
* Writes and reads the Proxmox inventory table populated by the
|
|
14
|
+
* telemetry ingest path. Callers are either:
|
|
15
|
+
* - OtelMetricsIngestService (bulkUpsert + bulkUpdateLatestMetrics,
|
|
16
|
+
* from the pve_* snapshot scan in processMetricsAsync)
|
|
17
|
+
* - CleanupStaleResources worker (deleteStaleForCluster)
|
|
18
|
+
* - ProxmoxResourceAPI / the dashboard pages (reads via the
|
|
19
|
+
* inherited DatabaseService CRUD)
|
|
20
|
+
*
|
|
21
|
+
* Identity + status and the latest-metric mirror both arrive on the
|
|
22
|
+
* same metric scrape (unlike K8s, which needs a separate k8sobjects
|
|
23
|
+
* log stream for identity), so both writes happen in the same flush.
|
|
24
|
+
*
|
|
25
|
+
* ------------------------------------------------------------------
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
export interface ParsedProxmoxResource {
|
|
29
|
+
kind: string; // Node | Guest | Storage
|
|
30
|
+
externalId: string; // raw pve `id` label, e.g. node/pve1, qemu/100
|
|
31
|
+
name: string | null;
|
|
32
|
+
vmid: number | null;
|
|
33
|
+
guestType: string | null; // qemu | lxc
|
|
34
|
+
parentNodeName: string | null;
|
|
35
|
+
isUp: boolean | null;
|
|
36
|
+
haState: string | null;
|
|
37
|
+
onboot: boolean | null;
|
|
38
|
+
/*
|
|
39
|
+
* WI-24 backup coverage: true = covered by at least one backup job,
|
|
40
|
+
* false = a pve_not_backed_up_info series carried this guest's id,
|
|
41
|
+
* null = batch lacked the backup-info collector output (keeps the
|
|
42
|
+
* last-known value via COALESCE) or non-Guest kind.
|
|
43
|
+
*/
|
|
44
|
+
isBackedUp: boolean | null;
|
|
45
|
+
uptimeSeconds: number | null;
|
|
46
|
+
lastSeenAt: Date;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface ProxmoxResourceLatestMetric {
|
|
50
|
+
kind: string;
|
|
51
|
+
externalId: string;
|
|
52
|
+
cpuPercent: number | null;
|
|
53
|
+
memoryBytes: number | null;
|
|
54
|
+
maxMemoryBytes: number | null;
|
|
55
|
+
memoryPercent: number | null;
|
|
56
|
+
diskBytes: number | null;
|
|
57
|
+
maxDiskBytes: number | null;
|
|
58
|
+
observedAt: Date;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface ProxmoxInventorySummary {
|
|
62
|
+
countsByKind: Record<string, number>;
|
|
63
|
+
nodeOnlineCount: number;
|
|
64
|
+
guestRunningCount: number;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const UPSERT_BATCH_SIZE: number = 500;
|
|
68
|
+
const STALE_DELETE_WARN_THRESHOLD: number = 100;
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
* Column order used by bulkUpsert() and its generated parameter tuples.
|
|
72
|
+
* Keep this and the INSERT column list in perfect sync.
|
|
73
|
+
*/
|
|
74
|
+
const UPSERT_COLUMNS: Array<string> = [
|
|
75
|
+
"projectId",
|
|
76
|
+
"proxmoxClusterId",
|
|
77
|
+
"kind",
|
|
78
|
+
"externalId",
|
|
79
|
+
"name",
|
|
80
|
+
"vmid",
|
|
81
|
+
"guestType",
|
|
82
|
+
"parentNodeName",
|
|
83
|
+
"isUp",
|
|
84
|
+
"haState",
|
|
85
|
+
"onboot",
|
|
86
|
+
"isBackedUp",
|
|
87
|
+
"uptimeSeconds",
|
|
88
|
+
"lastSeenAt",
|
|
89
|
+
"version",
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
export class Service extends DatabaseService<Model> {
|
|
93
|
+
public constructor() {
|
|
94
|
+
super(Model);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Upsert a batch of parsed resources for a single (project, cluster)
|
|
99
|
+
* pair. Uses ON CONFLICT on the UNIQUE (projectId, proxmoxClusterId,
|
|
100
|
+
* kind, externalId) index with a dominance guard on lastSeenAt so
|
|
101
|
+
* out-of-order ingest never regresses a newer snapshot.
|
|
102
|
+
*
|
|
103
|
+
* Identity/status columns COALESCE against the existing row (unlike
|
|
104
|
+
* the K8s upsert, which overwrites): a pve-exporter batch is usually
|
|
105
|
+
* a complete scrape, but a batch that happens to lack an info series
|
|
106
|
+
* (e.g. only pve_up made it through a pipeline filter) must not blank
|
|
107
|
+
* name/vmid/haState that an earlier batch already filled.
|
|
108
|
+
*/
|
|
109
|
+
@CaptureSpan()
|
|
110
|
+
public async bulkUpsert(data: {
|
|
111
|
+
projectId: ObjectID;
|
|
112
|
+
proxmoxClusterId: ObjectID;
|
|
113
|
+
resources: Array<ParsedProxmoxResource>;
|
|
114
|
+
}): Promise<void> {
|
|
115
|
+
if (data.resources.length === 0) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Chunk to keep individual statement parameter counts reasonable.
|
|
120
|
+
for (let i: number = 0; i < data.resources.length; i += UPSERT_BATCH_SIZE) {
|
|
121
|
+
const chunk: Array<ParsedProxmoxResource> = data.resources.slice(
|
|
122
|
+
i,
|
|
123
|
+
i + UPSERT_BATCH_SIZE,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
const valueFragments: Array<string> = [];
|
|
127
|
+
const params: Array<unknown> = [];
|
|
128
|
+
let paramIndex: number = 1;
|
|
129
|
+
|
|
130
|
+
for (const r of chunk) {
|
|
131
|
+
const placeholders: Array<string> = [];
|
|
132
|
+
for (let c: number = 0; c < UPSERT_COLUMNS.length; c++) {
|
|
133
|
+
placeholders.push(`$${paramIndex++}`);
|
|
134
|
+
}
|
|
135
|
+
valueFragments.push(`(${placeholders.join(", ")})`);
|
|
136
|
+
|
|
137
|
+
params.push(
|
|
138
|
+
data.projectId.toString(),
|
|
139
|
+
data.proxmoxClusterId.toString(),
|
|
140
|
+
r.kind,
|
|
141
|
+
r.externalId,
|
|
142
|
+
r.name,
|
|
143
|
+
r.vmid,
|
|
144
|
+
r.guestType,
|
|
145
|
+
r.parentNodeName,
|
|
146
|
+
r.isUp,
|
|
147
|
+
r.haState,
|
|
148
|
+
r.onboot,
|
|
149
|
+
r.isBackedUp,
|
|
150
|
+
r.uptimeSeconds !== null ? Math.trunc(r.uptimeSeconds) : null,
|
|
151
|
+
r.lastSeenAt,
|
|
152
|
+
0, // version (BaseModel @VersionColumn)
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const sql: string = `
|
|
157
|
+
INSERT INTO "ProxmoxResource" (
|
|
158
|
+
"projectId", "proxmoxClusterId", "kind", "externalId",
|
|
159
|
+
"name", "vmid", "guestType", "parentNodeName",
|
|
160
|
+
"isUp", "haState", "onboot", "isBackedUp", "uptimeSeconds",
|
|
161
|
+
"lastSeenAt", "version"
|
|
162
|
+
)
|
|
163
|
+
VALUES ${valueFragments.join(", ")}
|
|
164
|
+
ON CONFLICT ("projectId", "proxmoxClusterId", "kind", "externalId")
|
|
165
|
+
DO UPDATE SET
|
|
166
|
+
"name" = COALESCE(EXCLUDED."name", "ProxmoxResource"."name"),
|
|
167
|
+
"vmid" = COALESCE(EXCLUDED."vmid", "ProxmoxResource"."vmid"),
|
|
168
|
+
"guestType" = COALESCE(EXCLUDED."guestType", "ProxmoxResource"."guestType"),
|
|
169
|
+
"parentNodeName" = COALESCE(EXCLUDED."parentNodeName", "ProxmoxResource"."parentNodeName"),
|
|
170
|
+
"isUp" = COALESCE(EXCLUDED."isUp", "ProxmoxResource"."isUp"),
|
|
171
|
+
"haState" = COALESCE(EXCLUDED."haState", "ProxmoxResource"."haState"),
|
|
172
|
+
"onboot" = COALESCE(EXCLUDED."onboot", "ProxmoxResource"."onboot"),
|
|
173
|
+
"isBackedUp" = COALESCE(EXCLUDED."isBackedUp", "ProxmoxResource"."isBackedUp"),
|
|
174
|
+
"uptimeSeconds" = COALESCE(EXCLUDED."uptimeSeconds", "ProxmoxResource"."uptimeSeconds"),
|
|
175
|
+
"lastSeenAt" = EXCLUDED."lastSeenAt",
|
|
176
|
+
"updatedAt" = now()
|
|
177
|
+
WHERE EXCLUDED."lastSeenAt" >= "ProxmoxResource"."lastSeenAt"
|
|
178
|
+
`;
|
|
179
|
+
|
|
180
|
+
await this.getRepository().manager.query(sql, params);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Update the latest-metric mirror columns for a batch of resources.
|
|
186
|
+
* Plain UPDATE: in practice the row always exists because bulkUpsert
|
|
187
|
+
* runs in the same flush; if it somehow doesn't, the write is
|
|
188
|
+
* silently skipped and the next flush catches up.
|
|
189
|
+
*
|
|
190
|
+
* Guarded by metricsUpdatedAt so out-of-order points don't regress a
|
|
191
|
+
* newer observation. COALESCE keeps the existing value when a batch
|
|
192
|
+
* lacks a series — notably latestDiskBytes stays NULL (never 0) for
|
|
193
|
+
* qemu guests without the QEMU guest agent.
|
|
194
|
+
*/
|
|
195
|
+
@CaptureSpan()
|
|
196
|
+
public async bulkUpdateLatestMetrics(data: {
|
|
197
|
+
projectId: ObjectID;
|
|
198
|
+
proxmoxClusterId: ObjectID;
|
|
199
|
+
metrics: Array<ProxmoxResourceLatestMetric>;
|
|
200
|
+
}): Promise<void> {
|
|
201
|
+
if (data.metrics.length === 0) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (let i: number = 0; i < data.metrics.length; i += UPSERT_BATCH_SIZE) {
|
|
206
|
+
const chunk: Array<ProxmoxResourceLatestMetric> = data.metrics.slice(
|
|
207
|
+
i,
|
|
208
|
+
i + UPSERT_BATCH_SIZE,
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
const valueFragments: Array<string> = [];
|
|
212
|
+
const params: Array<unknown> = [
|
|
213
|
+
data.projectId.toString(),
|
|
214
|
+
data.proxmoxClusterId.toString(),
|
|
215
|
+
];
|
|
216
|
+
let paramIndex: number = 3;
|
|
217
|
+
|
|
218
|
+
for (const m of chunk) {
|
|
219
|
+
valueFragments.push(
|
|
220
|
+
`($${paramIndex++}, $${paramIndex++}, $${paramIndex++}::numeric, $${paramIndex++}::bigint, $${paramIndex++}::bigint, $${paramIndex++}::numeric, $${paramIndex++}::bigint, $${paramIndex++}::bigint, $${paramIndex++}::timestamptz)`,
|
|
221
|
+
);
|
|
222
|
+
params.push(
|
|
223
|
+
m.kind,
|
|
224
|
+
m.externalId,
|
|
225
|
+
m.cpuPercent !== null && m.cpuPercent !== undefined
|
|
226
|
+
? m.cpuPercent
|
|
227
|
+
: null,
|
|
228
|
+
m.memoryBytes !== null && m.memoryBytes !== undefined
|
|
229
|
+
? Math.trunc(m.memoryBytes).toString()
|
|
230
|
+
: null,
|
|
231
|
+
m.maxMemoryBytes !== null && m.maxMemoryBytes !== undefined
|
|
232
|
+
? Math.trunc(m.maxMemoryBytes).toString()
|
|
233
|
+
: null,
|
|
234
|
+
m.memoryPercent !== null && m.memoryPercent !== undefined
|
|
235
|
+
? m.memoryPercent
|
|
236
|
+
: null,
|
|
237
|
+
m.diskBytes !== null && m.diskBytes !== undefined
|
|
238
|
+
? Math.trunc(m.diskBytes).toString()
|
|
239
|
+
: null,
|
|
240
|
+
m.maxDiskBytes !== null && m.maxDiskBytes !== undefined
|
|
241
|
+
? Math.trunc(m.maxDiskBytes).toString()
|
|
242
|
+
: null,
|
|
243
|
+
m.observedAt,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const sql: string = `
|
|
248
|
+
UPDATE "ProxmoxResource" AS p
|
|
249
|
+
SET
|
|
250
|
+
"latestCpuPercent" = COALESCE(v."cpu", p."latestCpuPercent"),
|
|
251
|
+
"latestMemoryBytes" = COALESCE(v."mem", p."latestMemoryBytes"),
|
|
252
|
+
"maxMemoryBytes" = COALESCE(v."maxMem", p."maxMemoryBytes"),
|
|
253
|
+
"latestMemoryPercent" = COALESCE(v."memPct", p."latestMemoryPercent"),
|
|
254
|
+
"latestDiskBytes" = COALESCE(v."disk", p."latestDiskBytes"),
|
|
255
|
+
"maxDiskBytes" = COALESCE(v."maxDisk", p."maxDiskBytes"),
|
|
256
|
+
"metricsUpdatedAt" = v."observedAt",
|
|
257
|
+
"updatedAt" = now()
|
|
258
|
+
FROM (VALUES ${valueFragments.join(", ")})
|
|
259
|
+
AS v("kind", "externalId", "cpu", "mem", "maxMem", "memPct", "disk", "maxDisk", "observedAt")
|
|
260
|
+
WHERE
|
|
261
|
+
p."projectId" = $1
|
|
262
|
+
AND p."proxmoxClusterId" = $2
|
|
263
|
+
AND p."kind" = v."kind"
|
|
264
|
+
AND p."externalId" = v."externalId"
|
|
265
|
+
AND (p."metricsUpdatedAt" IS NULL OR v."observedAt" >= p."metricsUpdatedAt")
|
|
266
|
+
`;
|
|
267
|
+
|
|
268
|
+
await this.getRepository().manager.query(sql, params);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Hard-delete all resources in a cluster whose last scrape is older
|
|
274
|
+
* than olderThan. Returns the number of deleted rows. Only called by
|
|
275
|
+
* the cleanup worker for clusters that are still connected — a
|
|
276
|
+
* disconnected cluster keeps its last-known inventory.
|
|
277
|
+
*/
|
|
278
|
+
@CaptureSpan()
|
|
279
|
+
public async deleteStaleForCluster(data: {
|
|
280
|
+
proxmoxClusterId: ObjectID;
|
|
281
|
+
olderThan: Date;
|
|
282
|
+
}): Promise<number> {
|
|
283
|
+
const result: Array<{ affected?: number }> | { affected?: number } =
|
|
284
|
+
await this.getRepository().manager.query(
|
|
285
|
+
`DELETE FROM "ProxmoxResource" WHERE "proxmoxClusterId" = $1 AND "lastSeenAt" < $2`,
|
|
286
|
+
[data.proxmoxClusterId.toString(), data.olderThan],
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
// Postgres driver returns [rows, affected] for DELETE — normalize.
|
|
290
|
+
let affected: number = 0;
|
|
291
|
+
if (Array.isArray(result) && result.length >= 2) {
|
|
292
|
+
const second: unknown = (result as Array<unknown>)[1];
|
|
293
|
+
if (typeof second === "number") {
|
|
294
|
+
affected = second;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (affected > STALE_DELETE_WARN_THRESHOLD) {
|
|
299
|
+
logger.warn(
|
|
300
|
+
`ProxmoxResource cleanup deleted ${affected} stale rows for cluster ${data.proxmoxClusterId.toString()} — larger than expected; investigate agent health.`,
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return affected;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Compute the sidebar/overview summary in Postgres: counts per kind
|
|
309
|
+
* plus the online/running breakdowns, in a single round-trip.
|
|
310
|
+
*/
|
|
311
|
+
@CaptureSpan()
|
|
312
|
+
public async getInventorySummary(data: {
|
|
313
|
+
projectId: ObjectID;
|
|
314
|
+
proxmoxClusterId: ObjectID;
|
|
315
|
+
}): Promise<ProxmoxInventorySummary> {
|
|
316
|
+
const rows: Array<{
|
|
317
|
+
kind: string;
|
|
318
|
+
count: string;
|
|
319
|
+
upCount: string;
|
|
320
|
+
}> = await this.getRepository().manager.query(
|
|
321
|
+
`SELECT "kind",
|
|
322
|
+
COUNT(*)::text AS count,
|
|
323
|
+
COUNT(*) FILTER (WHERE "isUp" IS TRUE)::text AS "upCount"
|
|
324
|
+
FROM "ProxmoxResource"
|
|
325
|
+
WHERE "projectId" = $1 AND "proxmoxClusterId" = $2 AND "deletedAt" IS NULL
|
|
326
|
+
GROUP BY "kind"`,
|
|
327
|
+
[data.projectId.toString(), data.proxmoxClusterId.toString()],
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
const countsByKind: Record<string, number> = {};
|
|
331
|
+
let nodeOnlineCount: number = 0;
|
|
332
|
+
let guestRunningCount: number = 0;
|
|
333
|
+
for (const row of rows) {
|
|
334
|
+
countsByKind[row.kind] = parseInt(row.count, 10) || 0;
|
|
335
|
+
if (row.kind === "Node") {
|
|
336
|
+
nodeOnlineCount = parseInt(row.upCount, 10) || 0;
|
|
337
|
+
}
|
|
338
|
+
if (row.kind === "Guest") {
|
|
339
|
+
guestRunningCount = parseInt(row.upCount, 10) || 0;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
countsByKind,
|
|
345
|
+
nodeOnlineCount,
|
|
346
|
+
guestRunningCount,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Host cross-link heuristic (WI-17): resolve the cluster a guest
|
|
352
|
+
* with this name belongs to. Case-insensitive — host.name casing
|
|
353
|
+
* (canonicalized at ingest) rarely matches the PVE guest name's
|
|
354
|
+
* casing exactly. Returns null when no guest matches.
|
|
355
|
+
*/
|
|
356
|
+
@CaptureSpan()
|
|
357
|
+
public async findGuestClusterIdByName(data: {
|
|
358
|
+
projectId: ObjectID;
|
|
359
|
+
name: string;
|
|
360
|
+
}): Promise<ObjectID | null> {
|
|
361
|
+
const guest: Model | null = await this.findOneBy({
|
|
362
|
+
query: {
|
|
363
|
+
projectId: data.projectId,
|
|
364
|
+
kind: "Guest",
|
|
365
|
+
name: QueryHelper.findWithSameText(data.name),
|
|
366
|
+
},
|
|
367
|
+
select: {
|
|
368
|
+
_id: true,
|
|
369
|
+
proxmoxClusterId: true,
|
|
370
|
+
},
|
|
371
|
+
props: {
|
|
372
|
+
isRoot: true,
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
return guest?.proxmoxClusterId || null;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Helper for the cleanup worker: snapshot-interval aware cutoff.
|
|
381
|
+
* 3× the 5-minute scrape interval by default. Tune via
|
|
382
|
+
* PVE_INVENTORY_STALE_MINUTES (min 5).
|
|
383
|
+
*/
|
|
384
|
+
public getStaleThresholdDate(nowOverride?: Date): Date {
|
|
385
|
+
const minutes: number = this.getStaleThresholdMinutes();
|
|
386
|
+
return OneUptimeDate.addRemoveMinutes(
|
|
387
|
+
nowOverride || OneUptimeDate.getCurrentDate(),
|
|
388
|
+
-minutes,
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
public getStaleThresholdMinutes(): number {
|
|
393
|
+
const raw: string | undefined = process.env["PVE_INVENTORY_STALE_MINUTES"];
|
|
394
|
+
if (raw) {
|
|
395
|
+
const parsed: number = parseInt(raw, 10);
|
|
396
|
+
if (!isNaN(parsed) && parsed >= 5) {
|
|
397
|
+
return parsed;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return 15;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
export default new Service();
|
|
@@ -253,15 +253,23 @@ export class Service extends DatabaseService<Model> {
|
|
|
253
253
|
|
|
254
254
|
@CaptureSpan()
|
|
255
255
|
public async markDisconnectedApplications(): Promise<void> {
|
|
256
|
-
|
|
256
|
+
/*
|
|
257
|
+
* Threshold must stay well above the 5-minute OTel ingest
|
|
258
|
+
* maintenance fence (MAINTENANCE_FENCE_TTL_SECONDS in
|
|
259
|
+
* OtelIngestBaseService) — lastSeenAt is legitimately up to
|
|
260
|
+
* ~5 minutes stale during continuous telemetry, so a threshold
|
|
261
|
+
* equal to the fence TTL flaps healthy resources. 15 minutes
|
|
262
|
+
* gives 3x headroom.
|
|
263
|
+
*/
|
|
264
|
+
const fifteenMinutesAgo: Date = OneUptimeDate.addRemoveMinutes(
|
|
257
265
|
OneUptimeDate.getCurrentDate(),
|
|
258
|
-
-
|
|
266
|
+
-15,
|
|
259
267
|
);
|
|
260
268
|
|
|
261
269
|
const connectedApps: Array<Model> = await this.findBy({
|
|
262
270
|
query: {
|
|
263
271
|
otelCollectorStatus: "connected",
|
|
264
|
-
lastSeenAt: QueryHelper.lessThan(
|
|
272
|
+
lastSeenAt: QueryHelper.lessThan(fifteenMinutesAgo),
|
|
265
273
|
},
|
|
266
274
|
select: {
|
|
267
275
|
_id: true,
|
|
@@ -303,15 +303,23 @@ export class Service extends DatabaseService<Model> {
|
|
|
303
303
|
|
|
304
304
|
@CaptureSpan()
|
|
305
305
|
public async markDisconnectedFunctions(): Promise<void> {
|
|
306
|
-
|
|
306
|
+
/*
|
|
307
|
+
* Threshold must stay well above the 5-minute OTel ingest
|
|
308
|
+
* maintenance fence (MAINTENANCE_FENCE_TTL_SECONDS in
|
|
309
|
+
* OtelIngestBaseService) — lastSeenAt is legitimately up to
|
|
310
|
+
* ~5 minutes stale during continuous telemetry, so a threshold
|
|
311
|
+
* equal to the fence TTL flaps healthy resources. 15 minutes
|
|
312
|
+
* gives 3x headroom.
|
|
313
|
+
*/
|
|
314
|
+
const fifteenMinutesAgo: Date = OneUptimeDate.addRemoveMinutes(
|
|
307
315
|
OneUptimeDate.getCurrentDate(),
|
|
308
|
-
-
|
|
316
|
+
-15,
|
|
309
317
|
);
|
|
310
318
|
|
|
311
319
|
const connectedFunctions: Array<Model> = await this.findBy({
|
|
312
320
|
query: {
|
|
313
321
|
otelCollectorStatus: "connected",
|
|
314
|
-
lastSeenAt: QueryHelper.lessThan(
|
|
322
|
+
lastSeenAt: QueryHelper.lessThan(fifteenMinutesAgo),
|
|
315
323
|
},
|
|
316
324
|
select: {
|
|
317
325
|
_id: true,
|
|
@@ -26,9 +26,13 @@ import ServiceModel from "../../Models/DatabaseModels/Service";
|
|
|
26
26
|
import HostService from "./HostService";
|
|
27
27
|
import DockerHostService from "./DockerHostService";
|
|
28
28
|
import KubernetesClusterService from "./KubernetesClusterService";
|
|
29
|
+
import ProxmoxClusterService from "./ProxmoxClusterService";
|
|
30
|
+
import CephClusterService from "./CephClusterService";
|
|
29
31
|
import Host from "../../Models/DatabaseModels/Host";
|
|
30
32
|
import DockerHost from "../../Models/DatabaseModels/DockerHost";
|
|
31
33
|
import KubernetesCluster from "../../Models/DatabaseModels/KubernetesCluster";
|
|
34
|
+
import ProxmoxCluster from "../../Models/DatabaseModels/ProxmoxCluster";
|
|
35
|
+
import CephCluster from "../../Models/DatabaseModels/CephCluster";
|
|
32
36
|
import ServiceType from "../../Types/Telemetry/ServiceType";
|
|
33
37
|
import {
|
|
34
38
|
AverageSpanRowSizeInBytes,
|
|
@@ -347,9 +351,10 @@ export class Service extends DatabaseService<Model> {
|
|
|
347
351
|
/*
|
|
348
352
|
* Map of resourceId -> retainTelemetryDataForDays for every resource in
|
|
349
353
|
* the project that can own telemetry (Service, Host, DockerHost,
|
|
350
|
-
* KubernetesCluster). Used to scale billed
|
|
351
|
-
* applied to each resource's telemetry.
|
|
352
|
-
* (and the unattributed bucket) fall back
|
|
354
|
+
* KubernetesCluster, ProxmoxCluster, CephCluster). Used to scale billed
|
|
355
|
+
* cost by the actual retention applied to each resource's telemetry.
|
|
356
|
+
* Resources without an override (and the unattributed bucket) fall back
|
|
357
|
+
* to the project default.
|
|
353
358
|
*/
|
|
354
359
|
@CaptureSpan()
|
|
355
360
|
private async buildTelemetryRetentionMap(
|
|
@@ -422,6 +427,39 @@ export class Service extends DatabaseService<Model> {
|
|
|
422
427
|
}
|
|
423
428
|
}
|
|
424
429
|
|
|
430
|
+
const proxmoxClusters: Array<ProxmoxCluster> =
|
|
431
|
+
await ProxmoxClusterService.findBy({
|
|
432
|
+
query: { projectId: projectId },
|
|
433
|
+
select: { _id: true, retainTelemetryDataForDays: true },
|
|
434
|
+
skip: 0,
|
|
435
|
+
limit: LIMIT_MAX,
|
|
436
|
+
props: { isRoot: true },
|
|
437
|
+
});
|
|
438
|
+
for (const proxmoxCluster of proxmoxClusters) {
|
|
439
|
+
if (proxmoxCluster.id && proxmoxCluster.retainTelemetryDataForDays) {
|
|
440
|
+
retentionByServiceId.set(
|
|
441
|
+
proxmoxCluster.id.toString(),
|
|
442
|
+
proxmoxCluster.retainTelemetryDataForDays,
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
const cephClusters: Array<CephCluster> = await CephClusterService.findBy({
|
|
448
|
+
query: { projectId: projectId },
|
|
449
|
+
select: { _id: true, retainTelemetryDataForDays: true },
|
|
450
|
+
skip: 0,
|
|
451
|
+
limit: LIMIT_MAX,
|
|
452
|
+
props: { isRoot: true },
|
|
453
|
+
});
|
|
454
|
+
for (const cephCluster of cephClusters) {
|
|
455
|
+
if (cephCluster.id && cephCluster.retainTelemetryDataForDays) {
|
|
456
|
+
retentionByServiceId.set(
|
|
457
|
+
cephCluster.id.toString(),
|
|
458
|
+
cephCluster.retainTelemetryDataForDays,
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
425
463
|
return retentionByServiceId;
|
|
426
464
|
}
|
|
427
465
|
|
|
@@ -159,6 +159,8 @@ export class TraceAggregationService {
|
|
|
159
159
|
["hostId", ServiceType.Host],
|
|
160
160
|
["dockerHostId", ServiceType.DockerHost],
|
|
161
161
|
["kubernetesClusterId", ServiceType.KubernetesCluster],
|
|
162
|
+
["proxmoxClusterId", ServiceType.ProxmoxCluster],
|
|
163
|
+
["cephClusterId", ServiceType.CephCluster],
|
|
162
164
|
["serverlessFunctionId", ServiceType.ServerlessFunction],
|
|
163
165
|
["cloudResourceId", ServiceType.CloudResource],
|
|
164
166
|
["rumApplicationId", ServiceType.RealUserMonitor],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import AggregationInterval from "../../../Types/BaseDatabase/AggregationInterval";
|
|
2
|
+
import AggregationIntervalUtil from "../../../Types/BaseDatabase/AggregationIntervalUtil";
|
|
2
3
|
import CommonAggregateBy from "../../../Types/BaseDatabase/AggregateBy";
|
|
3
4
|
import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
|
|
4
5
|
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
5
|
-
import OneUptimeDate from "../../../Types/Date";
|
|
6
6
|
import CaptureSpan from "../../Utils/Telemetry/CaptureSpan";
|
|
7
7
|
|
|
8
8
|
export default interface AggregateBy<TBaseModel extends AnalyticsBaseModel>
|
|
@@ -11,32 +11,17 @@ export default interface AggregateBy<TBaseModel extends AnalyticsBaseModel>
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export class AggregateUtil {
|
|
14
|
+
/*
|
|
15
|
+
* Delegates to the isomorphic AggregationIntervalUtil so browser
|
|
16
|
+
* code reconstructing the server's bucket grid (heartbeat
|
|
17
|
+
* availability charts) always agrees with the interval the
|
|
18
|
+
* statement generator compiles into `toStartOfInterval(...)`.
|
|
19
|
+
*/
|
|
14
20
|
@CaptureSpan()
|
|
15
21
|
public static getAggregationInterval(data: {
|
|
16
22
|
startDate: Date;
|
|
17
23
|
endDate: Date;
|
|
18
24
|
}): AggregationInterval {
|
|
19
|
-
|
|
20
|
-
data.endDate = OneUptimeDate.fromString(data.endDate);
|
|
21
|
-
|
|
22
|
-
const diff: number = data.endDate.getTime() - data.startDate.getTime();
|
|
23
|
-
|
|
24
|
-
if (diff <= 1000 * 60 * 60 * 3) {
|
|
25
|
-
// if less than 3 hours, then get minute precision
|
|
26
|
-
return AggregationInterval.Minute;
|
|
27
|
-
} else if (diff <= 1000 * 60 * 60 * 24 * 7) {
|
|
28
|
-
// 3 days
|
|
29
|
-
return AggregationInterval.Hour;
|
|
30
|
-
} else if (diff <= 1000 * 60 * 60 * 24 * 7 * 6) {
|
|
31
|
-
// 3 weeks
|
|
32
|
-
return AggregationInterval.Day;
|
|
33
|
-
} else if (diff <= 1000 * 60 * 60 * 24 * 30 * 6) {
|
|
34
|
-
// 3 months
|
|
35
|
-
return AggregationInterval.Week;
|
|
36
|
-
} else if (diff <= 1000 * 60 * 60 * 24 * 365 * 6) {
|
|
37
|
-
// 3 years
|
|
38
|
-
return AggregationInterval.Month;
|
|
39
|
-
}
|
|
40
|
-
return AggregationInterval.Year;
|
|
25
|
+
return AggregationIntervalUtil.getAggregationIntervalForWindow(data);
|
|
41
26
|
}
|
|
42
27
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import Alert from "../../../Models/DatabaseModels/Alert";
|
|
2
2
|
import AlertSeverity from "../../../Models/DatabaseModels/AlertSeverity";
|
|
3
3
|
import AlertStateTimeline from "../../../Models/DatabaseModels/AlertStateTimeline";
|
|
4
|
+
import CephCluster from "../../../Models/DatabaseModels/CephCluster";
|
|
4
5
|
import Host from "../../../Models/DatabaseModels/Host";
|
|
5
6
|
import Label from "../../../Models/DatabaseModels/Label";
|
|
6
7
|
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
7
8
|
import OnCallDutyPolicy from "../../../Models/DatabaseModels/OnCallDutyPolicy";
|
|
9
|
+
import ProxmoxCluster from "../../../Models/DatabaseModels/ProxmoxCluster";
|
|
8
10
|
import Service from "../../../Models/DatabaseModels/Service";
|
|
9
11
|
import SortOrder from "../../../Types/BaseDatabase/SortOrder";
|
|
10
12
|
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
|
|
@@ -24,6 +26,9 @@ import ServiceService from "../../Services/ServiceService";
|
|
|
24
26
|
import logger, { LogAttributes } from "../Logger";
|
|
25
27
|
import CaptureSpan from "../Telemetry/CaptureSpan";
|
|
26
28
|
import DataToProcess from "./DataToProcess";
|
|
29
|
+
import MonitorClusterContextUtil, {
|
|
30
|
+
MonitorClusterContext,
|
|
31
|
+
} from "./MonitorClusterContext";
|
|
27
32
|
import MonitorTemplateUtil from "./MonitorTemplateUtil";
|
|
28
33
|
import { JSONObject } from "../../../Types/JSON";
|
|
29
34
|
import OneUptimeDate from "../../../Types/Date";
|
|
@@ -159,6 +164,19 @@ export default class MonitorAlert {
|
|
|
159
164
|
return;
|
|
160
165
|
}
|
|
161
166
|
|
|
167
|
+
/*
|
|
168
|
+
* Proxmox/Ceph monitors: resolve the monitored cluster once per
|
|
169
|
+
* evaluation (lookup-only, from the step config's clusterIdentifier)
|
|
170
|
+
* so every alert created below is attached to it. Series labels
|
|
171
|
+
* cannot supply this — they carry datapoint labels (`id`,
|
|
172
|
+
* `ceph_daemon`, `pool_id`), not cluster identity, and ungrouped
|
|
173
|
+
* templates have no series at all. No-op for other monitor types.
|
|
174
|
+
*/
|
|
175
|
+
const clusterContext: MonitorClusterContext =
|
|
176
|
+
await MonitorClusterContextUtil.resolveClusterContextForMonitor({
|
|
177
|
+
monitor: input.monitor,
|
|
178
|
+
});
|
|
179
|
+
|
|
162
180
|
const seriesToProcess: Array<PerSeriesCriteriaMatch | undefined> =
|
|
163
181
|
input.matchesPerSeries && input.matchesPerSeries.length > 0
|
|
164
182
|
? input.matchesPerSeries
|
|
@@ -376,6 +394,33 @@ export default class MonitorAlert {
|
|
|
376
394
|
}
|
|
377
395
|
}
|
|
378
396
|
|
|
397
|
+
/*
|
|
398
|
+
* Deterministic Proxmox/Ceph cluster link from the monitor's
|
|
399
|
+
* step config (resolved once above). Series labels never carry
|
|
400
|
+
* cluster identity for these monitor types, so this — not the
|
|
401
|
+
* label path above — is what makes the per-cluster Activity
|
|
402
|
+
* tabs and badge counts see monitor-created alerts. Runs for
|
|
403
|
+
* both grouped and ungrouped alerts.
|
|
404
|
+
*/
|
|
405
|
+
if (clusterContext.proxmoxClusterIds.length > 0) {
|
|
406
|
+
alert.proxmoxClusters = clusterContext.proxmoxClusterIds.map(
|
|
407
|
+
(id: string): ProxmoxCluster => {
|
|
408
|
+
const cluster: ProxmoxCluster = new ProxmoxCluster();
|
|
409
|
+
cluster._id = id;
|
|
410
|
+
return cluster;
|
|
411
|
+
},
|
|
412
|
+
);
|
|
413
|
+
}
|
|
414
|
+
if (clusterContext.cephClusterIds.length > 0) {
|
|
415
|
+
alert.cephClusters = clusterContext.cephClusterIds.map(
|
|
416
|
+
(id: string): CephCluster => {
|
|
417
|
+
const cluster: CephCluster = new CephCluster();
|
|
418
|
+
cluster._id = id;
|
|
419
|
+
return cluster;
|
|
420
|
+
},
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
379
424
|
alert.onCallDutyPolicies =
|
|
380
425
|
criteriaAlert.onCallPolicyIds?.map((id: ObjectID) => {
|
|
381
426
|
const onCallPolicy: OnCallDutyPolicy = new OnCallDutyPolicy();
|