@oneuptime/common 11.6.1 → 11.7.0
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/AnalyticsModels/Index.ts +4 -0
- package/Models/AnalyticsModels/KubernetesCostAllocation.ts +842 -0
- package/Models/AnalyticsModels/NetworkFlow.ts +54 -0
- package/Models/AnalyticsModels/SloHistory.ts +243 -0
- package/Models/DatabaseModels/Index.ts +20 -0
- package/Models/DatabaseModels/NetworkDevice.ts +453 -6
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +7 -6
- package/Models/DatabaseModels/NetworkEndpoint.ts +753 -0
- package/Models/DatabaseModels/NetworkSite.ts +1155 -0
- package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +517 -0
- package/Models/DatabaseModels/NetworkSiteLink.ts +611 -0
- package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +520 -0
- package/Models/DatabaseModels/NetworkSiteType.ts +499 -0
- package/Models/DatabaseModels/ServiceLevelObjective.ts +1115 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +762 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +444 -0
- package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +443 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.ts +359 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.ts +48 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.ts +65 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.ts +88 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.ts +391 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.ts +30 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Services/AnalyticsDatabaseService.ts +25 -9
- package/Server/Services/Index.ts +24 -0
- package/Server/Services/KubernetesCostAllocationService.ts +14 -0
- package/Server/Services/MetricService.ts +21 -2
- package/Server/Services/MonitorService.ts +22 -0
- package/Server/Services/NetworkDeviceService.ts +438 -2
- package/Server/Services/NetworkEndpointService.ts +414 -0
- package/Server/Services/NetworkSiteAssignmentRuleService.ts +98 -0
- package/Server/Services/NetworkSiteLinkService.ts +10 -0
- package/Server/Services/NetworkSiteService.ts +1254 -0
- package/Server/Services/NetworkSiteStatusTimelineService.ts +10 -0
- package/Server/Services/NetworkSiteTypeService.ts +10 -0
- package/Server/Services/ProjectService.ts +122 -2
- package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +457 -0
- package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +10 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +685 -0
- package/Server/Services/SloHistoryService.ts +101 -0
- package/Server/Services/UserNotificationSettingService.ts +37 -0
- package/Server/Types/AnalyticsDatabase/AggregateBy.ts +9 -0
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +15 -0
- package/Server/Utils/AnalyticsDatabase/Statement.ts +39 -3
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +87 -48
- package/Server/Utils/Memory.ts +9 -1
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +190 -12
- package/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/Server/Utils/Monitor/DnsResolutionCache.ts +129 -0
- package/Server/Utils/Monitor/MonitorResource.ts +4 -30
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +214 -39
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +343 -0
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +251 -0
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +176 -142
- package/Server/Utils/Monitor/OuiLookupUtil.ts +49 -0
- package/Server/Utils/Monitor/SnmpInterfaceRateUtil.ts +17 -13
- package/Server/Utils/WhatsAppTemplateUtil.ts +7 -3
- package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +135 -0
- package/Tests/Models/NetworkSiteHierarchy.test.ts +134 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +239 -0
- package/Tests/Server/Services/KubernetesCostAllocationAggregate.test.ts +338 -0
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +142 -0
- package/Tests/Server/Services/NetworkDeviceSiteAssignment.test.ts +484 -0
- package/Tests/Server/Services/NetworkEndpointServiceUpsert.test.ts +686 -0
- package/Tests/Server/Services/NetworkSiteAssignmentRuleService.test.ts +185 -0
- package/Tests/Server/Services/NetworkSiteService.test.ts +1354 -0
- package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +1313 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +1988 -0
- package/Tests/Server/Utils/AnalyticsDatabase/Statement.test.ts +22 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +404 -0
- package/Tests/Server/Utils/Encryption.test.ts +70 -0
- package/Tests/Server/Utils/FileAttachmentMarkdownUtil.test.ts +225 -0
- package/Tests/Server/Utils/JsonWebToken.test.ts +175 -0
- package/Tests/Server/Utils/LocalFile.test.ts +258 -0
- package/Tests/Server/Utils/Memory.test.ts +213 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +30 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +385 -0
- package/Tests/Server/Utils/Monitor/DnsResolutionCache.test.ts +194 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +155 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +600 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +151 -124
- package/Tests/Server/Utils/Monitor/SnmpInterfaceRateUtil.test.ts +496 -0
- package/Tests/Server/Utils/MonitorCriteriaDataExtractor.test.ts +175 -0
- package/Tests/Server/Utils/MonitorCriteriaMessageFormatter.test.ts +282 -0
- package/Tests/Server/Utils/OuiLookupUtil.test.ts +59 -0
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +117 -0
- package/Tests/Server/Utils/StackTraceParser.test.ts +370 -0
- package/Tests/Server/Utils/Stream.test.ts +87 -0
- package/Tests/Server/Utils/ValidateGlobalProviderProjectTeams.test.ts +221 -0
- package/Tests/Server/Utils/WhatsAppTemplateUtil.test.ts +199 -0
- package/Tests/Types/Database/CompareOperatorWireSerialization.test.ts +33 -0
- package/Tests/Types/Email.test.ts +198 -0
- package/Tests/Types/Kubernetes/KubernetesObjectParser.test.ts +177 -0
- package/Tests/Types/Log/LogQueryToFilter.test.ts +111 -0
- package/Tests/Types/Monitor/MonitorCriteria.test.ts +155 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +465 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +183 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +141 -1
- package/Tests/Types/Monitor/MonitorSteps.test.ts +183 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +59 -1
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +97 -0
- package/Tests/Types/Monitor/SnmpEndpointDiscovery.test.ts +151 -0
- package/Tests/Types/Monitor/SnmpVendorTemplate.test.ts +110 -6
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +129 -0
- package/Tests/Types/SerializableObjectDictionary.test.ts +166 -0
- package/Tests/Types/Time/RangeStartAndEndDateTime.test.ts +98 -0
- package/Tests/Types/WebsiteRequest.test.ts +230 -0
- package/Tests/UI/Components/EntityFilterRoundTrip.test.tsx +103 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +612 -0
- package/Tests/UI/Components/ModelTable/FilterDataToQuery.test.ts +275 -0
- package/Tests/UI/Utils/LogExport.test.ts +159 -0
- package/Tests/UI/Utils/Navigation.test.ts +183 -0
- package/Tests/UI/Utils/TableFilterUrlState.test.ts +539 -0
- package/Tests/UI/Utils/TableViewUrlState.test.ts +272 -0
- package/Tests/Utils/Base64.test.ts +51 -0
- package/Tests/Utils/Boolean.test.ts +76 -0
- package/Tests/Utils/Crypto.test.ts +48 -0
- package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +259 -0
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +162 -0
- package/Tests/Utils/Enum.test.ts +54 -0
- package/Tests/Utils/IpCanonicalUtil.test.ts +85 -0
- package/Tests/Utils/Memory.test.ts +44 -0
- package/Tests/Utils/Metrics/MetricSeriesFingerprint.test.ts +160 -0
- package/Tests/Utils/Monitor/EndpointAttachmentUtil.test.ts +836 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +218 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +447 -0
- package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +440 -0
- package/Tests/Utils/NetworkSite/MaterializedPathUtil.test.ts +205 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +221 -0
- package/Tests/Utils/NetworkSite/SiteUptimeUtil.test.ts +283 -0
- package/Tests/Utils/ObjectUtil.test.ts +30 -0
- package/Tests/Utils/Slo/SloBurnRateRuleState.test.ts +124 -0
- package/Tests/Utils/Slo/SloDuration.test.ts +148 -0
- package/Tests/Utils/Slo/SloHealth.test.ts +334 -0
- package/Tests/Utils/Slo/SloStatusColor.test.ts +89 -0
- package/Tests/Utils/Slo/SloUtil.test.ts +1980 -0
- package/Tests/Utils/Slo/SloWidgetFormat.test.ts +605 -0
- package/Tests/Utils/TechStack.test.ts +50 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +178 -0
- package/Types/AnalyticsDatabase/AnalyticsTableName.ts +10 -0
- package/Types/BaseDatabase/EqualTo.ts +9 -1
- package/Types/BaseDatabase/EqualToOrNull.ts +9 -1
- package/Types/BaseDatabase/NotEqual.ts +9 -1
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +42 -0
- package/Types/Dashboard/DashboardTemplates.ts +214 -0
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/Kubernetes/KubernetesCostIngest.ts +79 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/Monitor/MonitorStep.ts +5 -8
- package/Types/Monitor/MonitorStepNetworkDeviceMonitor.ts +27 -5
- package/Types/Monitor/MonitorType.ts +15 -5
- package/Types/Monitor/SnmpMonitor/ArpEntry.ts +14 -0
- package/Types/Monitor/SnmpMonitor/FdbEntry.ts +18 -0
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +10 -3
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +31 -5
- package/Types/Monitor/SnmpMonitor/SnmpMonitorResponse.ts +12 -0
- package/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.ts +231 -3
- package/Types/NetworkSite/DefaultNetworkSiteType.ts +20 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
- package/Types/Permission.ts +449 -0
- package/Types/ServiceLevelObjective/SliType.ts +6 -0
- package/Types/ServiceLevelObjective/SloMultiMonitorMode.ts +6 -0
- package/Types/ServiceLevelObjective/SloStatus.ts +9 -0
- package/Types/ServiceLevelObjective/SloWindowType.ts +6 -0
- package/Types/Telemetry/ServiceType.ts +1 -0
- package/UI/Components/Filters/EntityFilter.tsx +16 -0
- package/UI/Components/Filters/FilterViewer.tsx +22 -5
- package/UI/Components/List/List.tsx +8 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +309 -106
- package/UI/Components/ModelTable/FilterDataToQuery.ts +172 -0
- package/UI/Components/Navbar/NavBar.tsx +16 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +3 -3
- package/UI/Utils/Navigation.ts +10 -0
- package/UI/Utils/TableFilterUrlState.ts +204 -17
- package/UI/Utils/TableViewUrlState.ts +165 -0
- package/Utils/Dashboard/Components/DashboardSloComponent.ts +114 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/IpCanonicalUtil.ts +134 -0
- package/Utils/Monitor/EndpointAttachmentUtil.ts +508 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +157 -5
- package/Utils/NetworkSite/CidrMatchUtil.ts +296 -0
- package/Utils/NetworkSite/MaterializedPathUtil.ts +115 -0
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +97 -0
- package/Utils/NetworkSite/SiteUptimeUtil.ts +111 -0
- package/Utils/Slo/SloBurnRateRuleState.ts +91 -0
- package/Utils/Slo/SloDuration.ts +165 -0
- package/Utils/Slo/SloEvaluation.ts +22 -0
- package/Utils/Slo/SloHealth.ts +302 -0
- package/Utils/Slo/SloStatusColor.ts +54 -0
- package/Utils/Slo/SloUtil.ts +637 -0
- package/Utils/Slo/SloWidgetFormat.ts +383 -0
- package/build/dist/Models/AnalyticsModels/Index.js +4 -0
- package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +713 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -0
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js +44 -0
- package/build/dist/Models/AnalyticsModels/NetworkFlow.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/SloHistory.js +218 -0
- package/build/dist/Models/AnalyticsModels/SloHistory.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +20 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +458 -6
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +0 -6
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js +779 -0
- package/build/dist/Models/DatabaseModels/NetworkEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js +1180 -0
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +534 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js +629 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteLink.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +538 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +522 -0
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +1134 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +769 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +460 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +459 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js +130 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784757142154-AddNetworkSiteHierarchyAndEndpoints.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784897317860-AddNetworkSiteAlerting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784970388777-AddNetworkDevicePollingColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js +49 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784986826214-AddNetworkSiteTypeTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js +140 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784987015619-AddServiceLevelObjective.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.js +21 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785066759532-MigrationName.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/AnalyticsDatabaseService.js +23 -6
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +24 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/KubernetesCostAllocationService.js +12 -0
- package/build/dist/Server/Services/KubernetesCostAllocationService.js.map +1 -0
- package/build/dist/Server/Services/MetricService.js +21 -3
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +19 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +351 -1
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkEndpointService.js +319 -0
- package/build/dist/Server/Services/NetworkEndpointService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js +90 -0
- package/build/dist/Server/Services/NetworkSiteAssignmentRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteLinkService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteService.js +1038 -0
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteStatusTimelineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js +9 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -0
- package/build/dist/Server/Services/ProjectService.js +98 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +358 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +9 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +588 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -0
- package/build/dist/Server/Services/SloHistoryService.js +77 -0
- package/build/dist/Server/Services/SloHistoryService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +20 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +15 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +31 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +76 -48
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Memory.js +9 -1
- package/build/dist/Server/Utils/Memory.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +132 -10
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Data/OuiVendors.json +6920 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js +77 -0
- package/build/dist/Server/Utils/Monitor/DnsResolutionCache.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +21 -41
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +152 -40
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +262 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +201 -0
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +152 -120
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js +44 -0
- package/build/dist/Server/Utils/Monitor/OuiLookupUtil.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js +10 -10
- package/build/dist/Server/Utils/Monitor/SnmpInterfaceRateUtil.js.map +1 -1
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js +5 -0
- package/build/dist/Server/Utils/WhatsAppTemplateUtil.js.map +1 -1
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +10 -0
- package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualTo.js.map +1 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js +9 -1
- package/build/dist/Types/BaseDatabase/EqualToOrNull.js.map +1 -1
- package/build/dist/Types/BaseDatabase/NotEqual.js +9 -1
- package/build/dist/Types/BaseDatabase/NotEqual.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/DashboardSloComponent.js +23 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +205 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js +21 -0
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +5 -5
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js +8 -0
- package/build/dist/Types/Monitor/MonitorStepNetworkDeviceMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +15 -5
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/ArpEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js +2 -0
- package/build/dist/Types/Monitor/SnmpMonitor/FdbEntry.js.map +1 -0
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +9 -3
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js +217 -3
- package/build/dist/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js +21 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteType.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/Permission.js +409 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ServiceLevelObjective/SliType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SliType.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloMultiMonitorMode.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js +10 -0
- package/build/dist/Types/ServiceLevelObjective/SloStatus.js.map +1 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js +7 -0
- package/build/dist/Types/ServiceLevelObjective/SloWindowType.js.map +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Filters/EntityFilter.js +15 -0
- package/build/dist/UI/Components/Filters/EntityFilter.js.map +1 -1
- package/build/dist/UI/Components/Filters/FilterViewer.js +19 -4
- package/build/dist/UI/Components/Filters/FilterViewer.js.map +1 -1
- package/build/dist/UI/Components/List/List.js +1 -1
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +235 -89
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js +96 -0
- package/build/dist/UI/Components/ModelTable/FilterDataToQuery.js.map +1 -0
- package/build/dist/UI/Components/Navbar/NavBar.js +14 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +3 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +9 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/TableFilterUrlState.js +159 -15
- package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
- package/build/dist/UI/Utils/TableViewUrlState.js +103 -0
- package/build/dist/UI/Utils/TableViewUrlState.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +93 -0
- package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.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/IpCanonicalUtil.js +110 -0
- package/build/dist/Utils/IpCanonicalUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js +311 -0
- package/build/dist/Utils/Monitor/EndpointAttachmentUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +98 -5
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +222 -0
- package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js +89 -0
- package/build/dist/Utils/NetworkSite/MaterializedPathUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +60 -0
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js +76 -0
- package/build/dist/Utils/NetworkSite/SiteUptimeUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js +35 -0
- package/build/dist/Utils/Slo/SloBurnRateRuleState.js.map +1 -0
- package/build/dist/Utils/Slo/SloDuration.js +87 -0
- package/build/dist/Utils/Slo/SloDuration.js.map +1 -0
- package/build/dist/Utils/Slo/SloEvaluation.js +21 -0
- package/build/dist/Utils/Slo/SloEvaluation.js.map +1 -0
- package/build/dist/Utils/Slo/SloHealth.js +179 -0
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -0
- package/build/dist/Utils/Slo/SloStatusColor.js +18 -0
- package/build/dist/Utils/Slo/SloStatusColor.js.map +1 -0
- package/build/dist/Utils/Slo/SloUtil.js +393 -0
- package/build/dist/Utils/Slo/SloUtil.js.map +1 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js +174 -0
- package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -0
- package/package.json +2 -2
- package/Types/Dashboard/DashboardComponents/Index.ts +0 -7
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js +0 -8
- package/build/dist/Types/Dashboard/DashboardComponents/Index.js.map +0 -1
|
@@ -0,0 +1,685 @@
|
|
|
1
|
+
import AlertSeverity from "../../Models/DatabaseModels/AlertSeverity";
|
|
2
|
+
import MonitorStatus from "../../Models/DatabaseModels/MonitorStatus";
|
|
3
|
+
import Model from "../../Models/DatabaseModels/ServiceLevelObjective";
|
|
4
|
+
import ServiceLevelObjectiveBurnRateRule from "../../Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule";
|
|
5
|
+
import ServiceLevelObjectiveOwnerTeam from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam";
|
|
6
|
+
import ServiceLevelObjectiveOwnerUser from "../../Models/DatabaseModels/ServiceLevelObjectiveOwnerUser";
|
|
7
|
+
import User from "../../Models/DatabaseModels/User";
|
|
8
|
+
import URL from "../../Types/API/URL";
|
|
9
|
+
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
10
|
+
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
11
|
+
import OneUptimeDate from "../../Types/Date";
|
|
12
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
13
|
+
import ObjectID from "../../Types/ObjectID";
|
|
14
|
+
import SloWindowType from "../../Types/ServiceLevelObjective/SloWindowType";
|
|
15
|
+
import DatabaseConfig from "../DatabaseConfig";
|
|
16
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
17
|
+
import DeleteBy from "../Types/Database/DeleteBy";
|
|
18
|
+
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
19
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
20
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
21
|
+
import logger, { LogAttributes } from "../Utils/Logger";
|
|
22
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
23
|
+
import AlertSeverityService from "./AlertSeverityService";
|
|
24
|
+
import DatabaseService from "./DatabaseService";
|
|
25
|
+
import MonitorStatusService from "./MonitorStatusService";
|
|
26
|
+
import ProjectService from "./ProjectService";
|
|
27
|
+
import ServiceLevelObjectiveBurnRateRuleService from "./ServiceLevelObjectiveBurnRateRuleService";
|
|
28
|
+
import ServiceLevelObjectiveOwnerTeamService from "./ServiceLevelObjectiveOwnerTeamService";
|
|
29
|
+
import ServiceLevelObjectiveOwnerUserService from "./ServiceLevelObjectiveOwnerUserService";
|
|
30
|
+
import TeamMemberService from "./TeamMemberService";
|
|
31
|
+
|
|
32
|
+
export class Service extends DatabaseService<Model> {
|
|
33
|
+
public constructor() {
|
|
34
|
+
super(Model);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@CaptureSpan()
|
|
38
|
+
protected override async onBeforeCreate(
|
|
39
|
+
createBy: CreateBy<Model>,
|
|
40
|
+
): Promise<OnCreate<Model>> {
|
|
41
|
+
if (!createBy.data.projectId) {
|
|
42
|
+
throw new BadDataException("projectId is required");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* Numeric columns arrive as strings from the dashboard: the "Target (%)"
|
|
47
|
+
* form field is a `<input type="number">`, whose onChange hands Formik
|
|
48
|
+
* `e.target.value` (a string), ModelForm copies it verbatim and
|
|
49
|
+
* BaseModel.fromJSON does not coerce Number/Decimal columns. So every
|
|
50
|
+
* validator here coerces first and writes the coerced number back onto the
|
|
51
|
+
* payload, which also keeps Postgres from ever receiving a string.
|
|
52
|
+
*/
|
|
53
|
+
createBy.data.targetPercentage = this.validateTargetPercentage(
|
|
54
|
+
createBy.data.targetPercentage,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* Validate windowDays whenever it is supplied, regardless of windowType.
|
|
59
|
+
* A CalendarMonth SLO ignores the column today, but it is persisted, and
|
|
60
|
+
* switching that SLO to Rolling later (in an update that does not carry
|
|
61
|
+
* windowDays) would otherwise start evaluating against an out-of-range
|
|
62
|
+
* window. Validating on the way in also keeps create and update symmetric
|
|
63
|
+
* — onBeforeUpdate validates unconditionally, so a value accepted here
|
|
64
|
+
* but rejected there would make the column permanently un-updatable.
|
|
65
|
+
*/
|
|
66
|
+
if (
|
|
67
|
+
createBy.data.windowDays !== undefined &&
|
|
68
|
+
createBy.data.windowDays !== null
|
|
69
|
+
) {
|
|
70
|
+
createBy.data.windowDays = this.validateWindowDays(
|
|
71
|
+
createBy.data.windowDays,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (
|
|
76
|
+
createBy.data.atRiskThresholdPercentage !== undefined &&
|
|
77
|
+
createBy.data.atRiskThresholdPercentage !== null
|
|
78
|
+
) {
|
|
79
|
+
createBy.data.atRiskThresholdPercentage =
|
|
80
|
+
this.validateAtRiskThresholdPercentage(
|
|
81
|
+
createBy.data.atRiskThresholdPercentage,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
* Default the downtime statuses to all non-operational monitor statuses
|
|
87
|
+
* of the project (StatusPageService pattern).
|
|
88
|
+
*/
|
|
89
|
+
if (!createBy.data.downtimeMonitorStatuses) {
|
|
90
|
+
const monitorStatuses: Array<MonitorStatus> =
|
|
91
|
+
await MonitorStatusService.findBy({
|
|
92
|
+
query: {
|
|
93
|
+
projectId: createBy.data.projectId,
|
|
94
|
+
},
|
|
95
|
+
select: {
|
|
96
|
+
_id: true,
|
|
97
|
+
isOperationalState: true,
|
|
98
|
+
},
|
|
99
|
+
props: {
|
|
100
|
+
isRoot: true,
|
|
101
|
+
},
|
|
102
|
+
skip: 0,
|
|
103
|
+
limit: LIMIT_PER_PROJECT,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const nonOperationalStatuses: Array<MonitorStatus> =
|
|
107
|
+
monitorStatuses.filter((monitorStatus: MonitorStatus) => {
|
|
108
|
+
return !monitorStatus.isOperationalState;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
createBy.data.downtimeMonitorStatuses = nonOperationalStatuses;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
createBy,
|
|
116
|
+
carryForward: null,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@CaptureSpan()
|
|
121
|
+
protected override async onCreateSuccess(
|
|
122
|
+
_onCreate: OnCreate<Model>,
|
|
123
|
+
createdItem: Model,
|
|
124
|
+
): Promise<Model> {
|
|
125
|
+
/*
|
|
126
|
+
* Stamp nextEvaluationAt = now so the evaluation worker picks this SLO up
|
|
127
|
+
* on its next tick. Done here (isRoot update) instead of onBeforeCreate
|
|
128
|
+
* because the column is worker-owned (`create: []` access control) — a
|
|
129
|
+
* non-root dashboard create would fail the column permission check if the
|
|
130
|
+
* hook injected it into the create payload.
|
|
131
|
+
*/
|
|
132
|
+
try {
|
|
133
|
+
await this.updateOneById({
|
|
134
|
+
id: createdItem.id!,
|
|
135
|
+
data: {
|
|
136
|
+
nextEvaluationAt: OneUptimeDate.getCurrentDate(),
|
|
137
|
+
},
|
|
138
|
+
props: {
|
|
139
|
+
isRoot: true,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
} catch (err) {
|
|
143
|
+
logger.error(
|
|
144
|
+
`Error setting nextEvaluationAt for SLO ${createdItem.id?.toString()}: ${err}`,
|
|
145
|
+
{ projectId: createdItem.projectId?.toString() } as LogAttributes,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Seed the two canonical multi-window burn rate rules. Non-fatal.
|
|
150
|
+
try {
|
|
151
|
+
await this.seedDefaultBurnRateRules(createdItem);
|
|
152
|
+
} catch (err) {
|
|
153
|
+
logger.error(
|
|
154
|
+
`Error seeding default burn rate rules for SLO ${createdItem.id?.toString()}: ${err}`,
|
|
155
|
+
{ projectId: createdItem.projectId?.toString() } as LogAttributes,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return createdItem;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@CaptureSpan()
|
|
163
|
+
protected override async onBeforeUpdate(
|
|
164
|
+
updateBy: UpdateBy<Model>,
|
|
165
|
+
): Promise<OnUpdate<Model>> {
|
|
166
|
+
/*
|
|
167
|
+
* Same string-arrival path as onBeforeCreate — coerce, validate, and write
|
|
168
|
+
* the number back onto the update payload.
|
|
169
|
+
*/
|
|
170
|
+
const newTargetPercentage: unknown = updateBy.data
|
|
171
|
+
.targetPercentage as unknown;
|
|
172
|
+
|
|
173
|
+
if (newTargetPercentage !== undefined && newTargetPercentage !== null) {
|
|
174
|
+
updateBy.data.targetPercentage =
|
|
175
|
+
this.validateTargetPercentage(newTargetPercentage);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const newWindowDays: unknown = updateBy.data.windowDays as unknown;
|
|
179
|
+
|
|
180
|
+
if (newWindowDays !== undefined && newWindowDays !== null) {
|
|
181
|
+
updateBy.data.windowDays = this.validateWindowDays(newWindowDays);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const newAtRiskThresholdPercentage: unknown = updateBy.data
|
|
185
|
+
.atRiskThresholdPercentage as unknown;
|
|
186
|
+
|
|
187
|
+
if (
|
|
188
|
+
newAtRiskThresholdPercentage !== undefined &&
|
|
189
|
+
newAtRiskThresholdPercentage !== null
|
|
190
|
+
) {
|
|
191
|
+
updateBy.data.atRiskThresholdPercentage =
|
|
192
|
+
this.validateAtRiskThresholdPercentage(newAtRiskThresholdPercentage);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
updateBy,
|
|
197
|
+
carryForward: null,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@CaptureSpan()
|
|
202
|
+
protected override async onUpdateSuccess(
|
|
203
|
+
onUpdate: OnUpdate<Model>,
|
|
204
|
+
updatedItemIds: Array<ObjectID>,
|
|
205
|
+
): Promise<OnUpdate<Model>> {
|
|
206
|
+
/*
|
|
207
|
+
* When an SLO is disabled, resolve its open burn-rate alerts — the
|
|
208
|
+
* evaluation worker skips disabled SLOs, so nothing else would ever
|
|
209
|
+
* resolve them (and their on-call escalations would stay open forever).
|
|
210
|
+
*/
|
|
211
|
+
if ((onUpdate.updateBy.data.isEnabled as boolean | undefined) === false) {
|
|
212
|
+
for (const updatedItemId of updatedItemIds) {
|
|
213
|
+
try {
|
|
214
|
+
const slo: Model | null = await this.findOneById({
|
|
215
|
+
id: updatedItemId,
|
|
216
|
+
select: {
|
|
217
|
+
projectId: true,
|
|
218
|
+
},
|
|
219
|
+
props: {
|
|
220
|
+
isRoot: true,
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
if (!slo || !slo.projectId) {
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
await this.resolveOpenBurnRateAlertsForSlo({
|
|
229
|
+
sloId: updatedItemId,
|
|
230
|
+
projectId: slo.projectId,
|
|
231
|
+
});
|
|
232
|
+
} catch (err) {
|
|
233
|
+
logger.error(
|
|
234
|
+
`Error resolving open burn rate alerts for disabled SLO ${updatedItemId.toString()}: ${err}`,
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/*
|
|
241
|
+
* If the objective's math inputs changed, force a re-evaluation on the
|
|
242
|
+
* worker's next tick.
|
|
243
|
+
*/
|
|
244
|
+
const isEvaluationConfigUpdated: boolean =
|
|
245
|
+
onUpdate.updateBy.data.targetPercentage !== undefined ||
|
|
246
|
+
onUpdate.updateBy.data.windowDays !== undefined ||
|
|
247
|
+
onUpdate.updateBy.data.windowType !== undefined ||
|
|
248
|
+
onUpdate.updateBy.data.monitors !== undefined;
|
|
249
|
+
|
|
250
|
+
if (isEvaluationConfigUpdated) {
|
|
251
|
+
for (const updatedItemId of updatedItemIds) {
|
|
252
|
+
try {
|
|
253
|
+
await this.updateOneById({
|
|
254
|
+
id: updatedItemId,
|
|
255
|
+
data: {
|
|
256
|
+
nextEvaluationAt: OneUptimeDate.getCurrentDate(),
|
|
257
|
+
},
|
|
258
|
+
props: {
|
|
259
|
+
isRoot: true,
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
} catch (err) {
|
|
263
|
+
logger.error(
|
|
264
|
+
`Error forcing re-evaluation of SLO ${updatedItemId.toString()}: ${err}`,
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return onUpdate;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@CaptureSpan()
|
|
274
|
+
protected override async onBeforeDelete(
|
|
275
|
+
deleteBy: DeleteBy<Model>,
|
|
276
|
+
): Promise<OnDelete<Model>> {
|
|
277
|
+
const itemsToDelete: Array<Model> = await this.findBy({
|
|
278
|
+
query: deleteBy.query,
|
|
279
|
+
limit: LIMIT_MAX,
|
|
280
|
+
skip: 0,
|
|
281
|
+
select: {
|
|
282
|
+
_id: true,
|
|
283
|
+
projectId: true,
|
|
284
|
+
},
|
|
285
|
+
props: {
|
|
286
|
+
isRoot: true,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
for (const item of itemsToDelete) {
|
|
291
|
+
if (!item.id || !item.projectId) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
await this.resolveOpenBurnRateAlertsForSlo({
|
|
297
|
+
sloId: item.id,
|
|
298
|
+
projectId: item.projectId,
|
|
299
|
+
});
|
|
300
|
+
} catch (err) {
|
|
301
|
+
logger.error(
|
|
302
|
+
`Error resolving open burn rate alerts for SLO ${item.id?.toString()} before delete: ${err}`,
|
|
303
|
+
{ projectId: item.projectId?.toString() } as LogAttributes,
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return {
|
|
309
|
+
deleteBy,
|
|
310
|
+
carryForward: {
|
|
311
|
+
itemsToDelete: itemsToDelete,
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/*
|
|
317
|
+
* Resolve every open Alert fired by any of this SLO's burn rate rules.
|
|
318
|
+
* Called when the SLO is disabled or deleted.
|
|
319
|
+
*/
|
|
320
|
+
@CaptureSpan()
|
|
321
|
+
public async resolveOpenBurnRateAlertsForSlo(data: {
|
|
322
|
+
sloId: ObjectID;
|
|
323
|
+
projectId: ObjectID;
|
|
324
|
+
}): Promise<void> {
|
|
325
|
+
const burnRateRules: Array<ServiceLevelObjectiveBurnRateRule> =
|
|
326
|
+
await ServiceLevelObjectiveBurnRateRuleService.findBy({
|
|
327
|
+
query: {
|
|
328
|
+
serviceLevelObjectiveId: data.sloId,
|
|
329
|
+
projectId: data.projectId,
|
|
330
|
+
},
|
|
331
|
+
select: {
|
|
332
|
+
_id: true,
|
|
333
|
+
},
|
|
334
|
+
skip: 0,
|
|
335
|
+
limit: LIMIT_PER_PROJECT,
|
|
336
|
+
props: {
|
|
337
|
+
isRoot: true,
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
for (const rule of burnRateRules) {
|
|
342
|
+
if (!rule.id) {
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
try {
|
|
347
|
+
await ServiceLevelObjectiveBurnRateRuleService.resolveOpenAlertsForRule(
|
|
348
|
+
{
|
|
349
|
+
serviceLevelObjectiveId: data.sloId,
|
|
350
|
+
burnRateRuleId: rule.id,
|
|
351
|
+
projectId: data.projectId,
|
|
352
|
+
rootCause:
|
|
353
|
+
"Alert auto-resolved because the Service Level Objective was disabled or deleted.",
|
|
354
|
+
},
|
|
355
|
+
);
|
|
356
|
+
} catch (err) {
|
|
357
|
+
logger.error(
|
|
358
|
+
`Error resolving open alerts for burn rate rule ${rule.id?.toString()} of SLO ${data.sloId?.toString()}: ${err}`,
|
|
359
|
+
{ projectId: data.projectId?.toString() } as LogAttributes,
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/*
|
|
366
|
+
* All enabled SLOs in active projects that are due for evaluation
|
|
367
|
+
* (nextEvaluationAt in the past, or never evaluated). Selects every config
|
|
368
|
+
* and state column the evaluation worker needs.
|
|
369
|
+
*/
|
|
370
|
+
@CaptureSpan()
|
|
371
|
+
public async getDueSlos(): Promise<Array<Model>> {
|
|
372
|
+
return await this.findAllBy({
|
|
373
|
+
query: {
|
|
374
|
+
isEnabled: true,
|
|
375
|
+
nextEvaluationAt: QueryHelper.lessThanEqualToOrNull(
|
|
376
|
+
OneUptimeDate.getCurrentDate(),
|
|
377
|
+
),
|
|
378
|
+
project: {
|
|
379
|
+
...ProjectService.getActiveProjectStatusQuery(),
|
|
380
|
+
},
|
|
381
|
+
},
|
|
382
|
+
select: {
|
|
383
|
+
_id: true,
|
|
384
|
+
projectId: true,
|
|
385
|
+
name: true,
|
|
386
|
+
isEnabled: true,
|
|
387
|
+
sliType: true,
|
|
388
|
+
multiMonitorMode: true,
|
|
389
|
+
monitors: {
|
|
390
|
+
_id: true,
|
|
391
|
+
},
|
|
392
|
+
downtimeMonitorStatuses: {
|
|
393
|
+
_id: true,
|
|
394
|
+
},
|
|
395
|
+
metricQueryConfig: true,
|
|
396
|
+
targetPercentage: true,
|
|
397
|
+
windowType: true,
|
|
398
|
+
windowDays: true,
|
|
399
|
+
timezone: true,
|
|
400
|
+
atRiskThresholdPercentage: true,
|
|
401
|
+
currentSliPercentage: true,
|
|
402
|
+
errorBudgetRemainingPercentage: true,
|
|
403
|
+
errorBudgetRemainingSeconds: true,
|
|
404
|
+
errorBudgetTotalSeconds: true,
|
|
405
|
+
currentBurnRate: true,
|
|
406
|
+
sloStatus: true,
|
|
407
|
+
statusChangeNotificationSentAt: true,
|
|
408
|
+
lastEvaluatedAt: true,
|
|
409
|
+
nextEvaluationAt: true,
|
|
410
|
+
lastAccumulatedBucketEndAt: true,
|
|
411
|
+
},
|
|
412
|
+
sort: {
|
|
413
|
+
nextEvaluationAt: SortOrder.Ascending,
|
|
414
|
+
},
|
|
415
|
+
props: {
|
|
416
|
+
isRoot: true,
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
@CaptureSpan()
|
|
422
|
+
public async findOwners(
|
|
423
|
+
serviceLevelObjectiveId: ObjectID,
|
|
424
|
+
): Promise<Array<User>> {
|
|
425
|
+
if (!serviceLevelObjectiveId) {
|
|
426
|
+
throw new BadDataException("serviceLevelObjectiveId is required");
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const ownerUsers: Array<ServiceLevelObjectiveOwnerUser> =
|
|
430
|
+
await ServiceLevelObjectiveOwnerUserService.findBy({
|
|
431
|
+
query: {
|
|
432
|
+
serviceLevelObjectiveId: serviceLevelObjectiveId,
|
|
433
|
+
},
|
|
434
|
+
select: {
|
|
435
|
+
_id: true,
|
|
436
|
+
user: {
|
|
437
|
+
_id: true,
|
|
438
|
+
email: true,
|
|
439
|
+
name: true,
|
|
440
|
+
timezone: true,
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
props: {
|
|
444
|
+
isRoot: true,
|
|
445
|
+
},
|
|
446
|
+
limit: LIMIT_PER_PROJECT,
|
|
447
|
+
skip: 0,
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
const ownerTeams: Array<ServiceLevelObjectiveOwnerTeam> =
|
|
451
|
+
await ServiceLevelObjectiveOwnerTeamService.findBy({
|
|
452
|
+
query: {
|
|
453
|
+
serviceLevelObjectiveId: serviceLevelObjectiveId,
|
|
454
|
+
},
|
|
455
|
+
select: {
|
|
456
|
+
_id: true,
|
|
457
|
+
teamId: true,
|
|
458
|
+
},
|
|
459
|
+
skip: 0,
|
|
460
|
+
limit: LIMIT_PER_PROJECT,
|
|
461
|
+
props: {
|
|
462
|
+
isRoot: true,
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
const users: Array<User> =
|
|
467
|
+
ownerUsers.map((ownerUser: ServiceLevelObjectiveOwnerUser) => {
|
|
468
|
+
return ownerUser.user!;
|
|
469
|
+
}) || [];
|
|
470
|
+
|
|
471
|
+
if (ownerTeams.length > 0) {
|
|
472
|
+
const teamIds: Array<ObjectID> =
|
|
473
|
+
ownerTeams.map((ownerTeam: ServiceLevelObjectiveOwnerTeam) => {
|
|
474
|
+
return ownerTeam.teamId!;
|
|
475
|
+
}) || [];
|
|
476
|
+
|
|
477
|
+
const teamUsers: Array<User> =
|
|
478
|
+
await TeamMemberService.getUsersInTeams(teamIds);
|
|
479
|
+
|
|
480
|
+
for (const teamUser of teamUsers) {
|
|
481
|
+
// check if the user is already added.
|
|
482
|
+
const isUserAlreadyAdded: User | undefined = users.find(
|
|
483
|
+
(user: User) => {
|
|
484
|
+
return user.id!.toString() === teamUser.id!.toString();
|
|
485
|
+
},
|
|
486
|
+
);
|
|
487
|
+
|
|
488
|
+
if (!isUserAlreadyAdded) {
|
|
489
|
+
users.push(teamUser);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
return users;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
@CaptureSpan()
|
|
498
|
+
public async getSloLinkInDashboard(
|
|
499
|
+
projectId: ObjectID,
|
|
500
|
+
serviceLevelObjectiveId: ObjectID,
|
|
501
|
+
): Promise<URL> {
|
|
502
|
+
const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
|
|
503
|
+
|
|
504
|
+
return URL.fromString(dashboardUrl.toString()).addRoute(
|
|
505
|
+
`/${projectId.toString()}/slos/${serviceLevelObjectiveId.toString()}`,
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/*
|
|
510
|
+
* Seed the two canonical Google-SRE multi-window burn rate rules, with
|
|
511
|
+
* thresholds scaled to the SLO's compliance window. The textbook constants
|
|
512
|
+
* (14.4x over 1h/5m, 6x over 6h/30m) are derived from spending 2% / 5% of a
|
|
513
|
+
* 30-day budget: threshold = budgetFraction * windowHours / longWindowHours.
|
|
514
|
+
* A 30-day window reproduces exactly 14.4 and 6; shorter or longer windows
|
|
515
|
+
* stay correctly calibrated.
|
|
516
|
+
*/
|
|
517
|
+
private async seedDefaultBurnRateRules(createdItem: Model): Promise<void> {
|
|
518
|
+
if (!createdItem.id || !createdItem.projectId) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
const windowHours: number =
|
|
523
|
+
createdItem.windowType === SloWindowType.CalendarMonth
|
|
524
|
+
? 720
|
|
525
|
+
: (createdItem.windowDays || 30) * 24;
|
|
526
|
+
|
|
527
|
+
/*
|
|
528
|
+
* Default severity: the project's lowest-order (most severe) severity.
|
|
529
|
+
* A failure here must not cost the SLO its burn-rate rules — the rules are
|
|
530
|
+
* still useful without a severity (the worker falls back to the lowest
|
|
531
|
+
* order severity when it creates the alert), so a transient lookup error
|
|
532
|
+
* degrades to "no default severity" rather than "no rules at all".
|
|
533
|
+
*/
|
|
534
|
+
let severity: AlertSeverity | null = null;
|
|
535
|
+
|
|
536
|
+
try {
|
|
537
|
+
severity = await AlertSeverityService.findOneBy({
|
|
538
|
+
query: {
|
|
539
|
+
projectId: createdItem.projectId,
|
|
540
|
+
},
|
|
541
|
+
sort: {
|
|
542
|
+
order: SortOrder.Ascending,
|
|
543
|
+
},
|
|
544
|
+
select: {
|
|
545
|
+
_id: true,
|
|
546
|
+
},
|
|
547
|
+
props: {
|
|
548
|
+
isRoot: true,
|
|
549
|
+
},
|
|
550
|
+
});
|
|
551
|
+
} catch (error) {
|
|
552
|
+
logger.error(
|
|
553
|
+
`Could not look up the default alert severity for SLO ${createdItem.id.toString()}. Seeding burn rate rules without one.`,
|
|
554
|
+
);
|
|
555
|
+
logger.error(error);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const defaultRules: Array<{
|
|
559
|
+
name: string;
|
|
560
|
+
burnRateThreshold: number;
|
|
561
|
+
longWindowInMinutes: number;
|
|
562
|
+
shortWindowInMinutes: number;
|
|
563
|
+
}> = [
|
|
564
|
+
{
|
|
565
|
+
name: "Fast burn",
|
|
566
|
+
burnRateThreshold: this.roundToTwoDecimals((0.02 * windowHours) / 1),
|
|
567
|
+
longWindowInMinutes: 60,
|
|
568
|
+
shortWindowInMinutes: 5,
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
name: "Slow burn",
|
|
572
|
+
burnRateThreshold: this.roundToTwoDecimals((0.05 * windowHours) / 6),
|
|
573
|
+
longWindowInMinutes: 360,
|
|
574
|
+
shortWindowInMinutes: 30,
|
|
575
|
+
},
|
|
576
|
+
];
|
|
577
|
+
|
|
578
|
+
for (const defaultRule of defaultRules) {
|
|
579
|
+
try {
|
|
580
|
+
const rule: ServiceLevelObjectiveBurnRateRule =
|
|
581
|
+
new ServiceLevelObjectiveBurnRateRule();
|
|
582
|
+
rule.projectId = createdItem.projectId;
|
|
583
|
+
rule.serviceLevelObjectiveId = createdItem.id;
|
|
584
|
+
rule.name = defaultRule.name;
|
|
585
|
+
rule.isEnabled = true;
|
|
586
|
+
rule.burnRateThreshold = defaultRule.burnRateThreshold;
|
|
587
|
+
rule.longWindowInMinutes = defaultRule.longWindowInMinutes;
|
|
588
|
+
rule.shortWindowInMinutes = defaultRule.shortWindowInMinutes;
|
|
589
|
+
|
|
590
|
+
if (severity && severity.id) {
|
|
591
|
+
rule.alertSeverityId = severity.id;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
await ServiceLevelObjectiveBurnRateRuleService.create({
|
|
595
|
+
data: rule,
|
|
596
|
+
props: {
|
|
597
|
+
isRoot: true,
|
|
598
|
+
},
|
|
599
|
+
});
|
|
600
|
+
} catch (err) {
|
|
601
|
+
logger.error(
|
|
602
|
+
`Error seeding default burn rate rule "${defaultRule.name}" for SLO ${createdItem.id?.toString()}: ${err}`,
|
|
603
|
+
{ projectId: createdItem.projectId?.toString() } as LogAttributes,
|
|
604
|
+
);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
private roundToTwoDecimals(value: number): number {
|
|
610
|
+
return Math.round(value * 100) / 100;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/*
|
|
614
|
+
* Coerce an API-supplied numeric column to a number. HTML number inputs hand
|
|
615
|
+
* Formik strings, and neither ModelForm nor BaseModel.fromJSON coerces
|
|
616
|
+
* Number/Decimal columns, so a perfectly valid "99.9" reaches these hooks as
|
|
617
|
+
* a string. Anything that is not a finite numeric string or number becomes
|
|
618
|
+
* NaN, which every caller below rejects. Mirrors
|
|
619
|
+
* GlobalConfigService.normalizePercent.
|
|
620
|
+
*/
|
|
621
|
+
private normalizeNumericInput(value: unknown): number {
|
|
622
|
+
if (typeof value === "string") {
|
|
623
|
+
const trimmed: string = value.trim();
|
|
624
|
+
return trimmed === "" ? Number.NaN : Number(trimmed);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (typeof value === "number") {
|
|
628
|
+
return value;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
return Number.NaN;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
private validateTargetPercentage(value: unknown): number {
|
|
635
|
+
const targetPercentage: number = this.normalizeNumericInput(value);
|
|
636
|
+
|
|
637
|
+
if (
|
|
638
|
+
!Number.isFinite(targetPercentage) ||
|
|
639
|
+
targetPercentage <= 0 ||
|
|
640
|
+
targetPercentage > 99.999
|
|
641
|
+
) {
|
|
642
|
+
throw new BadDataException(
|
|
643
|
+
"SLO target must be greater than 0 and at most 99.999. A 100% target leaves no error budget.",
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
return targetPercentage;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
private validateWindowDays(value: unknown): number {
|
|
651
|
+
const windowDays: number = this.normalizeNumericInput(value);
|
|
652
|
+
|
|
653
|
+
/*
|
|
654
|
+
* The column is a Postgres integer, so a decimal that cleared only the
|
|
655
|
+
* range check would fail the INSERT with a raw driver error instead of
|
|
656
|
+
* this message.
|
|
657
|
+
*/
|
|
658
|
+
if (!Number.isInteger(windowDays) || windowDays < 1 || windowDays > 366) {
|
|
659
|
+
throw new BadDataException(
|
|
660
|
+
"SLO window must be a whole number of days between 1 and 366.",
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return windowDays;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
private validateAtRiskThresholdPercentage(value: unknown): number {
|
|
668
|
+
const atRiskThresholdPercentage: number = this.normalizeNumericInput(value);
|
|
669
|
+
|
|
670
|
+
// Integer column — see validateWindowDays.
|
|
671
|
+
if (
|
|
672
|
+
!Number.isInteger(atRiskThresholdPercentage) ||
|
|
673
|
+
atRiskThresholdPercentage < 0 ||
|
|
674
|
+
atRiskThresholdPercentage > 100
|
|
675
|
+
) {
|
|
676
|
+
throw new BadDataException(
|
|
677
|
+
"SLO at-risk threshold must be a whole percentage between 0 and 100.",
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
return atRiskThresholdPercentage;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
export default new Service();
|