@oneuptime/common 12.0.2 → 12.0.4
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/CephCluster.ts +14 -0
- package/Models/DatabaseModels/CodeRepository.ts +14 -6
- package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +14 -0
- package/Models/DatabaseModels/DockerHost.ts +14 -0
- package/Models/DatabaseModels/GlobalOidcProject.ts +18 -0
- package/Models/DatabaseModels/GlobalSsoProject.ts +18 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/IoTFleet.ts +14 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +14 -0
- package/Models/DatabaseModels/LogDropFilter.ts +9 -20
- package/Models/DatabaseModels/NetworkDevice.ts +14 -0
- package/Models/DatabaseModels/NetworkInterface.ts +18 -0
- package/Models/DatabaseModels/Project.ts +16 -2
- package/Models/DatabaseModels/ProxmoxCluster.ts +14 -0
- package/Models/DatabaseModels/Service.ts +30 -0
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +911 -0
- package/Models/DatabaseModels/StatusPagePrivateUser.ts +30 -0
- package/Models/DatabaseModels/StatusPageResource.ts +73 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +9 -20
- package/Models/DatabaseModels/User.ts +30 -0
- package/Server/API/AIAgentDataAPI.ts +31 -0
- package/Server/API/BaseAPI.ts +13 -2
- package/Server/API/DashboardAPI.ts +458 -12
- package/Server/API/GitHubAPI.ts +119 -283
- package/Server/API/UserAPI.ts +263 -1
- package/Server/EnvironmentConfig.ts +38 -4
- package/Server/Infrastructure/GlobalCache.ts +152 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +16 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.ts +123 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.ts +21 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.ts +68 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +100 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +214 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.ts +69 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Services/AlertStateTimelineService.ts +20 -0
- package/Server/Services/AnalyticsDatabaseService.ts +72 -1
- package/Server/Services/CephClusterService.ts +26 -86
- package/Server/Services/CloudResourceService.ts +23 -83
- package/Server/Services/CodeRepositoryService.ts +105 -2
- package/Server/Services/DatabaseService.ts +296 -2
- package/Server/Services/DockerHostService.ts +19 -79
- package/Server/Services/DockerSwarmClusterService.ts +27 -88
- package/Server/Services/HostService.ts +46 -99
- package/Server/Services/IncidentStateTimelineService.ts +20 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTFleetService.ts +19 -79
- package/Server/Services/KubernetesClusterService.ts +17 -78
- package/Server/Services/LabelService.ts +57 -10
- package/Server/Services/MetricTypeService.ts +84 -0
- package/Server/Services/MonitorService.ts +89 -14
- package/Server/Services/MonitorStatusTimelineService.ts +29 -0
- package/Server/Services/MonitorTemplateService.ts +65 -0
- package/Server/Services/OpenTelemetryIngestService.ts +230 -26
- package/Server/Services/PodmanHostService.ts +19 -79
- package/Server/Services/ProxmoxClusterService.ts +23 -83
- package/Server/Services/RumApplicationService.ts +19 -80
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +21 -0
- package/Server/Services/ServerlessFunctionService.ts +24 -85
- package/Server/Services/ServiceService.ts +299 -73
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +752 -0
- package/Server/Services/StatusPageMonitorRuleService.ts +471 -0
- package/Server/Services/TelemetryEntityRelationshipService.ts +1 -0
- package/Server/Services/TelemetryEntityService.ts +1 -0
- package/Server/Services/UserService.ts +184 -0
- package/Server/Utils/AI/Toolbox/CodeTools.ts +45 -4
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +13 -0
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +157 -4
- package/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.ts +130 -0
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +170 -39
- 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/PasswordHash.ts +306 -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/OverviewCustomFields.test.tsx +333 -0
- package/Tests/App/Dashboard/UserCustomFields.test.tsx +392 -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/AIAgentDataRepositoryToken.test.ts +381 -0
- package/Tests/Server/API/DashboardPublicAttributeValuesAPI.test.ts +943 -0
- package/Tests/Server/API/DashboardPublicMetricsAggregateAPI.test.ts +1296 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +26 -0
- package/Tests/Server/API/DashboardPublicTemplatePayloads.test.ts +598 -0
- package/Tests/Server/API/GitHubAppInstallationBindingAPI.test.ts +539 -0
- package/Tests/Server/API/Helpers.ts +6 -1
- package/Tests/Server/API/UserProjectsAPI.test.ts +852 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +354 -0
- package/Tests/Server/Infrastructure/PostgresLockTimeoutOptions.test.ts +181 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +215 -0
- package/Tests/Server/Services/AddPerUserPasswordSaltMigration.test.ts +178 -0
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +582 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +5 -0
- package/Tests/Server/Services/CodeRepositoryInstallationBinding.test.ts +305 -0
- package/Tests/Server/Services/CodeRepositoryResolutionBinding.test.ts +147 -0
- package/Tests/Server/Services/DatabaseServicePerUserPasswordSalt.test.ts +870 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlocked.test.ts +342 -0
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +245 -0
- package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +163 -15
- 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/OpenTelemetryServiceResolutionCache.test.ts +568 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +305 -56
- package/Tests/Server/Services/RestoreDroppedUniqueIndexesMigration.test.ts +386 -0
- package/Tests/Server/Services/RestoreServiceLowerNameIndexMigration.test.ts +240 -0
- package/Tests/Server/Services/ServiceUpdateLastSeenSplitGates.test.ts +705 -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/UserServiceFirstMasterAdminElection.test.ts +885 -0
- package/Tests/Server/Services/WidenHashedStringColumnsForScryptMigration.test.ts +220 -0
- package/Tests/Server/Utils/AI/CodeTools.test.ts +47 -1
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +10 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +267 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +120 -0
- package/Tests/Server/Utils/CodeRepository/GitHubInstallationBinding.test.ts +292 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +260 -13
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +302 -0
- package/Tests/Server/Utils/GitHubInstallationOwnershipVerification.test.ts +340 -0
- package/Tests/Server/Utils/GitHubWebhookAndTreeCacheIsolation.test.ts +250 -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/PasswordHash.test.ts +555 -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/ColumnLength.test.ts +7 -1
- 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/HashedStringPerUserSalt.test.ts +476 -0
- package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +293 -0
- package/Tests/Types/Monitor/HostAlertTemplates.test.ts +249 -0
- package/Tests/Types/Monitor/IotAlertTemplates.test.ts +320 -0
- package/Tests/Types/Monitor/PodmanAlertTemplates.test.ts +271 -0
- package/Tests/Types/Monitor/SnmpVersionParsing.test.ts +152 -0
- package/Tests/Types/Port.test.ts +38 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetail.test.tsx +696 -0
- package/Tests/UI/Components/LogsHistogram.test.tsx +276 -0
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +489 -0
- package/Tests/UI/Components/UseLogsHistogram.test.tsx +500 -0
- package/Tests/UI/Utils/UserProjectsModelAPI.test.ts +714 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentsUtil.test.ts +120 -0
- package/Tests/Utils/Dashboard/DashboardNetworkMapComponent.test.ts +327 -0
- package/Tests/Utils/TeamMembersByProject.test.ts +655 -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/ColumnLength.ts +9 -1
- package/Types/Database/DatabaseProperty.ts +26 -0
- package/Types/Database/NumericColumnValue.ts +128 -0
- package/Types/Database/TableColumn.ts +11 -0
- package/Types/Database/UnsynchronizedIndex.ts +48 -0
- package/Types/Decimal.ts +16 -4
- package/Types/HashedString.ts +139 -4
- package/Types/Permission.ts +48 -0
- package/Types/Port.ts +16 -4
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +85 -11
- package/UI/Components/LogsViewer/useLiveLogsRefresh.ts +86 -0
- package/UI/Components/LogsViewer/useLogsHistogram.ts +113 -0
- package/UI/Components/Navbar/NavBar.tsx +12 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +19 -7
- package/UI/Utils/ModelAPI/UserProjectsModelAPI.ts +257 -0
- package/Utils/Dashboard/Components/DashboardNetworkMapComponent.ts +136 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/TeamMembersByProject.ts +237 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +14 -6
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- 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/DockerHost.js +16 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +16 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +16 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.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/IoTFleet.js +16 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.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/NetworkDevice.js +16 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkInterface.js +16 -1
- package/build/dist/Models/DatabaseModels/NetworkInterface.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +16 -2
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +28 -1
- package/build/dist/Models/DatabaseModels/Service.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/StatusPagePrivateUser.js +32 -0
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
- 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/Models/DatabaseModels/User.js +32 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +21 -2
- package/build/dist/Server/API/AIAgentDataAPI.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 +343 -10
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GitHubAPI.js +94 -167
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +187 -2
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +34 -4
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +120 -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/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/1786018109307-AddPerUserPasswordSalt.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.js +59 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +93 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.js +101 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.js +66 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.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/AnalyticsDatabaseService.js +57 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +26 -76
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +23 -73
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/CodeRepositoryService.js +90 -2
- package/build/dist/Server/Services/CodeRepositoryService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +246 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +19 -69
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +27 -78
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +58 -102
- 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/IoTFleetService.js +19 -69
- package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +17 -68
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +42 -7
- 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 +81 -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/OpenTelemetryIngestService.js +155 -25
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +19 -69
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +23 -73
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationService.js +19 -70
- 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 -75
- package/build/dist/Server/Services/ServerlessFunctionService.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/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/Services/UserService.js +165 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js +31 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +13 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +126 -4
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.js +136 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.js.map +1 -0
- 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/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/PasswordHash.js +237 -0
- package/build/dist/Server/Utils/PasswordHash.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/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/ColumnLength.js +9 -1
- package/build/dist/Types/Database/ColumnLength.js.map +1 -1
- 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/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Database/UnsynchronizedIndex.js +46 -0
- package/build/dist/Types/Database/UnsynchronizedIndex.js.map +1 -0
- package/build/dist/Types/Decimal.js +14 -3
- package/build/dist/Types/Decimal.js.map +1 -1
- package/build/dist/Types/HashedString.js +95 -5
- package/build/dist/Types/HashedString.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/UI/Components/CustomFields/CustomFieldsDetail.js +51 -10
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- 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/Navbar/NavBar.js +3 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +19 -7
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/UserProjectsModelAPI.js +156 -0
- package/build/dist/UI/Utils/ModelAPI/UserProjectsModelAPI.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/TeamMembersByProject.js +145 -0
- package/build/dist/Utils/TeamMembersByProject.js.map +1 -0
- package/package.json +1 -1
|
@@ -5,22 +5,159 @@ import MetricType from "../../../Models/DatabaseModels/MetricType";
|
|
|
5
5
|
import MetricTypeService from "../../Services/MetricTypeService";
|
|
6
6
|
import Service from "../../../Models/DatabaseModels/Service";
|
|
7
7
|
import Dictionary from "../../../Types/Dictionary";
|
|
8
|
+
import GlobalCache from "../../Infrastructure/GlobalCache";
|
|
9
|
+
import logger from "../Logger";
|
|
10
|
+
import crypto from "crypto";
|
|
8
11
|
|
|
9
12
|
export type AttributeType = string | number | boolean | null;
|
|
10
13
|
|
|
14
|
+
/*
|
|
15
|
+
* Shares the namespace used by the OTLP maintenance fences so the metric
|
|
16
|
+
* catalog is throttled by the same machinery, with the same TTL, as every
|
|
17
|
+
* other per-batch reconcile on the ingest path.
|
|
18
|
+
*/
|
|
19
|
+
const METRIC_TYPE_FENCE_NAMESPACE: string = "otel-maintenance-fence";
|
|
20
|
+
const METRIC_TYPE_FENCE_TTL_SECONDS: number = 5 * 60; // 5 minutes
|
|
21
|
+
|
|
11
22
|
export default class TelemetryUtil {
|
|
23
|
+
/*
|
|
24
|
+
* Reconcile the metric catalog: one MetricType row per (project, metric
|
|
25
|
+
* name), carrying its description/unit/counter-semantics and the set of
|
|
26
|
+
* services that emit it.
|
|
27
|
+
*
|
|
28
|
+
* This runs on the ingest hot path, once per distinct metric name per batch,
|
|
29
|
+
* and it used to be the only per-batch Postgres writer with no fence, no
|
|
30
|
+
* cache and no dedup of any kind. It had two separate defects that together
|
|
31
|
+
* made it write on EVERY batch, forever:
|
|
32
|
+
*
|
|
33
|
+
* 1. Rows are created with `description || ""`, so the stored value is `""`
|
|
34
|
+
* whenever OTLP omits the field — but the INCOMING value is `undefined`
|
|
35
|
+
* for the same case (protobuf omits unset scalars). `"" !== undefined`
|
|
36
|
+
* is true, so the "has anything changed?" check answered yes on every
|
|
37
|
+
* batch for every metric without a description or unit. The counter
|
|
38
|
+
* semantics below already had the correct `!== undefined` guard;
|
|
39
|
+
* description and unit were simply left behind.
|
|
40
|
+
* 2. The write shipped the whole `services` array, which routes through
|
|
41
|
+
* `save()` — a multi-round-trip transaction holding the row's write lock
|
|
42
|
+
* — and deletes any association not present in the current batch.
|
|
43
|
+
*
|
|
44
|
+
* Both are fixed here. Absent now means "unknown", not "clear", and the two
|
|
45
|
+
* kinds of change are tracked separately so a scalar edit takes a single
|
|
46
|
+
* auto-committed UPDATE and an association takes an additive insert.
|
|
47
|
+
*
|
|
48
|
+
* A fence in front of the whole thing removes the SELECT as well as the
|
|
49
|
+
* write in the steady state. The fence key includes the batch's service set:
|
|
50
|
+
* `servicesInMap` holds only the services in THIS batch, so keying on the
|
|
51
|
+
* name alone would let a batch from service A satisfy the fence and suppress
|
|
52
|
+
* the association that a concurrent batch from service B still needs.
|
|
53
|
+
*/
|
|
12
54
|
@CaptureSpan()
|
|
13
55
|
public static async indexMetricNameServiceNameMap(data: {
|
|
14
56
|
projectId: ObjectID;
|
|
15
57
|
metricNameServiceNameMap: Dictionary<MetricType>;
|
|
16
58
|
}): Promise<void> {
|
|
17
59
|
for (const metricName of Object.keys(data.metricNameServiceNameMap)) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
60
|
+
const metricTypeInMap: MetricType =
|
|
61
|
+
data.metricNameServiceNameMap[metricName]!;
|
|
62
|
+
|
|
63
|
+
// check if services are same as the ones in the map
|
|
64
|
+
const servicesInMap: Array<ObjectID> =
|
|
65
|
+
metricTypeInMap?.services?.map((service: Service) => {
|
|
66
|
+
return service.id!;
|
|
67
|
+
}) || [];
|
|
68
|
+
|
|
69
|
+
const fenceKey: string = TelemetryUtil.buildMetricTypeFenceKey({
|
|
70
|
+
projectId: data.projectId,
|
|
71
|
+
metricName: metricName,
|
|
72
|
+
serviceIds: servicesInMap,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (
|
|
76
|
+
!(await TelemetryUtil.shouldIndexMetricType(
|
|
77
|
+
fenceKey,
|
|
78
|
+
TelemetryUtil.fingerprintMetricTypeScalars(metricTypeInMap),
|
|
79
|
+
))
|
|
80
|
+
) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
await TelemetryUtil.reconcileMetricType({
|
|
21
86
|
projectId: data.projectId,
|
|
22
|
-
|
|
23
|
-
|
|
87
|
+
metricName: metricName,
|
|
88
|
+
metricTypeInMap: metricTypeInMap,
|
|
89
|
+
servicesInMap: servicesInMap,
|
|
90
|
+
});
|
|
91
|
+
} catch (err) {
|
|
92
|
+
/*
|
|
93
|
+
* Per-metric isolation. This loop used to let any failure escape and
|
|
94
|
+
* abort indexing for every REMAINING metric name in the batch — and
|
|
95
|
+
* the only caller just logs, so a single bad row silently stopped the
|
|
96
|
+
* whole catalog from converging.
|
|
97
|
+
*/
|
|
98
|
+
await TelemetryUtil.clearMetricTypeFence(fenceKey);
|
|
99
|
+
|
|
100
|
+
logger.warn(
|
|
101
|
+
`TelemetryUtil.indexMetricNameServiceNameMap: failed to reconcile metric "${metricName}": ${
|
|
102
|
+
err instanceof Error ? err.message : String(err)
|
|
103
|
+
}`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private static async reconcileMetricType(data: {
|
|
110
|
+
projectId: ObjectID;
|
|
111
|
+
metricName: string;
|
|
112
|
+
metricTypeInMap: MetricType;
|
|
113
|
+
servicesInMap: Array<ObjectID>;
|
|
114
|
+
}): Promise<void> {
|
|
115
|
+
const { projectId, metricName, metricTypeInMap, servicesInMap } = data;
|
|
116
|
+
|
|
117
|
+
const metricType: MetricType | null = await MetricTypeService.findOneBy({
|
|
118
|
+
query: {
|
|
119
|
+
projectId: projectId,
|
|
120
|
+
name: metricName,
|
|
121
|
+
},
|
|
122
|
+
select: {
|
|
123
|
+
services: true,
|
|
124
|
+
name: true,
|
|
125
|
+
description: true,
|
|
126
|
+
unit: true,
|
|
127
|
+
isMonotonic: true,
|
|
128
|
+
aggregationTemporality: true,
|
|
129
|
+
},
|
|
130
|
+
props: {
|
|
131
|
+
isRoot: true,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
if (metricType) {
|
|
136
|
+
await TelemetryUtil.updateExistingMetricType({
|
|
137
|
+
metricType,
|
|
138
|
+
metricTypeInMap,
|
|
139
|
+
servicesInMap,
|
|
140
|
+
});
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
try {
|
|
145
|
+
await TelemetryUtil.createMetricType({
|
|
146
|
+
projectId,
|
|
147
|
+
metricName,
|
|
148
|
+
metricTypeInMap,
|
|
149
|
+
servicesInMap,
|
|
150
|
+
});
|
|
151
|
+
} catch (err) {
|
|
152
|
+
/*
|
|
153
|
+
* Uniqueness on (projectId, name) is enforced in application code by a
|
|
154
|
+
* countBy, not by a database constraint, so two workers can both decide
|
|
155
|
+
* to create the same metric. Re-find to disambiguate: a row now means a
|
|
156
|
+
* concurrent worker won (harmless — reconcile against it); no row means
|
|
157
|
+
* the insert itself was invalid and must surface.
|
|
158
|
+
*/
|
|
159
|
+
const winner: MetricType | null = await MetricTypeService.findOneBy({
|
|
160
|
+
query: { projectId: projectId, name: metricName },
|
|
24
161
|
select: {
|
|
25
162
|
services: true,
|
|
26
163
|
name: true,
|
|
@@ -29,137 +166,229 @@ export default class TelemetryUtil {
|
|
|
29
166
|
isMonotonic: true,
|
|
30
167
|
aggregationTemporality: true,
|
|
31
168
|
},
|
|
32
|
-
props: {
|
|
33
|
-
isRoot: true,
|
|
34
|
-
},
|
|
169
|
+
props: { isRoot: true },
|
|
35
170
|
});
|
|
36
171
|
|
|
37
|
-
|
|
38
|
-
|
|
172
|
+
if (!winner) {
|
|
173
|
+
throw err;
|
|
174
|
+
}
|
|
39
175
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return service.id!;
|
|
44
|
-
}) || [];
|
|
176
|
+
logger.debug(
|
|
177
|
+
`TelemetryUtil: create raced for metric "${metricName}" (concurrent insert); reconciling against the winning row.`,
|
|
178
|
+
);
|
|
45
179
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
180
|
+
await TelemetryUtil.updateExistingMetricType({
|
|
181
|
+
metricType: winner,
|
|
182
|
+
metricTypeInMap,
|
|
183
|
+
servicesInMap,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
50
187
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
188
|
+
private static async updateExistingMetricType(data: {
|
|
189
|
+
metricType: MetricType;
|
|
190
|
+
metricTypeInMap: MetricType;
|
|
191
|
+
servicesInMap: Array<ObjectID>;
|
|
192
|
+
}): Promise<void> {
|
|
193
|
+
const { metricType, metricTypeInMap, servicesInMap } = data;
|
|
56
194
|
|
|
57
|
-
|
|
195
|
+
if (!metricType.services) {
|
|
196
|
+
metricType.services = [];
|
|
197
|
+
}
|
|
58
198
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
199
|
+
const existingServiceIds: Set<string> = new Set<string>(
|
|
200
|
+
metricType.services.map((service: Service) => {
|
|
201
|
+
return service.id!.toString();
|
|
202
|
+
}),
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
/*
|
|
206
|
+
* Two flags, not one. A scalar edit and a new association need completely
|
|
207
|
+
* different statements, and conflating them is what forced every scalar
|
|
208
|
+
* edit through the relation-writing `save()` path.
|
|
209
|
+
*/
|
|
210
|
+
let scalarsChanged: boolean = false;
|
|
211
|
+
|
|
212
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
213
|
+
const scalarUpdate: any = {};
|
|
214
|
+
|
|
215
|
+
/*
|
|
216
|
+
* An absent incoming value means "this producer didn't say", not "clear
|
|
217
|
+
* the stored value" — the same rule the counter-semantics block below has
|
|
218
|
+
* always used. Without the truthiness guard, a stored `""` compared
|
|
219
|
+
* against an incoming `undefined` reported a change on every single batch.
|
|
220
|
+
*/
|
|
221
|
+
if (
|
|
222
|
+
metricTypeInMap.description &&
|
|
223
|
+
(metricType.description ?? "") !== metricTypeInMap.description
|
|
224
|
+
) {
|
|
225
|
+
scalarsChanged = true;
|
|
226
|
+
scalarUpdate.description = metricTypeInMap.description;
|
|
227
|
+
}
|
|
64
228
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
229
|
+
if (
|
|
230
|
+
metricTypeInMap.unit &&
|
|
231
|
+
(metricType.unit ?? "") !== metricTypeInMap.unit
|
|
232
|
+
) {
|
|
233
|
+
scalarsChanged = true;
|
|
234
|
+
scalarUpdate.unit = metricTypeInMap.unit;
|
|
235
|
+
}
|
|
70
236
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
237
|
+
/*
|
|
238
|
+
* Counter semantics (isMonotonic / aggregationTemporality) are only
|
|
239
|
+
* known on OTel metric ingest paths — other callers (monitor
|
|
240
|
+
* metrics, heartbeat metrics) never set them, so an undefined
|
|
241
|
+
* incoming value means "unknown", not "clear the stored value".
|
|
242
|
+
*/
|
|
243
|
+
if (
|
|
244
|
+
metricTypeInMap.isMonotonic !== undefined &&
|
|
245
|
+
metricType.isMonotonic !== metricTypeInMap.isMonotonic
|
|
246
|
+
) {
|
|
247
|
+
scalarsChanged = true;
|
|
248
|
+
scalarUpdate.isMonotonic = metricTypeInMap.isMonotonic;
|
|
249
|
+
}
|
|
84
250
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
251
|
+
if (
|
|
252
|
+
metricTypeInMap.aggregationTemporality !== undefined &&
|
|
253
|
+
metricType.aggregationTemporality !==
|
|
254
|
+
metricTypeInMap.aggregationTemporality
|
|
255
|
+
) {
|
|
256
|
+
scalarsChanged = true;
|
|
257
|
+
scalarUpdate.aggregationTemporality =
|
|
258
|
+
metricTypeInMap.aggregationTemporality;
|
|
259
|
+
}
|
|
94
260
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
261
|
+
const servicesToAttach: Array<ObjectID> = servicesInMap.filter(
|
|
262
|
+
(serviceId: ObjectID) => {
|
|
263
|
+
return !existingServiceIds.has(serviceId.toString());
|
|
264
|
+
},
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
if (scalarsChanged) {
|
|
268
|
+
/*
|
|
269
|
+
* One auto-committed UPDATE. Deliberately NOT updateOneById: with
|
|
270
|
+
* `services` absent from the payload that path still opens a transaction
|
|
271
|
+
* and bumps `version`, and MetricType declares no update workflow, no
|
|
272
|
+
* realtime events and no audit log, so the full pipeline buys nothing
|
|
273
|
+
* here. Nothing in the codebase uses TypeORM optimistic locking, so the
|
|
274
|
+
* skipped version bump has no consumer.
|
|
275
|
+
*/
|
|
276
|
+
await MetricTypeService.updateColumnsByIdWithoutHooks({
|
|
277
|
+
id: metricType.id!,
|
|
278
|
+
data: scalarUpdate,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
110
281
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
services: metricType.services || [],
|
|
119
|
-
description: metricTypeInMap.description || "",
|
|
120
|
-
unit: metricTypeInMap.unit || "",
|
|
121
|
-
...(metricType.isMonotonic !== undefined
|
|
122
|
-
? { isMonotonic: metricType.isMonotonic }
|
|
123
|
-
: {}),
|
|
124
|
-
...(metricType.aggregationTemporality !== undefined
|
|
125
|
-
? { aggregationTemporality: metricType.aggregationTemporality }
|
|
126
|
-
: {}),
|
|
127
|
-
},
|
|
128
|
-
props: {
|
|
129
|
-
isRoot: true,
|
|
130
|
-
},
|
|
131
|
-
} as any);
|
|
132
|
-
}
|
|
133
|
-
} else {
|
|
134
|
-
// create metric type
|
|
135
|
-
const metricType: MetricType = new MetricType();
|
|
136
|
-
metricType.name = metricName;
|
|
137
|
-
metricType.description = metricTypeInMap.description || "";
|
|
138
|
-
metricType.unit = metricTypeInMap.unit || "";
|
|
139
|
-
if (metricTypeInMap.isMonotonic !== undefined) {
|
|
140
|
-
metricType.isMonotonic = metricTypeInMap.isMonotonic;
|
|
141
|
-
}
|
|
142
|
-
if (metricTypeInMap.aggregationTemporality !== undefined) {
|
|
143
|
-
metricType.aggregationTemporality =
|
|
144
|
-
metricTypeInMap.aggregationTemporality;
|
|
145
|
-
}
|
|
146
|
-
metricType.projectId = data.projectId;
|
|
147
|
-
metricType.services = [];
|
|
282
|
+
if (servicesToAttach.length > 0) {
|
|
283
|
+
await MetricTypeService.attachServices({
|
|
284
|
+
metricTypeId: metricType.id!,
|
|
285
|
+
serviceIds: servicesToAttach,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
148
289
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
290
|
+
private static async createMetricType(data: {
|
|
291
|
+
projectId: ObjectID;
|
|
292
|
+
metricName: string;
|
|
293
|
+
metricTypeInMap: MetricType;
|
|
294
|
+
servicesInMap: Array<ObjectID>;
|
|
295
|
+
}): Promise<void> {
|
|
296
|
+
const metricType: MetricType = new MetricType();
|
|
297
|
+
metricType.name = data.metricName;
|
|
298
|
+
metricType.description = data.metricTypeInMap.description || "";
|
|
299
|
+
metricType.unit = data.metricTypeInMap.unit || "";
|
|
300
|
+
if (data.metricTypeInMap.isMonotonic !== undefined) {
|
|
301
|
+
metricType.isMonotonic = data.metricTypeInMap.isMonotonic;
|
|
302
|
+
}
|
|
303
|
+
if (data.metricTypeInMap.aggregationTemporality !== undefined) {
|
|
304
|
+
metricType.aggregationTemporality =
|
|
305
|
+
data.metricTypeInMap.aggregationTemporality;
|
|
306
|
+
}
|
|
307
|
+
metricType.projectId = data.projectId;
|
|
308
|
+
metricType.services = [];
|
|
154
309
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
310
|
+
for (const serviceId of data.servicesInMap) {
|
|
311
|
+
const service: Service = new Service();
|
|
312
|
+
service.id = serviceId;
|
|
313
|
+
metricType.services!.push(service);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/*
|
|
317
|
+
* Creates stay on the ORM path: a raw INSERT would bypass tenant stamping,
|
|
318
|
+
* slug generation and the uniqueness check. Creates are also rare — this
|
|
319
|
+
* runs once per metric name in a project's lifetime.
|
|
320
|
+
*/
|
|
321
|
+
await MetricTypeService.create({
|
|
322
|
+
data: metricType,
|
|
323
|
+
props: {
|
|
324
|
+
isRoot: true,
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private static buildMetricTypeFenceKey(data: {
|
|
330
|
+
projectId: ObjectID;
|
|
331
|
+
metricName: string;
|
|
332
|
+
serviceIds: Array<ObjectID>;
|
|
333
|
+
}): string {
|
|
334
|
+
const services: string = data.serviceIds
|
|
335
|
+
.map((serviceId: ObjectID) => {
|
|
336
|
+
return serviceId.toString();
|
|
337
|
+
})
|
|
338
|
+
.sort()
|
|
339
|
+
.join(",");
|
|
340
|
+
|
|
341
|
+
return `metric-type:${data.projectId.toString()}:${
|
|
342
|
+
data.metricName
|
|
343
|
+
}:${crypto.createHash("sha1").update(services).digest("hex")}`;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
private static fingerprintMetricTypeScalars(metricType: MetricType): string {
|
|
347
|
+
return crypto
|
|
348
|
+
.createHash("sha1")
|
|
349
|
+
.update(
|
|
350
|
+
JSON.stringify({
|
|
351
|
+
description: metricType.description ?? null,
|
|
352
|
+
unit: metricType.unit ?? null,
|
|
353
|
+
isMonotonic: metricType.isMonotonic ?? null,
|
|
354
|
+
aggregationTemporality: metricType.aggregationTemporality ?? null,
|
|
355
|
+
}),
|
|
356
|
+
)
|
|
357
|
+
.digest("hex");
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/*
|
|
361
|
+
* Compare-and-claim rather than plain set-if-absent: a metric whose
|
|
362
|
+
* description or unit genuinely changed must be written promptly, not wait
|
|
363
|
+
* out the window. Atomic, so concurrent workers cannot all pass the gate the
|
|
364
|
+
* way a read-then-write lets them.
|
|
365
|
+
*/
|
|
366
|
+
private static async shouldIndexMetricType(
|
|
367
|
+
fenceKey: string,
|
|
368
|
+
fingerprint: string,
|
|
369
|
+
): Promise<boolean> {
|
|
370
|
+
try {
|
|
371
|
+
return await GlobalCache.setStringIfChanged(
|
|
372
|
+
METRIC_TYPE_FENCE_NAMESPACE,
|
|
373
|
+
fenceKey,
|
|
374
|
+
fingerprint,
|
|
375
|
+
{
|
|
376
|
+
expiresInSeconds: GlobalCache.withJitter(
|
|
377
|
+
METRIC_TYPE_FENCE_TTL_SECONDS,
|
|
378
|
+
),
|
|
379
|
+
},
|
|
380
|
+
);
|
|
381
|
+
} catch {
|
|
382
|
+
// If the cache is down, default to running the reconcile.
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
private static async clearMetricTypeFence(fenceKey: string): Promise<void> {
|
|
388
|
+
try {
|
|
389
|
+
await GlobalCache.deleteKey(METRIC_TYPE_FENCE_NAMESPACE, fenceKey);
|
|
390
|
+
} catch {
|
|
391
|
+
// Best effort — losing the release costs one window of staleness.
|
|
163
392
|
}
|
|
164
393
|
}
|
|
165
394
|
|