@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
|
@@ -9,18 +9,31 @@ import SessionReplayConsentMode from "../../../Types/Rum/SessionReplayConsentMod
|
|
|
9
9
|
import { parseSessionReplayMaskingMode, } from "../../../Types/Rum/SessionReplayMaskingMode";
|
|
10
10
|
import { DEFAULT_SESSION_REPLAY_RETENTION_IN_DAYS, SESSION_REPLAY_ALLOWED_RETENTION_DAYS, } from "../../../Types/Rum/SessionReplay";
|
|
11
11
|
import SessionIdentity from "../../../Utils/Rum/SessionIdentity";
|
|
12
|
+
import OriginAllowList from "../../../Utils/Telemetry/OriginAllowList";
|
|
13
|
+
/*
|
|
14
|
+
* RumApplication.sessionReplaySamplePercentage's column default. Declared
|
|
15
|
+
* here rather than read off the model because this file compiles against
|
|
16
|
+
* checkouts whose model predates the column (see buildSelect).
|
|
17
|
+
*/
|
|
18
|
+
const DEFAULT_SESSION_REPLAY_SAMPLE_PERCENTAGE = 100;
|
|
12
19
|
/*
|
|
13
20
|
* Resolves the session-replay policy for one (project, appIdentifier) pair,
|
|
14
21
|
* which is what all three ingest-time gates need: the org-wide allow flag,
|
|
15
22
|
* the per-application enable flag, and the origin allowlist.
|
|
16
23
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
+
* The two SWITCHES default to refusing. An application that has never been
|
|
25
|
+
* configured, a project that has never opted in, a row whose enable columns
|
|
26
|
+
* have not been migrated yet, and a lookup that fails outright all resolve
|
|
27
|
+
* to "do not accept recordings". That is the opposite posture from the log
|
|
28
|
+
* and trace scrub loaders, which continue with empty rules on failure, and
|
|
29
|
+
* it is deliberate: a span recorded by mistake is a span, a session
|
|
30
|
+
* recorded by mistake is a video of a real person.
|
|
31
|
+
*
|
|
32
|
+
* Once both switches say yes, the remaining policy columns default to what
|
|
33
|
+
* the MODEL defaults to (consent NotRequired, trigger Always, sample 100),
|
|
34
|
+
* because those are instructions to a recorder the customer has already
|
|
35
|
+
* switched on, and a silent downgrade to "record nothing" is the failure
|
|
36
|
+
* the Dashboard cannot explain. See loadPolicy.
|
|
24
37
|
*
|
|
25
38
|
* Cache shape follows the house convention for hot-path policy (a
|
|
26
39
|
* process-local Map with a 60s TTL, as in LogScrubRuleService), with one
|
|
@@ -70,6 +83,40 @@ const RUM_APPLICATION_POLICY_COLUMNS = [
|
|
|
70
83
|
const PROJECT_POLICY_COLUMNS = [
|
|
71
84
|
"isSessionReplayAllowed",
|
|
72
85
|
];
|
|
86
|
+
/*
|
|
87
|
+
* WHY a policy lookup came back empty.
|
|
88
|
+
*
|
|
89
|
+
* getPolicy() folds every refusing state into null, which is the right
|
|
90
|
+
* shape for the gate (it must refuse, and the recorder is told "stop"), but
|
|
91
|
+
* the config endpoint, the /validate probe and the health counters all owe
|
|
92
|
+
* the customer a NAME: a project that was switched off, an application that
|
|
93
|
+
* was switched off, an identifier that matches no application, and a
|
|
94
|
+
* project killed by the operator's kill key are four different settings
|
|
95
|
+
* pages. Answering "not enabled for application" for all four sends the
|
|
96
|
+
* customer to the wrong one.
|
|
97
|
+
*
|
|
98
|
+
* A closed vocabulary that carries no project data; it is only ever
|
|
99
|
+
* answered to a request already holding a valid ingestion key for the
|
|
100
|
+
* project.
|
|
101
|
+
*/
|
|
102
|
+
export var SessionReplayPolicyRefusal;
|
|
103
|
+
(function (SessionReplayPolicyRefusal) {
|
|
104
|
+
/* Project.isSessionReplayAllowed is false: the org-wide switch. */
|
|
105
|
+
SessionReplayPolicyRefusal["ProjectNotAllowed"] = "project-not-allowed";
|
|
106
|
+
/* RumApplication.isSessionReplayEnabled is false for this application. */
|
|
107
|
+
SessionReplayPolicyRefusal["ApplicationNotEnabled"] = "application-not-enabled";
|
|
108
|
+
/*
|
|
109
|
+
* No application by that identifier could be found or created. With a
|
|
110
|
+
* project that allows replay the application is created on first sight,
|
|
111
|
+
* so this is either a project that does not allow it or a creation that
|
|
112
|
+
* failed.
|
|
113
|
+
*/
|
|
114
|
+
SessionReplayPolicyRefusal["ApplicationUnknown"] = "application-unknown";
|
|
115
|
+
/* The gate cache's Redis kill key is set for the project. */
|
|
116
|
+
SessionReplayPolicyRefusal["ProjectKilled"] = "project-killed";
|
|
117
|
+
/* No identifier was supplied at all. */
|
|
118
|
+
SessionReplayPolicyRefusal["IdentifierMissing"] = "app-identifier-missing";
|
|
119
|
+
})(SessionReplayPolicyRefusal || (SessionReplayPolicyRefusal = {}));
|
|
73
120
|
export default class SessionReplayGateCache {
|
|
74
121
|
/*
|
|
75
122
|
* Resolve the policy for one application.
|
|
@@ -81,36 +128,63 @@ export default class SessionReplayGateCache {
|
|
|
81
128
|
* produce different HTTP answers - a terminal 204 that stops the
|
|
82
129
|
* recorder, versus a retryable 503 that does not silently discard a
|
|
83
130
|
* recording during a database blip.
|
|
131
|
+
*
|
|
132
|
+
* Callers that need to say WHY the answer was null use resolvePolicy.
|
|
84
133
|
*/
|
|
85
134
|
static async getPolicy(data) {
|
|
135
|
+
const resolution = await this.resolvePolicy(data);
|
|
136
|
+
return resolution.policy;
|
|
137
|
+
}
|
|
138
|
+
/*
|
|
139
|
+
* getPolicy with the refusal reason attached. Same caching, same kill-key
|
|
140
|
+
* check, same throw-on-lookup-failure contract.
|
|
141
|
+
*/
|
|
142
|
+
static async resolvePolicy(data) {
|
|
86
143
|
const appIdentifier = data.appIdentifier.trim();
|
|
87
144
|
if (!appIdentifier) {
|
|
88
|
-
return
|
|
145
|
+
return {
|
|
146
|
+
policy: null,
|
|
147
|
+
refusal: SessionReplayPolicyRefusal.IdentifierMissing,
|
|
148
|
+
};
|
|
89
149
|
}
|
|
90
150
|
const cacheKey = `${data.projectId.toString()}:${appIdentifier.toLowerCase()}`;
|
|
91
151
|
const cached = SessionReplayGateCacheStore.getPolicyEntry(cacheKey);
|
|
92
|
-
if (cached &&
|
|
152
|
+
if (cached &&
|
|
153
|
+
cached.policy &&
|
|
154
|
+
Date.now() - cached.loadedAt < POLICY_CACHE_TTL_MS) {
|
|
93
155
|
/*
|
|
94
156
|
* The kill key is consulted even on a cache hit - that is the whole
|
|
95
157
|
* point of it. A cached "enabled" policy is only honoured while the
|
|
96
158
|
* project has not been switched off in the last few seconds.
|
|
97
159
|
*/
|
|
98
|
-
if (cached.policy &&
|
|
160
|
+
if (cached.policy.policy &&
|
|
99
161
|
(await SessionReplayGateCacheStore.isProjectKilled(data.projectId))) {
|
|
100
|
-
return
|
|
162
|
+
return {
|
|
163
|
+
policy: null,
|
|
164
|
+
refusal: SessionReplayPolicyRefusal.ProjectKilled,
|
|
165
|
+
};
|
|
101
166
|
}
|
|
102
|
-
return
|
|
167
|
+
return {
|
|
168
|
+
policy: cached.policy.policy,
|
|
169
|
+
refusal: cached.policy.refusal,
|
|
170
|
+
};
|
|
103
171
|
}
|
|
104
|
-
const
|
|
172
|
+
const loaded = await this.loadPolicy({
|
|
105
173
|
projectId: data.projectId,
|
|
106
174
|
appIdentifier: appIdentifier,
|
|
107
175
|
});
|
|
108
|
-
SessionReplayGateCacheStore.setPolicyEntry(cacheKey,
|
|
109
|
-
|
|
176
|
+
SessionReplayGateCacheStore.setPolicyEntry(cacheKey, {
|
|
177
|
+
policy: loaded.policy,
|
|
178
|
+
refusal: loaded.refusal,
|
|
179
|
+
});
|
|
180
|
+
if (loaded.policy &&
|
|
110
181
|
(await SessionReplayGateCacheStore.isProjectKilled(data.projectId))) {
|
|
111
|
-
return
|
|
182
|
+
return {
|
|
183
|
+
policy: null,
|
|
184
|
+
refusal: SessionReplayPolicyRefusal.ProjectKilled,
|
|
185
|
+
};
|
|
112
186
|
}
|
|
113
|
-
return
|
|
187
|
+
return loaded;
|
|
114
188
|
}
|
|
115
189
|
static async loadPolicy(data) {
|
|
116
190
|
const project = await ProjectService.findOneBy({
|
|
@@ -123,7 +197,14 @@ export default class SessionReplayGateCache {
|
|
|
123
197
|
},
|
|
124
198
|
});
|
|
125
199
|
if (!project) {
|
|
126
|
-
|
|
200
|
+
/*
|
|
201
|
+
* The key authenticated a project that no longer exists (deleted
|
|
202
|
+
* between the key check and here). Nothing about it is allowed.
|
|
203
|
+
*/
|
|
204
|
+
return {
|
|
205
|
+
policy: null,
|
|
206
|
+
refusal: SessionReplayPolicyRefusal.ProjectNotAllowed,
|
|
207
|
+
};
|
|
127
208
|
}
|
|
128
209
|
const projectView = project;
|
|
129
210
|
const isProjectAllowed = projectView["isSessionReplayAllowed"] === true;
|
|
@@ -153,7 +234,10 @@ export default class SessionReplayGateCache {
|
|
|
153
234
|
*/
|
|
154
235
|
if (!app) {
|
|
155
236
|
if (!isProjectAllowed) {
|
|
156
|
-
return
|
|
237
|
+
return {
|
|
238
|
+
policy: null,
|
|
239
|
+
refusal: SessionReplayPolicyRefusal.ProjectNotAllowed,
|
|
240
|
+
};
|
|
157
241
|
}
|
|
158
242
|
await RumApplicationService.findOrCreateByAppIdentifier({
|
|
159
243
|
projectId: data.projectId,
|
|
@@ -171,58 +255,89 @@ export default class SessionReplayGateCache {
|
|
|
171
255
|
});
|
|
172
256
|
}
|
|
173
257
|
if (!app || !app.id) {
|
|
174
|
-
return
|
|
258
|
+
return {
|
|
259
|
+
policy: null,
|
|
260
|
+
refusal: SessionReplayPolicyRefusal.ApplicationUnknown,
|
|
261
|
+
};
|
|
175
262
|
}
|
|
176
263
|
const appView = app;
|
|
177
264
|
const isAppEnabled = appView["isSessionReplayEnabled"] === true;
|
|
178
265
|
/*
|
|
179
266
|
* Both flags are required. Returning null rather than a disabled policy
|
|
180
267
|
* keeps every caller from having to remember to check them: if this
|
|
181
|
-
* function hands back an object at all, recording is permitted.
|
|
268
|
+
* function hands back an object at all, recording is permitted. The
|
|
269
|
+
* project switch is reported ahead of the application switch because
|
|
270
|
+
* flipping the application on does nothing while the project is off.
|
|
182
271
|
*/
|
|
183
|
-
if (!isProjectAllowed
|
|
184
|
-
return
|
|
272
|
+
if (!isProjectAllowed) {
|
|
273
|
+
return {
|
|
274
|
+
policy: null,
|
|
275
|
+
refusal: SessionReplayPolicyRefusal.ProjectNotAllowed,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
if (!isAppEnabled) {
|
|
279
|
+
return {
|
|
280
|
+
policy: null,
|
|
281
|
+
refusal: SessionReplayPolicyRefusal.ApplicationNotEnabled,
|
|
282
|
+
};
|
|
185
283
|
}
|
|
186
284
|
const requestedRetentionDays = this.readNumber(appView["sessionReplayRetentionInDays"], DEFAULT_SESSION_REPLAY_RETENTION_IN_DAYS);
|
|
285
|
+
/*
|
|
286
|
+
* Null-column fallbacks are the MODEL defaults (RumApplication.ts:
|
|
287
|
+
* consent NotRequired, trigger Always, sample 100), not the refusing
|
|
288
|
+
* ones. This gate refuses through the two boolean switches above; once
|
|
289
|
+
* those say yes, a policy column that is null - an explicit null via the
|
|
290
|
+
* CRUD API, a partially applied migration, a checkout behind on
|
|
291
|
+
* migrations - must read as "the default the settings page shows", or
|
|
292
|
+
* the row silently reverts to "capture only on error, sample 0%" while
|
|
293
|
+
* the ingest-status page reports the row's own (null) values and cannot
|
|
294
|
+
* explain the silence. The recorder honours these three as instructions,
|
|
295
|
+
* so they must match what the Dashboard says the application does.
|
|
296
|
+
*/
|
|
187
297
|
return {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
298
|
+
policy: {
|
|
299
|
+
projectId: data.projectId,
|
|
300
|
+
rumApplicationId: app.id,
|
|
301
|
+
isProjectAllowed: true,
|
|
302
|
+
isAppEnabled: true,
|
|
303
|
+
allowedOrigins: this.readStringArray(appView["sessionReplayAllowedOrigins"]),
|
|
304
|
+
maskingMode: parseSessionReplayMaskingMode(appView["sessionReplayMaskingMode"]),
|
|
305
|
+
consentMode: appView["sessionReplayConsentMode"] ===
|
|
306
|
+
SessionReplayConsentMode.RequireExplicit
|
|
307
|
+
? SessionReplayConsentMode.RequireExplicit
|
|
308
|
+
: SessionReplayConsentMode.NotRequired,
|
|
309
|
+
captureTrigger: appView["sessionReplayCaptureTrigger"] ===
|
|
310
|
+
SessionReplayCaptureTrigger.OnErrorOrFrustration
|
|
311
|
+
? SessionReplayCaptureTrigger.OnErrorOrFrustration
|
|
312
|
+
: SessionReplayCaptureTrigger.Always,
|
|
313
|
+
samplePercentage: this.readNumber(appView["sessionReplaySamplePercentage"], DEFAULT_SESSION_REPLAY_SAMPLE_PERCENTAGE),
|
|
314
|
+
maskSelectors: this.readStringArray(appView["sessionReplayMaskSelectors"]),
|
|
315
|
+
blockSelectors: this.readStringArray(appView["sessionReplayBlockSelectors"]),
|
|
316
|
+
recordCanvas: appView["sessionReplayRecordCanvas"] === true,
|
|
317
|
+
captureUserIdentity: appView["sessionReplayCaptureUserIdentity"] === true,
|
|
318
|
+
captureGeo: appView["sessionReplayCaptureGeo"] === true,
|
|
319
|
+
retentionInDays: SessionIdentity.clampRetentionDays(requestedRetentionDays, SESSION_REPLAY_ALLOWED_RETENTION_DAYS, DEFAULT_SESSION_REPLAY_RETENTION_IN_DAYS),
|
|
320
|
+
monthlyBudgetInGB: this.readNullableNumber(appView["sessionReplayMonthlyBudgetInGB"]),
|
|
321
|
+
ignoreErrorPatterns: this.readStringArray(appView["sessionReplayIgnoreErrorPatterns"]),
|
|
322
|
+
tracePropagationOrigins: this.readStringArray(appView["sessionReplayTracePropagationOrigins"]),
|
|
323
|
+
lcpBudgetMs: this.readNumber(appView["sessionReplayLcpBudgetMs"], 0),
|
|
324
|
+
longTaskBudgetMs: this.readNumber(appView["sessionReplayLongTaskBudgetMs"], 0),
|
|
325
|
+
slowRequestBudgetMs: this.readNumber(appView["sessionReplaySlowRequestBudgetMs"], 0),
|
|
326
|
+
configEpoch: this.getConfigEpoch(app),
|
|
327
|
+
},
|
|
328
|
+
refusal: null,
|
|
216
329
|
};
|
|
217
330
|
}
|
|
218
331
|
/*
|
|
219
332
|
* Is `origin` covered by the application's allowlist?
|
|
220
333
|
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
334
|
+
* The matching itself lives in Common/Utils/Telemetry/OriginAllowList so
|
|
335
|
+
* that this gate and the Browser telemetry-ingestion-key gate cannot drift
|
|
336
|
+
* apart - two allowlists with subtly different wildcard rules would be a
|
|
337
|
+
* confusing and exploitable split. What stays HERE is the empty-list
|
|
338
|
+
* policy, which is the one thing the two callers disagree about: session
|
|
339
|
+
* replay reads empty as "any origin", a Browser ingestion key reads it as
|
|
340
|
+
* "nothing". See the class comment in OriginAllowList.
|
|
226
341
|
*/
|
|
227
342
|
static isOriginAllowed(policy, origin) {
|
|
228
343
|
/*
|
|
@@ -245,40 +360,10 @@ export default class SessionReplayGateCache {
|
|
|
245
360
|
/*
|
|
246
361
|
* A configured allowlist is still enforced strictly: once the customer has
|
|
247
362
|
* named their origins, a request without an Origin header is refused
|
|
248
|
-
* rather than waved through.
|
|
363
|
+
* rather than waved through. OriginAllowList.matches answers false for a
|
|
364
|
+
* missing or blank origin, so that rule is carried by the delegate.
|
|
249
365
|
*/
|
|
250
|
-
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
const normalizedOrigin = origin.trim().toLowerCase();
|
|
254
|
-
if (!normalizedOrigin) {
|
|
255
|
-
return false;
|
|
256
|
-
}
|
|
257
|
-
for (const allowed of policy.allowedOrigins) {
|
|
258
|
-
const normalizedAllowed = allowed.trim().toLowerCase();
|
|
259
|
-
if (!normalizedAllowed) {
|
|
260
|
-
continue;
|
|
261
|
-
}
|
|
262
|
-
if (normalizedAllowed === normalizedOrigin) {
|
|
263
|
-
return true;
|
|
264
|
-
}
|
|
265
|
-
const wildcardIndex = normalizedAllowed.indexOf("://*.");
|
|
266
|
-
if (wildcardIndex === -1) {
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
const scheme = normalizedAllowed.substring(0, wildcardIndex + 3);
|
|
270
|
-
const suffix = normalizedAllowed.substring(wildcardIndex + 4);
|
|
271
|
-
/*
|
|
272
|
-
* suffix keeps its leading dot, so "https://*.example.com" matches
|
|
273
|
-
* "https://a.example.com" but NOT "https://evilexample.com".
|
|
274
|
-
*/
|
|
275
|
-
if (normalizedOrigin.startsWith(scheme) &&
|
|
276
|
-
normalizedOrigin.endsWith(suffix) &&
|
|
277
|
-
normalizedOrigin.length > scheme.length + suffix.length) {
|
|
278
|
-
return true;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return false;
|
|
366
|
+
return OriginAllowList.matches(origin, policy.allowedOrigins);
|
|
282
367
|
}
|
|
283
368
|
/*
|
|
284
369
|
* Invalidation. Delegated to the leaf store so the services that own the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionReplayGateCache.js","sourceRoot":"","sources":["../../../../../Server/Utils/SessionReplay/SessionReplayGateCache.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,+BAA+B,CAAC;AAC3D,OAAO,qBAAqB,MAAM,sCAAsC,CAAC;AACzE,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAC3D,OAAO,2BAA2B,EAAE,EAClC,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,OAAO,MAAM,wCAAwC,CAAC;AAC7D,OAAO,cAAc,MAAM,+CAA+C,CAAC;AAG3E,OAAO,2BAA2B,MAAM,gDAAgD,CAAC;AACzF,OAAO,wBAAwB,MAAM,6CAA6C,CAAC;AACnF,OAAiC,EAC/B,6BAA6B,GAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACL,wCAAwC,EACxC,qCAAqC,GACtC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,eAAe,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionReplayGateCache.js","sourceRoot":"","sources":["../../../../../Server/Utils/SessionReplay/SessionReplayGateCache.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,+BAA+B,CAAC;AAC3D,OAAO,qBAAqB,MAAM,sCAAsC,CAAC;AACzE,OAAO,WAAW,MAAM,kCAAkC,CAAC;AAC3D,OAAO,2BAA2B,EAAE,EAClC,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,OAAO,MAAM,wCAAwC,CAAC;AAC7D,OAAO,cAAc,MAAM,+CAA+C,CAAC;AAG3E,OAAO,2BAA2B,MAAM,gDAAgD,CAAC;AACzF,OAAO,wBAAwB,MAAM,6CAA6C,CAAC;AACnF,OAAiC,EAC/B,6BAA6B,GAC9B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACL,wCAAwC,EACxC,qCAAqC,GACtC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,eAAe,MAAM,oCAAoC,CAAC;AACjE,OAAO,eAAe,MAAM,0CAA0C,CAAC;AAEvE;;;;GAIG;AACH,MAAM,wCAAwC,GAAW,GAAG,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,8BAA8B,GAA0B;IAC5D,wBAAwB;IACxB,0BAA0B;IAC1B,4BAA4B;IAC5B,6BAA6B;IAC7B,6BAA6B;IAC7B,0BAA0B;IAC1B,6BAA6B;IAC7B,+BAA+B;IAC/B,kCAAkC;IAClC,yBAAyB;IACzB,2BAA2B;IAC3B,8BAA8B;IAC9B,gCAAgC;IAChC,kCAAkC;IAClC,sCAAsC;IACtC,0BAA0B;IAC1B,+BAA+B;IAC/B,kCAAkC;CACnC,CAAC;AAEF,MAAM,sBAAsB,GAA0B;IACpD,wBAAwB;CACzB,CAAC;AA+EF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAN,IAAY,0BAoBX;AApBD,WAAY,0BAA0B;IACpC,mEAAmE;IACnE,uEAAyC,CAAA;IAEzC,0EAA0E;IAC1E,+EAAiD,CAAA;IAEjD;;;;;OAKG;IACH,wEAA0C,CAAA;IAE1C,6DAA6D;IAC7D,8DAAgC,CAAA;IAEhC,wCAAwC;IACxC,0EAA4C,CAAA;AAC9C,CAAC,EApBW,0BAA0B,KAA1B,0BAA0B,QAoBrC;AAoBD,MAAM,CAAC,OAAO,OAAO,sBAAsB;IACzC;;;;;;;;;;;;OAYG;IACI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,IAG7B;QACC,MAAM,UAAU,GACd,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAEjC,OAAO,UAAU,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAGjC;QACC,MAAM,aAAa,GAAW,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QAExD,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,0BAA0B,CAAC,iBAAiB;aACtD,CAAC;QACJ,CAAC;QAED,MAAM,QAAQ,GAAW,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,aAAa,CAAC,WAAW,EAAE,EAAE,CAAC;QAEvF,MAAM,MAAM,GACV,2BAA2B,CAAC,cAAc,CAAmB,QAAQ,CAAC,CAAC;QAEzE,IACE,MAAM;YACN,MAAM,CAAC,MAAM;YACb,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,GAAG,mBAAmB,EAClD,CAAC;YACD;;;;eAIG;YACH,IACE,MAAM,CAAC,MAAM,CAAC,MAAM;gBACpB,CAAC,MAAM,2BAA2B,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EACnE,CAAC;gBACD,OAAO;oBACL,MAAM,EAAE,IAAI;oBACZ,OAAO,EAAE,0BAA0B,CAAC,aAAa;iBAClD,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;gBAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;aAC/B,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAkC,MAAM,IAAI,CAAC,UAAU,CAAC;YAClE,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,aAAa,EAAE,aAAa;SAC7B,CAAC,CAAC;QAEH,2BAA2B,CAAC,cAAc,CAAmB,QAAQ,EAAE;YACrE,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAC;QAEH,IACE,MAAM,CAAC,MAAM;YACb,CAAC,MAAM,2BAA2B,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EACnE,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,0BAA0B,CAAC,aAAa;aAClD,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,IAG/B;QACC,MAAM,OAAO,GAAmB,MAAM,cAAc,CAAC,SAAS,CAAC;YAC7D,KAAK,EAAE;gBACL,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE;aAC/B;YACD,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,OAAO,EAAE,EAAE,sBAAsB,CAAC;YAC/D,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb;;;eAGG;YACH,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,0BAA0B,CAAC,iBAAiB;aACtD,CAAC;QACJ,CAAC;QAED,MAAM,WAAW,GACf,OAA8C,CAAC;QAEjD,MAAM,gBAAgB,GACpB,WAAW,CAAC,wBAAwB,CAAC,KAAK,IAAI,CAAC;QAEjD,IAAI,GAAG,GAA0B,MAAM,qBAAqB,CAAC,SAAS,CAAC;YACrE,KAAK,EAAE;gBACL,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,aAAa,EAAE,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC;aAChE;YACD,MAAM,EAAE,IAAI,CAAC,WAAW,CACtB,IAAI,cAAc,EAAE,EACpB,8BAA8B,CAC/B;YACD,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CAAC;QAEH;;;;;;;;;;;;;WAaG;QACH,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,OAAO;oBACL,MAAM,EAAE,IAAI;oBACZ,OAAO,EAAE,0BAA0B,CAAC,iBAAiB;iBACtD,CAAC;YACJ,CAAC;YAED,MAAM,qBAAqB,CAAC,2BAA2B,CAAC;gBACtD,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,aAAa,EAAE,IAAI,CAAC,aAAa;aAClC,CAAC,CAAC;YAEH,GAAG,GAAG,MAAM,qBAAqB,CAAC,SAAS,CAAC;gBAC1C,KAAK,EAAE;oBACL,SAAS,EAAE,IAAI,CAAC,SAAS;oBACzB,aAAa,EAAE,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,aAAa,CAAC;iBAChE;gBACD,MAAM,EAAE,IAAI,CAAC,WAAW,CACtB,IAAI,cAAc,EAAE,EACpB,8BAA8B,CAC/B;gBACD,KAAK,EAAE;oBACL,MAAM,EAAE,IAAI;iBACb;aACF,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACpB,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,0BAA0B,CAAC,kBAAkB;aACvD,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GACX,GAA0C,CAAC;QAE7C,MAAM,YAAY,GAAY,OAAO,CAAC,wBAAwB,CAAC,KAAK,IAAI,CAAC;QAEzE;;;;;;WAMG;QACH,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,0BAA0B,CAAC,iBAAiB;aACtD,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,OAAO,EAAE,0BAA0B,CAAC,qBAAqB;aAC1D,CAAC;QACJ,CAAC;QAED,MAAM,sBAAsB,GAAW,IAAI,CAAC,UAAU,CACpD,OAAO,CAAC,8BAA8B,CAAC,EACvC,wCAAwC,CACzC,CAAC;QAEF;;;;;;;;;;;WAWG;QACH,OAAO;YACL,MAAM,EAAE;gBACN,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,gBAAgB,EAAE,GAAG,CAAC,EAAE;gBACxB,gBAAgB,EAAE,IAAI;gBACtB,YAAY,EAAE,IAAI;gBAClB,cAAc,EAAE,IAAI,CAAC,eAAe,CAClC,OAAO,CAAC,6BAA6B,CAAC,CACvC;gBACD,WAAW,EAAE,6BAA6B,CACxC,OAAO,CAAC,0BAA0B,CAAC,CACpC;gBACD,WAAW,EACT,OAAO,CAAC,0BAA0B,CAAC;oBACnC,wBAAwB,CAAC,eAAe;oBACtC,CAAC,CAAC,wBAAwB,CAAC,eAAe;oBAC1C,CAAC,CAAC,wBAAwB,CAAC,WAAW;gBAC1C,cAAc,EACZ,OAAO,CAAC,6BAA6B,CAAC;oBACtC,2BAA2B,CAAC,oBAAoB;oBAC9C,CAAC,CAAC,2BAA2B,CAAC,oBAAoB;oBAClD,CAAC,CAAC,2BAA2B,CAAC,MAAM;gBACxC,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAC/B,OAAO,CAAC,+BAA+B,CAAC,EACxC,wCAAwC,CACzC;gBACD,aAAa,EAAE,IAAI,CAAC,eAAe,CACjC,OAAO,CAAC,4BAA4B,CAAC,CACtC;gBACD,cAAc,EAAE,IAAI,CAAC,eAAe,CAClC,OAAO,CAAC,6BAA6B,CAAC,CACvC;gBACD,YAAY,EAAE,OAAO,CAAC,2BAA2B,CAAC,KAAK,IAAI;gBAC3D,mBAAmB,EACjB,OAAO,CAAC,kCAAkC,CAAC,KAAK,IAAI;gBACtD,UAAU,EAAE,OAAO,CAAC,yBAAyB,CAAC,KAAK,IAAI;gBACvD,eAAe,EAAE,eAAe,CAAC,kBAAkB,CACjD,sBAAsB,EACtB,qCAAqC,EACrC,wCAAwC,CACzC;gBACD,iBAAiB,EAAE,IAAI,CAAC,kBAAkB,CACxC,OAAO,CAAC,gCAAgC,CAAC,CAC1C;gBACD,mBAAmB,EAAE,IAAI,CAAC,eAAe,CACvC,OAAO,CAAC,kCAAkC,CAAC,CAC5C;gBACD,uBAAuB,EAAE,IAAI,CAAC,eAAe,CAC3C,OAAO,CAAC,sCAAsC,CAAC,CAChD;gBACD,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;gBACpE,gBAAgB,EAAE,IAAI,CAAC,UAAU,CAC/B,OAAO,CAAC,+BAA+B,CAAC,EACxC,CAAC,CACF;gBACD,mBAAmB,EAAE,IAAI,CAAC,UAAU,CAClC,OAAO,CAAC,kCAAkC,CAAC,EAC3C,CAAC,CACF;gBACD,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC;aACtC;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACI,MAAM,CAAC,eAAe,CAC3B,MAA+B,EAC/B,MAA0B;QAE1B;;;;;;;;;;;;;WAaG;QACH,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvC,OAAO,IAAI,CAAC;QACd,CAAC;QAED;;;;;WAKG;QACH,OAAO,eAAe,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,SAAmB;QACzD,OAAO,MAAM,2BAA2B,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC1E,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,SAAmB;QAC1D,OAAO,MAAM,2BAA2B,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC3E,CAAC;IAED,4DAA4D;IACrD,MAAM,CAAC,UAAU,CAAC,SAAgC;QACvD,2BAA2B,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;IAED;;;;;;;OAOG;IACK,MAAM,CAAC,WAAW,CACxB,QAAgB,EAChB,eAAsC;QAEtC,MAAM,QAAQ,GAAgB,IAAI,GAAG,CAAS,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAErE;;;;;;;WAOG;QACH,MAAM,MAAM,GAA4B;YACtC,GAAG,EAAE,IAAI;SACV,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC,EAAE,CAAC;YACpE,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzB,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,MAA+B,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACK,MAAM,CAAC,cAAc,CAAC,GAAmB;QAC/C,MAAM,SAAS,GAAqB,GAAG,CAAC,SAAS,CAAC;QAElD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,MAAM,GAAW,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QAErD,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,CAAC;IAEO,MAAM,CAAC,UAAU,CAAC,KAAc,EAAE,QAAgB;QACxD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC;YAErC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAEO,MAAM,CAAC,kBAAkB,CAAC,KAAc;QAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC;YAErC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5B,OAAO,MAAM,CAAC;YAChB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,MAAM,CAAC,eAAe,CAAC,KAAc;QAC3C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,MAAM,GAAkB,EAAE,CAAC;QAEjC,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC9C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import Redis from "../../Infrastructure/Redis";
|
|
2
|
+
import logger from "../Logger";
|
|
3
|
+
import { isSessionReplayRefusalReason, } from "../../../Types/Rum/SessionReplayHealth";
|
|
4
|
+
/*
|
|
5
|
+
* Per-application counters of what the session replay ingest path did NOT
|
|
6
|
+
* keep, and why.
|
|
7
|
+
*
|
|
8
|
+
* The chunk gate answers every refusal with a reason string the recorder
|
|
9
|
+
* can log, but the person who has to explain "why are there no recordings?"
|
|
10
|
+
* is looking at the Dashboard, not at a visitor's browser console. These
|
|
11
|
+
* counters are the server-side memory of those answers: one Redis hash per
|
|
12
|
+
* (project, application, UTC day) with one field per reason, incremented by
|
|
13
|
+
* HINCRBY from the gate for every non-accepted request, and read back by
|
|
14
|
+
* the ingest-status endpoint summed over today and yesterday so the
|
|
15
|
+
* "last 24h" figure is stable across midnight.
|
|
16
|
+
*
|
|
17
|
+
* Two rules that every reader of this module relies on:
|
|
18
|
+
*
|
|
19
|
+
* 1. Writes never throw and never delay a response. A counter is
|
|
20
|
+
* bookkeeping; the chunk decision has already been made.
|
|
21
|
+
* 2. Reads return null - never 0, never [] - when Redis could not be
|
|
22
|
+
* consulted. "Nothing was refused" and "we cannot tell" are different
|
|
23
|
+
* facts, and the health copy renders the second as "unknown".
|
|
24
|
+
*
|
|
25
|
+
* Day buckets are UTC so every pod agrees on which hash a refusal lands in,
|
|
26
|
+
* and the 48h TTL is what bounds the keyspace: a day's hash lives long
|
|
27
|
+
* enough to be yesterday's half of a 24h window and no longer.
|
|
28
|
+
*/
|
|
29
|
+
const REFUSAL_KEY_PREFIX = "replay:refusals:";
|
|
30
|
+
/*
|
|
31
|
+
* Worker-side drops are counted separately from gate refusals. A refusal
|
|
32
|
+
* was answered to the recorder (204 with a reason); a drop happened AFTER a
|
|
33
|
+
* 202, inside the queue consumer, and the recorder was never told. They
|
|
34
|
+
* are different explanations for the same missing recording and the
|
|
35
|
+
* Dashboard must not blur them: "212 refused: origin not allowed" tells the
|
|
36
|
+
* customer to fix a setting, "12 dropped: scrub incomplete" tells them the
|
|
37
|
+
* server chose not to store something it had already accepted.
|
|
38
|
+
*/
|
|
39
|
+
const DROP_KEY_PREFIX = "replay:drops:";
|
|
40
|
+
export const SESSION_REPLAY_HEALTH_COUNTER_TTL_SECONDS = 48 * 60 * 60;
|
|
41
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
42
|
+
/* Bounds a hostile or buggy caller: the reason is a Redis hash field. */
|
|
43
|
+
const MAX_REASON_LENGTH = 64;
|
|
44
|
+
export default class SessionReplayHealthCounters {
|
|
45
|
+
/* "YYYY-MM-DD" in UTC for the given instant. */
|
|
46
|
+
static getUtcDayBucket(unixMs) {
|
|
47
|
+
return new Date(unixMs).toISOString().substring(0, 10);
|
|
48
|
+
}
|
|
49
|
+
static getRefusalCounterKey(data) {
|
|
50
|
+
return `${REFUSAL_KEY_PREFIX}${this.buildScope(data)}:${data.utcDay}`;
|
|
51
|
+
}
|
|
52
|
+
static getDropCounterKey(data) {
|
|
53
|
+
return `${DROP_KEY_PREFIX}${this.buildScope(data)}:${data.utcDay}`;
|
|
54
|
+
}
|
|
55
|
+
/*
|
|
56
|
+
* Count one refused chunk request. Best-effort: a Redis failure is logged
|
|
57
|
+
* at debug (it would otherwise spam the log for the whole outage) and
|
|
58
|
+
* swallowed, because the gate has already decided and the response must
|
|
59
|
+
* not wait on bookkeeping.
|
|
60
|
+
*/
|
|
61
|
+
static async recordRefusal(data) {
|
|
62
|
+
var _a;
|
|
63
|
+
await this.increment({
|
|
64
|
+
key: this.getRefusalCounterKey({
|
|
65
|
+
projectId: data.projectId,
|
|
66
|
+
appIdentifier: data.appIdentifier,
|
|
67
|
+
utcDay: this.getUtcDayBucket((_a = data.nowUnixMs) !== null && _a !== void 0 ? _a : Date.now()),
|
|
68
|
+
}),
|
|
69
|
+
reason: data.reason,
|
|
70
|
+
describe: "refusal",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
/* Count one chunk the worker dropped after the route had answered 202. */
|
|
74
|
+
static async recordDrop(data) {
|
|
75
|
+
var _a;
|
|
76
|
+
await this.increment({
|
|
77
|
+
key: this.getDropCounterKey({
|
|
78
|
+
projectId: data.projectId,
|
|
79
|
+
appIdentifier: data.appIdentifier,
|
|
80
|
+
utcDay: this.getUtcDayBucket((_a = data.nowUnixMs) !== null && _a !== void 0 ? _a : Date.now()),
|
|
81
|
+
}),
|
|
82
|
+
reason: data.reason,
|
|
83
|
+
describe: "drop",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/*
|
|
87
|
+
* Refusals over the last 24 hours, summed over today's and yesterday's
|
|
88
|
+
* buckets, highest count first. Only the gate's closed vocabulary is
|
|
89
|
+
* returned: a field that is not a known reason (an older or newer build
|
|
90
|
+
* of the gate) is dropped rather than rendered as a bare string.
|
|
91
|
+
*
|
|
92
|
+
* null when Redis is unavailable or either read failed.
|
|
93
|
+
*/
|
|
94
|
+
static async readRefusalsLast24h(data) {
|
|
95
|
+
var _a;
|
|
96
|
+
const nowUnixMs = (_a = data.nowUnixMs) !== null && _a !== void 0 ? _a : Date.now();
|
|
97
|
+
const totals = await this.readTwoDayTotals([
|
|
98
|
+
this.getRefusalCounterKey({
|
|
99
|
+
projectId: data.projectId,
|
|
100
|
+
appIdentifier: data.appIdentifier,
|
|
101
|
+
utcDay: this.getUtcDayBucket(nowUnixMs),
|
|
102
|
+
}),
|
|
103
|
+
this.getRefusalCounterKey({
|
|
104
|
+
projectId: data.projectId,
|
|
105
|
+
appIdentifier: data.appIdentifier,
|
|
106
|
+
utcDay: this.getUtcDayBucket(nowUnixMs - DAY_MS),
|
|
107
|
+
}),
|
|
108
|
+
]);
|
|
109
|
+
if (totals === null) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
const refusals = [];
|
|
113
|
+
for (const [reason, count] of totals.entries()) {
|
|
114
|
+
if (isSessionReplayRefusalReason(reason) && count > 0) {
|
|
115
|
+
refusals.push({ reason: reason, count: count });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return this.sortByCountDescending(refusals);
|
|
119
|
+
}
|
|
120
|
+
/*
|
|
121
|
+
* Worker drops over the last 24 hours. The drop vocabulary is open (it is
|
|
122
|
+
* whatever recordDrop in the ingest service names), so every non-empty
|
|
123
|
+
* field is returned. null when Redis is unavailable.
|
|
124
|
+
*/
|
|
125
|
+
static async readDropsLast24h(data) {
|
|
126
|
+
var _a;
|
|
127
|
+
const nowUnixMs = (_a = data.nowUnixMs) !== null && _a !== void 0 ? _a : Date.now();
|
|
128
|
+
const totals = await this.readTwoDayTotals([
|
|
129
|
+
this.getDropCounterKey({
|
|
130
|
+
projectId: data.projectId,
|
|
131
|
+
appIdentifier: data.appIdentifier,
|
|
132
|
+
utcDay: this.getUtcDayBucket(nowUnixMs),
|
|
133
|
+
}),
|
|
134
|
+
this.getDropCounterKey({
|
|
135
|
+
projectId: data.projectId,
|
|
136
|
+
appIdentifier: data.appIdentifier,
|
|
137
|
+
utcDay: this.getUtcDayBucket(nowUnixMs - DAY_MS),
|
|
138
|
+
}),
|
|
139
|
+
]);
|
|
140
|
+
if (totals === null) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
const drops = [];
|
|
144
|
+
for (const [reason, count] of totals.entries()) {
|
|
145
|
+
if (reason && count > 0) {
|
|
146
|
+
drops.push({ reason: reason, count: count });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return this.sortByCountDescending(drops);
|
|
150
|
+
}
|
|
151
|
+
/*
|
|
152
|
+
* The application identifier is lower-cased because RumApplication lookup
|
|
153
|
+
* is case-insensitive (QueryHelper.findWithSameText): two recorders that
|
|
154
|
+
* spell the identifier differently are one application and must share one
|
|
155
|
+
* counter.
|
|
156
|
+
*/
|
|
157
|
+
static buildScope(data) {
|
|
158
|
+
return `${data.projectId.toString()}:${data.appIdentifier.trim().toLowerCase()}`;
|
|
159
|
+
}
|
|
160
|
+
static async increment(data) {
|
|
161
|
+
const reason = data.reason.trim().substring(0, MAX_REASON_LENGTH);
|
|
162
|
+
if (!reason) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const client = Redis.getClient();
|
|
166
|
+
if (!client || !Redis.isConnected()) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
/*
|
|
171
|
+
* One round trip, not two. The EXPIRE is refreshed on every write
|
|
172
|
+
* rather than only on the first (HINCRBY cannot say whether it
|
|
173
|
+
* created the key), so pipelining is what keeps the cost of that
|
|
174
|
+
* choice at a single RTT - which matters because the gate counts a
|
|
175
|
+
* refusal for every refused request, including the cheap 204s a
|
|
176
|
+
* misconfigured site sends every 15 seconds.
|
|
177
|
+
*/
|
|
178
|
+
await client
|
|
179
|
+
.pipeline()
|
|
180
|
+
.hincrby(data.key, reason, 1)
|
|
181
|
+
.expire(data.key, SESSION_REPLAY_HEALTH_COUNTER_TTL_SECONDS)
|
|
182
|
+
.exec();
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
logger.debug(`SessionReplayHealthCounters: could not record a ${data.describe} at ${data.key}`);
|
|
186
|
+
logger.debug(err);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
static async readTwoDayTotals(keys) {
|
|
190
|
+
const client = Redis.getClient();
|
|
191
|
+
if (!client || !Redis.isConnected()) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
const totals = new Map();
|
|
195
|
+
try {
|
|
196
|
+
for (const key of keys) {
|
|
197
|
+
const fields = await client.hgetall(key);
|
|
198
|
+
for (const reason of Object.keys(fields || {})) {
|
|
199
|
+
const parsed = parseInt(fields[reason], 10);
|
|
200
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
totals.set(reason, (totals.get(reason) || 0) + parsed);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (err) {
|
|
208
|
+
logger.warn("SessionReplayHealthCounters: could not read the replay health counters");
|
|
209
|
+
logger.warn(err);
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
return totals;
|
|
213
|
+
}
|
|
214
|
+
static sortByCountDescending(entries) {
|
|
215
|
+
return entries.sort((a, b) => {
|
|
216
|
+
if (b.count !== a.count) {
|
|
217
|
+
return b.count - a.count;
|
|
218
|
+
}
|
|
219
|
+
return a.reason < b.reason ? -1 : a.reason > b.reason ? 1 : 0;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=SessionReplayHealthCounters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionReplayHealthCounters.js","sourceRoot":"","sources":["../../../../../Server/Utils/SessionReplay/SessionReplayHealthCounters.ts"],"names":[],"mappings":"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"}
|