@oneuptime/common 12.0.1 → 12.0.3
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/DatabaseBaseModel/DatabaseBaseModel.ts +14 -0
- package/Models/DatabaseModels/Host.ts +12 -4
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/KubernetesContainer.ts +5 -4
- package/Models/DatabaseModels/KubernetesResource.ts +8 -7
- package/Models/DatabaseModels/LogDropFilter.ts +9 -20
- package/Models/DatabaseModels/PodmanResource.ts +6 -6
- package/Models/DatabaseModels/ServiceLevelObjective.ts +91 -0
- package/Models/DatabaseModels/StatusPage.ts +95 -0
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +911 -0
- package/Models/DatabaseModels/StatusPageResource.ts +73 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +9 -20
- package/Server/API/BaseAPI.ts +13 -2
- package/Server/API/DashboardAPI.ts +39 -0
- package/Server/API/TeamMemberAPI.ts +85 -0
- package/Server/EnvironmentConfig.ts +31 -1
- package/Server/Infrastructure/GlobalCache.ts +115 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +16 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.ts +84 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.ts +131 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.ts +123 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Middleware/ProjectAuthorization.ts +66 -4
- package/Server/Services/AlertStateTimelineService.ts +20 -0
- package/Server/Services/BillingService.ts +600 -51
- package/Server/Services/CephClusterService.ts +27 -45
- package/Server/Services/CephResourceService.ts +43 -4
- package/Server/Services/CloudResourceService.ts +24 -42
- package/Server/Services/DatabaseService.ts +198 -6
- package/Server/Services/DockerHostService.ts +20 -38
- package/Server/Services/DockerResourceService.ts +62 -8
- package/Server/Services/DockerSwarmClusterService.ts +28 -46
- package/Server/Services/DockerSwarmResourceService.ts +53 -4
- package/Server/Services/HostService.ts +47 -57
- package/Server/Services/IncidentStateTimelineService.ts +20 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTDeviceService.ts +1 -17
- package/Server/Services/IoTFleetService.ts +20 -38
- package/Server/Services/KubernetesClusterService.ts +18 -36
- package/Server/Services/KubernetesContainerService.ts +50 -9
- package/Server/Services/KubernetesResourceService.ts +53 -7
- package/Server/Services/LabelService.ts +153 -1
- package/Server/Services/MetricTypeService.ts +84 -0
- package/Server/Services/MonitorService.ts +146 -14
- package/Server/Services/MonitorStatusTimelineService.ts +29 -0
- package/Server/Services/MonitorTemplateService.ts +65 -0
- package/Server/Services/PodmanHostService.ts +20 -38
- package/Server/Services/PodmanResourceService.ts +62 -8
- package/Server/Services/ProjectService.ts +165 -35
- package/Server/Services/ProxmoxClusterService.ts +24 -42
- package/Server/Services/ProxmoxResourceService.ts +43 -4
- package/Server/Services/RumApplicationService.ts +20 -38
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +21 -0
- package/Server/Services/ServerlessFunctionService.ts +25 -43
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +426 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +39 -0
- package/Server/Services/ServiceService.ts +299 -73
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +752 -0
- package/Server/Services/StatusPageMonitorRuleService.ts +471 -0
- package/Server/Services/StatusPageService.ts +95 -36
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +18 -1
- package/Server/Services/StatusPageSubscriberService.ts +3 -0
- package/Server/Services/TelemetryEntityRelationshipService.ts +1 -0
- package/Server/Services/TelemetryEntityService.ts +1 -0
- package/Server/Types/Database/JSONColumnQuery.ts +621 -0
- package/Server/Types/Database/Permissions/PublicPermission.ts +9 -2
- package/Server/Types/Database/QueryHelper.ts +17 -32
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +170 -39
- package/Server/Utils/Database/TruncateColumnValue.ts +84 -0
- package/Server/Utils/Monitor/MonitorResource.ts +63 -36
- package/Server/Utils/Monitor/MonitorStatusTimeline.ts +36 -0
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +148 -127
- package/Server/Utils/Monitor/MonitorStepsReferenceExtractor.ts +434 -0
- package/Server/Utils/SingleFlight.ts +83 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +46 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +107 -26
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +314 -0
- package/Server/Utils/Telemetry/Telemetry.ts +351 -122
- package/Tests/App/Dashboard/UsersTableGroupsByPerson.test.tsx +448 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +2 -0
- package/Tests/Models/DatabaseModels/ColumnTransformerInvariants.test.ts +306 -0
- package/Tests/Models/DatabaseModels/NumberColumnDeserialization.test.ts +333 -0
- package/Tests/Models/DatabaseModels/StatusPageMonitorRuleModel.test.ts +190 -0
- package/Tests/Server/API/BaseAPIApiKeyAuth.test.ts +704 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +26 -0
- package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +303 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +226 -0
- package/Tests/Server/Infrastructure/PostgresLockTimeoutOptions.test.ts +181 -0
- package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +350 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyHeader.test.ts +362 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +687 -0
- package/Tests/Server/Services/BillingService.test.ts +78 -3
- package/Tests/Server/Services/BillingServiceChangePlanCancel.test.ts +645 -0
- package/Tests/Server/Services/BillingServiceTrialPlanChange.test.ts +1005 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlocked.test.ts +342 -0
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +245 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +503 -0
- package/Tests/Server/Services/HostIpAddressesColumnWidth.test.ts +198 -0
- package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +658 -0
- package/Tests/Server/Services/InventoryResourceNameColumnWidth.test.ts +500 -0
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +586 -0
- package/Tests/Server/Services/InventoryUpsertTruncationGuard.test.ts +1242 -0
- package/Tests/Server/Services/MetricTypeAttachServices.test.ts +222 -0
- package/Tests/Server/Services/MissingReferenceWriteGuard.test.ts +614 -0
- package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +23 -0
- package/Tests/Server/Services/ProjectServiceChangePlan.test.ts +650 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +1 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +636 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +770 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +130 -0
- package/Tests/Server/Services/ServiceUpdateLastSeenSplitGates.test.ts +705 -0
- package/Tests/Server/Services/SloMonitorLabelRuleHooks.test.ts +352 -0
- package/Tests/Server/Services/StatusPageMonitorRuleEngineService.test.ts +1719 -0
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +1212 -0
- package/Tests/Server/Services/StatusPageMonitorRuleMonitorCreateHook.test.ts +228 -0
- package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +29 -13
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +69 -8
- package/Tests/Server/Types/Database/JSONColumnQuery.test.ts +593 -0
- package/Tests/Server/Types/Database/Permissions/PublicPermission.test.ts +495 -0
- package/Tests/Server/Types/Database/QueryUtil.test.ts +113 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +267 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +260 -13
- package/Tests/Server/Utils/Database/TruncateColumnValue.test.ts +179 -0
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +302 -0
- package/Tests/Server/Utils/MetricTypeIndexConvergence.test.ts +598 -0
- package/Tests/Server/Utils/Monitor/MonitorStatusTimelineUnusableStatus.test.ts +154 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +638 -92
- package/Tests/Server/Utils/Monitor/MonitorStepsReferenceExtractor.test.ts +724 -0
- package/Tests/Server/Utils/SingleFlight.test.ts +221 -0
- package/Tests/Types/Dashboard/NetworkDashboardTemplate.test.ts +793 -0
- package/Tests/Types/Database/BigIntColumnTransformer.test.ts +147 -0
- package/Tests/Types/Database/DatabasePropertyTransformer.test.ts +140 -0
- package/Tests/Types/Database/NumericColumnValue.test.ts +127 -0
- package/Tests/Types/Decimal.test.ts +37 -0
- package/Tests/Types/Events/Recurring.test.ts +157 -0
- package/Tests/Types/Monitor/SnmpVersionParsing.test.ts +152 -0
- package/Tests/Types/Port.test.ts +38 -0
- package/Tests/UI/Components/LogsHistogram.test.tsx +276 -0
- package/Tests/UI/Components/ModelTable/ModelTableGroupsProjectUsers.test.tsx +375 -0
- package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +196 -0
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +489 -0
- package/Tests/UI/Components/UseLogsHistogram.test.tsx +500 -0
- package/Tests/UI/Utils/ProjectUsersModelAPI.test.ts +739 -0
- package/Tests/UI/Utils/TeamMembersByUser.test.ts +633 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentsUtil.test.ts +120 -0
- package/Tests/Utils/Dashboard/DashboardNetworkMapComponent.test.ts +327 -0
- package/Tests/Utils/StatusPage/ReportPeriod.test.ts +218 -0
- package/Tests/Utils/Telemetry/HostIpAddresses.test.ts +291 -0
- package/Types/CustomField/CustomFieldDefinition.ts +24 -0
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.ts +40 -0
- package/Types/Dashboard/DashboardTemplates.ts +397 -0
- package/Types/Database/BigIntColumnTransformer.ts +74 -0
- package/Types/Database/DatabaseProperty.ts +26 -0
- package/Types/Database/NumericColumnValue.ts +128 -0
- package/Types/Date.ts +112 -0
- package/Types/Decimal.ts +16 -4
- package/Types/Events/Recurring.ts +99 -1
- package/Types/Permission.ts +48 -0
- package/Types/Port.ts +16 -4
- package/Types/StatusPage/StatusPageReport.ts +11 -0
- package/Types/StatusPage/StatusPageReportPeriodType.ts +21 -0
- package/UI/Components/LogsViewer/useLiveLogsRefresh.ts +86 -0
- package/UI/Components/LogsViewer/useLogsHistogram.ts +113 -0
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +2 -6
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +21 -2
- package/UI/Utils/ModelAPI/ProjectUsersModelAPI.ts +305 -0
- package/UI/Utils/TeamMembersByUser.ts +302 -0
- package/Utils/Dashboard/Components/DashboardNetworkMapComponent.ts +136 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/StatusPage/ReportPeriod.ts +236 -0
- package/Utils/Telemetry/HostIpAddresses.ts +98 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +12 -4
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesContainer.js +4 -4
- package/build/dist/Models/DatabaseModels/KubernetesContainer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesResource.js +7 -7
- package/build/dist/Models/DatabaseModels/KubernetesResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanResource.js +6 -6
- package/build/dist/Models/DatabaseModels/PodmanResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +87 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +98 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js +925 -0
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageResource.js +72 -0
- package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +11 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +39 -0
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +57 -2
- package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +27 -1
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +91 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +5 -3
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.js +45 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.js +90 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +59 -4
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AlertStateTimelineService.js +19 -0
- package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +466 -36
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +26 -39
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CephResourceService.js +28 -3
- package/build/dist/Server/Services/CephResourceService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +23 -36
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +155 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +19 -32
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerResourceService.js +34 -4
- package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +27 -40
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmResourceService.js +28 -3
- package/build/dist/Server/Services/DockerSwarmResourceService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +58 -64
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceService.js +1 -8
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetService.js +19 -32
- package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +17 -30
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesContainerService.js +29 -3
- package/build/dist/Server/Services/KubernetesContainerService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesResourceService.js +32 -4
- package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +127 -0
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MetricTypeService.js +74 -0
- package/build/dist/Server/Services/MetricTypeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +128 -9
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +28 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +60 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +19 -32
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/PodmanResourceService.js +34 -4
- package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +135 -21
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +23 -36
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxResourceService.js +28 -3
- package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationService.js +19 -32
- package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +20 -0
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionService.js +24 -37
- package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +347 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +33 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +236 -61
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +603 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js +401 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageService.js +69 -46
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +17 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +3 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityService.js.map +1 -1
- package/build/dist/Server/Types/Database/JSONColumnQuery.js +402 -0
- package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -0
- package/build/dist/Server/Types/Database/Permissions/PublicPermission.js +9 -2
- package/build/dist/Server/Types/Database/Permissions/PublicPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +17 -27
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +105 -29
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/Database/TruncateColumnValue.js +32 -0
- package/build/dist/Server/Utils/Database/TruncateColumnValue.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +56 -32
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +30 -3
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +110 -98
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js +312 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js.map +1 -0
- package/build/dist/Server/Utils/SingleFlight.js +76 -0
- package/build/dist/Server/Utils/SingleFlight.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +29 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +78 -19
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +160 -0
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +279 -104
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldDefinition.js +2 -0
- package/build/dist/Types/CustomField/CustomFieldDefinition.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +368 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Database/BigIntColumnTransformer.js +66 -0
- package/build/dist/Types/Database/BigIntColumnTransformer.js.map +1 -0
- package/build/dist/Types/Database/DatabaseProperty.js +25 -0
- package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
- package/build/dist/Types/Database/NumericColumnValue.js +97 -0
- package/build/dist/Types/Database/NumericColumnValue.js.map +1 -0
- package/build/dist/Types/Date.js +68 -0
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Decimal.js +14 -3
- package/build/dist/Types/Decimal.js.map +1 -1
- package/build/dist/Types/Events/Recurring.js +63 -0
- package/build/dist/Types/Events/Recurring.js.map +1 -1
- package/build/dist/Types/Permission.js +42 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Port.js +15 -5
- package/build/dist/Types/Port.js.map +1 -1
- package/build/dist/Types/StatusPage/StatusPageReportPeriodType.js +22 -0
- package/build/dist/Types/StatusPage/StatusPageReportPeriodType.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js +44 -0
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js +75 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +18 -2
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js +213 -0
- package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js.map +1 -0
- package/build/dist/UI/Utils/TeamMembersByUser.js +195 -0
- package/build/dist/UI/Utils/TeamMembersByUser.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js +114 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/StatusPage/ReportPeriod.js +131 -0
- package/build/dist/Utils/StatusPage/ReportPeriod.js.map +1 -0
- package/build/dist/Utils/Telemetry/HostIpAddresses.js +82 -0
- package/build/dist/Utils/Telemetry/HostIpAddresses.js.map +1 -0
- package/jest.config.json +2 -0
- package/package.json +1 -1
- package/tsconfig.json +12 -1
|
@@ -606,6 +606,7 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
606
606
|
subscriptionId: string;
|
|
607
607
|
meteredSubscriptionId: string;
|
|
608
608
|
trialEndsAt?: Date | undefined;
|
|
609
|
+
subscriptionIdsPendingCancellation: Array<string>;
|
|
609
610
|
} = await BillingService.changePlan({
|
|
610
611
|
projectId: project.id!,
|
|
611
612
|
subscriptionId: project.paymentProviderSubscriptionId,
|
|
@@ -617,36 +618,51 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
617
618
|
endTrialAt: endTrialAt,
|
|
618
619
|
});
|
|
619
620
|
|
|
620
|
-
const subscriptionState: SubscriptionStatus =
|
|
621
|
-
await
|
|
621
|
+
const subscriptionState: SubscriptionStatus | null =
|
|
622
|
+
await this.findSubscriptionStatus(subscription.subscriptionId);
|
|
622
623
|
|
|
623
|
-
const meteredSubscriptionState: SubscriptionStatus =
|
|
624
|
-
await
|
|
625
|
-
|
|
626
|
-
|
|
624
|
+
const meteredSubscriptionState: SubscriptionStatus | null =
|
|
625
|
+
await this.findSubscriptionStatus(subscription.meteredSubscriptionId);
|
|
626
|
+
|
|
627
|
+
const updateData: QueryDeepPartialEntity<Model> = {
|
|
628
|
+
paymentProviderPlanId: params.paymentProviderPlanId,
|
|
629
|
+
paymentProviderSubscriptionId: subscription.subscriptionId,
|
|
630
|
+
paymentProviderMeteredSubscriptionId: subscription.meteredSubscriptionId,
|
|
631
|
+
paymentProviderSubscriptionSeats: seats,
|
|
632
|
+
trialEndsAt: subscription.trialEndsAt || endTrialAt || new Date(),
|
|
633
|
+
planName: SubscriptionPlan.getPlanType(
|
|
634
|
+
params.paymentProviderPlanId,
|
|
635
|
+
getAllEnvVars(),
|
|
636
|
+
),
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
if (meteredSubscriptionState) {
|
|
640
|
+
updateData.paymentProviderMeteredSubscriptionStatus =
|
|
641
|
+
meteredSubscriptionState;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (subscriptionState) {
|
|
645
|
+
updateData.paymentProviderSubscriptionStatus = subscriptionState;
|
|
646
|
+
}
|
|
627
647
|
|
|
628
648
|
await this.updateOneById({
|
|
629
649
|
id: project.id!,
|
|
630
|
-
data:
|
|
631
|
-
paymentProviderPlanId: params.paymentProviderPlanId,
|
|
632
|
-
paymentProviderSubscriptionId: subscription.subscriptionId,
|
|
633
|
-
paymentProviderMeteredSubscriptionId:
|
|
634
|
-
subscription.meteredSubscriptionId,
|
|
635
|
-
paymentProviderSubscriptionSeats: seats,
|
|
636
|
-
trialEndsAt: subscription.trialEndsAt || endTrialAt || new Date(),
|
|
637
|
-
planName: SubscriptionPlan.getPlanType(
|
|
638
|
-
params.paymentProviderPlanId,
|
|
639
|
-
getAllEnvVars(),
|
|
640
|
-
),
|
|
641
|
-
paymentProviderMeteredSubscriptionStatus: meteredSubscriptionState,
|
|
642
|
-
paymentProviderSubscriptionStatus: subscriptionState,
|
|
643
|
-
},
|
|
650
|
+
data: updateData,
|
|
644
651
|
props: {
|
|
645
652
|
isRoot: true,
|
|
646
653
|
ignoreHooks: true,
|
|
647
654
|
},
|
|
648
655
|
});
|
|
649
656
|
|
|
657
|
+
/*
|
|
658
|
+
* Raised after the row is written, because the row is what makes these ids
|
|
659
|
+
* unreachable: it now carries the replacements.
|
|
660
|
+
*/
|
|
661
|
+
this.alertOnSubscriptionsPendingCancellation({
|
|
662
|
+
projectId: project.id!,
|
|
663
|
+
subscriptionIds: subscription.subscriptionIdsPendingCancellation,
|
|
664
|
+
});
|
|
665
|
+
|
|
650
666
|
this.capturePlanChangeAnalytics({
|
|
651
667
|
project: project,
|
|
652
668
|
newPlan: plan,
|
|
@@ -657,6 +673,103 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
657
673
|
await this.sendSubscriptionChangeWebhookSlackNotification(project.id!);
|
|
658
674
|
}
|
|
659
675
|
|
|
676
|
+
/*
|
|
677
|
+
* Reads a subscription's status back, and gives up rather than throwing.
|
|
678
|
+
*
|
|
679
|
+
* This sits between a plan change returning and the project row being
|
|
680
|
+
* written, and that write is what records the subscription ids the plan
|
|
681
|
+
* change produced. A replacement already exists at the payment provider and
|
|
682
|
+
* is already billing by this point, and the row is the only thing in
|
|
683
|
+
* OneUptime that will ever point at it - so a rate limit or a dropped
|
|
684
|
+
* connection reading a status back must not be what stops it being written
|
|
685
|
+
* down. Worse than the missing status: reactivation is retried from
|
|
686
|
+
* BillingInvoiceService whenever the customer's invoices look settled, so a
|
|
687
|
+
* row left pointing at the old id mints another live subscription every
|
|
688
|
+
* time it runs.
|
|
689
|
+
*
|
|
690
|
+
* The status columns are refreshed daily by
|
|
691
|
+
* PaymentProvider:CheckSubscriptionStatus, so leaving one behind costs a
|
|
692
|
+
* day of staleness. Losing the id costs a subscription nobody can find.
|
|
693
|
+
*/
|
|
694
|
+
private async findSubscriptionStatus(
|
|
695
|
+
subscriptionId: string,
|
|
696
|
+
): Promise<SubscriptionStatus | null> {
|
|
697
|
+
try {
|
|
698
|
+
return await BillingService.getSubscriptionStatus(subscriptionId);
|
|
699
|
+
} catch (err) {
|
|
700
|
+
logger.error(err, { subscriptionId } as LogAttributes);
|
|
701
|
+
return null;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/*
|
|
706
|
+
* Raises the subscriptions a plan change replaced but could not cancel.
|
|
707
|
+
*
|
|
708
|
+
* The project row now carries the replacement ids, so these ones exist
|
|
709
|
+
* nowhere in OneUptime any more. They were not billing when the plan change
|
|
710
|
+
* read them and the cancel has already been retried, so this is a loose end
|
|
711
|
+
* rather than a double charge - but it is one nobody will find on their own,
|
|
712
|
+
* which is why the ids travel with the alert instead of only reaching a log
|
|
713
|
+
* line. The replacements also carry them in their payment-provider metadata,
|
|
714
|
+
* as replacedSubscriptionId.
|
|
715
|
+
*
|
|
716
|
+
* Called once the plan change has already been applied and written down, so
|
|
717
|
+
* nothing in here is allowed to throw, and nothing in here is allowed to
|
|
718
|
+
* hold the response open either: failing - or being slow - to raise a loose
|
|
719
|
+
* end must not turn a plan change that worked into one the caller is told
|
|
720
|
+
* failed, or one that never comes back.
|
|
721
|
+
*/
|
|
722
|
+
private alertOnSubscriptionsPendingCancellation(data: {
|
|
723
|
+
projectId: ObjectID;
|
|
724
|
+
subscriptionIds: Array<string>;
|
|
725
|
+
}): void {
|
|
726
|
+
if (!data.subscriptionIds || data.subscriptionIds.length === 0) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
logger.error(
|
|
731
|
+
`Could not cancel subscriptions replaced by a plan change for project ${data.projectId.toString()}. They are still open at the payment provider and have to be cancelled by hand: ${data.subscriptionIds.join(
|
|
732
|
+
", ",
|
|
733
|
+
)}`,
|
|
734
|
+
{
|
|
735
|
+
projectId: data.projectId.toString(),
|
|
736
|
+
} as LogAttributes,
|
|
737
|
+
);
|
|
738
|
+
|
|
739
|
+
if (!NotificationSlackWebhookOnSubscriptionUpdate) {
|
|
740
|
+
return;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
const slackMessage: string = `*Subscriptions could not be cancelled after a plan change:*
|
|
744
|
+
*Project ID:* ${data.projectId.toString()}
|
|
745
|
+
*Subscriptions still open at the payment provider:* ${data.subscriptionIds.join(", ")}
|
|
746
|
+
These are no longer recorded against the project and have to be cancelled by hand.
|
|
747
|
+
`;
|
|
748
|
+
|
|
749
|
+
/*
|
|
750
|
+
* Delivery is deliberately not awaited, and neither is reading the
|
|
751
|
+
* configured webhook. SlackUtil retries three times with exponential
|
|
752
|
+
* backoff and sets no HTTP timeout, so awaiting it would let a webhook
|
|
753
|
+
* that hangs hold the plan-change response open with it - for a message
|
|
754
|
+
* whose contents are already on the error log above. Same shape as
|
|
755
|
+
* sendSubscriptionChangeWebhookSlackNotification below.
|
|
756
|
+
*/
|
|
757
|
+
try {
|
|
758
|
+
SlackUtil.sendMessageToChannelViaIncomingWebhook({
|
|
759
|
+
url: URL.fromString(NotificationSlackWebhookOnSubscriptionUpdate),
|
|
760
|
+
text: slackMessage,
|
|
761
|
+
}).catch((error: Error) => {
|
|
762
|
+
logger.error("Error sending slack message: " + error, {
|
|
763
|
+
projectId: data.projectId.toString(),
|
|
764
|
+
} as LogAttributes);
|
|
765
|
+
});
|
|
766
|
+
} catch (error) {
|
|
767
|
+
logger.error("Error sending slack message: " + error, {
|
|
768
|
+
projectId: data.projectId.toString(),
|
|
769
|
+
} as LogAttributes);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
|
|
660
773
|
/*
|
|
661
774
|
* Pushes a project's trial end date out to a new date, in the payment
|
|
662
775
|
* provider first and then on the project row.
|
|
@@ -2224,11 +2337,13 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
2224
2337
|
}
|
|
2225
2338
|
|
|
2226
2339
|
/*
|
|
2227
|
-
* Reactivating goes through changePlan,
|
|
2228
|
-
*
|
|
2229
|
-
*
|
|
2230
|
-
* trial
|
|
2231
|
-
*
|
|
2340
|
+
* Reactivating goes through changePlan, and it is the one caller that
|
|
2341
|
+
* genuinely lands on its recreate path: the subscriptions being reactivated
|
|
2342
|
+
* are not live, so there is nothing to update and new ones are created. A
|
|
2343
|
+
* trial the project still has to run therefore has to be carried onto the
|
|
2344
|
+
* replacements explicitly. Otherwise a customer whose trial a master admin
|
|
2345
|
+
* extended as a goodwill gesture loses the extension the moment their
|
|
2346
|
+
* subscription is reactivated, and is billed right away.
|
|
2232
2347
|
*
|
|
2233
2348
|
* A trial that has already lapsed is not revived: reactivation is not the
|
|
2234
2349
|
* place to hand out free service.
|
|
@@ -2242,6 +2357,7 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
2242
2357
|
subscriptionId: string;
|
|
2243
2358
|
meteredSubscriptionId: string;
|
|
2244
2359
|
trialEndsAt?: Date | undefined;
|
|
2360
|
+
subscriptionIdsPendingCancellation: Array<string>;
|
|
2245
2361
|
} = await BillingService.changePlan({
|
|
2246
2362
|
projectId: project.id as ObjectID,
|
|
2247
2363
|
subscriptionId: project.paymentProviderSubscriptionId,
|
|
@@ -2254,25 +2370,34 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
2254
2370
|
});
|
|
2255
2371
|
|
|
2256
2372
|
// refresh subscription status.
|
|
2257
|
-
const subscriptionState: SubscriptionStatus =
|
|
2258
|
-
await
|
|
2259
|
-
result.subscriptionId as string,
|
|
2260
|
-
);
|
|
2373
|
+
const subscriptionState: SubscriptionStatus | null =
|
|
2374
|
+
await this.findSubscriptionStatus(result.subscriptionId as string);
|
|
2261
2375
|
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2376
|
+
/*
|
|
2377
|
+
* The metered subscription changePlan returns, not the one the project row
|
|
2378
|
+
* still points at. When changePlan replaced the subscriptions the old id
|
|
2379
|
+
* names a cancelled subscription, and its status would be persisted against
|
|
2380
|
+
* the new one.
|
|
2381
|
+
*/
|
|
2382
|
+
const meteredSubscriptionState: SubscriptionStatus | null =
|
|
2383
|
+
await this.findSubscriptionStatus(result.meteredSubscriptionId as string);
|
|
2266
2384
|
|
|
2267
2385
|
// now update project with new subscription id.
|
|
2268
2386
|
|
|
2269
2387
|
const updateData: QueryDeepPartialEntity<Model> = {
|
|
2270
2388
|
paymentProviderSubscriptionId: result.subscriptionId,
|
|
2271
2389
|
paymentProviderMeteredSubscriptionId: result.meteredSubscriptionId,
|
|
2272
|
-
paymentProviderSubscriptionStatus: subscriptionState,
|
|
2273
|
-
paymentProviderMeteredSubscriptionStatus: meteredSubscriptionState,
|
|
2274
2390
|
};
|
|
2275
2391
|
|
|
2392
|
+
if (subscriptionState) {
|
|
2393
|
+
updateData.paymentProviderSubscriptionStatus = subscriptionState;
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
if (meteredSubscriptionState) {
|
|
2397
|
+
updateData.paymentProviderMeteredSubscriptionStatus =
|
|
2398
|
+
meteredSubscriptionState;
|
|
2399
|
+
}
|
|
2400
|
+
|
|
2276
2401
|
/*
|
|
2277
2402
|
* The payment provider is the source of truth for the trial the new
|
|
2278
2403
|
* subscriptions were created with, so its date wins over the one sent.
|
|
@@ -2293,6 +2418,11 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
2293
2418
|
},
|
|
2294
2419
|
});
|
|
2295
2420
|
|
|
2421
|
+
this.alertOnSubscriptionsPendingCancellation({
|
|
2422
|
+
projectId: project.id!,
|
|
2423
|
+
subscriptionIds: result.subscriptionIdsPendingCancellation,
|
|
2424
|
+
});
|
|
2425
|
+
|
|
2296
2426
|
// send slack message on plan change.
|
|
2297
2427
|
await this.sendSubscriptionChangeWebhookSlackNotification(projectId);
|
|
2298
2428
|
}
|
|
@@ -5,6 +5,7 @@ import Model from "../../Models/DatabaseModels/ProxmoxCluster";
|
|
|
5
5
|
import Label from "../../Models/DatabaseModels/Label";
|
|
6
6
|
import { OnCreate } from "../Types/Database/Hooks";
|
|
7
7
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
8
|
+
import ResourceHeartbeat from "../Utils/Telemetry/ResourceHeartbeat";
|
|
8
9
|
import ObjectID from "../../Types/ObjectID";
|
|
9
10
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
10
11
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -177,7 +178,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
177
178
|
guestsWithoutBackupCount?: number | undefined;
|
|
178
179
|
},
|
|
179
180
|
): Promise<void> {
|
|
180
|
-
const cacheKey: string = clusterId.toString();
|
|
181
181
|
const extrasFingerprint: string = crypto
|
|
182
182
|
.createHash("sha1")
|
|
183
183
|
.update(
|
|
@@ -193,71 +193,53 @@ export class Service extends DatabaseService<Model> {
|
|
|
193
193
|
)
|
|
194
194
|
.digest("hex");
|
|
195
195
|
|
|
196
|
-
let cached: string | null = null;
|
|
197
|
-
try {
|
|
198
|
-
cached = await GlobalCache.getString(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
199
|
-
} catch {
|
|
200
|
-
/*
|
|
201
|
-
* Cache unavailable — fail open and refresh lastSeenAt anyway. A
|
|
202
|
-
* cache error must never skip the DB write below, otherwise the
|
|
203
|
-
* resource is wrongly marked "disconnected" while telemetry is
|
|
204
|
-
* still flowing. Mirrors shouldRunMaintenance's fail-open stance.
|
|
205
|
-
*/
|
|
206
|
-
cached = null;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (cached === extrasFingerprint) {
|
|
210
|
-
return; // same data was written recently
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
await GlobalCache.setString(
|
|
215
|
-
LAST_SEEN_CACHE_NAMESPACE,
|
|
216
|
-
cacheKey,
|
|
217
|
-
extrasFingerprint,
|
|
218
|
-
{ expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
|
|
219
|
-
);
|
|
220
|
-
} catch {
|
|
221
|
-
// Best-effort throttle write; proceed with the DB update regardless.
|
|
222
|
-
}
|
|
223
|
-
|
|
224
196
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
225
|
-
const
|
|
197
|
+
const liveness: any = {
|
|
226
198
|
lastSeenAt: OneUptimeDate.getCurrentDate(),
|
|
227
199
|
otelCollectorStatus: "connected",
|
|
228
200
|
};
|
|
229
201
|
|
|
202
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
203
|
+
const metadata: any = {};
|
|
204
|
+
|
|
230
205
|
if (extra?.pveVersion) {
|
|
231
|
-
|
|
206
|
+
metadata.pveVersion = extra.pveVersion;
|
|
232
207
|
}
|
|
233
208
|
if (extra?.agentVersion) {
|
|
234
|
-
|
|
209
|
+
metadata.agentVersion = extra.agentVersion;
|
|
235
210
|
}
|
|
236
211
|
// Counts: 0 is a legitimate value — gate on undefined, not falsiness.
|
|
237
212
|
if (extra?.nodeCount !== undefined) {
|
|
238
|
-
|
|
213
|
+
metadata.nodeCount = extra.nodeCount;
|
|
239
214
|
}
|
|
240
215
|
if (extra?.onlineNodeCount !== undefined) {
|
|
241
|
-
|
|
216
|
+
metadata.onlineNodeCount = extra.onlineNodeCount;
|
|
242
217
|
}
|
|
243
218
|
if (extra?.guestCount !== undefined) {
|
|
244
|
-
|
|
219
|
+
metadata.guestCount = extra.guestCount;
|
|
245
220
|
}
|
|
246
221
|
if (extra?.storageCount !== undefined) {
|
|
247
|
-
|
|
222
|
+
metadata.storageCount = extra.storageCount;
|
|
248
223
|
}
|
|
249
224
|
if (extra?.guestsWithoutBackupCount !== undefined) {
|
|
250
|
-
|
|
225
|
+
metadata.guestsWithoutBackupCount = extra.guestsWithoutBackupCount;
|
|
251
226
|
}
|
|
252
227
|
|
|
253
228
|
/*
|
|
254
|
-
*
|
|
255
|
-
*
|
|
256
|
-
*
|
|
229
|
+
* One gated, non-blocking heartbeat write. The gates, the fail-open /
|
|
230
|
+
* fail-closed split and the liveness-only fallback all live in
|
|
231
|
+
* ResourceHeartbeat — see there for why this row's throttle used to
|
|
232
|
+
* provide no throttling at all.
|
|
257
233
|
*/
|
|
258
|
-
await
|
|
234
|
+
await ResourceHeartbeat.write({
|
|
235
|
+
service: this,
|
|
259
236
|
id: clusterId,
|
|
260
|
-
|
|
237
|
+
cacheNamespace: LAST_SEEN_CACHE_NAMESPACE,
|
|
238
|
+
throttleInSeconds: LAST_SEEN_THROTTLE_SECONDS,
|
|
239
|
+
liveness: liveness,
|
|
240
|
+
metadata: metadata,
|
|
241
|
+
fingerprint: extrasFingerprint,
|
|
242
|
+
describe: `proxmox cluster ${clusterId.toString()}`,
|
|
261
243
|
});
|
|
262
244
|
}
|
|
263
245
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import DatabaseService from "./DatabaseService";
|
|
2
2
|
import Model from "../../Models/DatabaseModels/ProxmoxResource";
|
|
3
3
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
4
|
+
import ColumnLength from "../../Types/Database/ColumnLength";
|
|
4
5
|
import ObjectID from "../../Types/ObjectID";
|
|
5
6
|
import OneUptimeDate from "../../Types/Date";
|
|
6
7
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
8
|
+
import { truncateShortText } from "../Utils/Database/TruncateColumnValue";
|
|
7
9
|
import logger from "../Utils/Logger";
|
|
8
10
|
|
|
9
11
|
/*
|
|
@@ -89,6 +91,26 @@ const UPSERT_COLUMNS: Array<string> = [
|
|
|
89
91
|
"version",
|
|
90
92
|
];
|
|
91
93
|
|
|
94
|
+
/*
|
|
95
|
+
* ProxmoxResource's text columns are all ShortText (100 chars). The
|
|
96
|
+
* bulk paths below go through manager.query(), which skips the length
|
|
97
|
+
* validation DatabaseService applies to ordinary writes, so a single
|
|
98
|
+
* oversized value aborts the whole 500-row INSERT chunk it rides in.
|
|
99
|
+
* Clamp per value instead, so one pathological guest can never drop the
|
|
100
|
+
* rest of the scrape.
|
|
101
|
+
*/
|
|
102
|
+
function sanitizeResource(r: ParsedProxmoxResource): ParsedProxmoxResource {
|
|
103
|
+
return {
|
|
104
|
+
...r,
|
|
105
|
+
kind: truncateShortText(r.kind),
|
|
106
|
+
externalId: truncateShortText(r.externalId),
|
|
107
|
+
name: truncateShortText(r.name),
|
|
108
|
+
guestType: truncateShortText(r.guestType),
|
|
109
|
+
parentNodeName: truncateShortText(r.parentNodeName),
|
|
110
|
+
haState: truncateShortText(r.haState),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
92
114
|
export class Service extends DatabaseService<Model> {
|
|
93
115
|
public constructor() {
|
|
94
116
|
super(Model);
|
|
@@ -116,9 +138,21 @@ export class Service extends DatabaseService<Model> {
|
|
|
116
138
|
return;
|
|
117
139
|
}
|
|
118
140
|
|
|
141
|
+
const resources: Array<ParsedProxmoxResource> = data.resources.map(
|
|
142
|
+
(r: ParsedProxmoxResource) => {
|
|
143
|
+
const sanitized: ParsedProxmoxResource = sanitizeResource(r);
|
|
144
|
+
if (sanitized.externalId !== r.externalId) {
|
|
145
|
+
logger.warn(
|
|
146
|
+
`ProxmoxResource externalId exceeds ${ColumnLength.ShortText} chars; truncated to "${sanitized.externalId}" (cluster ${data.proxmoxClusterId.toString()}).`,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return sanitized;
|
|
150
|
+
},
|
|
151
|
+
);
|
|
152
|
+
|
|
119
153
|
// Chunk to keep individual statement parameter counts reasonable.
|
|
120
|
-
for (let i: number = 0; i <
|
|
121
|
-
const chunk: Array<ParsedProxmoxResource> =
|
|
154
|
+
for (let i: number = 0; i < resources.length; i += UPSERT_BATCH_SIZE) {
|
|
155
|
+
const chunk: Array<ParsedProxmoxResource> = resources.slice(
|
|
122
156
|
i,
|
|
123
157
|
i + UPSERT_BATCH_SIZE,
|
|
124
158
|
);
|
|
@@ -219,9 +253,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
219
253
|
valueFragments.push(
|
|
220
254
|
`($${paramIndex++}, $${paramIndex++}, $${paramIndex++}::numeric, $${paramIndex++}::bigint, $${paramIndex++}::bigint, $${paramIndex++}::numeric, $${paramIndex++}::bigint, $${paramIndex++}::bigint, $${paramIndex++}::timestamptz)`,
|
|
221
255
|
);
|
|
256
|
+
/*
|
|
257
|
+
* The identity clamps MUST match bulkUpsert's, or this mirror
|
|
258
|
+
* UPDATE would silently miss the row the upsert just wrote
|
|
259
|
+
* under the truncated externalId.
|
|
260
|
+
*/
|
|
222
261
|
params.push(
|
|
223
|
-
m.kind,
|
|
224
|
-
m.externalId,
|
|
262
|
+
truncateShortText(m.kind),
|
|
263
|
+
truncateShortText(m.externalId),
|
|
225
264
|
m.cpuPercent !== null && m.cpuPercent !== undefined
|
|
226
265
|
? m.cpuPercent
|
|
227
266
|
: null,
|
|
@@ -2,6 +2,7 @@ import DatabaseService from "./DatabaseService";
|
|
|
2
2
|
import Model from "../../Models/DatabaseModels/RumApplication";
|
|
3
3
|
import Label from "../../Models/DatabaseModels/Label";
|
|
4
4
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
5
|
+
import ResourceHeartbeat from "../Utils/Telemetry/ResourceHeartbeat";
|
|
5
6
|
import ObjectID from "../../Types/ObjectID";
|
|
6
7
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
7
8
|
import OneUptimeDate from "../../Types/Date";
|
|
@@ -276,7 +277,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
276
277
|
sdkLanguage?: string | undefined;
|
|
277
278
|
},
|
|
278
279
|
): Promise<void> {
|
|
279
|
-
const cacheKey: string = rumApplicationId.toString();
|
|
280
280
|
const extrasFingerprint: string = crypto
|
|
281
281
|
.createHash("sha1")
|
|
282
282
|
.update(
|
|
@@ -288,58 +288,40 @@ export class Service extends DatabaseService<Model> {
|
|
|
288
288
|
)
|
|
289
289
|
.digest("hex");
|
|
290
290
|
|
|
291
|
-
let cached: string | null = null;
|
|
292
|
-
try {
|
|
293
|
-
cached = await GlobalCache.getString(LAST_SEEN_CACHE_NAMESPACE, cacheKey);
|
|
294
|
-
} catch {
|
|
295
|
-
/*
|
|
296
|
-
* Cache unavailable — fail open and refresh lastSeenAt anyway. A
|
|
297
|
-
* cache error must never skip the DB write below, otherwise the
|
|
298
|
-
* resource is wrongly marked "disconnected" while telemetry is
|
|
299
|
-
* still flowing. Mirrors shouldRunMaintenance's fail-open stance.
|
|
300
|
-
*/
|
|
301
|
-
cached = null;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (cached === extrasFingerprint) {
|
|
305
|
-
return; // same data was written recently
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
try {
|
|
309
|
-
await GlobalCache.setString(
|
|
310
|
-
LAST_SEEN_CACHE_NAMESPACE,
|
|
311
|
-
cacheKey,
|
|
312
|
-
extrasFingerprint,
|
|
313
|
-
{ expiresInSeconds: LAST_SEEN_THROTTLE_SECONDS },
|
|
314
|
-
);
|
|
315
|
-
} catch {
|
|
316
|
-
// Best-effort throttle write; proceed with the DB update regardless.
|
|
317
|
-
}
|
|
318
|
-
|
|
319
291
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
320
|
-
const
|
|
292
|
+
const liveness: any = {
|
|
321
293
|
lastSeenAt: OneUptimeDate.getCurrentDate(),
|
|
322
294
|
otelCollectorStatus: "connected",
|
|
323
295
|
};
|
|
324
296
|
|
|
297
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
298
|
+
const metadata: any = {};
|
|
299
|
+
|
|
325
300
|
if (extra?.agentVersion) {
|
|
326
|
-
|
|
301
|
+
metadata.agentVersion = extra.agentVersion;
|
|
327
302
|
}
|
|
328
303
|
if (extra?.clientType) {
|
|
329
|
-
|
|
304
|
+
metadata.clientType = extra.clientType;
|
|
330
305
|
}
|
|
331
306
|
if (extra?.sdkLanguage) {
|
|
332
|
-
|
|
307
|
+
metadata.sdkLanguage = extra.sdkLanguage;
|
|
333
308
|
}
|
|
334
309
|
|
|
335
310
|
/*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
311
|
+
* One gated, non-blocking heartbeat write. The gates, the fail-open /
|
|
312
|
+
* fail-closed split and the liveness-only fallback all live in
|
|
313
|
+
* ResourceHeartbeat — see there for why this row's throttle used to
|
|
314
|
+
* provide no throttling at all.
|
|
339
315
|
*/
|
|
340
|
-
await
|
|
316
|
+
await ResourceHeartbeat.write({
|
|
317
|
+
service: this,
|
|
341
318
|
id: rumApplicationId,
|
|
342
|
-
|
|
319
|
+
cacheNamespace: LAST_SEEN_CACHE_NAMESPACE,
|
|
320
|
+
throttleInSeconds: LAST_SEEN_THROTTLE_SECONDS,
|
|
321
|
+
liveness: liveness,
|
|
322
|
+
metadata: metadata,
|
|
323
|
+
fingerprint: extrasFingerprint,
|
|
324
|
+
describe: `rum application ${rumApplicationId.toString()}`,
|
|
343
325
|
});
|
|
344
326
|
}
|
|
345
327
|
|
|
@@ -26,6 +26,7 @@ import ScheduledMaintenanceStateTimeline from "../../Models/DatabaseModels/Sched
|
|
|
26
26
|
import { IsBillingEnabled } from "../EnvironmentConfig";
|
|
27
27
|
import ScheduledMaintenanceFeedService from "./ScheduledMaintenanceFeedService";
|
|
28
28
|
import { ScheduledMaintenanceFeedEventType } from "../../Models/DatabaseModels/ScheduledMaintenanceFeed";
|
|
29
|
+
import ProjectScopedReferenceValidator from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
29
30
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
30
31
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
31
32
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
@@ -122,6 +123,26 @@ export class Service extends DatabaseService<ScheduledMaintenanceStateTimeline>
|
|
|
122
123
|
throw new BadDataException("scheduledMaintenanceStateId is null");
|
|
123
124
|
}
|
|
124
125
|
|
|
126
|
+
/*
|
|
127
|
+
* Same guard, same reason, as MonitorStatusTimelineService: an id that
|
|
128
|
+
* exists nowhere (or belongs to another project) used to reach Postgres
|
|
129
|
+
* and come back as a raw foreign key violation. The ordering check below
|
|
130
|
+
* does look the state up, but only when there IS a preceding row with an
|
|
131
|
+
* order, so the first timeline row for a scheduled maintenance event went
|
|
132
|
+
* through unchecked.
|
|
133
|
+
*/
|
|
134
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
135
|
+
projectId: createBy.props.tenantId || createBy.data.projectId,
|
|
136
|
+
subject: "scheduled maintenance state timeline",
|
|
137
|
+
references: [
|
|
138
|
+
{
|
|
139
|
+
modelName: "Scheduled Maintenance State",
|
|
140
|
+
id: scheduledMaintenanceStateId,
|
|
141
|
+
service: ScheduledMaintenanceStateService,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
});
|
|
145
|
+
|
|
125
146
|
const stateBeforeThis: ScheduledMaintenanceStateTimeline | null =
|
|
126
147
|
await this.findOneBy({
|
|
127
148
|
query: {
|