@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,666 @@
|
|
|
1
|
+
import PinServiceName from "../../../../Server/Utils/Telemetry/PinServiceName";
|
|
2
|
+
import { JSONObject, JSONValue } from "../../../../Types/JSON";
|
|
3
|
+
import { describe, expect, test } from "@jest/globals";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* PinServiceName is the control that stops telemetry written with a scraped
|
|
7
|
+
* Browser ingestion key from masquerading as a backend service.
|
|
8
|
+
*
|
|
9
|
+
* A Browser key is published in page source by design, so it must be assumed
|
|
10
|
+
* scraped. The origin allowlist and the rate limit bound HOW MUCH forged data
|
|
11
|
+
* an attacker can write and FROM WHERE; neither stops them writing it under
|
|
12
|
+
* `service.name: "payments-api"` and poisoning the dashboards, SLOs, telemetry
|
|
13
|
+
* monitors and alert rules of a service that never emitted a byte of it.
|
|
14
|
+
* Pinning is what makes forged data self-identifying, so it has to hold on
|
|
15
|
+
* every payload an attacker can compose - not just the well-formed ones.
|
|
16
|
+
*
|
|
17
|
+
* Three properties are pinned here, and each maps to a concrete bypass:
|
|
18
|
+
*
|
|
19
|
+
* 1. TOTALITY. Every resource block under resourceSpans / resourceLogs /
|
|
20
|
+
* resourceMetrics / resourceProfiles is rewritten. One unwalked
|
|
21
|
+
* container, or one skipped block in a batch of a thousand, is a forged
|
|
22
|
+
* span filed under someone else's service.
|
|
23
|
+
* 2. EXACTLY ONE service.name survives, and it is ours. Replacement - not
|
|
24
|
+
* appending - is the whole game: a forger who sends several service.name
|
|
25
|
+
* attributes hoping a downstream consumer takes the first (or the one
|
|
26
|
+
* with a non-string OTLP value, or the oddly-cased one) must end up with
|
|
27
|
+
* a payload where there is nothing left to take but the pin.
|
|
28
|
+
* 3. IT NEVER THROWS, AND IT NEVER SKIPS ON MALFORMED INPUT. This runs in a
|
|
29
|
+
* queue worker on JSON that has not been schema-validated yet. A
|
|
30
|
+
* TypeError would fail the whole batch and would be reachable by anyone
|
|
31
|
+
* holding a scraped key; a `"resource": "not-an-object"` that merely got
|
|
32
|
+
* skipped would be a one-character bypass of the entire control. So a
|
|
33
|
+
* hostile shape is repaired where there is somewhere to write, and only
|
|
34
|
+
* ever skipped where there is not.
|
|
35
|
+
*
|
|
36
|
+
* The suite therefore leans hard on attacker-shaped input: nulls, primitives
|
|
37
|
+
* and arrays in every position a spec-shaped payload has an object.
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
const PINNED: string = "browser-frontend";
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* pinInPlace's signature is typed for well-formed OTLP; every hostile case
|
|
44
|
+
* below has to go in through `unknown` to be expressible at all, so funnel
|
|
45
|
+
* every call through one helper rather than scattering casts.
|
|
46
|
+
*/
|
|
47
|
+
const pinRaw: (body: unknown, serviceName: unknown) => number = (
|
|
48
|
+
body: unknown,
|
|
49
|
+
serviceName: unknown,
|
|
50
|
+
): number => {
|
|
51
|
+
return PinServiceName.pinInPlace(body as JSONObject, serviceName as string);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
* Note the two entry points: `pin` defaults the name, so it cannot be used to
|
|
56
|
+
* test an explicitly-undefined name (the default would swallow it) - those
|
|
57
|
+
* cases go through pinRaw and reach pinInPlace with the argument as written.
|
|
58
|
+
*/
|
|
59
|
+
const pin: (body: unknown, serviceName?: unknown) => number = (
|
|
60
|
+
body: unknown,
|
|
61
|
+
serviceName: unknown = PINNED,
|
|
62
|
+
): number => {
|
|
63
|
+
return pinRaw(body, serviceName);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const attributesOf: (block: unknown) => Array<JSONObject> = (
|
|
67
|
+
block: unknown,
|
|
68
|
+
): Array<JSONObject> => {
|
|
69
|
+
const resource: JSONObject = (block as JSONObject)["resource"] as JSONObject;
|
|
70
|
+
return resource["attributes"] as unknown as Array<JSONObject>;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const serviceNameAttributesOf: (block: unknown) => Array<JSONObject> = (
|
|
74
|
+
block: unknown,
|
|
75
|
+
): Array<JSONObject> => {
|
|
76
|
+
return attributesOf(block).filter((attribute: JSONObject): boolean => {
|
|
77
|
+
return (
|
|
78
|
+
typeof attribute === "object" &&
|
|
79
|
+
attribute !== null &&
|
|
80
|
+
!Array.isArray(attribute) &&
|
|
81
|
+
String(attribute["key"] ?? "")
|
|
82
|
+
.trim()
|
|
83
|
+
.toLowerCase() === "service.name"
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const pinnedAttribute: (serviceName?: string) => JSONObject = (
|
|
89
|
+
serviceName: string = PINNED,
|
|
90
|
+
): JSONObject => {
|
|
91
|
+
return {
|
|
92
|
+
key: "service.name",
|
|
93
|
+
value: {
|
|
94
|
+
stringValue: serviceName,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const blockWithAttributes: (attributes: unknown) => JSONObject = (
|
|
100
|
+
attributes: unknown,
|
|
101
|
+
): JSONObject => {
|
|
102
|
+
return {
|
|
103
|
+
resource: {
|
|
104
|
+
attributes: attributes as JSONValue,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const clone: (value: unknown) => unknown = (value: unknown): unknown => {
|
|
110
|
+
return JSON.parse(JSON.stringify(value)) as unknown;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
* All four OTLP resource containers. Profiles are in the list even though a
|
|
115
|
+
* Browser key cannot reach the profiles surface: a SERVER key may carry a pin
|
|
116
|
+
* too, and the pin has to mean the same thing for every signal.
|
|
117
|
+
*/
|
|
118
|
+
const CONTAINER_KEYS: Array<string> = [
|
|
119
|
+
"resourceSpans",
|
|
120
|
+
"resourceLogs",
|
|
121
|
+
"resourceMetrics",
|
|
122
|
+
"resourceProfiles",
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
describe("PinServiceName.pinInPlace: coverage of every OTLP resource container", () => {
|
|
126
|
+
test.each(CONTAINER_KEYS)(
|
|
127
|
+
"pins every resource block under %s and returns the number rewritten",
|
|
128
|
+
(containerKey: string) => {
|
|
129
|
+
const body: JSONObject = {
|
|
130
|
+
[containerKey]: [
|
|
131
|
+
blockWithAttributes([]),
|
|
132
|
+
blockWithAttributes([pinnedAttribute("forged-backend")]),
|
|
133
|
+
],
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const rewritten: number = pin(body);
|
|
137
|
+
|
|
138
|
+
expect(rewritten).toBe(2);
|
|
139
|
+
|
|
140
|
+
const blocks: Array<JSONObject> = body[
|
|
141
|
+
containerKey
|
|
142
|
+
] as unknown as Array<JSONObject>;
|
|
143
|
+
|
|
144
|
+
for (const block of blocks) {
|
|
145
|
+
expect(serviceNameAttributesOf(block)).toEqual([pinnedAttribute()]);
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
test("a payload carrying all four signals has all four pinned and counts every block", () => {
|
|
151
|
+
const body: JSONObject = {
|
|
152
|
+
resourceSpans: [blockWithAttributes([]), blockWithAttributes([])],
|
|
153
|
+
resourceLogs: [blockWithAttributes([])],
|
|
154
|
+
resourceMetrics: [
|
|
155
|
+
blockWithAttributes([pinnedAttribute("payments-api")]),
|
|
156
|
+
blockWithAttributes([]),
|
|
157
|
+
blockWithAttributes([]),
|
|
158
|
+
],
|
|
159
|
+
resourceProfiles: [blockWithAttributes([pinnedAttribute("profiler")])],
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
expect(pin(body)).toBe(7);
|
|
163
|
+
|
|
164
|
+
for (const containerKey of CONTAINER_KEYS) {
|
|
165
|
+
const blocks: Array<JSONObject> = body[
|
|
166
|
+
containerKey
|
|
167
|
+
] as unknown as Array<JSONObject>;
|
|
168
|
+
|
|
169
|
+
for (const block of blocks) {
|
|
170
|
+
expect(serviceNameAttributesOf(block)).toEqual([pinnedAttribute()]);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("an empty container contributes nothing to the count but is not an error", () => {
|
|
176
|
+
const body: JSONObject = {
|
|
177
|
+
resourceSpans: [],
|
|
178
|
+
resourceLogs: [blockWithAttributes([])],
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
expect(pin(body)).toBe(1);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("rewrites the caller's body in place rather than returning a copy", () => {
|
|
185
|
+
const resource: JSONObject = { attributes: [] };
|
|
186
|
+
const container: Array<JSONObject> = [{ resource: resource }];
|
|
187
|
+
const body: JSONObject = {
|
|
188
|
+
resourceSpans: container as unknown as JSONValue,
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
pin(body);
|
|
192
|
+
|
|
193
|
+
// The caller keeps its own references; nothing is deep-cloned on the hot path.
|
|
194
|
+
expect(body["resourceSpans"]).toBe(container);
|
|
195
|
+
expect((container[0] as JSONObject)["resource"]).toBe(resource);
|
|
196
|
+
expect(resource["attributes"]).toEqual([pinnedAttribute()]);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe("PinServiceName.pinInPlace: exactly one service.name survives", () => {
|
|
201
|
+
test("an existing service.name is replaced, not duplicated", () => {
|
|
202
|
+
const block: JSONObject = blockWithAttributes([
|
|
203
|
+
pinnedAttribute("payments-api"),
|
|
204
|
+
]);
|
|
205
|
+
|
|
206
|
+
expect(pin({ resourceSpans: [block] })).toBe(1);
|
|
207
|
+
|
|
208
|
+
expect(attributesOf(block)).toEqual([pinnedAttribute()]);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("several forged service.name entries all collapse to exactly one pinned entry", () => {
|
|
212
|
+
const block: JSONObject = blockWithAttributes([
|
|
213
|
+
pinnedAttribute("payments-api"),
|
|
214
|
+
{ key: "http.method", value: { stringValue: "GET" } },
|
|
215
|
+
pinnedAttribute("auth-service"),
|
|
216
|
+
pinnedAttribute("billing-worker"),
|
|
217
|
+
]);
|
|
218
|
+
|
|
219
|
+
pin({ resourceLogs: [block] });
|
|
220
|
+
|
|
221
|
+
expect(serviceNameAttributesOf(block)).toHaveLength(1);
|
|
222
|
+
expect(attributesOf(block)).toEqual([
|
|
223
|
+
{ key: "http.method", value: { stringValue: "GET" } },
|
|
224
|
+
pinnedAttribute(),
|
|
225
|
+
]);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("a service.name that differs only by case or padding is still removed", () => {
|
|
229
|
+
/*
|
|
230
|
+
* Deliberately looser than the OTLP spec, which is case-sensitive: the
|
|
231
|
+
* cost of over-matching is that an exotic key is dropped, and the cost of
|
|
232
|
+
* under-matching is a bypass through any consumer that folds case.
|
|
233
|
+
*/
|
|
234
|
+
const block: JSONObject = blockWithAttributes([
|
|
235
|
+
{ key: "Service.Name", value: { stringValue: "payments-api" } },
|
|
236
|
+
{ key: " service.name ", value: { stringValue: "auth-service" } },
|
|
237
|
+
{ key: "SERVICE.NAME", value: { stringValue: "billing-worker" } },
|
|
238
|
+
]);
|
|
239
|
+
|
|
240
|
+
pin({ resourceMetrics: [block] });
|
|
241
|
+
|
|
242
|
+
expect(attributesOf(block)).toEqual([pinnedAttribute()]);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
test("a service.name attribute carrying a non-string OTLP value is still replaced by a stringValue", () => {
|
|
246
|
+
const forgedValues: Array<JSONObject> = [
|
|
247
|
+
{ key: "service.name", value: { intValue: "42" } },
|
|
248
|
+
{ key: "service.name", value: { boolValue: true } },
|
|
249
|
+
{
|
|
250
|
+
key: "service.name",
|
|
251
|
+
value: {
|
|
252
|
+
arrayValue: { values: [{ stringValue: "payments-api" }] },
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
{ key: "service.name", value: null },
|
|
256
|
+
{ key: "service.name" },
|
|
257
|
+
{ key: "service.name", value: { kvlistValue: { values: [] } } },
|
|
258
|
+
{ key: "service.name", value: "payments-api" },
|
|
259
|
+
{ key: "service.name", value: ["payments-api"] },
|
|
260
|
+
];
|
|
261
|
+
|
|
262
|
+
for (const forged of forgedValues) {
|
|
263
|
+
const block: JSONObject = blockWithAttributes([forged]);
|
|
264
|
+
|
|
265
|
+
expect(pin({ resourceSpans: [block] })).toBe(1);
|
|
266
|
+
|
|
267
|
+
expect(attributesOf(block)).toEqual([pinnedAttribute()]);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
test("service.name is appended when the resource never carried one", () => {
|
|
272
|
+
const block: JSONObject = blockWithAttributes([
|
|
273
|
+
{ key: "host.name", value: { stringValue: "laptop" } },
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
pin({ resourceSpans: [block] });
|
|
277
|
+
|
|
278
|
+
expect(attributesOf(block)).toEqual([
|
|
279
|
+
{ key: "host.name", value: { stringValue: "laptop" } },
|
|
280
|
+
pinnedAttribute(),
|
|
281
|
+
]);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("unrelated attributes keep their identity and relative order, and the pin lands last", () => {
|
|
285
|
+
const first: JSONObject = {
|
|
286
|
+
key: "telemetry.sdk.name",
|
|
287
|
+
value: { stringValue: "opentelemetry" },
|
|
288
|
+
};
|
|
289
|
+
const second: JSONObject = {
|
|
290
|
+
key: "deployment.environment",
|
|
291
|
+
value: { stringValue: "production" },
|
|
292
|
+
};
|
|
293
|
+
const third: JSONObject = {
|
|
294
|
+
key: "host.arch",
|
|
295
|
+
value: { stringValue: "arm64" },
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const block: JSONObject = blockWithAttributes([
|
|
299
|
+
first,
|
|
300
|
+
pinnedAttribute("payments-api"),
|
|
301
|
+
second,
|
|
302
|
+
third,
|
|
303
|
+
]);
|
|
304
|
+
|
|
305
|
+
pin({ resourceLogs: [block] });
|
|
306
|
+
|
|
307
|
+
const attributes: Array<JSONObject> = attributesOf(block);
|
|
308
|
+
|
|
309
|
+
expect(attributes).toHaveLength(4);
|
|
310
|
+
// Same objects, same order - nothing is rebuilt or reordered.
|
|
311
|
+
expect(attributes[0]).toBe(first);
|
|
312
|
+
expect(attributes[1]).toBe(second);
|
|
313
|
+
expect(attributes[2]).toBe(third);
|
|
314
|
+
expect(attributes[3]).toEqual(pinnedAttribute());
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
describe("PinServiceName.pinInPlace: missing or malformed structure is repaired, never skipped", () => {
|
|
319
|
+
test("a resource block with no resource at all gets one created and pinned", () => {
|
|
320
|
+
const block: JSONObject = { scopeSpans: [] };
|
|
321
|
+
|
|
322
|
+
expect(pin({ resourceSpans: [block] })).toBe(1);
|
|
323
|
+
|
|
324
|
+
expect(block["resource"]).toEqual({ attributes: [pinnedAttribute()] });
|
|
325
|
+
// The rest of the envelope is untouched.
|
|
326
|
+
expect(block["scopeSpans"]).toEqual([]);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test("a resource with no attributes array gets one created and pinned", () => {
|
|
330
|
+
const resource: JSONObject = { droppedAttributesCount: 0 };
|
|
331
|
+
const block: JSONObject = { resource: resource };
|
|
332
|
+
|
|
333
|
+
expect(pin({ resourceLogs: [block] })).toBe(1);
|
|
334
|
+
|
|
335
|
+
expect(resource["attributes"]).toEqual([pinnedAttribute()]);
|
|
336
|
+
expect(resource["droppedAttributesCount"]).toBe(0);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test.each([
|
|
340
|
+
["an object", { "service.name": "payments-api" } as unknown],
|
|
341
|
+
["a string", "service.name=payments-api" as unknown],
|
|
342
|
+
["a number", 7 as unknown],
|
|
343
|
+
["null", null as unknown],
|
|
344
|
+
["a boolean", true as unknown],
|
|
345
|
+
])(
|
|
346
|
+
"attributes that are %s are replaced with a valid array holding only the pin",
|
|
347
|
+
(_label: string, attributes: unknown) => {
|
|
348
|
+
const block: JSONObject = blockWithAttributes(attributes);
|
|
349
|
+
|
|
350
|
+
expect(pin({ resourceMetrics: [block] })).toBe(1);
|
|
351
|
+
|
|
352
|
+
/*
|
|
353
|
+
* The malformed value is discarded rather than preserved. That is the
|
|
354
|
+
* safe direction: leaving it in place would let a forged payload keep an
|
|
355
|
+
* unpinned service.name under a shape the walker cannot read.
|
|
356
|
+
*/
|
|
357
|
+
expect(attributesOf(block)).toEqual([pinnedAttribute()]);
|
|
358
|
+
},
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
test.each([
|
|
362
|
+
["a string", "not-a-resource" as unknown],
|
|
363
|
+
["a number", 1 as unknown],
|
|
364
|
+
["an array", [{ attributes: [] }] as unknown],
|
|
365
|
+
["a boolean", false as unknown],
|
|
366
|
+
["null", null as unknown],
|
|
367
|
+
])(
|
|
368
|
+
"a resource that is %s is replaced with a real resource carrying the pin",
|
|
369
|
+
(_label: string, resource: unknown) => {
|
|
370
|
+
const block: JSONObject = { resource: resource as JSONValue };
|
|
371
|
+
|
|
372
|
+
expect(pin({ resourceSpans: [block] })).toBe(1);
|
|
373
|
+
|
|
374
|
+
expect(block["resource"]).toEqual({ attributes: [pinnedAttribute()] });
|
|
375
|
+
},
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
test("attribute entries that are null, primitives or arrays are preserved untouched alongside the pin", () => {
|
|
379
|
+
const block: JSONObject = blockWithAttributes([
|
|
380
|
+
null,
|
|
381
|
+
"not-an-attribute",
|
|
382
|
+
42,
|
|
383
|
+
true,
|
|
384
|
+
["service.name", "payments-api"],
|
|
385
|
+
{ value: { stringValue: "no key at all" } },
|
|
386
|
+
{ key: 7, value: { stringValue: "non-string key" } },
|
|
387
|
+
{ key: null },
|
|
388
|
+
pinnedAttribute("payments-api"),
|
|
389
|
+
]);
|
|
390
|
+
|
|
391
|
+
expect(pin({ resourceLogs: [block] })).toBe(1);
|
|
392
|
+
|
|
393
|
+
expect(attributesOf(block)).toEqual([
|
|
394
|
+
null,
|
|
395
|
+
"not-an-attribute",
|
|
396
|
+
42,
|
|
397
|
+
true,
|
|
398
|
+
["service.name", "payments-api"],
|
|
399
|
+
{ value: { stringValue: "no key at all" } },
|
|
400
|
+
{ key: 7, value: { stringValue: "non-string key" } },
|
|
401
|
+
{ key: null },
|
|
402
|
+
pinnedAttribute(),
|
|
403
|
+
]);
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
test("blocks that are not objects are skipped, and their well-formed siblings are still pinned", () => {
|
|
407
|
+
const good: JSONObject = blockWithAttributes([]);
|
|
408
|
+
const alsoGood: JSONObject = blockWithAttributes([
|
|
409
|
+
pinnedAttribute("payments-api"),
|
|
410
|
+
]);
|
|
411
|
+
|
|
412
|
+
const body: JSONObject = {
|
|
413
|
+
resourceSpans: [
|
|
414
|
+
null,
|
|
415
|
+
undefined,
|
|
416
|
+
"resource",
|
|
417
|
+
0,
|
|
418
|
+
false,
|
|
419
|
+
[],
|
|
420
|
+
[{ resource: {} }],
|
|
421
|
+
good,
|
|
422
|
+
alsoGood,
|
|
423
|
+
] as unknown as JSONValue,
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// Only the two real envelopes are rewritable; there is nowhere to write on the rest.
|
|
427
|
+
expect(pin(body)).toBe(2);
|
|
428
|
+
expect(attributesOf(good)).toEqual([pinnedAttribute()]);
|
|
429
|
+
expect(attributesOf(alsoGood)).toEqual([pinnedAttribute()]);
|
|
430
|
+
});
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
describe("PinServiceName.pinInPlace: hostile input never throws", () => {
|
|
434
|
+
const hostileBodies: Array<[string, unknown]> = [
|
|
435
|
+
["null body", null],
|
|
436
|
+
["undefined body", undefined],
|
|
437
|
+
["array body", [{ resourceSpans: [] }]],
|
|
438
|
+
["string body", "resourceSpans"],
|
|
439
|
+
["number body", 42],
|
|
440
|
+
["boolean body", true],
|
|
441
|
+
["empty body", {}],
|
|
442
|
+
["resourceSpans is a string", { resourceSpans: "resourceSpans" }],
|
|
443
|
+
["resourceSpans is a number", { resourceSpans: 1 }],
|
|
444
|
+
["resourceSpans is null", { resourceSpans: null }],
|
|
445
|
+
["resourceSpans is undefined", { resourceSpans: undefined }],
|
|
446
|
+
["resourceSpans is a boolean", { resourceSpans: false }],
|
|
447
|
+
[
|
|
448
|
+
"resourceSpans is an object, not an array",
|
|
449
|
+
{ resourceSpans: { "0": { resource: {} } } },
|
|
450
|
+
],
|
|
451
|
+
["resourceLogs is a string", { resourceLogs: "x" }],
|
|
452
|
+
["resourceMetrics is an object", { resourceMetrics: { resource: {} } }],
|
|
453
|
+
["array of nulls", { resourceSpans: [null, null] }],
|
|
454
|
+
["array of primitives", { resourceSpans: ["a", 1, true] }],
|
|
455
|
+
["array of arrays", { resourceSpans: [[], [[]]] }],
|
|
456
|
+
["resource is a primitive", { resourceSpans: [{ resource: 5 }] }],
|
|
457
|
+
[
|
|
458
|
+
"attributes is a primitive",
|
|
459
|
+
{ resourceSpans: [{ resource: { attributes: 5 } }] },
|
|
460
|
+
],
|
|
461
|
+
[
|
|
462
|
+
"attributes holds hostile entries",
|
|
463
|
+
{
|
|
464
|
+
resourceSpans: [
|
|
465
|
+
{ resource: { attributes: [null, 1, [], { key: {} }] } },
|
|
466
|
+
],
|
|
467
|
+
},
|
|
468
|
+
],
|
|
469
|
+
[
|
|
470
|
+
"deeply nested but malformed",
|
|
471
|
+
{
|
|
472
|
+
resourceSpans: [
|
|
473
|
+
{
|
|
474
|
+
resource: {
|
|
475
|
+
attributes: [
|
|
476
|
+
{
|
|
477
|
+
key: "service.name",
|
|
478
|
+
value: { arrayValue: { values: [{ stringValue: "x" }] } },
|
|
479
|
+
},
|
|
480
|
+
],
|
|
481
|
+
},
|
|
482
|
+
scopeSpans: [
|
|
483
|
+
{ scope: null, spans: "not-an-array" },
|
|
484
|
+
{ spans: [{ attributes: { key: "service.name" } }] },
|
|
485
|
+
],
|
|
486
|
+
},
|
|
487
|
+
],
|
|
488
|
+
resourceLogs: [{ resource: [], scopeLogs: 3 }],
|
|
489
|
+
resourceMetrics: "none",
|
|
490
|
+
},
|
|
491
|
+
],
|
|
492
|
+
];
|
|
493
|
+
|
|
494
|
+
test.each(hostileBodies)(
|
|
495
|
+
"returns a number and does not throw on: %s",
|
|
496
|
+
(_label: string, body: unknown) => {
|
|
497
|
+
let result: number = -1;
|
|
498
|
+
|
|
499
|
+
expect((): void => {
|
|
500
|
+
result = pin(body);
|
|
501
|
+
}).not.toThrow();
|
|
502
|
+
|
|
503
|
+
expect(typeof result).toBe("number");
|
|
504
|
+
expect(Number.isInteger(result)).toBe(true);
|
|
505
|
+
expect(result).toBeGreaterThanOrEqual(0);
|
|
506
|
+
},
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
test("a body whose container is not an array is left completely alone", () => {
|
|
510
|
+
const body: JSONObject = {
|
|
511
|
+
resourceSpans: { "0": { resource: { attributes: [] } } },
|
|
512
|
+
};
|
|
513
|
+
const before: unknown = clone(body);
|
|
514
|
+
|
|
515
|
+
expect(pin(body)).toBe(0);
|
|
516
|
+
expect(body).toEqual(before);
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
test("a large hostile batch is walked to the end without throwing", () => {
|
|
520
|
+
const blocks: Array<unknown> = [];
|
|
521
|
+
|
|
522
|
+
for (let index: number = 0; index < 500; index++) {
|
|
523
|
+
blocks.push(index % 2 === 0 ? blockWithAttributes([]) : null);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
expect(pin({ resourceSpans: blocks as unknown as JSONValue })).toBe(250);
|
|
527
|
+
});
|
|
528
|
+
});
|
|
529
|
+
|
|
530
|
+
describe("PinServiceName.pinInPlace: the pinned name itself", () => {
|
|
531
|
+
test.each([
|
|
532
|
+
["an empty string", ""],
|
|
533
|
+
["whitespace only", " "],
|
|
534
|
+
])(
|
|
535
|
+
"refuses to pin when the name is %s, leaving the payload untouched",
|
|
536
|
+
(_label: string, serviceName: string) => {
|
|
537
|
+
const body: JSONObject = {
|
|
538
|
+
resourceSpans: [blockWithAttributes([pinnedAttribute("payments-api")])],
|
|
539
|
+
};
|
|
540
|
+
const before: unknown = clone(body);
|
|
541
|
+
|
|
542
|
+
/*
|
|
543
|
+
* Stamping `service.name: ""` on everything would be strictly worse than
|
|
544
|
+
* not pinning - it destroys the customer's own attribution AND makes the
|
|
545
|
+
* forged data indistinguishable from it.
|
|
546
|
+
*/
|
|
547
|
+
expect(pin(body, serviceName)).toBe(0);
|
|
548
|
+
expect(body).toEqual(before);
|
|
549
|
+
},
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
test.each([
|
|
553
|
+
["undefined", undefined as unknown],
|
|
554
|
+
["null", null as unknown],
|
|
555
|
+
["a number", 42 as unknown],
|
|
556
|
+
["an object", { name: "payments-api" } as unknown],
|
|
557
|
+
])(
|
|
558
|
+
"refuses to pin when the name is %s rather than a string",
|
|
559
|
+
(_label: string, serviceName: unknown) => {
|
|
560
|
+
const body: JSONObject = {
|
|
561
|
+
resourceSpans: [blockWithAttributes([])],
|
|
562
|
+
};
|
|
563
|
+
const before: unknown = clone(body);
|
|
564
|
+
|
|
565
|
+
expect(pinRaw(body, serviceName)).toBe(0);
|
|
566
|
+
expect(body).toEqual(before);
|
|
567
|
+
},
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
test("surrounding whitespace on the pinned name is trimmed before it is written", () => {
|
|
571
|
+
const block: JSONObject = blockWithAttributes([]);
|
|
572
|
+
|
|
573
|
+
expect(pin({ resourceSpans: [block] }, " browser-frontend ")).toBe(1);
|
|
574
|
+
|
|
575
|
+
expect(attributesOf(block)).toEqual([pinnedAttribute()]);
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
test("a very long pinned name is written verbatim rather than truncated or rejected", () => {
|
|
579
|
+
const longName: string = "a".repeat(10000);
|
|
580
|
+
const block: JSONObject = blockWithAttributes([
|
|
581
|
+
pinnedAttribute("payments-api"),
|
|
582
|
+
]);
|
|
583
|
+
|
|
584
|
+
expect(pin({ resourceSpans: [block] }, longName)).toBe(1);
|
|
585
|
+
|
|
586
|
+
expect(attributesOf(block)).toEqual([pinnedAttribute(longName)]);
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
test("a name full of odd characters is written verbatim, not escaped or dropped", () => {
|
|
590
|
+
const oddName: string = 'svc"\\/<>& name';
|
|
591
|
+
const block: JSONObject = blockWithAttributes([]);
|
|
592
|
+
|
|
593
|
+
expect(pin({ resourceSpans: [block] }, oddName)).toBe(1);
|
|
594
|
+
|
|
595
|
+
expect(attributesOf(block)).toEqual([pinnedAttribute(oddName)]);
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
describe("PinServiceName.pinInPlace: every OTLP container, and nothing else", () => {
|
|
600
|
+
test("resourceProfiles is walked like the other three", () => {
|
|
601
|
+
/*
|
|
602
|
+
* A Browser key cannot reach the profiles surface at all
|
|
603
|
+
* (BROWSER_ALLOWED_INGEST_SURFACES), so this is not part of containing a
|
|
604
|
+
* scraped credential. It is here because a SERVER key may carry a pin too,
|
|
605
|
+
* and the dashboard field promises the pin applies to "everything the key
|
|
606
|
+
* writes" - a promise that would be quietly false for one signal if
|
|
607
|
+
* profiles were skipped.
|
|
608
|
+
*/
|
|
609
|
+
const body: JSONObject = {
|
|
610
|
+
resourceProfiles: [
|
|
611
|
+
blockWithAttributes([pinnedAttribute("payments-api")]),
|
|
612
|
+
],
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
expect(pin(body)).toBe(1);
|
|
616
|
+
|
|
617
|
+
expect(
|
|
618
|
+
attributesOf((body["resourceProfiles"] as Array<JSONObject>)[0]!),
|
|
619
|
+
).toEqual([pinnedAttribute(PINNED)]);
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
test("unrelated top-level keys survive a payload that does get pinned", () => {
|
|
623
|
+
const body: JSONObject = {
|
|
624
|
+
resourceSpans: [blockWithAttributes([])],
|
|
625
|
+
partialSuccess: { rejectedSpans: "0" },
|
|
626
|
+
someVendorExtension: { nested: { deep: [1, 2, 3] } },
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
expect(pin(body)).toBe(1);
|
|
630
|
+
|
|
631
|
+
expect(body["partialSuccess"]).toEqual({ rejectedSpans: "0" });
|
|
632
|
+
expect(body["someVendorExtension"]).toEqual({
|
|
633
|
+
nested: { deep: [1, 2, 3] },
|
|
634
|
+
});
|
|
635
|
+
});
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
describe("PinServiceName.pinInPlace: idempotence", () => {
|
|
639
|
+
test("pinning an already-pinned payload changes nothing and reports the same count", () => {
|
|
640
|
+
const body: JSONObject = {
|
|
641
|
+
resourceSpans: [
|
|
642
|
+
blockWithAttributes([
|
|
643
|
+
{ key: "host.name", value: { stringValue: "laptop" } },
|
|
644
|
+
pinnedAttribute("payments-api"),
|
|
645
|
+
]),
|
|
646
|
+
{ scopeSpans: [] },
|
|
647
|
+
],
|
|
648
|
+
resourceLogs: [blockWithAttributes("not-an-array")],
|
|
649
|
+
resourceMetrics: [blockWithAttributes([null, pinnedAttribute("x")])],
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
const firstCount: number = pin(body);
|
|
653
|
+
const afterFirst: unknown = clone(body);
|
|
654
|
+
|
|
655
|
+
const secondCount: number = pin(body);
|
|
656
|
+
const afterSecond: unknown = clone(body);
|
|
657
|
+
|
|
658
|
+
expect(firstCount).toBe(4);
|
|
659
|
+
expect(secondCount).toBe(firstCount);
|
|
660
|
+
expect(afterSecond).toEqual(afterFirst);
|
|
661
|
+
|
|
662
|
+
// And a third pass is still a fixed point.
|
|
663
|
+
expect(pin(body)).toBe(firstCount);
|
|
664
|
+
expect(clone(body)).toEqual(afterFirst);
|
|
665
|
+
});
|
|
666
|
+
});
|