@oneuptime/common 12.0.33 → 12.0.34
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/RumSession.ts +117 -1
- package/Models/AnalyticsModels/RumSessionChunk.ts +13 -0
- package/Models/DatabaseModels/AlertCustomField.ts +77 -3
- package/Models/DatabaseModels/ApiKeyPermission.ts +3 -27
- package/Models/DatabaseModels/IncidentCustomField.ts +77 -3
- package/Models/DatabaseModels/InventoryItemCustomField.ts +77 -3
- package/Models/DatabaseModels/MonitorCustomField.ts +77 -3
- package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +77 -3
- package/Models/DatabaseModels/RumApplication.ts +6 -6
- package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +77 -3
- package/Models/DatabaseModels/StatusPageCustomField.ts +77 -3
- package/Models/DatabaseModels/TeamCustomField.ts +77 -3
- package/Models/DatabaseModels/TeamMember.ts +0 -9
- package/Models/DatabaseModels/TeamMemberCustomField.ts +77 -3
- package/Models/DatabaseModels/TeamPermission.ts +3 -24
- package/Models/DatabaseModels/TelemetryIngestionKey.ts +260 -0
- package/Models/DatabaseModels/UserTelegram.ts +0 -4
- package/Scripts/benchmark-fanin-capacity.js +181 -0
- package/Server/API/TelemetryAPI.ts +1284 -164
- package/Server/API/UserNotificationSettingAPI.ts +55 -0
- package/Server/API/UserTelegramAPI.ts +48 -4
- package/Server/EnvironmentConfig.ts +35 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.ts +91 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.ts +139 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.ts +121 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Infrastructure/QueueWorker.ts +20 -14
- package/Server/Infrastructure/Semaphore.ts +2 -0
- package/Server/Middleware/TelemetryIngest.ts +453 -7
- package/Server/Services/AccessTokenService.ts +1 -0
- package/Server/Services/AlertCustomFieldService.ts +98 -0
- package/Server/Services/AlertService.ts +37 -0
- package/Server/Services/ApiKeyPermissionService.ts +461 -29
- package/Server/Services/CustomFieldMappingService.ts +879 -0
- package/Server/Services/GlobalConfigService.ts +194 -0
- package/Server/Services/IncidentCustomFieldService.ts +98 -0
- package/Server/Services/IncidentService.ts +35 -0
- package/Server/Services/MetricService.ts +194 -0
- package/Server/Services/MonitorService.ts +32 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +78 -25
- package/Server/Services/ProjectService.ts +22 -0
- package/Server/Services/RoutineEmailSettingsService.ts +73 -0
- package/Server/Services/RumSessionReplayViewService.ts +104 -24
- package/Server/Services/ScheduledMaintenanceCustomFieldService.ts +98 -0
- package/Server/Services/ScheduledMaintenanceService.ts +32 -0
- package/Server/Services/TeamMemberService.ts +78 -0
- package/Server/Services/TeamPermissionService.ts +235 -3
- package/Server/Services/TelemetryIngestionKeyService.ts +722 -19
- package/Server/Services/UserNotificationSettingService.ts +34 -6
- package/Server/Services/UserTelegramService.ts +326 -5
- package/Server/Types/Database/QueryHelper.ts +2 -0
- package/Server/Utils/APIKey/AccessPermission.ts +5 -2
- package/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.ts +54 -0
- package/Server/Utils/CustomField/CustomFieldMappingRegistry.ts +415 -0
- package/Server/Utils/CustomField/CustomFieldMappingValidator.ts +335 -0
- package/Server/Utils/DataSource/EgressGuard.ts +177 -8
- package/Server/Utils/EmailRollup/EmailRollupConstants.ts +38 -5
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +57 -4
- package/Server/Utils/FrontendEnvironment.ts +40 -0
- package/Server/Utils/LogRedaction.ts +20 -0
- package/Server/Utils/Logger.ts +11 -0
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +338 -77
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +30 -4
- package/Server/Utils/Monitor/MonitorAlert.ts +29 -6
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +110 -15
- package/Server/Utils/Monitor/MonitorIncident.ts +22 -6
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +29 -0
- package/Server/Utils/Monitor/SeriesContextEnricher.ts +304 -0
- package/Server/Utils/SSRFProtection.ts +217 -10
- package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +239 -138
- package/Server/Utils/SessionReplay/SessionReplayHealthCounters.ts +305 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +1430 -289
- package/Server/Utils/StartServer.ts +2 -17
- package/Server/Utils/TelegramVerificationToken.ts +185 -0
- package/Server/Utils/Telemetry/PinServiceName.ts +197 -0
- package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +38 -16
- package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +92 -0
- package/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.ts +217 -0
- package/Server/Utils/VM/VMAPI.ts +1 -0
- package/Server/Utils/VM/VMRunner.ts +975 -95
- package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +202 -0
- package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +404 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +468 -0
- package/Tests/App/Dashboard/NotificationEmailPreferences.test.tsx +399 -0
- package/Tests/App/StatusPage/StatusPageLastUpdated.test.tsx +263 -0
- package/Tests/App/StatusPage/StatusPageOverviewLiveAndSearch.test.tsx +753 -0
- package/Tests/App/StatusPage/StatusPageResourceSearchBox.test.tsx +224 -0
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +262 -0
- package/Tests/Models/CustomFieldMappingColumns.test.ts +166 -0
- package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +20 -6
- package/Tests/ResponsiveVisibility.test.ts +115 -0
- package/Tests/ResponsiveVisibility.ts +183 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +1940 -216
- package/Tests/Server/API/UserNotificationSettingAPI.test.ts +186 -0
- package/Tests/Server/API/UserTelegramAPISecurity.test.ts +231 -0
- package/Tests/Server/EnvironmentConfigFrontendSecurity.test.ts +234 -0
- package/Tests/Server/Infrastructure/Postgres/CustomFieldValueMappingMigration.test.ts +202 -0
- package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +41 -0
- package/Tests/Server/Infrastructure/Postgres/SessionReplayRecordEverySessionByDefaultMigration.test.ts +169 -0
- package/Tests/Server/Infrastructure/QueueWorkerTimeout.test.ts +210 -0
- package/Tests/Server/Infrastructure/TelemetryExporterDeploymentConfig.test.ts +130 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -1
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +1163 -0
- package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +5 -3
- package/Tests/Server/Services/AddTelemetryIngestionKeyTypeMigration.test.ts +555 -0
- package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +678 -0
- package/Tests/Server/Services/ApiKeyPermissionService.test.ts +276 -28
- package/Tests/Server/Services/CustomFieldDropdownOptionsColumnWidth.test.ts +431 -0
- package/Tests/Server/Services/CustomFieldMappingService.test.ts +850 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +32 -0
- package/Tests/Server/Services/GlobalConfigService.test.ts +414 -1
- package/Tests/Server/Services/MetricRawEntityKeyPrune.test.ts +592 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +226 -1
- package/Tests/Server/Services/RoutineEmailSettingsPostgres.test.ts +329 -0
- package/Tests/Server/Services/RumSessionReplayViewService.test.ts +267 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +9 -0
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +9 -0
- package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +834 -0
- package/Tests/Server/Services/TelemetryIngestionKeyPolicyResolution.test.ts +814 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +998 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +141 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +18 -10
- package/Tests/Server/Services/UserTelegramVerificationSecurity.test.ts +688 -0
- package/Tests/Server/Utils/AI/SRE/Insights/FixRouting.test.ts +497 -0
- package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +383 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +7 -3
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterConfig.test.ts +315 -0
- package/Tests/Server/Utils/CustomField/CustomFieldMappingValidator.test.ts +437 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +300 -11
- package/Tests/Server/Utils/EmailRollup/EmailRollupBurstWindow.test.ts +83 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1 -1
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerPreferences.test.ts +362 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +77 -1
- package/Tests/Server/Utils/FrontendEnvironment.test.ts +190 -0
- package/Tests/Server/Utils/LogRedaction.test.ts +26 -0
- package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +23 -9
- package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +584 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestHeaderCriteria.test.ts +236 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +437 -0
- package/Tests/Server/Utils/Monitor/MonitorTemplateUtilSeriesContext.test.ts +176 -0
- package/Tests/Server/Utils/Monitor/SeriesContextEnricher.test.ts +356 -0
- package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +595 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +198 -1
- package/Tests/Server/Utils/SessionReplay/SessionReplayHealthCounters.test.ts +453 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1378 -0
- package/Tests/Server/Utils/SessionReplayOriginAllowListRefactor.test.ts +420 -0
- package/Tests/Server/Utils/TelegramVerificationToken.test.ts +253 -0
- package/Tests/Server/Utils/Telemetry/PinServiceName.test.ts +666 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriterCapacity.test.ts +458 -0
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +424 -0
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.test.ts +528 -0
- package/Tests/Server/Utils/TelemetryExporterEnvironment.test.ts +56 -0
- package/Tests/Server/Utils/VM/VMRunnerHostBridgeLatency.test.ts +74 -0
- package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +100 -7
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +1176 -6
- package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +220 -0
- package/Tests/Types/CustomField/CustomFieldValueMapping.test.ts +348 -0
- package/Tests/Types/JSONFunctions.test.ts +260 -0
- package/Tests/Types/Monitor/CephAlertTemplates.test.ts +422 -53
- package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +495 -15
- package/Tests/Types/Monitor/DockerSwarmAlertTemplates.test.ts +191 -45
- package/Tests/Types/Monitor/HostAlertTemplates.test.ts +370 -42
- package/Tests/Types/Monitor/IotAlertTemplates.test.ts +375 -20
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +636 -42
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +189 -0
- package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +95 -14
- package/Tests/Types/Monitor/PodmanAlertTemplates.test.ts +190 -21
- package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +352 -22
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationAlertDebuggability.test.ts +363 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +93 -18
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +259 -0
- package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +476 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +136 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesDebugHints.test.ts +661 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +507 -0
- package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +270 -0
- package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +38 -10
- package/Tests/Types/Monitor/Utils/RecommendationCriteriaAssertions.ts +102 -0
- package/Tests/Types/NotificationSetting/RoutineEmailEvents.test.ts +47 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +608 -0
- package/Tests/Types/Rum/SessionReplayCustomEvents.test.ts +434 -0
- package/Tests/Types/WebsiteRequest.test.ts +285 -3
- package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +16 -3
- package/Tests/UI/Components/Charts/ChartTrailingBucketGap.test.ts +691 -0
- package/Tests/UI/Components/ComponentsModal.test.tsx +12 -4
- package/Tests/UI/Components/ComponentsModalUsability.test.tsx +518 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetailMapping.test.tsx +324 -0
- package/Tests/UI/Components/CustomFields/MapFromCustomFieldInput.test.tsx +176 -0
- package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +484 -0
- package/Tests/UI/Components/HeaderRightRail.test.tsx +157 -0
- package/Tests/UI/Components/IconDropdownItem.test.tsx +102 -0
- package/Tests/UI/Components/JSONTablePrototypePollution.test.tsx +117 -0
- package/Tests/UI/Components/KeyboardShortcutsModal.test.tsx +214 -0
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +561 -0
- package/Tests/UI/Components/MonitorGraphs/UptimeBarDayModal.test.tsx +302 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +28 -12
- package/Tests/UI/Components/ShortcutDialogGuard.test.tsx +74 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSectionAutoExpand.test.tsx +248 -0
- package/Tests/UI/Components/TableCellWrapping.test.tsx +625 -0
- package/Tests/UI/Components/TableLoadingStates.test.tsx +205 -0
- package/Tests/UI/Components/Workflow/NodePlacement.test.ts +148 -0
- package/Tests/UI/Components/Workflow/Workflow.test.tsx +981 -0
- package/Tests/UI/ConfigBrowserTelemetry.test.ts +70 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +1036 -2
- package/Tests/UI/Rum/FidelityNotices.test.ts +187 -0
- package/Tests/UI/Rum/InactivityMap.test.ts +341 -0
- package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +259 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +855 -0
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +594 -0
- package/Tests/UI/Rum/ReplayCard.test.tsx +451 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +536 -0
- package/Tests/UI/Rum/ReplayEngine.test.ts +2503 -0
- package/Tests/UI/Rum/ReplayEngineTypes.test.ts +171 -0
- package/Tests/UI/Rum/ReplayHeader.test.tsx +711 -0
- package/Tests/UI/Rum/ReplayLink.test.tsx +119 -0
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +408 -0
- package/Tests/UI/Rum/ReplayPlaybackIntent.test.ts +152 -0
- package/Tests/UI/Rum/ReplayRail.test.tsx +1296 -0
- package/Tests/UI/Rum/ReplayRailDetail.test.tsx +900 -0
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +763 -147
- package/Tests/UI/Rum/ReplaySignalTypes.test.ts +189 -0
- package/Tests/UI/Rum/ReplaySignals.test.ts +1579 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +396 -473
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +918 -0
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +696 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +499 -0
- package/Tests/UI/Rum/SessionReplaySearchBar.test.tsx +346 -0
- package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +545 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +991 -0
- package/Tests/UI/Rum/TargetedCapturePanel.test.tsx +254 -0
- package/Tests/UI/Telemetry/BrowserExporterIsolation.test.ts +71 -0
- package/Tests/UI/Utils/GlobalKeyboardShortcut.test.ts +344 -0
- package/Tests/Utils/API.test.ts +308 -0
- package/Tests/Utils/HTTPResponseBodyReader.test.ts +323 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveryScanStatus.test.ts +117 -0
- package/Tests/Utils/Rum/ChunkMath.test.ts +83 -0
- package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +993 -0
- package/Tests/Utils/Rum/SessionReplayStringMap.test.ts +245 -0
- package/Tests/Utils/StatusPage/ResourceSearch.test.ts +631 -0
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +633 -0
- package/Tests/Utils/Uptime/DayUptimeGraphUtil.test.ts +461 -0
- package/Tests/Utils/ValueFormatter.test.ts +148 -0
- package/Types/CustomField/CustomFieldMappingCatalog.ts +161 -0
- package/Types/CustomField/CustomFieldMappingSourceResource.ts +19 -0
- package/Types/CustomField/CustomFieldValueMapping.ts +288 -0
- package/Types/Icon/IconProp.ts +1 -0
- package/Types/JSONFunctions.ts +189 -43
- package/Types/Monitor/CephAlertTemplates.ts +157 -195
- package/Types/Monitor/DockerAlertTemplates.ts +338 -128
- package/Types/Monitor/DockerSwarmAlertTemplates.ts +95 -112
- package/Types/Monitor/HostAlertTemplates.ts +302 -130
- package/Types/Monitor/IotAlertTemplates.ts +112 -104
- package/Types/Monitor/KubernetesAlertTemplates.ts +415 -224
- package/Types/Monitor/KubernetesMetricCatalog.ts +23 -19
- package/Types/Monitor/PodmanAlertTemplates.ts +116 -163
- package/Types/Monitor/ProxmoxAlertTemplates.ts +217 -99
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +98 -6
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +44 -7
- package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +383 -0
- package/Types/Monitor/RumAlertTemplates.ts +46 -7
- package/Types/Monitor/SeriesContext/SeriesDebugHints.ts +596 -0
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +554 -0
- package/Types/Monitor/ServiceAlertTemplates.ts +98 -11
- package/Types/Monitor/UptimeHistoryLabels.ts +56 -0
- package/Types/NotificationSetting/RoutineEmailEvents.ts +30 -0
- package/Types/Rum/SessionReplay.ts +209 -0
- package/Types/Rum/SessionReplayApi.ts +722 -0
- package/Types/Rum/SessionReplayCaptureTrigger.ts +21 -12
- package/Types/Rum/SessionReplayConsentMode.ts +11 -7
- package/Types/Rum/SessionReplayCustomEvents.ts +549 -0
- package/Types/Rum/SessionReplayHealth.ts +238 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +95 -0
- package/Types/Telemetry/TelemetryIngestionKeyPolicy.ts +75 -0
- package/Types/Telemetry/TelemetryIngestionKeyType.ts +29 -0
- package/Types/WebsiteRequest.ts +85 -3
- package/UI/Components/Charts/Area/AreaChart.tsx +13 -2
- package/UI/Components/Charts/Bar/BarChart.tsx +6 -2
- package/UI/Components/Charts/Line/LineChart.tsx +13 -2
- package/UI/Components/Charts/Types/XAxis/XAxis.ts +29 -0
- package/UI/Components/Charts/Utils/DataPoint.ts +22 -3
- package/UI/Components/Charts/Utils/TimeAnnotation.ts +76 -9
- package/UI/Components/Charts/Utils/XAxis.ts +217 -0
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +143 -25
- package/UI/Components/CustomFields/MapFromCustomFieldInput.tsx +216 -0
- package/UI/Components/Graphs/DayUptimeGraph.tsx +173 -8
- package/UI/Components/Graphs/UptimeBarTooltip.tsx +22 -278
- package/UI/Components/Graphs/UptimeDaySummary.tsx +327 -0
- package/UI/Components/Header/Header.tsx +25 -9
- package/UI/Components/Header/IconDropdown/IconDropdownItem.tsx +10 -1
- package/UI/Components/Header/IconDropdown/IconDropdownMenu.tsx +6 -1
- package/UI/Components/Header/ProjectPicker/ProjectPicker.tsx +6 -1
- package/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.tsx +6 -1
- package/UI/Components/Icon/Icon.tsx +11 -0
- package/UI/Components/JSONTable/JSONTable.tsx +2 -2
- package/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.tsx +125 -0
- package/UI/Components/KeyboardShortcut/Screenshots/README.md +19 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-command-palette.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog-dark.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-help-menu.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-narrow.png +0 -0
- package/UI/Components/ModelTable/Column.ts +15 -0
- package/UI/Components/Monitor/SeriesDebugCommandsViewer.tsx +64 -0
- package/UI/Components/Monitor/SeriesLabelsViewer.tsx +93 -0
- package/UI/Components/MonitorGraphs/Uptime.tsx +14 -2
- package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +63 -10
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/StatusPage/ResourceGroupSection.tsx +40 -0
- package/UI/Components/Table/CellClassName.ts +81 -0
- package/UI/Components/Table/TableRow.tsx +20 -14
- package/UI/Components/Table/TableSkeletonRows.tsx +9 -9
- package/UI/Components/Table/Types/Column.ts +36 -0
- package/UI/Components/Tooltip/Tooltip.tsx +11 -1
- package/UI/Components/Workflow/ComponentsModal.tsx +60 -39
- package/UI/Components/Workflow/NodePlacement.ts +57 -0
- package/UI/Components/Workflow/Workflow.tsx +47 -18
- package/UI/Config.ts +15 -33
- package/UI/Utils/GlobalKeyboardShortcut.ts +208 -0
- package/UI/Utils/Telemetry/BrowserTelemetryConfig.ts +28 -0
- package/UI/Utils/Telemetry/Telemetry.ts +10 -8
- package/Utils/API.ts +129 -3
- package/Utils/HTTPResponseBodyReader.ts +221 -0
- package/Utils/NetworkDiscovery/DiscoveryScanStatus.ts +77 -0
- package/Utils/Rum/ChunkMath.ts +106 -0
- package/Utils/Rum/SessionReplayHealth.ts +732 -0
- package/Utils/Rum/SessionReplayStringMap.ts +226 -0
- package/Utils/Schema/ModelSchema.ts +1 -0
- package/Utils/StatusPage/ResourceSearch.ts +290 -0
- package/Utils/Telemetry/OriginAllowList.ts +355 -0
- package/Utils/Uptime/DayUptimeGraphUtil.ts +205 -0
- package/Utils/ValueFormatter.ts +35 -1
- package/build/dist/Models/AnalyticsModels/RumSession.js +102 -19
- package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/RumSessionChunk.js +11 -9
- package/build/dist/Models/AnalyticsModels/RumSessionChunk.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ApiKeyPermission.js +3 -27
- package/build/dist/Models/DatabaseModels/ApiKeyPermission.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +6 -6
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/TeamCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamMember.js +0 -9
- package/build/dist/Models/DatabaseModels/TeamMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamPermission.js +3 -24
- package/build/dist/Models/DatabaseModels/TeamPermission.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js +267 -0
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTelegram.js +0 -4
- package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +769 -109
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/API/UserNotificationSettingAPI.js +35 -0
- package/build/dist/Server/API/UserNotificationSettingAPI.js.map +1 -0
- package/build/dist/Server/API/UserTelegramAPI.js +28 -6
- package/build/dist/Server/API/UserTelegramAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +29 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js +60 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js +53 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js +82 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js +46 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +19 -7
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +1 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +315 -8
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AccessTokenService.js +1 -0
- package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
- package/build/dist/Server/Services/AlertCustomFieldService.js +93 -0
- package/build/dist/Server/Services/AlertCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +34 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js +331 -28
- package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
- package/build/dist/Server/Services/CustomFieldMappingService.js +614 -0
- package/build/dist/Server/Services/CustomFieldMappingService.js.map +1 -0
- package/build/dist/Server/Services/GlobalConfigService.js +133 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +93 -0
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +32 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +163 -0
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +29 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +79 -27
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +22 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RoutineEmailSettingsService.js +69 -0
- package/build/dist/Server/Services/RoutineEmailSettingsService.js.map +1 -0
- package/build/dist/Server/Services/RumSessionReplayViewService.js +86 -24
- package/build/dist/Server/Services/RumSessionReplayViewService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js +93 -0
- package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +29 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +62 -2
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TeamPermissionService.js +166 -3
- package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +562 -18
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js +26 -6
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserTelegramService.js +257 -4
- package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/APIKey/AccessPermission.js +2 -2
- package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
- package/build/dist/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.js +27 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.js.map +1 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js +226 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js.map +1 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js +189 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +121 -7
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +38 -5
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +44 -2
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
- package/build/dist/Server/Utils/FrontendEnvironment.js +33 -0
- package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -0
- package/build/dist/Server/Utils/LogRedaction.js +20 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +10 -0
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +287 -68
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +20 -4
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +29 -6
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +88 -13
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +22 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesContextEnricher.js +237 -0
- package/build/dist/Server/Utils/Monitor/SeriesContextEnricher.js.map +1 -0
- package/build/dist/Server/Utils/SSRFProtection.js +136 -9
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +174 -89
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js +223 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +945 -164
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +3 -14
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/TelegramVerificationToken.js +129 -0
- package/build/dist/Server/Utils/TelegramVerificationToken.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/PinServiceName.js +163 -0
- package/build/dist/Server/Utils/Telemetry/PinServiceName.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +28 -15
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +64 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js +171 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +780 -69
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +60 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js +20 -0
- package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldValueMapping.js +141 -0
- package/build/dist/Types/CustomField/CustomFieldValueMapping.js.map +1 -0
- package/build/dist/Types/Icon/IconProp.js +1 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +118 -37
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Monitor/CephAlertTemplates.js +130 -171
- package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/DockerAlertTemplates.js +286 -121
- package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js +84 -105
- package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/HostAlertTemplates.js +250 -122
- package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/IotAlertTemplates.js +81 -81
- package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +375 -215
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +19 -19
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/PodmanAlertTemplates.js +104 -153
- package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +156 -91
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +67 -6
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +38 -7
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +261 -0
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -0
- package/build/dist/Types/Monitor/RumAlertTemplates.js +46 -7
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js +422 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js.map +1 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +441 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -0
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js +79 -15
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/UptimeHistoryLabels.js +17 -0
- package/build/dist/Types/Monitor/UptimeHistoryLabels.js.map +1 -0
- package/build/dist/Types/NotificationSetting/RoutineEmailEvents.js +29 -0
- package/build/dist/Types/NotificationSetting/RoutineEmailEvents.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplay.js +117 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js +181 -0
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js +21 -12
- package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayConsentMode.js +11 -7
- package/build/dist/Types/Rum/SessionReplayConsentMode.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayCustomEvents.js +172 -0
- package/build/dist/Types/Rum/SessionReplayCustomEvents.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayHealth.js +37 -0
- package/build/dist/Types/Rum/SessionReplayHealth.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +85 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js +15 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.js +30 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.js.map +1 -0
- package/build/dist/Types/WebsiteRequest.js +55 -3
- package/build/dist/Types/WebsiteRequest.js.map +1 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +13 -2
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +6 -2
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +13 -2
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Types/XAxis/XAxis.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -3
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +40 -9
- package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/XAxis.js +186 -0
- package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +80 -6
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js +118 -0
- package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js.map +1 -0
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +112 -7
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +5 -162
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
- package/build/dist/UI/Components/Graphs/UptimeDaySummary.js +181 -0
- package/build/dist/UI/Components/Graphs/UptimeDaySummary.js.map +1 -0
- package/build/dist/UI/Components/Header/Header.js +2 -3
- package/build/dist/UI/Components/Header/Header.js.map +1 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js +2 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js.map +1 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js +7 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js.map +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js +7 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js +7 -1
- package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +5 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/JSONTable/JSONTable.js +2 -2
- package/build/dist/UI/Components/JSONTable/JSONTable.js.map +1 -1
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js +35 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js.map +1 -0
- package/build/dist/UI/Components/Monitor/SeriesDebugCommandsViewer.js +34 -0
- package/build/dist/UI/Components/Monitor/SeriesDebugCommandsViewer.js.map +1 -0
- package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js +49 -0
- package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js.map +1 -0
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +32 -6
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +38 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +22 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -1
- package/build/dist/UI/Components/Table/CellClassName.js +55 -0
- package/build/dist/UI/Components/Table/CellClassName.js.map +1 -0
- package/build/dist/UI/Components/Table/TableRow.js +16 -13
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/Table/TableSkeletonRows.js +9 -8
- package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +25 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +47 -30
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/NodePlacement.js +37 -0
- package/build/dist/UI/Components/Workflow/NodePlacement.js.map +1 -0
- package/build/dist/UI/Components/Workflow/Workflow.js +35 -18
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Config.js +10 -20
- package/build/dist/UI/Config.js.map +1 -1
- package/build/dist/UI/Utils/GlobalKeyboardShortcut.js +138 -0
- package/build/dist/UI/Utils/GlobalKeyboardShortcut.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/BrowserTelemetryConfig.js +14 -0
- package/build/dist/UI/Utils/Telemetry/BrowserTelemetryConfig.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/Telemetry.js +7 -5
- package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Utils/API.js +67 -5
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/HTTPResponseBodyReader.js +157 -0
- package/build/dist/Utils/HTTPResponseBodyReader.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js +69 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js.map +1 -0
- package/build/dist/Utils/Rum/ChunkMath.js +76 -0
- package/build/dist/Utils/Rum/ChunkMath.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayHealth.js +534 -0
- package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -0
- package/build/dist/Utils/Rum/SessionReplayStringMap.js +165 -0
- package/build/dist/Utils/Rum/SessionReplayStringMap.js.map +1 -0
- package/build/dist/Utils/Schema/ModelSchema.js +1 -0
- package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
- package/build/dist/Utils/StatusPage/ResourceSearch.js +200 -0
- package/build/dist/Utils/StatusPage/ResourceSearch.js.map +1 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js +299 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -0
- package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js +147 -0
- package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js.map +1 -0
- package/build/dist/Utils/ValueFormatter.js +32 -1
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +1 -1
|
@@ -219,9 +219,26 @@ const semaphoreLockMock: jest.Mock = Semaphore.lock as unknown as jest.Mock;
|
|
|
219
219
|
const semaphoreReleaseMock: jest.Mock =
|
|
220
220
|
Semaphore.release as unknown as jest.Mock;
|
|
221
221
|
const loggerErrorMock: jest.Mock = logger.error as unknown as jest.Mock;
|
|
222
|
+
const loggerWarnMock: jest.Mock = logger.warn as unknown as jest.Mock;
|
|
222
223
|
|
|
223
224
|
const RECENT_COMPLETED_AT: Date = OneUptimeDate.getCurrentDate();
|
|
224
225
|
|
|
226
|
+
/*
|
|
227
|
+
* The values behind a QueryHelper.any() filter.
|
|
228
|
+
*
|
|
229
|
+
* QueryHelper.any builds a raw TypeORM FindOperator whose parameters hold the
|
|
230
|
+
* list, so a status filter cannot be compared to a string any more. Reading
|
|
231
|
+
* the values back out is what lets a test still say WHICH statuses a query
|
|
232
|
+
* accepts rather than merely that it is some operator.
|
|
233
|
+
*/
|
|
234
|
+
function statusesMatchedBy(filter: unknown): Array<string> {
|
|
235
|
+
const parameters: Record<string, Array<string>> = (
|
|
236
|
+
filter as { _objectLiteralParameters?: Record<string, Array<string>> }
|
|
237
|
+
)._objectLiteralParameters!;
|
|
238
|
+
|
|
239
|
+
return Object.values(parameters)[0]!;
|
|
240
|
+
}
|
|
241
|
+
|
|
225
242
|
/*
|
|
226
243
|
* The scan's credential sets (issue #3458), and the ids the probe stamps onto
|
|
227
244
|
* a discovered host to record which one answered it. Opaque literals, because
|
|
@@ -542,9 +559,19 @@ describe("NetworkDeviceAutoImportRuleEngineService.processCompletedScan", () =>
|
|
|
542
559
|
expect(updateCall.data.autoImportProcessedAt).toBeInstanceOf(Date);
|
|
543
560
|
// Nothing was created, so the stored results are not rewritten.
|
|
544
561
|
expect(Object.keys(updateCall.data)).toEqual(["autoImportProcessedAt"]);
|
|
562
|
+
/*
|
|
563
|
+
* The compare-and-set is over the run state this pass READ, not over the
|
|
564
|
+
* literal "Completed" it used to pin: a scan that is still sweeping is
|
|
565
|
+
* importable now (issue #3599), and its status is exactly what changes
|
|
566
|
+
* when its run ends. The two host counters ride along because they are
|
|
567
|
+
* what a running scan's partial uploads move, so a partial landing between
|
|
568
|
+
* the read and the stamp is caught the way a completion is.
|
|
569
|
+
*/
|
|
545
570
|
expect(updateCall.expectedData).toEqual({
|
|
546
571
|
status: "Completed",
|
|
547
572
|
completedAt: RECENT_COMPLETED_AT,
|
|
573
|
+
scannedHostCount: null,
|
|
574
|
+
respondedHostCount: null,
|
|
548
575
|
});
|
|
549
576
|
});
|
|
550
577
|
|
|
@@ -1779,7 +1806,16 @@ describe("NetworkDeviceAutoImportRuleEngineService.applyRuleToCompletedScans", (
|
|
|
1779
1806
|
|
|
1780
1807
|
expect(scanFindOneByMock).toHaveBeenCalledTimes(1);
|
|
1781
1808
|
const rereadCall: any = scanFindOneByMock.mock.calls[0]![0];
|
|
1782
|
-
|
|
1809
|
+
/*
|
|
1810
|
+
* The status filter is a SET now, not the single "Completed" it used to
|
|
1811
|
+
* be: a scan that is still sweeping already holds real results, and
|
|
1812
|
+
* refusing to look at them is what left 527 discovered switches
|
|
1813
|
+
* unimportable for a day (issue #3599).
|
|
1814
|
+
*/
|
|
1815
|
+
expect(statusesMatchedBy(rereadCall.query.status)).toEqual([
|
|
1816
|
+
"Completed",
|
|
1817
|
+
"In Progress",
|
|
1818
|
+
]);
|
|
1783
1819
|
expect(rereadCall.query.projectId.toString()).toBe(PROJECT_ID.toString());
|
|
1784
1820
|
expect(rereadCall.select.discoveredDevices).toBe(true);
|
|
1785
1821
|
});
|
|
@@ -2025,3 +2061,192 @@ describe("NetworkDeviceAutoImportRuleEngineService.applyRuleToCompletedScans", (
|
|
|
2025
2061
|
});
|
|
2026
2062
|
});
|
|
2027
2063
|
});
|
|
2064
|
+
|
|
2065
|
+
/*
|
|
2066
|
+
* github.com/OneUptime/oneuptime/issues/3599 — "Auto Import Rule can't see
|
|
2067
|
+
* already-discovered devices while the Discovery Scan is still running".
|
|
2068
|
+
*
|
|
2069
|
+
* A discovery sweep reports incrementally now: the probe uploads what it has
|
|
2070
|
+
* found every 30 seconds, so an In Progress scan's row already holds real
|
|
2071
|
+
* hosts. The engine used to read only Completed scans, which meant that on the
|
|
2072
|
+
* 24-hour sweep of #3598 the 527 switches it had already found — stored,
|
|
2073
|
+
* visible in the product, correct — were unimportable for the whole day.
|
|
2074
|
+
*
|
|
2075
|
+
* These tests pin that a running scan's results are treated as first-class,
|
|
2076
|
+
* and that the marker protocol still holds when the row underneath is moving.
|
|
2077
|
+
*/
|
|
2078
|
+
describe("auto-import from a scan that is still sweeping (issue #3599)", () => {
|
|
2079
|
+
/*
|
|
2080
|
+
* A scan mid-sweep: no completedAt (the run has not ended), and the two
|
|
2081
|
+
* host counters its partial uploads have been moving.
|
|
2082
|
+
*/
|
|
2083
|
+
function makeInProgressScan(
|
|
2084
|
+
overrides: Record<string, unknown> = {},
|
|
2085
|
+
): NetworkDeviceDiscoveryScan {
|
|
2086
|
+
return makeScan({
|
|
2087
|
+
status: "In Progress",
|
|
2088
|
+
completedAt: undefined,
|
|
2089
|
+
scannedHostCount: 4096,
|
|
2090
|
+
respondedHostCount: 12,
|
|
2091
|
+
...overrides,
|
|
2092
|
+
});
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
it("imports the hosts a running sweep has already found", async () => {
|
|
2096
|
+
scanFindOneByMock.mockResolvedValue(
|
|
2097
|
+
makeInProgressScan({ discoveredDevices: [makeHost()] }),
|
|
2098
|
+
);
|
|
2099
|
+
ruleFindByMock.mockResolvedValue([makeRule()]);
|
|
2100
|
+
|
|
2101
|
+
const result: AutoImportRuleRunResult | null = await processScan();
|
|
2102
|
+
|
|
2103
|
+
expect(result).toMatchObject({ hostsMatched: 1, devicesCreated: 1 });
|
|
2104
|
+
expect(createdDevice(0).hostname).toBe("10.0.0.5");
|
|
2105
|
+
});
|
|
2106
|
+
|
|
2107
|
+
it("asks for a running scan as well as a finished one", async () => {
|
|
2108
|
+
scanFindOneByMock.mockResolvedValue(makeInProgressScan());
|
|
2109
|
+
ruleFindByMock.mockResolvedValue([makeRule()]);
|
|
2110
|
+
|
|
2111
|
+
await processScan();
|
|
2112
|
+
|
|
2113
|
+
const query: any = scanFindOneByMock.mock.calls[0]![0].query;
|
|
2114
|
+
|
|
2115
|
+
expect(statusesMatchedBy(query.status)).toEqual([
|
|
2116
|
+
"Completed",
|
|
2117
|
+
"In Progress",
|
|
2118
|
+
]);
|
|
2119
|
+
});
|
|
2120
|
+
|
|
2121
|
+
/*
|
|
2122
|
+
* The freshness horizon retires results older than MAX_RESULT_AGE_IN_HOURS
|
|
2123
|
+
* without importing them. It is keyed on completedAt, which a running scan
|
|
2124
|
+
* does not have — and must not be read as "infinitely old". A sweep that has
|
|
2125
|
+
* been running for two hours is the opposite of stale.
|
|
2126
|
+
*/
|
|
2127
|
+
it("never treats a running scan's results as too old to import", async () => {
|
|
2128
|
+
scanFindOneByMock.mockResolvedValue(
|
|
2129
|
+
makeInProgressScan({ discoveredDevices: [makeHost()] }),
|
|
2130
|
+
);
|
|
2131
|
+
ruleFindByMock.mockResolvedValue([makeRule()]);
|
|
2132
|
+
|
|
2133
|
+
const result: AutoImportRuleRunResult | null = await processScan();
|
|
2134
|
+
|
|
2135
|
+
expect(result).toMatchObject({ devicesCreated: 1 });
|
|
2136
|
+
expect(loggerWarnMock).not.toHaveBeenCalledWith(
|
|
2137
|
+
expect.stringContaining("stamping it processed without importing"),
|
|
2138
|
+
expect.anything(),
|
|
2139
|
+
);
|
|
2140
|
+
});
|
|
2141
|
+
|
|
2142
|
+
/*
|
|
2143
|
+
* The marker protocol, on a row that is still moving.
|
|
2144
|
+
*
|
|
2145
|
+
* A running scan's status and completedAt do not change between uploads, so
|
|
2146
|
+
* they cannot by themselves tell "the results I evaluated" from "the results
|
|
2147
|
+
* that landed while I was evaluating". The host counters can, and they are
|
|
2148
|
+
* what a partial upload moves.
|
|
2149
|
+
*/
|
|
2150
|
+
it("guards the stamp on the run state it actually read, counters included", async () => {
|
|
2151
|
+
scanFindOneByMock.mockResolvedValue(
|
|
2152
|
+
makeInProgressScan({ discoveredDevices: [makeHost()] }),
|
|
2153
|
+
);
|
|
2154
|
+
ruleFindByMock.mockResolvedValue([makeRule()]);
|
|
2155
|
+
|
|
2156
|
+
await processScan();
|
|
2157
|
+
|
|
2158
|
+
const stamp: any = scanUpdateMock.mock.calls[0]![0];
|
|
2159
|
+
|
|
2160
|
+
expect(stamp.expectedData).toEqual({
|
|
2161
|
+
status: "In Progress",
|
|
2162
|
+
completedAt: null,
|
|
2163
|
+
scannedHostCount: 4096,
|
|
2164
|
+
respondedHostCount: 12,
|
|
2165
|
+
});
|
|
2166
|
+
});
|
|
2167
|
+
|
|
2168
|
+
// The counters are only a version token if they are actually read.
|
|
2169
|
+
it("selects the counters it guards on", async () => {
|
|
2170
|
+
scanFindOneByMock.mockResolvedValue(makeInProgressScan());
|
|
2171
|
+
ruleFindByMock.mockResolvedValue([makeRule()]);
|
|
2172
|
+
|
|
2173
|
+
await processScan();
|
|
2174
|
+
|
|
2175
|
+
const select: any = scanFindOneByMock.mock.calls[0]![0].select;
|
|
2176
|
+
|
|
2177
|
+
expect(select.scannedHostCount).toBe(true);
|
|
2178
|
+
expect(select.respondedHostCount).toBe(true);
|
|
2179
|
+
expect(select.status).toBe(true);
|
|
2180
|
+
expect(select.completedAt).toBe(true);
|
|
2181
|
+
});
|
|
2182
|
+
|
|
2183
|
+
/*
|
|
2184
|
+
* The write-back still retires the hosts this pass consumed, so the Review
|
|
2185
|
+
* dialog stops offering them — on a running scan just as on a finished one.
|
|
2186
|
+
*/
|
|
2187
|
+
it("flips isAlreadyRegistered on the rows it imported", async () => {
|
|
2188
|
+
scanFindOneByMock.mockResolvedValue(
|
|
2189
|
+
makeInProgressScan({
|
|
2190
|
+
discoveredDevices: [makeHost(), makeHost({ ipAddress: "10.0.0.99" })],
|
|
2191
|
+
}),
|
|
2192
|
+
);
|
|
2193
|
+
ruleFindByMock.mockResolvedValue([makeRule({ ipMatchTarget: "10.0.0.5" })]);
|
|
2194
|
+
|
|
2195
|
+
await processScan();
|
|
2196
|
+
|
|
2197
|
+
const written: Array<DiscoveredNetworkDevice> = scanUpdateMock.mock
|
|
2198
|
+
.calls[0]![0].data.discoveredDevices as Array<DiscoveredNetworkDevice>;
|
|
2199
|
+
|
|
2200
|
+
expect(written[0]!.isAlreadyRegistered).toBe(true);
|
|
2201
|
+
expect(written[1]!.isAlreadyRegistered).toBeUndefined();
|
|
2202
|
+
});
|
|
2203
|
+
|
|
2204
|
+
/*
|
|
2205
|
+
* A running scan is offered again on the next tick — its next partial upload
|
|
2206
|
+
* clears the marker — so an address it already imported must read as
|
|
2207
|
+
* registered rather than being created twice.
|
|
2208
|
+
*/
|
|
2209
|
+
it("skips an address it already imported when the scan is offered again", async () => {
|
|
2210
|
+
const alreadyImported: NetworkDevice = {
|
|
2211
|
+
id: new ObjectID("55555555-5555-4555-8555-555555555555"),
|
|
2212
|
+
projectId: PROJECT_ID,
|
|
2213
|
+
hostname: "10.0.0.5",
|
|
2214
|
+
} as unknown as NetworkDevice;
|
|
2215
|
+
|
|
2216
|
+
deviceFindByMock.mockResolvedValue([alreadyImported]);
|
|
2217
|
+
scanFindOneByMock.mockResolvedValue(
|
|
2218
|
+
makeInProgressScan({ discoveredDevices: [makeHost()] }),
|
|
2219
|
+
);
|
|
2220
|
+
ruleFindByMock.mockResolvedValue([makeRule()]);
|
|
2221
|
+
|
|
2222
|
+
const result: AutoImportRuleRunResult | null = await processScan();
|
|
2223
|
+
|
|
2224
|
+
expect(createMock).not.toHaveBeenCalled();
|
|
2225
|
+
expect(result).toMatchObject({
|
|
2226
|
+
hostsMatched: 1,
|
|
2227
|
+
devicesCreated: 0,
|
|
2228
|
+
hostsSkippedAlreadyRegistered: 1,
|
|
2229
|
+
});
|
|
2230
|
+
});
|
|
2231
|
+
|
|
2232
|
+
/*
|
|
2233
|
+
* The manual path, which is where the report came from: "Run Now" said it
|
|
2234
|
+
* had checked 25 hosts while 527 sat in the Devices list, because the scan
|
|
2235
|
+
* that found them had not finished.
|
|
2236
|
+
*/
|
|
2237
|
+
it("Run Now reads a running scan's results too", async () => {
|
|
2238
|
+
ruleFindOneByMock.mockResolvedValue(makeRule());
|
|
2239
|
+
ruleFindByMock.mockResolvedValue([]);
|
|
2240
|
+
mockRunNowScans([makeInProgressScan({ discoveredDevices: [makeHost()] })]);
|
|
2241
|
+
|
|
2242
|
+
const result: AutoImportRuleRunResult = await runRule(true);
|
|
2243
|
+
|
|
2244
|
+
expect(result).toMatchObject({ hostsEvaluated: 1, hostsMatched: 1 });
|
|
2245
|
+
|
|
2246
|
+
const listQuery: any = scanFindByMock.mock.calls[0]![0].query;
|
|
2247
|
+
expect(statusesMatchedBy(listQuery.status)).toEqual([
|
|
2248
|
+
"Completed",
|
|
2249
|
+
"In Progress",
|
|
2250
|
+
]);
|
|
2251
|
+
});
|
|
2252
|
+
});
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import RoutineEmailSettingsService from "../../../Server/Services/RoutineEmailSettingsService";
|
|
2
|
+
import UserNotificationSettingService from "../../../Server/Services/UserNotificationSettingService";
|
|
3
|
+
import PostgresAppInstance from "../../../Server/Infrastructure/PostgresDatabase";
|
|
4
|
+
import Entities from "../../../Models/DatabaseModels/Index";
|
|
5
|
+
import NotificationSettingEventType from "../../../Types/NotificationSetting/NotificationSettingEventType";
|
|
6
|
+
import { ROUTINE_EMAIL_EVENT_TYPES } from "../../../Types/NotificationSetting/RoutineEmailEvents";
|
|
7
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
8
|
+
import { DataSource } from "typeorm";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* Opt in with RUN_POSTGRES_NOTIFICATION_TESTS=true and the normal database
|
|
12
|
+
* credentials. Uses the local development Postgres port unless overridden by
|
|
13
|
+
* NOTIFICATION_TEST_DATABASE_HOST / NOTIFICATION_TEST_DATABASE_PORT.
|
|
14
|
+
* All writes go to a uniquely named schema; no project data is modified.
|
|
15
|
+
* Cloning the production table also verifies the statements against its actual
|
|
16
|
+
* defaults and column types rather than a hand-maintained test schema.
|
|
17
|
+
*/
|
|
18
|
+
const describePostgres: typeof describe =
|
|
19
|
+
process.env["RUN_POSTGRES_NOTIFICATION_TESTS"] === "true"
|
|
20
|
+
? describe
|
|
21
|
+
: describe.skip;
|
|
22
|
+
|
|
23
|
+
const USER_ID: ObjectID = ObjectID.generate();
|
|
24
|
+
const OTHER_USER_ID: ObjectID = ObjectID.generate();
|
|
25
|
+
const PROJECT_ID: ObjectID = ObjectID.generate();
|
|
26
|
+
const OTHER_PROJECT_ID: ObjectID = ObjectID.generate();
|
|
27
|
+
const ROUTINE_EVENT: NotificationSettingEventType =
|
|
28
|
+
NotificationSettingEventType.SEND_INCIDENT_NOTE_POSTED_OWNER_NOTIFICATION;
|
|
29
|
+
const CHANNELS: Array<string> = [
|
|
30
|
+
"alertBySMS",
|
|
31
|
+
"alertByCall",
|
|
32
|
+
"alertByPush",
|
|
33
|
+
"alertByWhatsApp",
|
|
34
|
+
"alertByTelegram",
|
|
35
|
+
"alertBySlack",
|
|
36
|
+
"alertByMicrosoftTeams",
|
|
37
|
+
"alertByWebhook",
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
interface StoredSetting {
|
|
41
|
+
_id: string;
|
|
42
|
+
userId: string;
|
|
43
|
+
projectId: string;
|
|
44
|
+
eventType: NotificationSettingEventType;
|
|
45
|
+
alertByEmail: boolean;
|
|
46
|
+
version: number;
|
|
47
|
+
deletedAt: Date | null;
|
|
48
|
+
[key: string]: unknown;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
describePostgres("reduce routine emails against Postgres", () => {
|
|
52
|
+
const schema: string = `routine_email_test_${ObjectID.generate().toString().replace(/-/g, "")}`;
|
|
53
|
+
let database: DataSource;
|
|
54
|
+
|
|
55
|
+
beforeAll(async () => {
|
|
56
|
+
database = new DataSource({
|
|
57
|
+
type: "postgres",
|
|
58
|
+
host: process.env["NOTIFICATION_TEST_DATABASE_HOST"] || "localhost",
|
|
59
|
+
port: Number(process.env["NOTIFICATION_TEST_DATABASE_PORT"] || "5400"),
|
|
60
|
+
username: process.env["DATABASE_USERNAME"] || "postgres",
|
|
61
|
+
password: process.env["DATABASE_PASSWORD"] || "password",
|
|
62
|
+
database: process.env["DATABASE_NAME"] || "oneuptimedb",
|
|
63
|
+
entities: Entities,
|
|
64
|
+
schema: schema,
|
|
65
|
+
synchronize: false,
|
|
66
|
+
extra: { options: `-c search_path=${schema},public` },
|
|
67
|
+
});
|
|
68
|
+
await database.initialize();
|
|
69
|
+
await database.query(`CREATE SCHEMA "${schema}"`);
|
|
70
|
+
await database.query(
|
|
71
|
+
`CREATE TABLE "${schema}"."UserNotificationSetting" (LIKE public."UserNotificationSetting" INCLUDING ALL)`,
|
|
72
|
+
);
|
|
73
|
+
const currentSchema: Array<{ current_schema: string }> =
|
|
74
|
+
await database.query("SELECT current_schema()");
|
|
75
|
+
expect(currentSchema[0]?.current_schema).toBe(schema);
|
|
76
|
+
jest.spyOn(PostgresAppInstance, "isConnected").mockReturnValue(true);
|
|
77
|
+
jest.spyOn(PostgresAppInstance, "getDataSource").mockReturnValue(database);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
beforeEach(async () => {
|
|
81
|
+
await database.query(`TRUNCATE "${schema}"."UserNotificationSetting"`);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
afterAll(async () => {
|
|
85
|
+
jest.restoreAllMocks();
|
|
86
|
+
if (database?.isInitialized) {
|
|
87
|
+
await database.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
|
|
88
|
+
await database.destroy();
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
async function seed(data: {
|
|
93
|
+
eventType: NotificationSettingEventType;
|
|
94
|
+
email?: boolean;
|
|
95
|
+
userId?: ObjectID;
|
|
96
|
+
projectId?: ObjectID;
|
|
97
|
+
deleted?: boolean;
|
|
98
|
+
}): Promise<StoredSetting> {
|
|
99
|
+
const rows: Array<StoredSetting> = await database.query(
|
|
100
|
+
`INSERT INTO "UserNotificationSetting"
|
|
101
|
+
("userId", "projectId", "eventType", "alertByEmail", "version", "deletedAt", ${CHANNELS.map(
|
|
102
|
+
(channel: string) => {
|
|
103
|
+
return `"${channel}"`;
|
|
104
|
+
},
|
|
105
|
+
).join(", ")})
|
|
106
|
+
VALUES ($1, $2, $3, $4, 1, $5, ${CHANNELS.map(() => {
|
|
107
|
+
return "true";
|
|
108
|
+
}).join(", ")})
|
|
109
|
+
RETURNING *`,
|
|
110
|
+
[
|
|
111
|
+
(data.userId || USER_ID).toString(),
|
|
112
|
+
(data.projectId || PROJECT_ID).toString(),
|
|
113
|
+
data.eventType,
|
|
114
|
+
data.email ?? true,
|
|
115
|
+
data.deleted ? new Date() : null,
|
|
116
|
+
],
|
|
117
|
+
);
|
|
118
|
+
return rows[0]!;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function rows(): Promise<Array<StoredSetting>> {
|
|
122
|
+
return await database.query(
|
|
123
|
+
'SELECT * FROM "UserNotificationSetting" ORDER BY "_id"',
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function apply(): Promise<void> {
|
|
128
|
+
await RoutineEmailSettingsService.reduceRoutineEmails({
|
|
129
|
+
userId: USER_ID,
|
|
130
|
+
projectId: PROJECT_ID,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
test("creates a persisted opt-out for every missing routine event", async () => {
|
|
135
|
+
await apply();
|
|
136
|
+
const settings: Array<StoredSetting> = await rows();
|
|
137
|
+
expect(settings).toHaveLength(ROUTINE_EMAIL_EVENT_TYPES.length);
|
|
138
|
+
expect(
|
|
139
|
+
new Set(
|
|
140
|
+
settings.map((setting: StoredSetting) => {
|
|
141
|
+
return setting.eventType;
|
|
142
|
+
}),
|
|
143
|
+
),
|
|
144
|
+
).toEqual(new Set(ROUTINE_EMAIL_EVENT_TYPES));
|
|
145
|
+
for (const setting of settings) {
|
|
146
|
+
expect(setting.userId).toBe(USER_ID.toString());
|
|
147
|
+
expect(setting.projectId).toBe(PROJECT_ID.toString());
|
|
148
|
+
expect(setting["createdByUserId"]).toBe(USER_ID.toString());
|
|
149
|
+
expect(setting.alertByEmail).toBe(false);
|
|
150
|
+
expect(setting.version).toBe(1);
|
|
151
|
+
for (const channel of CHANNELS) {
|
|
152
|
+
expect(setting[channel]).toBe(false);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("disables only email while preserving every other channel on existing rows", async () => {
|
|
158
|
+
for (const eventType of ROUTINE_EMAIL_EVENT_TYPES) {
|
|
159
|
+
await seed({ eventType });
|
|
160
|
+
}
|
|
161
|
+
await apply();
|
|
162
|
+
const settings: Array<StoredSetting> = await rows();
|
|
163
|
+
expect(settings).toHaveLength(ROUTINE_EMAIL_EVENT_TYPES.length);
|
|
164
|
+
for (const setting of settings) {
|
|
165
|
+
expect(setting.alertByEmail).toBe(false);
|
|
166
|
+
expect(setting.version).toBe(2);
|
|
167
|
+
for (const channel of CHANNELS) {
|
|
168
|
+
expect(setting[channel]).toBe(true);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("preserves every non-routine event, including existing opt-outs", async () => {
|
|
174
|
+
const preserved: Array<StoredSetting> = [];
|
|
175
|
+
for (const eventType of Object.values(NotificationSettingEventType)) {
|
|
176
|
+
if (!ROUTINE_EMAIL_EVENT_TYPES.includes(eventType)) {
|
|
177
|
+
preserved.push(await seed({ eventType }));
|
|
178
|
+
preserved.push(await seed({ eventType, email: false }));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
await apply();
|
|
182
|
+
const settings: Array<StoredSetting> = await rows();
|
|
183
|
+
for (const before of preserved) {
|
|
184
|
+
expect(
|
|
185
|
+
settings.find((setting: StoredSetting) => {
|
|
186
|
+
return setting._id === before._id;
|
|
187
|
+
}),
|
|
188
|
+
).toEqual(before);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("does not create missing incident, alert or on-call preferences", async () => {
|
|
193
|
+
await apply();
|
|
194
|
+
for (const setting of await rows()) {
|
|
195
|
+
expect(ROUTINE_EMAIL_EVENT_TYPES).toContain(setting.eventType);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("preserves an event introduced after this preset was defined", async () => {
|
|
200
|
+
const futureEvent: StoredSetting = await seed({
|
|
201
|
+
eventType: "Future notification event" as NotificationSettingEventType,
|
|
202
|
+
});
|
|
203
|
+
await apply();
|
|
204
|
+
expect(
|
|
205
|
+
(await rows()).find((setting: StoredSetting) => {
|
|
206
|
+
return setting._id === futureEvent._id;
|
|
207
|
+
}),
|
|
208
|
+
).toEqual(futureEvent);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("leaves other users and projects unchanged", async () => {
|
|
212
|
+
const preserved: Array<StoredSetting> = [
|
|
213
|
+
await seed({ eventType: ROUTINE_EVENT, userId: OTHER_USER_ID }),
|
|
214
|
+
await seed({ eventType: ROUTINE_EVENT, projectId: OTHER_PROJECT_ID }),
|
|
215
|
+
await seed({
|
|
216
|
+
eventType: ROUTINE_EVENT,
|
|
217
|
+
userId: OTHER_USER_ID,
|
|
218
|
+
projectId: OTHER_PROJECT_ID,
|
|
219
|
+
}),
|
|
220
|
+
];
|
|
221
|
+
await apply();
|
|
222
|
+
const settings: Array<StoredSetting> = await rows();
|
|
223
|
+
for (const before of preserved) {
|
|
224
|
+
expect(
|
|
225
|
+
settings.find((setting: StoredSetting) => {
|
|
226
|
+
return setting._id === before._id;
|
|
227
|
+
}),
|
|
228
|
+
).toEqual(before);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test("repeated requests do not create duplicates or change row versions and timestamps", async () => {
|
|
233
|
+
await seed({ eventType: ROUTINE_EVENT });
|
|
234
|
+
await apply();
|
|
235
|
+
const first: Array<StoredSetting> = await rows();
|
|
236
|
+
await apply();
|
|
237
|
+
expect(await rows()).toEqual(first);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test("later default seeding respects every persisted opt-out", async () => {
|
|
241
|
+
await apply();
|
|
242
|
+
const before: Array<StoredSetting> = await rows();
|
|
243
|
+
for (const eventType of ROUTINE_EMAIL_EVENT_TYPES) {
|
|
244
|
+
await UserNotificationSettingService.ensureSettingExistsForUser({
|
|
245
|
+
userId: USER_ID,
|
|
246
|
+
projectId: PROJECT_ID,
|
|
247
|
+
eventType: eventType,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
expect(await rows()).toEqual(before);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("simultaneous requests create only one live row per routine event", async () => {
|
|
254
|
+
await Promise.all(
|
|
255
|
+
Array.from({ length: 8 }, async () => {
|
|
256
|
+
return apply();
|
|
257
|
+
}),
|
|
258
|
+
);
|
|
259
|
+
const settings: Array<StoredSetting> = await rows();
|
|
260
|
+
expect(settings).toHaveLength(ROUTINE_EMAIL_EVENT_TYPES.length);
|
|
261
|
+
expect(
|
|
262
|
+
new Set(
|
|
263
|
+
settings.map((setting: StoredSetting) => {
|
|
264
|
+
return setting.eventType;
|
|
265
|
+
}),
|
|
266
|
+
).size,
|
|
267
|
+
).toBe(ROUTINE_EMAIL_EVENT_TYPES.length);
|
|
268
|
+
expect(
|
|
269
|
+
settings.every((setting: StoredSetting) => {
|
|
270
|
+
return setting.alertByEmail === false;
|
|
271
|
+
}),
|
|
272
|
+
).toBe(true);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test("disables all live historical duplicates for the same event", async () => {
|
|
276
|
+
const first: StoredSetting = await seed({ eventType: ROUTINE_EVENT });
|
|
277
|
+
const second: StoredSetting = await seed({ eventType: ROUTINE_EVENT });
|
|
278
|
+
await apply();
|
|
279
|
+
const settings: Array<StoredSetting> = await rows();
|
|
280
|
+
for (const id of [first._id, second._id]) {
|
|
281
|
+
expect(
|
|
282
|
+
settings.find((setting: StoredSetting) => {
|
|
283
|
+
return setting._id === id;
|
|
284
|
+
})?.alertByEmail,
|
|
285
|
+
).toBe(false);
|
|
286
|
+
}
|
|
287
|
+
expect(settings).toHaveLength(ROUTINE_EMAIL_EVENT_TYPES.length + 1);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test("retains deleted history and creates a new live opt-out", async () => {
|
|
291
|
+
const deleted: StoredSetting = await seed({
|
|
292
|
+
eventType: ROUTINE_EVENT,
|
|
293
|
+
deleted: true,
|
|
294
|
+
});
|
|
295
|
+
await apply();
|
|
296
|
+
const settings: Array<StoredSetting> = await rows();
|
|
297
|
+
expect(
|
|
298
|
+
settings.find((setting: StoredSetting) => {
|
|
299
|
+
return setting._id === deleted._id;
|
|
300
|
+
}),
|
|
301
|
+
).toEqual(deleted);
|
|
302
|
+
expect(
|
|
303
|
+
settings.filter((setting: StoredSetting) => {
|
|
304
|
+
return (
|
|
305
|
+
setting.eventType === ROUTINE_EVENT && setting.deletedAt === null
|
|
306
|
+
);
|
|
307
|
+
}),
|
|
308
|
+
).toEqual([expect.objectContaining({ alertByEmail: false })]);
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("rolls back existing changes when inserting a missing preference fails", async () => {
|
|
312
|
+
const original: StoredSetting = await seed({ eventType: ROUTINE_EVENT });
|
|
313
|
+
// A database constraint supplies a real statement failure after UPDATE.
|
|
314
|
+
await database.query(
|
|
315
|
+
'ALTER TABLE "UserNotificationSetting" ADD CONSTRAINT "fail_missing_preferences" CHECK ("eventType" = \'Send incident note posted notification when I am the owner of the incident\')',
|
|
316
|
+
);
|
|
317
|
+
try {
|
|
318
|
+
await expect(apply()).rejects.toThrow();
|
|
319
|
+
expect(await rows()).toEqual([original]);
|
|
320
|
+
} finally {
|
|
321
|
+
await database.query(
|
|
322
|
+
'ALTER TABLE "UserNotificationSetting" DROP CONSTRAINT "fail_missing_preferences"',
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
// The failed transaction also releases the advisory lock, so retry works.
|
|
326
|
+
await apply();
|
|
327
|
+
expect(await rows()).toHaveLength(ROUTINE_EMAIL_EVENT_TYPES.length);
|
|
328
|
+
});
|
|
329
|
+
});
|