@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
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
3
|
+
import React from "react";
|
|
4
|
+
import { describe, expect, jest, test } from "@jest/globals";
|
|
5
|
+
|
|
6
|
+
jest.mock("react-i18next", () => {
|
|
7
|
+
return {
|
|
8
|
+
useTranslation: () => {
|
|
9
|
+
return {
|
|
10
|
+
t: (
|
|
11
|
+
key: string,
|
|
12
|
+
opts?: { defaultValue?: string } & Record<string, unknown>,
|
|
13
|
+
): string => {
|
|
14
|
+
let out: string = opts?.defaultValue ?? key;
|
|
15
|
+
|
|
16
|
+
for (const name of Object.keys(opts || {})) {
|
|
17
|
+
out = out
|
|
18
|
+
.split(`{{${name}}}`)
|
|
19
|
+
.join(String((opts as Record<string, unknown>)[name]));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return out;
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
import ResourceSearchBox from "../../../../App/FeatureSet/StatusPage/src/Components/Search/ResourceSearchBox";
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* Contract under test - the field that answers "which of these is mine?".
|
|
33
|
+
*
|
|
34
|
+
* A status page with a couple of hundred resources under nested groups had no
|
|
35
|
+
* way to answer that except opening every group and reading. The field is a
|
|
36
|
+
* small thing, so what it has to get right is the small things: it has to be
|
|
37
|
+
* announced as a search, it has to say how much of the page is left after
|
|
38
|
+
* filtering (out loud, for a screen reader, not only on screen), it has to be
|
|
39
|
+
* clearable without reaching for the mouse, and clearing it has to leave the
|
|
40
|
+
* cursor where the visitor was already typing.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
type OnChangeMock = ReturnType<typeof jest.fn<(value: string) => void>>;
|
|
44
|
+
|
|
45
|
+
function renderBox(
|
|
46
|
+
props: Partial<React.ComponentProps<typeof ResourceSearchBox>> = {},
|
|
47
|
+
): { onChange: OnChangeMock } {
|
|
48
|
+
const onChange: OnChangeMock = jest.fn<(value: string) => void>();
|
|
49
|
+
|
|
50
|
+
render(
|
|
51
|
+
<ResourceSearchBox
|
|
52
|
+
value={props.value === undefined ? "" : props.value}
|
|
53
|
+
onChange={props.onChange || onChange}
|
|
54
|
+
matchedCount={props.matchedCount === undefined ? 12 : props.matchedCount}
|
|
55
|
+
totalCount={props.totalCount === undefined ? 12 : props.totalCount}
|
|
56
|
+
/>,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
return { onChange: onChange };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function input(): HTMLElement {
|
|
63
|
+
return screen.getByTestId("status-page-resource-search-input");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
describe("ResourceSearchBox", () => {
|
|
67
|
+
test("is announced as a search landmark", () => {
|
|
68
|
+
renderBox();
|
|
69
|
+
|
|
70
|
+
expect(screen.getByRole("search")).toBeInTheDocument();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* The field carries no visible label, so without this the only thing a
|
|
75
|
+
* screen reader has to go on is the placeholder - which is not a label.
|
|
76
|
+
*/
|
|
77
|
+
test("the field has an accessible name of its own", () => {
|
|
78
|
+
renderBox();
|
|
79
|
+
|
|
80
|
+
expect(input()).toHaveAttribute("aria-label", "Search resources");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("typing is reported to the caller", () => {
|
|
84
|
+
const { onChange } = renderBox();
|
|
85
|
+
|
|
86
|
+
fireEvent.change(input(), { target: { value: "checkout" } });
|
|
87
|
+
|
|
88
|
+
expect(onChange).toHaveBeenCalledWith("checkout");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("the field shows what the caller says it holds", () => {
|
|
92
|
+
renderBox({ value: "checkout" });
|
|
93
|
+
|
|
94
|
+
expect(input()).toHaveValue("checkout");
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("ResourceSearchBox - the result count", () => {
|
|
99
|
+
test("says how much of the page survived the query", () => {
|
|
100
|
+
renderBox({ value: "checkout", matchedCount: 3, totalCount: 42 });
|
|
101
|
+
|
|
102
|
+
expect(
|
|
103
|
+
screen.getByTestId("status-page-resource-search-count"),
|
|
104
|
+
).toHaveTextContent("3 of 42 resources");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
test("says nothing at all when nothing has been typed", () => {
|
|
108
|
+
renderBox({ value: "", matchedCount: 42, totalCount: 42 });
|
|
109
|
+
|
|
110
|
+
expect(
|
|
111
|
+
screen.getByTestId("status-page-resource-search-count"),
|
|
112
|
+
).toHaveTextContent("");
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/*
|
|
116
|
+
* Polite, not assertive: this changes on every keystroke, and an assertive
|
|
117
|
+
* region would interrupt the visitor's own typing.
|
|
118
|
+
*/
|
|
119
|
+
test("the count is announced politely", () => {
|
|
120
|
+
renderBox({ value: "checkout" });
|
|
121
|
+
|
|
122
|
+
expect(
|
|
123
|
+
screen.getByTestId("status-page-resource-search-count"),
|
|
124
|
+
).toHaveAttribute("aria-live", "polite");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test("the field points at the count so it is read with the field", () => {
|
|
128
|
+
renderBox({ value: "checkout" });
|
|
129
|
+
|
|
130
|
+
const describedBy: string | null = input().getAttribute("aria-describedby");
|
|
131
|
+
|
|
132
|
+
expect(describedBy).toBeTruthy();
|
|
133
|
+
expect(document.getElementById(describedBy as string)).toBe(
|
|
134
|
+
screen.getByTestId("status-page-resource-search-count"),
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("zero matches is still a count, not a blank", () => {
|
|
139
|
+
renderBox({ value: "kubernetes", matchedCount: 0, totalCount: 42 });
|
|
140
|
+
|
|
141
|
+
expect(
|
|
142
|
+
screen.getByTestId("status-page-resource-search-count"),
|
|
143
|
+
).toHaveTextContent("0 of 42 resources");
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe("ResourceSearchBox - clearing", () => {
|
|
148
|
+
test("there is nothing to clear until something is typed", () => {
|
|
149
|
+
renderBox({ value: "" });
|
|
150
|
+
|
|
151
|
+
expect(
|
|
152
|
+
screen.queryByTestId("status-page-resource-search-clear"),
|
|
153
|
+
).not.toBeInTheDocument();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("a query brings out a clear control", () => {
|
|
157
|
+
renderBox({ value: "checkout" });
|
|
158
|
+
|
|
159
|
+
expect(
|
|
160
|
+
screen.getByTestId("status-page-resource-search-clear"),
|
|
161
|
+
).toHaveAttribute("aria-label", "Clear search");
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("pressing it empties the query", () => {
|
|
165
|
+
const { onChange } = renderBox({ value: "checkout" });
|
|
166
|
+
|
|
167
|
+
fireEvent.click(screen.getByTestId("status-page-resource-search-clear"));
|
|
168
|
+
|
|
169
|
+
expect(onChange).toHaveBeenCalledWith("");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
/*
|
|
173
|
+
* Clearing with the mouse and then having to click back into the field to
|
|
174
|
+
* carry on typing is the kind of small friction that makes a search feel
|
|
175
|
+
* broken.
|
|
176
|
+
*/
|
|
177
|
+
test("clearing leaves the cursor in the field", () => {
|
|
178
|
+
renderBox({ value: "checkout" });
|
|
179
|
+
|
|
180
|
+
fireEvent.click(screen.getByTestId("status-page-resource-search-clear"));
|
|
181
|
+
|
|
182
|
+
expect(document.activeElement).toBe(input());
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
/*
|
|
186
|
+
* Escape clears rather than blurs: getting the whole page back is what a
|
|
187
|
+
* visitor wants, and a blurred field with text still in it looks like the
|
|
188
|
+
* page is stuck.
|
|
189
|
+
*/
|
|
190
|
+
test("Escape clears the query", () => {
|
|
191
|
+
const { onChange } = renderBox({ value: "checkout" });
|
|
192
|
+
|
|
193
|
+
fireEvent.keyDown(input(), { key: "Escape" });
|
|
194
|
+
|
|
195
|
+
expect(onChange).toHaveBeenCalledWith("");
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("Escape on an empty field is left to the browser", () => {
|
|
199
|
+
const { onChange } = renderBox({ value: "" });
|
|
200
|
+
|
|
201
|
+
const notPrevented: boolean = fireEvent.keyDown(input(), {
|
|
202
|
+
key: "Escape",
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
206
|
+
expect(notPrevented).toBe(true);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
test("a query of only spaces is not treated as a query", () => {
|
|
210
|
+
renderBox({ value: " " });
|
|
211
|
+
|
|
212
|
+
expect(
|
|
213
|
+
screen.queryByTestId("status-page-resource-search-clear"),
|
|
214
|
+
).not.toBeInTheDocument();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("other keys are left alone so typing still works", () => {
|
|
218
|
+
const { onChange } = renderBox({ value: "check" });
|
|
219
|
+
|
|
220
|
+
fireEvent.keyDown(input(), { key: "o" });
|
|
221
|
+
|
|
222
|
+
expect(onChange).not.toHaveBeenCalled();
|
|
223
|
+
});
|
|
224
|
+
});
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { describe, expect, it, jest } from "@jest/globals";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import AnalyticsBaseModel from "../../../Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
|
|
5
|
+
import AnalyticsTableColumn from "../../../Types/AnalyticsDatabase/TableColumn";
|
|
6
|
+
import TableColumnType from "../../../Types/AnalyticsDatabase/TableColumnType";
|
|
7
|
+
import Permission from "../../../Types/Permission";
|
|
8
|
+
import RumSession from "../../../Models/AnalyticsModels/RumSession";
|
|
9
|
+
import RumSessionChunk from "../../../Models/AnalyticsModels/RumSessionChunk";
|
|
10
|
+
import AddSessionReplayEngagementColumns from "../../../../App/FeatureSet/Workers/DataMigrations/AddSessionReplayEngagementColumns";
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* The migration imports the two ClickHouse services for their column DDL
|
|
14
|
+
* helpers. Neither is exercised here (the migration is a no-op on
|
|
15
|
+
* clusters and the column assertions read the models directly), and
|
|
16
|
+
* loading them for real drags the ClickHouse client into a model test.
|
|
17
|
+
*/
|
|
18
|
+
jest.mock("Common/Server/Services/RumSessionService", () => {
|
|
19
|
+
return { __esModule: true, default: {} };
|
|
20
|
+
});
|
|
21
|
+
jest.mock("Common/Server/Services/RumSessionChunkService", () => {
|
|
22
|
+
return { __esModule: true, default: {} };
|
|
23
|
+
});
|
|
24
|
+
jest.mock("Common/Server/Utils/Logger", () => {
|
|
25
|
+
return {
|
|
26
|
+
__esModule: true,
|
|
27
|
+
default: { info: jest.fn(), warn: jest.fn(), error: jest.fn() },
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* The engagement columns added for identify()/setTags()/track() and the
|
|
33
|
+
* click recorder. Two of these decisions are privacy decisions and are
|
|
34
|
+
* pinned by identity, not by value: identifiedUserTraits describes a
|
|
35
|
+
* PERSON and must sit behind exactly the ACL object identifiedUserLabel
|
|
36
|
+
* uses, and tags describe a SESSION and must sit behind exactly the
|
|
37
|
+
* object the rest of the row uses. Sharing the object (not a copy) is
|
|
38
|
+
* what guarantees a future ACL change moves both columns together.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
function findColumn(
|
|
42
|
+
model: AnalyticsBaseModel,
|
|
43
|
+
key: string,
|
|
44
|
+
): AnalyticsTableColumn | undefined {
|
|
45
|
+
return model.tableColumns.find((column: AnalyticsTableColumn): boolean => {
|
|
46
|
+
return column.key === key;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function requireColumn(
|
|
51
|
+
model: AnalyticsBaseModel,
|
|
52
|
+
key: string,
|
|
53
|
+
): AnalyticsTableColumn {
|
|
54
|
+
const column: AnalyticsTableColumn | undefined = findColumn(model, key);
|
|
55
|
+
|
|
56
|
+
if (!column) {
|
|
57
|
+
throw new Error(`${model.tableName} does not declare ${key}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return column;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe("RumSession engagement columns", () => {
|
|
64
|
+
const model: RumSession = new RumSession();
|
|
65
|
+
|
|
66
|
+
it("declares every engagement column", () => {
|
|
67
|
+
for (const key of [
|
|
68
|
+
"tags",
|
|
69
|
+
"identifiedUserTraits",
|
|
70
|
+
"clickCount",
|
|
71
|
+
"customEventCount",
|
|
72
|
+
"firstErrorOffsetMs",
|
|
73
|
+
"activeMs",
|
|
74
|
+
]) {
|
|
75
|
+
expect(findColumn(model, key)).toBeDefined();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("identifiedUserTraits carries the SAME ACL object as identifiedUserLabel", () => {
|
|
80
|
+
const label: AnalyticsTableColumn = requireColumn(
|
|
81
|
+
model,
|
|
82
|
+
"identifiedUserLabel",
|
|
83
|
+
);
|
|
84
|
+
const traits: AnalyticsTableColumn = requireColumn(
|
|
85
|
+
model,
|
|
86
|
+
"identifiedUserTraits",
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
expect(traits.accessControl).toBeDefined();
|
|
90
|
+
expect(traits.accessControl).toBe(label.accessControl);
|
|
91
|
+
/* And that object is the narrow one: no plain list permission. */
|
|
92
|
+
expect(traits.accessControl?.read).not.toContain(
|
|
93
|
+
Permission.ReadRumSessionReplay,
|
|
94
|
+
);
|
|
95
|
+
expect(traits.accessControl?.read).not.toContain(Permission.TelemetryAdmin);
|
|
96
|
+
expect(traits.accessControl?.read).toContain(
|
|
97
|
+
Permission.ReadRumSessionReplayPayload,
|
|
98
|
+
);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("identifiedUserTraits is a Map(String, String) defaulting to {} with no skip index", () => {
|
|
102
|
+
const traits: AnalyticsTableColumn = requireColumn(
|
|
103
|
+
model,
|
|
104
|
+
"identifiedUserTraits",
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
expect(traits.type).toBe(TableColumnType.MapStringString);
|
|
108
|
+
expect(traits.defaultValue).toEqual({});
|
|
109
|
+
expect(traits.required).toBe(true);
|
|
110
|
+
/* Traits are never filtered on; an index would only index PII. */
|
|
111
|
+
expect(traits.skipIndex).toBeUndefined();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("tags carries the SAME ACL object as the ordinary session columns", () => {
|
|
115
|
+
const tags: AnalyticsTableColumn = requireColumn(model, "tags");
|
|
116
|
+
const durationMs: AnalyticsTableColumn = requireColumn(model, "durationMs");
|
|
117
|
+
const errorCount: AnalyticsTableColumn = requireColumn(model, "errorCount");
|
|
118
|
+
|
|
119
|
+
expect(tags.accessControl).toBeDefined();
|
|
120
|
+
expect(tags.accessControl).toBe(durationMs.accessControl);
|
|
121
|
+
expect(tags.accessControl).toBe(errorCount.accessControl);
|
|
122
|
+
expect(tags.accessControl?.read).toContain(Permission.ReadRumSessionReplay);
|
|
123
|
+
expect(tags.type).toBe(TableColumnType.MapStringString);
|
|
124
|
+
expect(tags.defaultValue).toEqual({});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("tags and traits are distinct columns with distinct ACLs", () => {
|
|
128
|
+
const tags: AnalyticsTableColumn = requireColumn(model, "tags");
|
|
129
|
+
const traits: AnalyticsTableColumn = requireColumn(
|
|
130
|
+
model,
|
|
131
|
+
"identifiedUserTraits",
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
expect(tags.accessControl).not.toBe(traits.accessControl);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("clickCount and customEventCount are Int32 counters under the session ACL, defaulting to 0", () => {
|
|
138
|
+
for (const key of ["clickCount", "customEventCount"]) {
|
|
139
|
+
const column: AnalyticsTableColumn = requireColumn(model, key);
|
|
140
|
+
const errorCount: AnalyticsTableColumn = requireColumn(
|
|
141
|
+
model,
|
|
142
|
+
"errorCount",
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
expect(column.type).toBe(TableColumnType.Number);
|
|
146
|
+
expect(column.defaultValue).toBe(0);
|
|
147
|
+
expect(column.accessControl).toBe(errorCount.accessControl);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("firstErrorOffsetMs and activeMs are Int64 (BigNumber), default 0, and never T64-coded", () => {
|
|
152
|
+
for (const key of ["firstErrorOffsetMs", "activeMs"]) {
|
|
153
|
+
const column: AnalyticsTableColumn = requireColumn(model, key);
|
|
154
|
+
const durationMs: AnalyticsTableColumn = requireColumn(
|
|
155
|
+
model,
|
|
156
|
+
"durationMs",
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
expect(column.type).toBe(TableColumnType.BigNumber);
|
|
160
|
+
expect(column.defaultValue).toBe(0);
|
|
161
|
+
expect(column.accessControl).toBe(durationMs.accessControl);
|
|
162
|
+
|
|
163
|
+
const codecs: Array<{ codec: string }> = Array.isArray(column.codec)
|
|
164
|
+
? (column.codec as Array<{ codec: string }>)
|
|
165
|
+
: column.codec
|
|
166
|
+
? [column.codec as { codec: string }]
|
|
167
|
+
: [];
|
|
168
|
+
|
|
169
|
+
expect(
|
|
170
|
+
codecs.some((codec: { codec: string }): boolean => {
|
|
171
|
+
return codec.codec === "T64";
|
|
172
|
+
}),
|
|
173
|
+
).toBe(false);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("the existing counters and the sort key are untouched", () => {
|
|
178
|
+
expect(requireColumn(model, "errorCount").defaultValue).toBeUndefined();
|
|
179
|
+
expect(model.sortKeys).toEqual([
|
|
180
|
+
"projectId",
|
|
181
|
+
"rumApplicationId",
|
|
182
|
+
"startTime",
|
|
183
|
+
"sessionId",
|
|
184
|
+
]);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe("RumSessionChunk engagement columns", () => {
|
|
189
|
+
const model: RumSessionChunk = new RumSessionChunk();
|
|
190
|
+
|
|
191
|
+
it("declares clickCount and customEventCount as Int32 counters defaulting to 0 under the chunk metadata ACL", () => {
|
|
192
|
+
const errorCount: AnalyticsTableColumn = requireColumn(model, "errorCount");
|
|
193
|
+
|
|
194
|
+
for (const key of ["clickCount", "customEventCount"]) {
|
|
195
|
+
const column: AnalyticsTableColumn = requireColumn(model, key);
|
|
196
|
+
|
|
197
|
+
expect(column.type).toBe(TableColumnType.Number);
|
|
198
|
+
expect(column.defaultValue).toBe(0);
|
|
199
|
+
expect(column.accessControl).toBe(errorCount.accessControl);
|
|
200
|
+
expect(column.accessControl?.read).not.toContain(Permission.Viewer);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
it("already carries a per-chunk url column, so none is added", () => {
|
|
205
|
+
expect(requireColumn(model, "url").type).toBe(TableColumnType.Text);
|
|
206
|
+
expect(
|
|
207
|
+
model.tableColumns.filter((column: AnalyticsTableColumn): boolean => {
|
|
208
|
+
return column.key === "url";
|
|
209
|
+
}),
|
|
210
|
+
).toHaveLength(1);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
it("the existing counters keep no default, so a missing envelope counter is still an insert error", () => {
|
|
214
|
+
expect(requireColumn(model, "errorCount").defaultValue).toBeUndefined();
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe("AddSessionReplayEngagementColumns migration", () => {
|
|
219
|
+
/*
|
|
220
|
+
* Registration is pinned by reading Index.ts as text, the same way the
|
|
221
|
+
* App-side migration tests do: importing the index would instantiate
|
|
222
|
+
* every migration in the repo and their Postgres services.
|
|
223
|
+
*/
|
|
224
|
+
const indexSource: string = fs.readFileSync(
|
|
225
|
+
path.resolve(
|
|
226
|
+
__dirname,
|
|
227
|
+
"../../../../App/FeatureSet/Workers/DataMigrations/Index.ts",
|
|
228
|
+
),
|
|
229
|
+
"utf8",
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
it("is imported and instantiated in DataMigrations/Index.ts exactly once", () => {
|
|
233
|
+
expect(indexSource).toContain(
|
|
234
|
+
'import AddSessionReplayEngagementColumns from "./AddSessionReplayEngagementColumns";',
|
|
235
|
+
);
|
|
236
|
+
expect(
|
|
237
|
+
indexSource.split("new AddSessionReplayEngagementColumns()"),
|
|
238
|
+
).toHaveLength(2);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("is registered LAST in the data-migration chain", () => {
|
|
242
|
+
const instantiations: Array<string> =
|
|
243
|
+
indexSource.match(/new [A-Za-z0-9_]+\(\)/g) || [];
|
|
244
|
+
|
|
245
|
+
expect(instantiations.length).toBeGreaterThan(0);
|
|
246
|
+
expect(instantiations[instantiations.length - 1]).toBe(
|
|
247
|
+
"new AddSessionReplayEngagementColumns()",
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("does not run in cluster mode, because boot schema-sync performs the same ADD COLUMN there", () => {
|
|
252
|
+
expect(new AddSessionReplayEngagementColumns().runsInClusterMode()).toBe(
|
|
253
|
+
false,
|
|
254
|
+
);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it("names itself so the runner records it under a stable key", () => {
|
|
258
|
+
expect(new AddSessionReplayEngagementColumns().name).toBe(
|
|
259
|
+
"AddSessionReplayEngagementColumns",
|
|
260
|
+
);
|
|
261
|
+
});
|
|
262
|
+
});
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import BaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
5
|
+
import AlertCustomField from "../../Models/DatabaseModels/AlertCustomField";
|
|
6
|
+
import IncidentCustomField from "../../Models/DatabaseModels/IncidentCustomField";
|
|
7
|
+
import InventoryItemCustomField from "../../Models/DatabaseModels/InventoryItemCustomField";
|
|
8
|
+
import MonitorCustomField from "../../Models/DatabaseModels/MonitorCustomField";
|
|
9
|
+
import OnCallDutyPolicyCustomField from "../../Models/DatabaseModels/OnCallDutyPolicyCustomField";
|
|
10
|
+
import ScheduledMaintenanceCustomField from "../../Models/DatabaseModels/ScheduledMaintenanceCustomField";
|
|
11
|
+
import StatusPageCustomField from "../../Models/DatabaseModels/StatusPageCustomField";
|
|
12
|
+
import TeamCustomField from "../../Models/DatabaseModels/TeamCustomField";
|
|
13
|
+
import TeamMemberCustomField from "../../Models/DatabaseModels/TeamMemberCustomField";
|
|
14
|
+
import { ColumnAccessControl } from "../../Types/BaseDatabase/AccessControl";
|
|
15
|
+
import { getColumnAccessControl } from "../../Types/Database/AccessControl/ColumnAccessControl";
|
|
16
|
+
import {
|
|
17
|
+
getTableColumn,
|
|
18
|
+
TableColumnMetadata,
|
|
19
|
+
} from "../../Types/Database/TableColumn";
|
|
20
|
+
import TableColumnType from "../../Types/Database/TableColumnType";
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* The nine `*CustomField` definition tables are near-identical clones, and
|
|
24
|
+
* this test exists because ONE of them missing a column is not a small
|
|
25
|
+
* cosmetic inconsistency — it is an outage on unrelated pages.
|
|
26
|
+
*
|
|
27
|
+
* CustomFieldsDetail (the Custom Fields card on every resource) issues ONE
|
|
28
|
+
* select for whatever definition model it is handed, and SelectPermission
|
|
29
|
+
* throws BadDataException on a column the model does not declare. So adding
|
|
30
|
+
* the value-mapping columns to only the three resources that can actually use
|
|
31
|
+
* them, while asking for them in that shared select, would make the Monitor,
|
|
32
|
+
* Team, Status Page, On-Call and Inventory custom-field cards error out and
|
|
33
|
+
* their table columns and facet chips silently vanish.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
const MODELS_DIRECTORY: string = path.join(
|
|
37
|
+
__dirname,
|
|
38
|
+
"..",
|
|
39
|
+
"..",
|
|
40
|
+
"Models",
|
|
41
|
+
"DatabaseModels",
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const MAPPING_COLUMNS: Array<string> = [
|
|
45
|
+
"mapFromResourceType",
|
|
46
|
+
"mapFromCustomFieldName",
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
type ModelClass = { new (): BaseModel };
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
* Imported statically rather than resolved by path: dynamic `require` is
|
|
53
|
+
* banned by this repo's lint config. A hand-written map is only a liability if
|
|
54
|
+
* it can fall behind the directory, which the first test below rules out — a
|
|
55
|
+
* tenth definition table fails this suite the day it is added.
|
|
56
|
+
*/
|
|
57
|
+
const DEFINITION_MODELS: Record<string, ModelClass> = {
|
|
58
|
+
AlertCustomField: AlertCustomField,
|
|
59
|
+
IncidentCustomField: IncidentCustomField,
|
|
60
|
+
InventoryItemCustomField: InventoryItemCustomField,
|
|
61
|
+
MonitorCustomField: MonitorCustomField,
|
|
62
|
+
OnCallDutyPolicyCustomField: OnCallDutyPolicyCustomField,
|
|
63
|
+
ScheduledMaintenanceCustomField: ScheduledMaintenanceCustomField,
|
|
64
|
+
StatusPageCustomField: StatusPageCustomField,
|
|
65
|
+
TeamCustomField: TeamCustomField,
|
|
66
|
+
TeamMemberCustomField: TeamMemberCustomField,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const definitionModelNames: Array<string> = fs
|
|
70
|
+
.readdirSync(MODELS_DIRECTORY)
|
|
71
|
+
.filter((fileName: string) => {
|
|
72
|
+
return fileName.endsWith("CustomField.ts");
|
|
73
|
+
})
|
|
74
|
+
.map((fileName: string) => {
|
|
75
|
+
return fileName.replace(/\.ts$/, "");
|
|
76
|
+
})
|
|
77
|
+
.sort();
|
|
78
|
+
|
|
79
|
+
type LoadModelFunction = (modelName: string) => BaseModel;
|
|
80
|
+
|
|
81
|
+
const loadModel: LoadModelFunction = (modelName: string): BaseModel => {
|
|
82
|
+
return new DEFINITION_MODELS[modelName]!();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
describe("custom field definition models", () => {
|
|
86
|
+
/*
|
|
87
|
+
* Also a guard against the suite passing vacuously: if the glob stopped
|
|
88
|
+
* matching, every test.each below would silently run zero cases.
|
|
89
|
+
*/
|
|
90
|
+
test("covers every definition model on disk", () => {
|
|
91
|
+
expect(definitionModelNames.length).toBeGreaterThanOrEqual(9);
|
|
92
|
+
expect(Object.keys(DEFINITION_MODELS).sort()).toEqual(definitionModelNames);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test.each(definitionModelNames)(
|
|
96
|
+
"%s declares both value-mapping columns",
|
|
97
|
+
(modelName: string) => {
|
|
98
|
+
const model: BaseModel = loadModel(modelName);
|
|
99
|
+
|
|
100
|
+
for (const columnName of MAPPING_COLUMNS) {
|
|
101
|
+
expect(Object.prototype.hasOwnProperty.call(model, columnName)).toBe(
|
|
102
|
+
true,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
const tableColumn: TableColumnMetadata = getTableColumn(
|
|
106
|
+
model,
|
|
107
|
+
columnName,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
expect(tableColumn).toBeTruthy();
|
|
111
|
+
expect(tableColumn.type).toBe(TableColumnType.ShortText);
|
|
112
|
+
expect(tableColumn.required).toBe(false);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* ModelForm drops any field the user has no declared permission on, without
|
|
119
|
+
* an error. A column with no @ColumnAccessControl would therefore ship the
|
|
120
|
+
* whole feature as an invisible no-op: the settings form would simply not
|
|
121
|
+
* render the picker.
|
|
122
|
+
*/
|
|
123
|
+
test.each(definitionModelNames)(
|
|
124
|
+
"%s gates both value-mapping columns with read, create and update permissions",
|
|
125
|
+
(modelName: string) => {
|
|
126
|
+
const model: BaseModel = loadModel(modelName);
|
|
127
|
+
|
|
128
|
+
for (const columnName of MAPPING_COLUMNS) {
|
|
129
|
+
const accessControl: ColumnAccessControl = getColumnAccessControl(
|
|
130
|
+
model,
|
|
131
|
+
columnName,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
expect(accessControl).toBeTruthy();
|
|
135
|
+
expect(accessControl.read.length).toBeGreaterThan(0);
|
|
136
|
+
expect(accessControl.create.length).toBeGreaterThan(0);
|
|
137
|
+
expect(accessControl.update.length).toBeGreaterThan(0);
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
* The mapping columns must be gated exactly as this model's other editable
|
|
144
|
+
* definition columns are — copying `dropdownOptions`' permission family is
|
|
145
|
+
* what keeps a resource's own Create/Read/Edit roles in charge of them
|
|
146
|
+
* (and is why InventoryItemCustomField correctly reuses the Telemetry
|
|
147
|
+
* family rather than minting one of its own).
|
|
148
|
+
*/
|
|
149
|
+
test.each(definitionModelNames)(
|
|
150
|
+
"%s gates the value-mapping columns like its other editable columns",
|
|
151
|
+
(modelName: string) => {
|
|
152
|
+
const model: BaseModel = loadModel(modelName);
|
|
153
|
+
|
|
154
|
+
const reference: ColumnAccessControl = getColumnAccessControl(
|
|
155
|
+
model,
|
|
156
|
+
"dropdownOptions",
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
expect(reference).toBeTruthy();
|
|
160
|
+
|
|
161
|
+
for (const columnName of MAPPING_COLUMNS) {
|
|
162
|
+
expect(getColumnAccessControl(model, columnName)).toEqual(reference);
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
});
|
|
@@ -166,14 +166,21 @@ describe("RumApplication session replay configuration", () => {
|
|
|
166
166
|
}
|
|
167
167
|
});
|
|
168
168
|
|
|
169
|
-
it("is enabled by default
|
|
169
|
+
it("is enabled by default and records every session out of the box", () => {
|
|
170
170
|
/*
|
|
171
|
-
* Recording is on out of the box
|
|
172
|
-
*
|
|
173
|
-
*
|
|
171
|
+
* Recording is on out of the box AND sampling is 100%. The previous
|
|
172
|
+
* defaults (sample 0%, upload only on error or frustration) were the
|
|
173
|
+
* exact configuration behind issues #3527 / #3601: a customer installed
|
|
174
|
+
* the recorder, watched it buffer forever, and concluded the product was
|
|
175
|
+
* broken because a quiet day looks identical to a dead one. A customer
|
|
176
|
+
* who configures NOTHING must see a recording of their very first
|
|
177
|
+
* session; sampling down is a deliberate, visible choice made later.
|
|
178
|
+
*
|
|
179
|
+
* This test is a tripwire: a regression back to record-nothing defaults
|
|
180
|
+
* has to change this expectation and say why in the same commit.
|
|
174
181
|
*/
|
|
175
182
|
expect(getColumn("isSessionReplayEnabled").defaultValue).toBe(true);
|
|
176
|
-
expect(getColumn("sessionReplaySamplePercentage").defaultValue).toBe(
|
|
183
|
+
expect(getColumn("sessionReplaySamplePercentage").defaultValue).toBe(100);
|
|
177
184
|
});
|
|
178
185
|
|
|
179
186
|
it("pins the shipped privacy defaults", () => {
|
|
@@ -204,8 +211,15 @@ describe("RumApplication session replay configuration", () => {
|
|
|
204
211
|
expect(getColumn("sessionReplayConsentMode").defaultValue).toBe(
|
|
205
212
|
SessionReplayConsentMode.NotRequired,
|
|
206
213
|
);
|
|
214
|
+
/*
|
|
215
|
+
* Always, not OnErrorOrFrustration: with sampling at 100% (asserted
|
|
216
|
+
* above) the trigger is what decides whether a healthy session is ever
|
|
217
|
+
* uploaded, and "only broken sessions" made a working install look
|
|
218
|
+
* dead. The error/frustration trigger remains available per
|
|
219
|
+
* application for customers who want to trade coverage for bytes.
|
|
220
|
+
*/
|
|
207
221
|
expect(getColumn("sessionReplayCaptureTrigger").defaultValue).toBe(
|
|
208
|
-
SessionReplayCaptureTrigger.
|
|
222
|
+
SessionReplayCaptureTrigger.Always,
|
|
209
223
|
);
|
|
210
224
|
/*
|
|
211
225
|
* Identity and country capture are ON, so a support engineer can find
|