@oneuptime/common 13.0.3 → 13.0.5
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/DatabaseModels/Index.ts +4 -0
- package/Models/DatabaseModels/RumApplication.ts +1 -1
- package/Models/DatabaseModels/SecurityEventConnection.ts +457 -0
- package/Models/DatabaseModels/SecurityEventConnectionRun.ts +263 -0
- package/Models/DatabaseModels/TelemetryIngestionKey.ts +2 -2
- package/Server/API/AIInvestigationAPI.ts +484 -24
- package/Server/API/GoogleSecOpsConnectionAPI.ts +249 -8
- package/Server/API/SecurityEventConnectionAPI.ts +250 -0
- package/Server/API/TelemetryAPI.ts +402 -265
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.ts +99 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Middleware/TelemetryIngest.ts +101 -6
- package/Server/Services/ExceptionAggregationService.ts +7 -16
- package/Server/Services/GoogleSecOpsConnectionService.ts +15 -0
- package/Server/Services/Index.ts +4 -0
- package/Server/Services/InventoryItemService.ts +28 -0
- package/Server/Services/LogAggregationService.ts +17 -23
- package/Server/Services/MetricAggregationService.ts +4 -14
- package/Server/Services/SecurityEventConnectionRunService.ts +10 -0
- package/Server/Services/SecurityEventConnectionService.ts +538 -0
- package/Server/Services/TraceAggregationService.ts +77 -28
- package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +13 -1
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +15 -1
- package/Server/Utils/AI/SRE/InvestigationEvidence.ts +658 -0
- package/Server/Utils/AI/SRE/InvestigationReferences.ts +324 -0
- package/Server/Utils/AI/Toolbox/Index.ts +38 -0
- package/Server/Utils/AI/Toolbox/TimelineTools.ts +9 -2
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +80 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +5 -3
- package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.ts +1108 -0
- package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.ts +732 -0
- package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +495 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.ts +689 -0
- package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.ts +767 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.ts +571 -0
- package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.ts +827 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.ts +610 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.ts +549 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.ts +830 -0
- package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.ts +684 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.ts +487 -0
- package/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.ts +778 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +1002 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +556 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +275 -0
- package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +53 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.ts +709 -0
- package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.ts +596 -0
- package/Server/Utils/SecurityEvent/Connectors/Types.ts +191 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +353 -65
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +777 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +747 -148
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +48 -2
- package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +81 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +741 -40
- package/Server/Utils/StartServer.ts +10 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +8 -0
- package/Server/Utils/Telemetry/KubernetesResourceAttributes.ts +108 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +174 -93
- package/Server/Utils/Telemetry/ResourceFacetPlanner.ts +251 -0
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +248 -413
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +668 -0
- package/Server/Utils/Telemetry/TraceContextPropagation.ts +348 -0
- package/Server/Utils/Telemetry.ts +18 -0
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +413 -0
- package/Tests/App/Dashboard/AIRootCauseFeedItem.test.tsx +285 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +242 -0
- package/Tests/App/Dashboard/AlertEpisodeViewFields.test.tsx +601 -15
- package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +835 -0
- package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +41 -0
- package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +604 -0
- package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +738 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +153 -6
- package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +165 -0
- package/Tests/App/Dashboard/EpisodeChangeState.test.tsx +1069 -0
- package/Tests/App/Dashboard/EpisodeMembersCard.test.tsx +772 -0
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +2354 -0
- package/Tests/App/Dashboard/EventOverviewSkeleton.test.tsx +210 -0
- package/Tests/App/Dashboard/EventStatBar.test.tsx +392 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +247 -0
- package/Tests/App/Dashboard/ExceptionAIAssistance.test.tsx +606 -0
- package/Tests/App/Dashboard/ExceptionBreadcrumbTimeline.test.tsx +273 -0
- package/Tests/App/Dashboard/ExceptionDetailSideMenu.test.tsx +176 -0
- package/Tests/App/Dashboard/ExceptionOverviewCards.test.tsx +366 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +371 -0
- package/Tests/App/Dashboard/ExceptionStackFrameViewer.test.tsx +440 -0
- package/Tests/App/Dashboard/ExceptionSummary.test.tsx +381 -0
- package/Tests/App/Dashboard/ExceptionTriage.test.tsx +306 -0
- package/Tests/App/Dashboard/ExceptionsResourceFacets.test.tsx +604 -0
- package/Tests/App/Dashboard/ExceptionsViewerEntityChips.test.tsx +706 -0
- package/Tests/App/Dashboard/FeedOrdering.test.ts +32 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +838 -0
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +18 -0
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +297 -20
- package/Tests/App/Dashboard/IncidentEpisodeViewFields.test.tsx +618 -13
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +254 -207
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +303 -135
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +1251 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +303 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +876 -8
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +35 -0
- package/Tests/App/Dashboard/InvestigationReferenceLink.test.tsx +177 -0
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +1295 -0
- package/Tests/App/Dashboard/KubernetesImageReferenceView.test.tsx +114 -0
- package/Tests/App/Dashboard/KubernetesLogsTabChips.test.tsx +285 -0
- package/Tests/App/Dashboard/LogsEntityChipNames.test.tsx +316 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +361 -0
- package/Tests/App/Dashboard/ProfileTableEntityNames.test.tsx +432 -0
- package/Tests/App/Dashboard/ProfileViewEntityName.test.tsx +250 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +10 -0
- package/Tests/App/Dashboard/ResourceLogsTabsBareLayout.test.tsx +700 -0
- package/Tests/App/Dashboard/ResourcePageEntityNameProps.test.tsx +803 -0
- package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +11 -1
- package/Tests/App/Dashboard/ScheduledMaintenanceChangeState.test.tsx +1026 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +436 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +1195 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1022 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +905 -0
- package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +247 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +375 -274
- package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +410 -0
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +774 -0
- package/Tests/App/Dashboard/TopErrorsPanelResourceNames.test.tsx +316 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +30 -0
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +88 -24
- package/Tests/App/Dashboard/TraceExplorer.test.tsx +1590 -0
- package/Tests/App/Dashboard/TraceWaterfall.test.tsx +488 -0
- package/Tests/App/Dashboard/TracesAnalyticsSeriesLabels.test.tsx +367 -0
- package/Tests/App/Dashboard/TracesEntityNames.test.tsx +585 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +613 -0
- package/Tests/App/Dashboard/UseServiceNames.test.tsx +359 -0
- package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +7 -0
- package/Tests/Models/InventoryItemNaming.test.ts +132 -16
- package/Tests/Models/SecurityDomainAccessControl.test.ts +61 -17
- package/Tests/Server/API/AIInvestigationAPI.test.ts +611 -2
- package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +1098 -0
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +409 -0
- package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +856 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +528 -1
- package/Tests/Server/API/TelemetryFacetsAPI.test.ts +810 -0
- package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +240 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +229 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +66 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- package/Tests/Server/Services/SecurityEventConnectionService.test.ts +1233 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +53 -0
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +218 -0
- package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +155 -1
- package/Tests/Server/Services/TraceAggregationExceptionScope.test.ts +142 -0
- package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +85 -24
- package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +33 -0
- package/Tests/Server/Utils/AI/InvestigationEvidence.test.ts +1395 -0
- package/Tests/Server/Utils/AI/InvestigationReferences.test.ts +616 -0
- package/Tests/Server/Utils/AI/TimelineTools.test.ts +119 -0
- package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +151 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +65 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorExceptionScope.test.ts +224 -0
- package/Tests/Server/Utils/LoggerCore.test.ts +597 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +55 -2
- package/Tests/Server/Utils/Monitor/MonitorTemplateUtil.test.ts +1109 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.test.ts +1240 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.test.ts +1853 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +1129 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.test.ts +1066 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.test.ts +1568 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.test.ts +930 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.test.ts +1409 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.test.ts +763 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.test.ts +1296 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.test.ts +1102 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.test.ts +1174 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.test.ts +1032 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.test.ts +1558 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +3041 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +1168 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +906 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.test.ts +1068 -0
- package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.test.ts +1004 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +784 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +113 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +5 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +93 -13
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsHttpIntegration.test.ts +23 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +25 -3
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +22 -8
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +82 -16
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSearchDetections.test.ts +730 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +1577 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayOriginAllowlist.test.ts +41 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1453 -18
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +711 -0
- package/Tests/Server/Utils/Telemetry/KubernetesResourceAttributes.test.ts +162 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +460 -13
- package/Tests/Server/Utils/Telemetry/ResourceFacetPlanner.test.ts +678 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +868 -0
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +525 -0
- package/Tests/Server/Utils/Telemetry/TraceContextPropagation.test.ts +420 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilCorePaths.test.ts +1014 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilExhaustiveRotation.test.ts +9 -6
- package/Tests/Types/Rules/RuleCriteriaFieldRegistry.test.ts +276 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +73 -0
- package/Tests/Types/Rum/SessionReplayTransportContracts.test.ts +95 -0
- package/Tests/Types/SecurityEvent/Connectors/ConnectorDiagnostics.test.ts +82 -0
- package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +314 -0
- package/Tests/Types/Telemetry/ExceptionSpanScope.test.ts +89 -0
- package/Tests/Types/Telemetry/LlmConventions.test.ts +495 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +96 -0
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +304 -0
- package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +357 -0
- package/Tests/UI/Components/Card.test.tsx +312 -1
- package/Tests/UI/Components/CardModelDetailHeaderLayout.test.tsx +253 -0
- package/Tests/UI/Components/CardModelDetailRefresher.test.tsx +342 -0
- package/Tests/UI/Components/Checkbox.test.tsx +79 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +142 -0
- package/Tests/UI/Components/DetailCompactStyle.test.tsx +621 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +60 -0
- package/Tests/UI/Components/FacetSections.test.tsx +581 -0
- package/Tests/UI/Components/FacetSidebarControls.test.tsx +812 -0
- package/Tests/UI/Components/FacetVisibility.test.ts +429 -0
- package/Tests/UI/Components/LockedFilterActions.test.tsx +396 -0
- package/Tests/UI/Components/LockedFilterChip.test.tsx +651 -0
- package/Tests/UI/Components/LogsEntityNames.test.ts +1769 -0
- package/Tests/UI/Components/LogsEntityNamesComponents.test.tsx +696 -0
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +600 -0
- package/Tests/UI/Components/LogsViewerEntityNames.test.tsx +713 -0
- package/Tests/UI/Components/MarkdownInlineReferences.test.tsx +2079 -0
- package/Tests/UI/Components/MemberRoleAssignment.test.tsx +446 -0
- package/Tests/UI/Components/ModelDetailRefetch.test.tsx +397 -0
- package/Tests/UI/Components/ModelListRefetch.test.tsx +233 -0
- package/Tests/UI/Components/ModelPageModelChange.test.tsx +409 -0
- package/Tests/UI/Components/PaginationIntegration.test.tsx +25 -0
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +172 -0
- package/Tests/UI/Components/SavedViewsSidebarIntegration.test.tsx +32 -14
- package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +44 -1
- package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +304 -0
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +718 -0
- package/Tests/UI/Monitor/EvaluationLogList.test.tsx +303 -0
- package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +55 -1
- package/Tests/UI/Rum/FidelityNotices.test.ts +22 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +120 -136
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +988 -0
- package/Tests/UI/Rum/ReplayCard.test.tsx +32 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +709 -12
- package/Tests/UI/Rum/ReplayHeader.test.tsx +50 -1
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +67 -10
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +41 -12
- package/Tests/UI/Rum/ReplayStage.test.tsx +663 -1
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +173 -0
- package/Tests/UI/Rum/ReplayUi.test.tsx +189 -2
- package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +91 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +1 -1
- package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +585 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +844 -51
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +29 -1
- package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +288 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +31 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +6 -0
- package/Tests/UI/Utils/Clipboard.test.ts +154 -0
- package/Tests/UI/Utils/Navigation.test.ts +24 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +2205 -0
- package/Tests/UI/Utils/Telemetry/UseTelemetryEntityNames.test.tsx +844 -0
- package/Tests/Utils/AI/InvestigationReport.test.ts +2430 -0
- package/Tests/Utils/APIOutgoingRequestTracer.test.ts +137 -0
- package/Tests/Utils/Rum/SessionReplayHealth.test.ts +884 -0
- package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +40 -0
- package/Tests/Utils/Rum/SessionReplayRecordingEnded.test.ts +619 -0
- package/Tests/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.test.ts +631 -0
- package/Tests/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.test.ts +479 -0
- package/Tests/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.test.ts +507 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.test.ts +686 -0
- package/Tests/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.test.ts +474 -0
- package/Tests/Utils/SecurityEvent/Connectors/OktaNormalizer.test.ts +736 -0
- package/Tests/Utils/SecurityEvent/Connectors/SplunkNormalizer.test.ts +407 -0
- package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.test.ts +129 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +57 -1
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +36 -0
- package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +600 -0
- package/Tests/Utils/Telemetry/NetworkHost.test.ts +48 -0
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +154 -0
- package/Tests/Utils/Traces/CriticalPath.test.ts +25 -0
- package/Types/AI/AIChatTypes.ts +8 -0
- package/Types/AI/InvestigationEvidence.ts +96 -0
- package/Types/Monitor/MonitorEvaluationSummary.ts +5 -0
- package/Types/OnCallDutyPolicy/Layer.ts +12 -0
- package/Types/Permission.ts +2 -2
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rum/SessionReplay.ts +109 -0
- package/Types/Rum/SessionReplayApi.ts +31 -0
- package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +111 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +87 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +492 -0
- package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +41 -0
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +56 -1
- package/Types/SecurityEvent/GoogleSecOpsRegion.ts +34 -0
- package/Types/Telemetry/EntityType.ts +14 -0
- package/Types/Telemetry/ExceptionSpanScope.ts +83 -0
- package/Types/Telemetry/LockedFilterDetail.ts +46 -0
- package/Types/Telemetry/ResourceEntityFacet.ts +17 -10
- package/Types/Telemetry/ResourceFacetCatalog.ts +171 -0
- package/UI/Components/Card/Card.tsx +118 -83
- package/UI/Components/Checkbox/Checkbox.tsx +8 -5
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +7 -1
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +4 -1
- package/UI/Components/Detail/Detail.tsx +137 -22
- package/UI/Components/ErrorBoundary.tsx +38 -0
- package/UI/Components/LogsViewer/LogsEntityNames.ts +912 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +156 -77
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +28 -11
- package/UI/Components/LogsViewer/components/FacetSection.tsx +66 -79
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +17 -2
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +45 -5
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +100 -19
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +156 -39
- package/UI/Components/LogsViewer/components/LogsTable.tsx +30 -8
- package/UI/Components/LogsViewer/types.ts +6 -0
- package/UI/Components/Markdown.tsx/InlineReferences.tsx +628 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +385 -312
- package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +50 -22
- package/UI/Components/ModelDetail/CardModelDetail.tsx +15 -0
- package/UI/Components/ModelDetail/ModelDetail.tsx +64 -19
- package/UI/Components/ModelList/ModelList.tsx +33 -8
- package/UI/Components/Page/ModelPage.tsx +119 -54
- package/UI/Components/Table/Table.tsx +8 -0
- package/UI/Components/Table/TableRow.tsx +13 -5
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +229 -0
- package/UI/Components/TelemetryViewer/ResourceFacetConfigs.ts +46 -0
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +11 -0
- package/UI/Components/TelemetryViewer/components/FacetSearchInput.tsx +79 -0
- package/UI/Components/TelemetryViewer/components/FacetSectionHeader.tsx +69 -0
- package/UI/Components/TelemetryViewer/components/FacetShowMoreButton.tsx +36 -0
- package/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.tsx +88 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +205 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +496 -0
- package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +30 -10
- package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +203 -10
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSection.tsx +60 -73
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +94 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +17 -2
- package/UI/Components/TelemetryViewer/types.ts +19 -0
- package/UI/Components/TelemetryViewer/useFacetSearchExemptions.ts +158 -0
- package/UI/Components/TelemetryViewer/useFacetSectionSearch.ts +102 -0
- package/UI/Utils/Clipboard.ts +68 -2
- package/UI/Utils/Navigation.ts +17 -2
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +620 -0
- package/UI/Utils/Telemetry/UseTelemetryEntityNames.ts +151 -0
- package/Utils/AI/InvestigationReport.ts +1789 -0
- package/Utils/API.ts +90 -1
- package/Utils/Rum/SessionReplayHealth.ts +11 -0
- package/Utils/Rum/SessionReplayRecordingEnded.ts +134 -0
- package/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.ts +427 -0
- package/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.ts +197 -0
- package/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.ts +464 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.ts +567 -0
- package/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.ts +299 -0
- package/Utils/SecurityEvent/Connectors/OktaNormalizer.ts +467 -0
- package/Utils/SecurityEvent/Connectors/SplunkNormalizer.ts +439 -0
- package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +124 -12
- package/Utils/Telemetry/CrossSignalScope.ts +22 -8
- package/Utils/Telemetry/EntityRelationship.ts +8 -0
- package/Utils/Telemetry/LockedFilterSearch.ts +412 -0
- package/Utils/Telemetry/NetworkHost.ts +43 -0
- package/Utils/Telemetry/OriginAllowList.ts +139 -4
- package/Utils/Traces/CriticalPath.ts +10 -4
- package/build/dist/Models/DatabaseModels/Index.js +4 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +490 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnection.js.map +1 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js +287 -0
- package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js +2 -2
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +336 -27
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +182 -7
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +1 -1
- package/build/dist/Server/API/SecurityEventConnectionAPI.js +171 -0
- package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -0
- package/build/dist/Server/API/TelemetryAPI.js +248 -170
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +57 -4
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +7 -16
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +8 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +4 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +22 -0
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +8 -17
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +4 -14
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventConnectionRunService.js +9 -0
- package/build/dist/Server/Services/SecurityEventConnectionRunService.js.map +1 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js +356 -0
- package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -0
- package/build/dist/Server/Services/TraceAggregationService.js +51 -25
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
- package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +14 -7
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js +468 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js +230 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +32 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +6 -2
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +59 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +5 -3
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js +752 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js +493 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +352 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js +405 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js +466 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js +344 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js +511 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js +406 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js +336 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js +474 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js +417 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js +314 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +719 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +404 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +209 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +40 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js +494 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js +379 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +27 -0
- package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +234 -61
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +537 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +1 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +572 -115
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +35 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +52 -0
- package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +521 -32
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +10 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +8 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js +80 -0
- package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +122 -67
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js +146 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +174 -248
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +492 -0
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js +259 -0
- package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry.js +11 -5
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/InvestigationEvidence.js +2 -0
- package/build/dist/Types/AI/InvestigationEvidence.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +11 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/Permission.js +2 -2
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +9 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplay.js +95 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js +18 -0
- package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +2 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +374 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +35 -0
- package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js +35 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js.map +1 -0
- package/build/dist/Types/Telemetry/EntityType.js +14 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js +59 -0
- package/build/dist/Types/Telemetry/ExceptionSpanScope.js.map +1 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js +16 -0
- package/build/dist/Types/Telemetry/LockedFilterDetail.js.map +1 -0
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js +16 -10
- package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +119 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -0
- package/build/dist/UI/Components/Card/Card.js +34 -17
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js +6 -4
- package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +63 -13
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +34 -0
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js +535 -0
- package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +117 -57
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +5 -7
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js +31 -44
- package/build/dist/UI/Components/LogsViewer/components/FacetSection.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +17 -3
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +19 -3
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +64 -18
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +100 -41
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +13 -5
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js +403 -0
- package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +197 -179
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +30 -21
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +12 -0
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js +46 -12
- package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelList/ModelList.js +26 -7
- package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
- package/build/dist/UI/Components/Page/ModelPage.js +62 -34
- package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +3 -1
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +8 -1
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +111 -0
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js +22 -0
- package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js +36 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js +21 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js +14 -0
- package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js +27 -0
- package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +88 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +228 -0
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +6 -6
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +111 -12
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js +27 -40
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +70 -10
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +17 -3
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/types.js +0 -4
- package/build/dist/UI/Components/TelemetryViewer/types.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js +70 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js.map +1 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js +52 -0
- package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js.map +1 -0
- package/build/dist/UI/Utils/Clipboard.js +59 -2
- package/build/dist/UI/Utils/Clipboard.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +11 -2
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +471 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js +113 -0
- package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js.map +1 -0
- package/build/dist/Utils/AI/InvestigationReport.js +1241 -0
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -0
- package/build/dist/Utils/API.js +25 -0
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayHealth.js +10 -0
- package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js +54 -0
- package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js +311 -0
- package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js +150 -0
- package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js +328 -0
- package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js +405 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js +212 -0
- package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js +351 -0
- package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js +348 -0
- package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js.map +1 -0
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +103 -10
- package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +16 -5
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +7 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js +277 -0
- package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js +39 -0
- package/build/dist/Utils/Telemetry/NetworkHost.js.map +1 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js +105 -4
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
- package/build/dist/Utils/Traces/CriticalPath.js +9 -4
- package/build/dist/Utils/Traces/CriticalPath.js.map +1 -1
- package/package.json +1 -1
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +0 -600
- package/UI/Components/GanttChart/Bar/BarLabel.tsx +0 -17
- package/UI/Components/GanttChart/Bar/Index.tsx +0 -149
- package/UI/Components/GanttChart/ChartContainer.tsx +0 -50
- package/UI/Components/GanttChart/Index.tsx +0 -90
- package/UI/Components/GanttChart/Row/Index.tsx +0 -22
- package/UI/Components/GanttChart/Row/Row.tsx +0 -231
- package/UI/Components/GanttChart/Row/RowLabel.tsx +0 -30
- package/UI/Components/GanttChart/Rows.tsx +0 -59
- package/UI/Components/GanttChart/Timeline/Index.tsx +0 -46
- package/UI/Components/GanttChart/Timeline/TimelineInterval.tsx +0 -33
- package/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.tsx +0 -43
- package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js +0 -8
- package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Bar/Index.js +0 -77
- package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +0 -33
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Index.js +0 -39
- package/build/dist/UI/Components/GanttChart/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Index.js +0 -7
- package/build/dist/UI/Components/GanttChart/Row/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/Row.js +0 -106
- package/build/dist/UI/Components/GanttChart/Row/Row.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js +0 -10
- package/build/dist/UI/Components/GanttChart/Row/RowLabel.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Rows.js +0 -19
- package/build/dist/UI/Components/GanttChart/Rows.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js +0 -16
- package/build/dist/UI/Components/GanttChart/Timeline/Index.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js.map +0 -1
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js +0 -13
- package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js.map +0 -1
|
@@ -18,10 +18,12 @@ import TableColumnType from "../../../Types/AnalyticsDatabase/TableColumnType";
|
|
|
18
18
|
import Includes from "../../../Types/BaseDatabase/Includes";
|
|
19
19
|
import OneUptimeDate from "../../../Types/Date";
|
|
20
20
|
import ChunkMath from "../../../Utils/Rum/ChunkMath";
|
|
21
|
+
import { hasSessionRecordingEnded, } from "../../../Utils/Rum/SessionReplayRecordingEnded";
|
|
21
22
|
import { MAX_SESSION_REPLAY_CHUNKS_PER_READ, MAX_SESSION_REPLAY_READ_BYTES, SESSION_REPLAY_LIST_SEARCH_MAX_LENGTH, SESSION_REPLAY_MAX_SESSION_MS, SESSION_REPLAY_MAX_TAG_KEYS, SESSION_REPLAY_RECORDER_CAPABILITIES, SessionReplaySealedReason, } from "../../../Types/Rum/SessionReplay";
|
|
22
23
|
import { SESSION_REPLAY_SORT_BY_VALUES, } from "../../../Types/Rum/SessionReplayApi";
|
|
23
24
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
24
25
|
import CaptureSpan from "../Telemetry/CaptureSpan";
|
|
26
|
+
import ServiceType from "../../../Types/Telemetry/ServiceType";
|
|
25
27
|
/*
|
|
26
28
|
* Bespoke ClickHouse reads for session-replay playback.
|
|
27
29
|
*
|
|
@@ -77,6 +79,14 @@ const READ_QUERY_SETTINGS = getQuerySettings({
|
|
|
77
79
|
/* Page sizes for the session list. */
|
|
78
80
|
export const DEFAULT_SESSION_REPLAY_LIST_LIMIT = 50;
|
|
79
81
|
export const MAX_SESSION_REPLAY_LIST_LIMIT = 200;
|
|
82
|
+
/*
|
|
83
|
+
* Audit tables resolve the opaque session ids on one page in a single
|
|
84
|
+
* ClickHouse read. Keep both the number of bound IN values and each value's
|
|
85
|
+
* size bounded; session ids are browser-minted 32-character hex strings, but
|
|
86
|
+
* older recorders and hand-written API callers may have stored another shape.
|
|
87
|
+
*/
|
|
88
|
+
export const MAX_SESSION_REPLAY_SUMMARIES_BATCH_SIZE = 200;
|
|
89
|
+
export const MAX_SESSION_REPLAY_SESSION_ID_LENGTH = 128;
|
|
80
90
|
/*
|
|
81
91
|
* Page sizes for the per-user rollup (listUsers). Same figures as the
|
|
82
92
|
* list, but the cost model differs: every page of the rollup
|
|
@@ -253,6 +263,29 @@ const HEADER_AGGREGATES = [
|
|
|
253
263
|
{ alias: "aggExpiresAt", expression: argMaxDate("retentionDate") },
|
|
254
264
|
{ alias: "aggTags", expression: argMaxColumn("tags") },
|
|
255
265
|
];
|
|
266
|
+
/*
|
|
267
|
+
* The narrow projection used by the audit-table summary lookup. Derive it
|
|
268
|
+
* from the list's aggregates so live duration and replacement-row handling
|
|
269
|
+
* cannot drift between the two reads.
|
|
270
|
+
*/
|
|
271
|
+
const SESSION_SUMMARY_AGGREGATE_ALIASES = [
|
|
272
|
+
"aggStartTime",
|
|
273
|
+
"aggDurationMs",
|
|
274
|
+
"aggEntryUrl",
|
|
275
|
+
"aggBrowserName",
|
|
276
|
+
"aggBrowserVersion",
|
|
277
|
+
"aggOsName",
|
|
278
|
+
"aggDeviceType",
|
|
279
|
+
];
|
|
280
|
+
const SESSION_SUMMARY_AGGREGATES = SESSION_SUMMARY_AGGREGATE_ALIASES.map((alias) => {
|
|
281
|
+
const column = HEADER_AGGREGATES.find((candidate) => {
|
|
282
|
+
return candidate.alias === alias;
|
|
283
|
+
});
|
|
284
|
+
if (!column) {
|
|
285
|
+
throw new Error(`HEADER_AGGREGATES has no column aliased ${alias}`);
|
|
286
|
+
}
|
|
287
|
+
return column;
|
|
288
|
+
});
|
|
256
289
|
/* Only the manifest needs these; the list never renders them. */
|
|
257
290
|
const HEADER_DETAIL_AGGREGATES = [
|
|
258
291
|
{ alias: "aggMaskingMode", expression: argMaxColumn("maskingMode") },
|
|
@@ -535,6 +568,75 @@ function readStringMap(row, key) {
|
|
|
535
568
|
function readDate(row, key) {
|
|
536
569
|
return new Date(readNumber(row, key));
|
|
537
570
|
}
|
|
571
|
+
/*
|
|
572
|
+
* A number that has to be MEASURED, not defaulted. readNumber answers 0 for
|
|
573
|
+
* a missing or garbled value, which is the right degradation for a counter
|
|
574
|
+
* on a table row but the wrong one for a clock the "has this tab ended?"
|
|
575
|
+
* rule compares: a missing last-chunk start read as 0 would sit before
|
|
576
|
+
* every final chunk and call a live tab ended. NaN instead, which the
|
|
577
|
+
* shared rule refuses outright.
|
|
578
|
+
*/
|
|
579
|
+
function readMeasuredNumber(row, key) {
|
|
580
|
+
const value = row[key];
|
|
581
|
+
if (typeof value === "number") {
|
|
582
|
+
return Number.isFinite(value) ? value : Number.NaN;
|
|
583
|
+
}
|
|
584
|
+
/* Number("") and Number(" ") are 0, which is exactly the default above. */
|
|
585
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
586
|
+
const parsed = Number(value);
|
|
587
|
+
return Number.isFinite(parsed) ? parsed : Number.NaN;
|
|
588
|
+
}
|
|
589
|
+
return Number.NaN;
|
|
590
|
+
}
|
|
591
|
+
/*
|
|
592
|
+
* The per-tab facts the shared rule in
|
|
593
|
+
* Common/Utils/Rum/SessionReplayRecordingEnded.ts is judged on, written
|
|
594
|
+
* exactly as that file documents them. The clocks and the version are
|
|
595
|
+
* wrapped in toFloat64 for the same reason as every wide column above:
|
|
596
|
+
* ClickHouse's JSON format quotes Int64 and UInt64 as strings. The chunk
|
|
597
|
+
* index is an Int32 and would come back as a number anyway; it is wrapped
|
|
598
|
+
* too so every fact in the group parses the same way. The aliases do not
|
|
599
|
+
* collide with a real column (see the NOTE on aliases at the top of this
|
|
600
|
+
* file).
|
|
601
|
+
*
|
|
602
|
+
* Two of the five are not about the tab's own clock:
|
|
603
|
+
*
|
|
604
|
+
* - tabMaxChunkIndex lets the rule call a tab that stored its last
|
|
605
|
+
* permitted chunk index ended. The ingest gate refuses everything past
|
|
606
|
+
* it, the recorder's own truncation seal included, so that tab never
|
|
607
|
+
* gets a final chunk and would otherwise read as "recording" until the
|
|
608
|
+
* idle finalizer.
|
|
609
|
+
* - tabLastChunkStoredAtUnixMs is max(version): the SERVER unix ms at
|
|
610
|
+
* which the tab's newest chunk row was written. The grace is measured
|
|
611
|
+
* on it, never on the device clock the chunk times come from.
|
|
612
|
+
*/
|
|
613
|
+
const TAB_HAS_FINAL_CHUNK_ALIAS = "tabHasFinalChunk";
|
|
614
|
+
const TAB_FINAL_CHUNK_END_ALIAS = "tabFinalChunkEndUnixMs";
|
|
615
|
+
const TAB_LAST_CHUNK_START_ALIAS = "tabLastChunkStartUnixMs";
|
|
616
|
+
const TAB_MAX_CHUNK_INDEX_ALIAS = "tabMaxChunkIndex";
|
|
617
|
+
const TAB_LAST_CHUNK_STORED_AT_ALIAS = "tabLastChunkStoredAtUnixMs";
|
|
618
|
+
const TAB_END_FACT_AGGREGATES = [
|
|
619
|
+
{
|
|
620
|
+
alias: TAB_HAS_FINAL_CHUNK_ALIAS,
|
|
621
|
+
expression: "max(toUInt8(isFinal))",
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
alias: TAB_FINAL_CHUNK_END_ALIAS,
|
|
625
|
+
expression: "toFloat64(toUnixTimestamp64Milli(maxIf(chunkEndTime, isFinal)))",
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
alias: TAB_LAST_CHUNK_START_ALIAS,
|
|
629
|
+
expression: "toFloat64(toUnixTimestamp64Milli(max(chunkStartTime)))",
|
|
630
|
+
},
|
|
631
|
+
{
|
|
632
|
+
alias: TAB_MAX_CHUNK_INDEX_ALIAS,
|
|
633
|
+
expression: "toFloat64(max(chunkIndex))",
|
|
634
|
+
},
|
|
635
|
+
{
|
|
636
|
+
alias: TAB_LAST_CHUNK_STORED_AT_ALIAS,
|
|
637
|
+
expression: "toFloat64(max(version))",
|
|
638
|
+
},
|
|
639
|
+
];
|
|
538
640
|
/*
|
|
539
641
|
* The capability list chunk 0 declared, filtered to the vocabulary this
|
|
540
642
|
* build knows so a stored typo never reaches the player as a capability.
|
|
@@ -576,6 +678,82 @@ export default class SessionReplayReadService {
|
|
|
576
678
|
static clearActivitySummaryCache() {
|
|
577
679
|
activitySummaryCache.clear();
|
|
578
680
|
}
|
|
681
|
+
/*
|
|
682
|
+
* Resolve the opaque ids stored on audit rows into compact session facts.
|
|
683
|
+
* This is intentionally one bespoke query instead of N getSessionHeader
|
|
684
|
+
* calls (or AnalyticsModelAPI, which RumSession does not expose). The
|
|
685
|
+
* project and application are both pinned before the caller-controlled IN
|
|
686
|
+
* list, and argMax collapses provisional/finalized ReplacingMergeTree rows.
|
|
687
|
+
*/
|
|
688
|
+
static async getSessionSummaries(request) {
|
|
689
|
+
if (request.sessionIds.length === 0) {
|
|
690
|
+
throw new BadDataException("sessionIds must contain at least one id");
|
|
691
|
+
}
|
|
692
|
+
if (request.sessionIds.length > MAX_SESSION_REPLAY_SUMMARIES_BATCH_SIZE) {
|
|
693
|
+
throw new BadDataException(`sessionIds must contain at most ${MAX_SESSION_REPLAY_SUMMARIES_BATCH_SIZE} ids`);
|
|
694
|
+
}
|
|
695
|
+
for (const sessionId of request.sessionIds) {
|
|
696
|
+
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
697
|
+
throw new BadDataException("Every sessionId must be a non-empty string");
|
|
698
|
+
}
|
|
699
|
+
if (sessionId.length > MAX_SESSION_REPLAY_SESSION_ID_LENGTH) {
|
|
700
|
+
throw new BadDataException(`Every sessionId must be at most ${MAX_SESSION_REPLAY_SESSION_ID_LENGTH} characters.`);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
/* Preserve first occurrence order while binding every id only once. */
|
|
704
|
+
const sessionIds = Array.from(new Set(request.sessionIds));
|
|
705
|
+
const statement = SQL `
|
|
706
|
+
SELECT
|
|
707
|
+
sessionId,
|
|
708
|
+
`;
|
|
709
|
+
statement.append(` ${toSelectList(SESSION_SUMMARY_AGGREGATES)}`);
|
|
710
|
+
statement.append(SQL `
|
|
711
|
+
FROM ${AnalyticsTableName.RumSession}
|
|
712
|
+
WHERE projectId = ${{
|
|
713
|
+
type: TableColumnType.ObjectID,
|
|
714
|
+
value: request.projectId,
|
|
715
|
+
}}
|
|
716
|
+
AND rumApplicationId = ${{
|
|
717
|
+
type: TableColumnType.ObjectID,
|
|
718
|
+
value: request.rumApplicationId,
|
|
719
|
+
}}
|
|
720
|
+
AND sessionId IN (${{
|
|
721
|
+
type: TableColumnType.Text,
|
|
722
|
+
value: new Includes(sessionIds),
|
|
723
|
+
}})
|
|
724
|
+
`);
|
|
725
|
+
statement.append(RETENTION_FILTER);
|
|
726
|
+
statement.append(" GROUP BY projectId, rumApplicationId, sessionId ORDER BY aggStartTime DESC");
|
|
727
|
+
statement.append(READ_QUERY_SETTINGS);
|
|
728
|
+
const dbResult = await RumSessionService.executeQuery(statement);
|
|
729
|
+
const response = await dbResult.json();
|
|
730
|
+
const requestedIds = new Set(sessionIds);
|
|
731
|
+
const summariesById = new Map();
|
|
732
|
+
for (const row of response.data || []) {
|
|
733
|
+
const sessionId = readString(row, "sessionId");
|
|
734
|
+
/* A malformed/unexpected driver row can never add data to the reply. */
|
|
735
|
+
if (!requestedIds.has(sessionId) || summariesById.has(sessionId)) {
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
const startTime = readDate(row, "aggStartTime");
|
|
739
|
+
summariesById.set(sessionId, {
|
|
740
|
+
sessionId: sessionId,
|
|
741
|
+
startTime: startTime,
|
|
742
|
+
startTimeUnixMs: startTime.getTime(),
|
|
743
|
+
durationMs: readNumber(row, "aggDurationMs"),
|
|
744
|
+
entryUrl: readString(row, "aggEntryUrl"),
|
|
745
|
+
browserName: readString(row, "aggBrowserName"),
|
|
746
|
+
browserVersion: readString(row, "aggBrowserVersion"),
|
|
747
|
+
osName: readString(row, "aggOsName"),
|
|
748
|
+
deviceType: readString(row, "aggDeviceType"),
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
/* Stable request order makes consumers deterministic; missing ids omit. */
|
|
752
|
+
return sessionIds.flatMap((sessionId) => {
|
|
753
|
+
const summary = summariesById.get(sessionId);
|
|
754
|
+
return summary ? [summary] : [];
|
|
755
|
+
});
|
|
756
|
+
}
|
|
579
757
|
/*
|
|
580
758
|
* Session list.
|
|
581
759
|
*
|
|
@@ -596,6 +774,7 @@ export default class SessionReplayReadService {
|
|
|
596
774
|
* the truth - or, worse, would drop the group entirely.
|
|
597
775
|
*/
|
|
598
776
|
static async listSessions(request) {
|
|
777
|
+
var _a;
|
|
599
778
|
const limit = Math.max(1, Math.min(request.limit, MAX_SESSION_REPLAY_LIST_LIMIT));
|
|
600
779
|
const sortBy = request.sortBy || "startTime";
|
|
601
780
|
if (!SESSION_REPLAY_SORT_BY_VALUES.includes(sortBy)) {
|
|
@@ -740,6 +919,8 @@ export default class SessionReplayReadService {
|
|
|
740
919
|
tags: readStringMap(row, "aggTags"),
|
|
741
920
|
startTimeUnixMs: startTime.getTime(),
|
|
742
921
|
endTimeUnixMs: endTime.getTime(),
|
|
922
|
+
/* Judged below, only for the page's unfinalized sessions. */
|
|
923
|
+
hasRecordingEnded: false,
|
|
743
924
|
};
|
|
744
925
|
if (request.includeIdentifiedUserLabel) {
|
|
745
926
|
item.identifiedUserLabel = readString(row, "aggIdentifiedUserLabel");
|
|
@@ -747,6 +928,40 @@ export default class SessionReplayReadService {
|
|
|
747
928
|
}
|
|
748
929
|
return item;
|
|
749
930
|
});
|
|
931
|
+
/*
|
|
932
|
+
* "Recording now" or "recording ended"? The header cannot say: a
|
|
933
|
+
* provisional header stays unfinalized for the whole idle window
|
|
934
|
+
* after its last tab closed, which is how a closed tab kept its
|
|
935
|
+
* "Recording now" badge for 10-15 minutes. The chunk rows can, so the
|
|
936
|
+
* page's unfinalized sessions - and only those - get ONE follow-up
|
|
937
|
+
* read over the chunk table. A page of finalized sessions (the
|
|
938
|
+
* overwhelming majority of any list older than a few minutes) runs
|
|
939
|
+
* no second query at all.
|
|
940
|
+
*
|
|
941
|
+
* It is a separate statement rather than a JOIN on the list query
|
|
942
|
+
* because the list's own read is a range over the HEADER table's sort
|
|
943
|
+
* key, and joining the chunk table there would aggregate chunk rows
|
|
944
|
+
* for every session in the window before the LIMIT picked a page.
|
|
945
|
+
*/
|
|
946
|
+
const unfinalizedSessionIds = sessions
|
|
947
|
+
.filter((session) => {
|
|
948
|
+
return !session.isFinalized;
|
|
949
|
+
})
|
|
950
|
+
.map((session) => {
|
|
951
|
+
return session.sessionId;
|
|
952
|
+
});
|
|
953
|
+
if (unfinalizedSessionIds.length > 0) {
|
|
954
|
+
const endedSessionIds = await SessionReplayReadService.readRecordingEndedSessionIds({
|
|
955
|
+
projectId: request.projectId,
|
|
956
|
+
rumApplicationId: request.rumApplicationId,
|
|
957
|
+
sessionIds: unfinalizedSessionIds,
|
|
958
|
+
nowUnixMs: (_a = request.nowUnixMs) !== null && _a !== void 0 ? _a : Date.now(),
|
|
959
|
+
});
|
|
960
|
+
for (const session of sessions) {
|
|
961
|
+
session.hasRecordingEnded =
|
|
962
|
+
!session.isFinalized && endedSessionIds.has(session.sessionId);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
750
965
|
const lastSession = sessions[sessions.length - 1];
|
|
751
966
|
return {
|
|
752
967
|
sessions: sessions,
|
|
@@ -1051,6 +1266,12 @@ export default class SessionReplayReadService {
|
|
|
1051
1266
|
recorderCapabilities: readRecorderCapabilities(row),
|
|
1052
1267
|
identifiedUserKey: readString(row, "aggIdentifiedUserKey"),
|
|
1053
1268
|
visitorId: readString(row, "aggVisitorId"),
|
|
1269
|
+
/*
|
|
1270
|
+
* Not judged here: see SessionReplaySessionHeader.hasRecordingEnded.
|
|
1271
|
+
* getManifest, the read that returns this header to the Dashboard,
|
|
1272
|
+
* replaces it for an unfinalized session.
|
|
1273
|
+
*/
|
|
1274
|
+
hasRecordingEnded: false,
|
|
1054
1275
|
};
|
|
1055
1276
|
}
|
|
1056
1277
|
/*
|
|
@@ -1153,6 +1374,7 @@ export default class SessionReplayReadService {
|
|
|
1153
1374
|
* megabytes of decompressed recording.
|
|
1154
1375
|
*/
|
|
1155
1376
|
static async getManifest(data) {
|
|
1377
|
+
var _a;
|
|
1156
1378
|
/*
|
|
1157
1379
|
* LIMIT 1 BY (tabId, chunkIndex) after ORDER BY ... version DESC
|
|
1158
1380
|
* keeps exactly the highest-version row per chunk. tabId is part of
|
|
@@ -1205,7 +1427,34 @@ export default class SessionReplayReadService {
|
|
|
1205
1427
|
value: MAX_MANIFEST_ROWS,
|
|
1206
1428
|
}}`);
|
|
1207
1429
|
statement.append(READ_QUERY_SETTINGS);
|
|
1208
|
-
|
|
1430
|
+
/*
|
|
1431
|
+
* Whether this unfinalized session's recording is already over, read
|
|
1432
|
+
* alongside the manifest rather than after it: the player re-fetches
|
|
1433
|
+
* the manifest every 30s while a session is not finalized, and this
|
|
1434
|
+
* is what lets it stop calling a closed session "Live" once the
|
|
1435
|
+
* ended grace has passed, instead of waiting for a finalizer run to
|
|
1436
|
+
* seal the header. The same helper, the same grace and the same
|
|
1437
|
+
* clock the list uses, so the list badge and the player pill can
|
|
1438
|
+
* never disagree about one session.
|
|
1439
|
+
*
|
|
1440
|
+
* Its own grouped read rather than a fold over the rows below: those
|
|
1441
|
+
* rows are capped at MAX_MANIFEST_ROWS in (tabId, chunkIndex) order, so
|
|
1442
|
+
* a truncated manifest would lose a tab's newest chunks - exactly the
|
|
1443
|
+
* rows that say whether it kept recording after its final chunk. A
|
|
1444
|
+
* finalized header is authoritative and runs no second read. The
|
|
1445
|
+
* helper never rejects (a failure answers "not ended"), so it cannot
|
|
1446
|
+
* fail the manifest. The manifest statement is issued first.
|
|
1447
|
+
*/
|
|
1448
|
+
const manifestResultPromise = RumSessionChunkService.executeQuery(statement);
|
|
1449
|
+
const endedSessionIdsPromise = data.header.isFinalized
|
|
1450
|
+
? Promise.resolve(new Set())
|
|
1451
|
+
: SessionReplayReadService.readRecordingEndedSessionIds({
|
|
1452
|
+
projectId: data.projectId,
|
|
1453
|
+
rumApplicationId: data.rumApplicationId,
|
|
1454
|
+
sessionIds: [data.sessionId],
|
|
1455
|
+
nowUnixMs: (_a = data.nowUnixMs) !== null && _a !== void 0 ? _a : Date.now(),
|
|
1456
|
+
});
|
|
1457
|
+
const [dbResult, endedSessionIds] = await Promise.all([manifestResultPromise, endedSessionIdsPromise]);
|
|
1209
1458
|
const response = await dbResult.json();
|
|
1210
1459
|
const rows = response.data || [];
|
|
1211
1460
|
const tabsById = new Map();
|
|
@@ -1287,6 +1536,7 @@ export default class SessionReplayReadService {
|
|
|
1287
1536
|
liveDurationMs: liveDurationMs,
|
|
1288
1537
|
liveEventCount: liveEventCount,
|
|
1289
1538
|
liveMaxChunkIndex: liveMaxChunkIndex,
|
|
1539
|
+
hasRecordingEnded: endedSessionIds.has(data.sessionId),
|
|
1290
1540
|
}),
|
|
1291
1541
|
tabs: tabs,
|
|
1292
1542
|
isChunkIndexTruncated: rows.length >= MAX_MANIFEST_ROWS,
|
|
@@ -1297,14 +1547,143 @@ export default class SessionReplayReadService {
|
|
|
1297
1547
|
* 0 and eventCount 0 while its chunk rows say otherwise; the manifest
|
|
1298
1548
|
* has just read every chunk row, so it reports what the rows prove. A
|
|
1299
1549
|
* finalized header is authoritative and returned untouched.
|
|
1550
|
+
*
|
|
1551
|
+
* hasRecordingEnded is set on every unfinalized header, including one
|
|
1552
|
+
* whose chunk rows have not landed yet: getSessionHeader never judges
|
|
1553
|
+
* it, so the manifest is the only place the field is ever true.
|
|
1300
1554
|
*/
|
|
1301
1555
|
static reconcileLiveHeader(data) {
|
|
1302
|
-
if (data.header.isFinalized
|
|
1556
|
+
if (data.header.isFinalized) {
|
|
1303
1557
|
return data.header;
|
|
1304
1558
|
}
|
|
1559
|
+
if (data.chunkRowCount === 0) {
|
|
1560
|
+
return Object.assign(Object.assign({}, data.header), { hasRecordingEnded: data.hasRecordingEnded });
|
|
1561
|
+
}
|
|
1305
1562
|
const durationMs = Math.max(data.header.durationMs, data.liveDurationMs);
|
|
1306
1563
|
const endTimeUnixMs = Math.max(data.header.endTimeUnixMs, data.header.startTimeUnixMs + durationMs);
|
|
1307
|
-
return Object.assign(Object.assign({}, data.header), { durationMs: durationMs, endTime: new Date(endTimeUnixMs), endTimeUnixMs: endTimeUnixMs, chunkCount: Math.max(data.header.chunkCount, data.chunkRowCount), eventCount: Math.max(data.header.eventCount, data.liveEventCount), maxChunkIndex: Math.max(data.header.maxChunkIndex, data.liveMaxChunkIndex) });
|
|
1564
|
+
return Object.assign(Object.assign({}, data.header), { durationMs: durationMs, endTime: new Date(endTimeUnixMs), endTimeUnixMs: endTimeUnixMs, chunkCount: Math.max(data.header.chunkCount, data.chunkRowCount), eventCount: Math.max(data.header.eventCount, data.liveEventCount), maxChunkIndex: Math.max(data.header.maxChunkIndex, data.liveMaxChunkIndex), hasRecordingEnded: data.hasRecordingEnded });
|
|
1565
|
+
}
|
|
1566
|
+
/*
|
|
1567
|
+
* Which of these unfinalized sessions have stopped recording, judged by
|
|
1568
|
+
* the shared rule (Common/Utils/Rum/SessionReplayRecordingEnded.ts) over
|
|
1569
|
+
* their chunk rows. The one helper behind both the list badge and the
|
|
1570
|
+
* player's Live pill.
|
|
1571
|
+
*
|
|
1572
|
+
* One statement for any number of sessions:
|
|
1573
|
+
*
|
|
1574
|
+
* WHERE projectId = ? AND sessionId IN (...) AND rumApplicationId = ?
|
|
1575
|
+
* GROUP BY sessionId, tabId
|
|
1576
|
+
*
|
|
1577
|
+
* A KEY-RANGE READ. RumSessionChunk is sorted (and primary-keyed) by
|
|
1578
|
+
* (projectId, sessionId, tabId, chunkIndex), so projectId plus a
|
|
1579
|
+
* sessionId IN list is a prefix of the primary index: ClickHouse reads
|
|
1580
|
+
* only the granules of the named sessions - a handful of narrow columns
|
|
1581
|
+
* over at most a few hundred rows each - and never the payload column.
|
|
1582
|
+
* The GROUP BY follows the same key order. rumApplicationId is a plain
|
|
1583
|
+
* column filtered over those granules, and it is not optional: the
|
|
1584
|
+
* table's replace key has no application in it, so two applications
|
|
1585
|
+
* that share a browser-minted sessionId share one key space, and
|
|
1586
|
+
* without the pin one application's closed tab could end another's
|
|
1587
|
+
* recording.
|
|
1588
|
+
*
|
|
1589
|
+
* Grouped per tab, never per session, because the rule is per tab: a
|
|
1590
|
+
* session shared by several tabs (or several page loads of a multi-page
|
|
1591
|
+
* app) is over only when every one of them is. The five aggregates are
|
|
1592
|
+
* maxima, so a redelivered chunk's duplicate row - or a pinned copy -
|
|
1593
|
+
* cannot make a live tab look ended and no LIMIT 1 BY is needed. Such a
|
|
1594
|
+
* row can carry a NEWER version than the original, which only restarts
|
|
1595
|
+
* the grace once; it never shortens it. The retention filter is kept
|
|
1596
|
+
* like on every other replay read.
|
|
1597
|
+
*
|
|
1598
|
+
* The grace. Every tab having ended is not enough on its own: in a
|
|
1599
|
+
* multi-page app, page A's final chunk lands while page B - a new tab id
|
|
1600
|
+
* under the same session - has not stored its first chunk yet, and for
|
|
1601
|
+
* that moment the only tab the rows know about has ended. So the rule
|
|
1602
|
+
* also wants the newest stored chunk of the session to be at least
|
|
1603
|
+
* SESSION_REPLAY_ENDED_FINALIZE_GRACE_MS older than nowUnixMs, the same
|
|
1604
|
+
* grace the finalizer waits on, measured on the same server clock (the
|
|
1605
|
+
* rows' version against this process's Date.now()). The list, the player
|
|
1606
|
+
* and the finalizer therefore call a session ended at the same moment,
|
|
1607
|
+
* give or take the finalizer's one-minute schedule, and none of them
|
|
1608
|
+
* depends on Redis for it.
|
|
1609
|
+
*
|
|
1610
|
+
* Best-effort. A failure logs a warning and answers "nothing has ended",
|
|
1611
|
+
* which is what the Dashboard showed before this existed; neither the
|
|
1612
|
+
* list nor the manifest may fail because of it. A session with no chunk
|
|
1613
|
+
* rows has no tabs, and no tabs is "not known", never "ended".
|
|
1614
|
+
*/
|
|
1615
|
+
static async readRecordingEndedSessionIds(data) {
|
|
1616
|
+
const endedSessionIds = new Set();
|
|
1617
|
+
const sessionIds = Array.from(new Set(data.sessionIds.filter((sessionId) => {
|
|
1618
|
+
return sessionId.length > 0;
|
|
1619
|
+
})));
|
|
1620
|
+
if (sessionIds.length === 0) {
|
|
1621
|
+
return endedSessionIds;
|
|
1622
|
+
}
|
|
1623
|
+
const statement = SQL `
|
|
1624
|
+
SELECT
|
|
1625
|
+
sessionId,
|
|
1626
|
+
tabId,
|
|
1627
|
+
`;
|
|
1628
|
+
statement.append(` ${toSelectList(TAB_END_FACT_AGGREGATES)}`);
|
|
1629
|
+
statement.append(SQL `
|
|
1630
|
+
FROM ${AnalyticsTableName.RumSessionChunk}
|
|
1631
|
+
WHERE projectId = ${{
|
|
1632
|
+
type: TableColumnType.ObjectID,
|
|
1633
|
+
value: data.projectId,
|
|
1634
|
+
}}
|
|
1635
|
+
AND sessionId IN (${{
|
|
1636
|
+
type: TableColumnType.Text,
|
|
1637
|
+
value: new Includes(sessionIds),
|
|
1638
|
+
}})
|
|
1639
|
+
AND rumApplicationId = ${{
|
|
1640
|
+
type: TableColumnType.ObjectID,
|
|
1641
|
+
value: data.rumApplicationId,
|
|
1642
|
+
}}
|
|
1643
|
+
`);
|
|
1644
|
+
statement.append(RETENTION_FILTER);
|
|
1645
|
+
statement.append(" GROUP BY sessionId, tabId");
|
|
1646
|
+
statement.append(READ_QUERY_SETTINGS);
|
|
1647
|
+
let rows;
|
|
1648
|
+
try {
|
|
1649
|
+
const dbResult = await RumSessionChunkService.executeQuery(statement);
|
|
1650
|
+
const response = await dbResult.json();
|
|
1651
|
+
rows = response.data || [];
|
|
1652
|
+
}
|
|
1653
|
+
catch (err) {
|
|
1654
|
+
logger.warn("SessionReplayReadService: could not read chunk rows to tell whether unfinalized sessions have ended; reporting them as still recording");
|
|
1655
|
+
logger.warn(err);
|
|
1656
|
+
return endedSessionIds;
|
|
1657
|
+
}
|
|
1658
|
+
const requested = new Set(sessionIds);
|
|
1659
|
+
const tabsBySessionId = new Map();
|
|
1660
|
+
for (const row of rows) {
|
|
1661
|
+
const sessionId = readString(row, "sessionId");
|
|
1662
|
+
/* Defensive: a row for a session nobody asked about decides nothing. */
|
|
1663
|
+
if (!requested.has(sessionId)) {
|
|
1664
|
+
continue;
|
|
1665
|
+
}
|
|
1666
|
+
const tab = {
|
|
1667
|
+
hasFinalChunk: readBoolean(row, TAB_HAS_FINAL_CHUNK_ALIAS),
|
|
1668
|
+
finalChunkEndUnixMs: readMeasuredNumber(row, TAB_FINAL_CHUNK_END_ALIAS),
|
|
1669
|
+
lastChunkStartUnixMs: readMeasuredNumber(row, TAB_LAST_CHUNK_START_ALIAS),
|
|
1670
|
+
maxChunkIndex: readMeasuredNumber(row, TAB_MAX_CHUNK_INDEX_ALIAS),
|
|
1671
|
+
lastChunkStoredAtUnixMs: readMeasuredNumber(row, TAB_LAST_CHUNK_STORED_AT_ALIAS),
|
|
1672
|
+
};
|
|
1673
|
+
const existing = tabsBySessionId.get(sessionId);
|
|
1674
|
+
if (existing) {
|
|
1675
|
+
existing.push(tab);
|
|
1676
|
+
}
|
|
1677
|
+
else {
|
|
1678
|
+
tabsBySessionId.set(sessionId, [tab]);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
for (const [sessionId, tabs] of tabsBySessionId) {
|
|
1682
|
+
if (hasSessionRecordingEnded(tabs, data.nowUnixMs)) {
|
|
1683
|
+
endedSessionIds.add(sessionId);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
return endedSessionIds;
|
|
1308
1687
|
}
|
|
1309
1688
|
/*
|
|
1310
1689
|
* The payload read. The only query in the system that names the
|
|
@@ -1451,11 +1830,22 @@ export default class SessionReplayReadService {
|
|
|
1451
1830
|
* fingerprint present only on a superseded row does not produce a false
|
|
1452
1831
|
* positive.
|
|
1453
1832
|
*
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
1833
|
+
* Typed RUM and fully unscoped legacy lookups are windowed in WHERE for
|
|
1834
|
+
* partition pruning. Scoped non-RUM and ID-only type-unknown lookups apply
|
|
1835
|
+
* the window in QUALIFY: their instance-proven session ids must first be
|
|
1836
|
+
* checked across every retained application in the project so a duplicate
|
|
1837
|
+
* id cannot be hidden outside the caller's time or authorization scope.
|
|
1457
1838
|
*/
|
|
1458
1839
|
static async getSessionsForException(data) {
|
|
1840
|
+
const hasPrimaryEntityId = data.primaryEntityId !== undefined;
|
|
1841
|
+
const hasPrimaryEntityType = data.primaryEntityType !== undefined;
|
|
1842
|
+
if (!hasPrimaryEntityId && hasPrimaryEntityType) {
|
|
1843
|
+
throw new BadDataException("primaryEntityId is required with its type");
|
|
1844
|
+
}
|
|
1845
|
+
if (data.primaryEntityType !== undefined &&
|
|
1846
|
+
!Object.values(ServiceType).includes(data.primaryEntityType)) {
|
|
1847
|
+
throw new BadDataException("primaryEntityType is not valid");
|
|
1848
|
+
}
|
|
1459
1849
|
if (data.accessibleRumApplicationIds &&
|
|
1460
1850
|
data.accessibleRumApplicationIds.length === 0) {
|
|
1461
1851
|
return [];
|
|
@@ -1467,10 +1857,23 @@ export default class SessionReplayReadService {
|
|
|
1467
1857
|
const instanceSessionIds = await SessionReplayReadService.getSessionIdsForExceptionInstances({
|
|
1468
1858
|
projectId: data.projectId,
|
|
1469
1859
|
exceptionFingerprint: data.exceptionFingerprint,
|
|
1860
|
+
primaryEntityId: data.primaryEntityId,
|
|
1861
|
+
primaryEntityType: data.primaryEntityType,
|
|
1470
1862
|
startTime: startTime,
|
|
1471
1863
|
endTime: endTime,
|
|
1472
1864
|
sessionId: data.sessionId,
|
|
1473
1865
|
});
|
|
1866
|
+
const isScopedRumException = data.primaryEntityType === ServiceType.RealUserMonitor;
|
|
1867
|
+
const isScopedNonRumOrUnknownException = hasPrimaryEntityId && !isScopedRumException;
|
|
1868
|
+
/*
|
|
1869
|
+
* A finalized replay header has only a flat fingerprint list. For a
|
|
1870
|
+
* non-RUM or legacy type-unknown entity that list cannot prove ownership,
|
|
1871
|
+
* so only the scoped instance side index may admit a session. Failure or
|
|
1872
|
+
* an empty lookup must therefore fail closed.
|
|
1873
|
+
*/
|
|
1874
|
+
if (isScopedNonRumOrUnknownException && instanceSessionIds.length === 0) {
|
|
1875
|
+
return [];
|
|
1876
|
+
}
|
|
1474
1877
|
const selectList = toSelectList([
|
|
1475
1878
|
{ alias: "aggStartTime", expression: argMaxDateTime("startTime") },
|
|
1476
1879
|
{ alias: "aggEndTime", expression: argMaxDateTime("endTime") },
|
|
@@ -1517,6 +1920,10 @@ export default class SessionReplayReadService {
|
|
|
1517
1920
|
toString(rumApplicationId) AS applicationId,
|
|
1518
1921
|
`;
|
|
1519
1922
|
statement.append(` ${selectList}`);
|
|
1923
|
+
if (isScopedNonRumOrUnknownException) {
|
|
1924
|
+
/* One grouped row per application makes this a cross-app collision count. */
|
|
1925
|
+
statement.append(", count() OVER (PARTITION BY sessionId) AS matchedApplicationCount");
|
|
1926
|
+
}
|
|
1520
1927
|
statement.append(SQL `
|
|
1521
1928
|
FROM ${AnalyticsTableName.RumSession}
|
|
1522
1929
|
WHERE projectId = ${{
|
|
@@ -1524,19 +1931,26 @@ export default class SessionReplayReadService {
|
|
|
1524
1931
|
value: data.projectId,
|
|
1525
1932
|
}}
|
|
1526
1933
|
`);
|
|
1527
|
-
|
|
1934
|
+
/*
|
|
1935
|
+
* For non-RUM and legacy type-unknown exceptions, authorization belongs
|
|
1936
|
+
* in QUALIFY after the window has counted inaccessible applications too.
|
|
1937
|
+
* Applying it here would make an ambiguous id appear unique.
|
|
1938
|
+
*/
|
|
1939
|
+
if (!isScopedNonRumOrUnknownException && data.accessibleRumApplicationIds) {
|
|
1528
1940
|
statement.append(SQL ` AND rumApplicationId IN (${{
|
|
1529
1941
|
type: TableColumnType.ObjectID,
|
|
1530
1942
|
value: new Includes(data.accessibleRumApplicationIds),
|
|
1531
1943
|
}})`);
|
|
1532
1944
|
}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1945
|
+
if (!isScopedNonRumOrUnknownException) {
|
|
1946
|
+
statement.append(SQL ` AND startTime >= ${{
|
|
1947
|
+
type: TableColumnType.DateTime64,
|
|
1948
|
+
value: startTime,
|
|
1949
|
+
}} AND startTime <= ${{
|
|
1950
|
+
type: TableColumnType.DateTime64,
|
|
1951
|
+
value: endTime,
|
|
1952
|
+
}}`);
|
|
1953
|
+
}
|
|
1540
1954
|
statement.append(RETENTION_FILTER);
|
|
1541
1955
|
if (data.sessionId) {
|
|
1542
1956
|
statement.append(SQL ` AND sessionId = ${{
|
|
@@ -1544,29 +1958,69 @@ export default class SessionReplayReadService {
|
|
|
1544
1958
|
value: data.sessionId,
|
|
1545
1959
|
}}`);
|
|
1546
1960
|
}
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1961
|
+
if (isScopedRumException && data.primaryEntityId) {
|
|
1962
|
+
/* Both finalized fingerprints and instance-proven ids stay in this RUM app. */
|
|
1963
|
+
statement.append(SQL ` AND rumApplicationId = ${{
|
|
1964
|
+
type: TableColumnType.ObjectID,
|
|
1965
|
+
value: data.primaryEntityId,
|
|
1966
|
+
}}`);
|
|
1967
|
+
}
|
|
1968
|
+
statement.append(" AND (");
|
|
1969
|
+
if (isScopedNonRumOrUnknownException) {
|
|
1970
|
+
statement.append(SQL `sessionId IN (${{
|
|
1553
1971
|
type: TableColumnType.Text,
|
|
1554
1972
|
value: new Includes(instanceSessionIds),
|
|
1555
1973
|
}})`);
|
|
1556
1974
|
}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
}
|
|
1563
|
-
if (instanceSessionIds.length > 0) {
|
|
1975
|
+
else {
|
|
1976
|
+
statement.append(SQL `hasAny(exceptionFingerprints, [${{
|
|
1977
|
+
type: TableColumnType.Text,
|
|
1978
|
+
value: data.exceptionFingerprint,
|
|
1979
|
+
}}])`);
|
|
1980
|
+
}
|
|
1981
|
+
if (!isScopedNonRumOrUnknownException && instanceSessionIds.length > 0) {
|
|
1564
1982
|
statement.append(SQL ` OR sessionId IN (${{
|
|
1565
1983
|
type: TableColumnType.Text,
|
|
1566
1984
|
value: new Includes(instanceSessionIds),
|
|
1567
1985
|
}})`);
|
|
1568
1986
|
}
|
|
1569
1987
|
statement.append(")");
|
|
1988
|
+
statement.append(" GROUP BY projectId, rumApplicationId, sessionId");
|
|
1989
|
+
if (isScopedNonRumOrUnknownException) {
|
|
1990
|
+
/*
|
|
1991
|
+
* Windowing happens over every application before either the time
|
|
1992
|
+
* window or accessible-app filter is applied. QUALIFY also precedes
|
|
1993
|
+
* ORDER/LIMIT, so a second application can never be sorted away.
|
|
1994
|
+
*/
|
|
1995
|
+
statement.append(" QUALIFY matchedApplicationCount = 1");
|
|
1996
|
+
statement.append(SQL ` AND aggStartTime >= ${{
|
|
1997
|
+
type: TableColumnType.BigNumber,
|
|
1998
|
+
value: startTime.getTime(),
|
|
1999
|
+
}} AND aggStartTime <= ${{
|
|
2000
|
+
type: TableColumnType.BigNumber,
|
|
2001
|
+
value: endTime.getTime(),
|
|
2002
|
+
}}`);
|
|
2003
|
+
if (data.accessibleRumApplicationIds) {
|
|
2004
|
+
statement.append(SQL ` AND rumApplicationId IN (${{
|
|
2005
|
+
type: TableColumnType.ObjectID,
|
|
2006
|
+
value: new Includes(data.accessibleRumApplicationIds),
|
|
2007
|
+
}})`);
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
else {
|
|
2011
|
+
statement.append(" HAVING (");
|
|
2012
|
+
statement.append(SQL `hasAny(aggExceptionFingerprints, [${{
|
|
2013
|
+
type: TableColumnType.Text,
|
|
2014
|
+
value: data.exceptionFingerprint,
|
|
2015
|
+
}}])`);
|
|
2016
|
+
if (instanceSessionIds.length > 0) {
|
|
2017
|
+
statement.append(SQL ` OR sessionId IN (${{
|
|
2018
|
+
type: TableColumnType.Text,
|
|
2019
|
+
value: new Includes(instanceSessionIds),
|
|
2020
|
+
}})`);
|
|
2021
|
+
}
|
|
2022
|
+
statement.append(")");
|
|
2023
|
+
}
|
|
1570
2024
|
statement.append(SQL ` ORDER BY aggStartTime DESC
|
|
1571
2025
|
LIMIT ${{
|
|
1572
2026
|
type: TableColumnType.Number,
|
|
@@ -1575,7 +2029,16 @@ export default class SessionReplayReadService {
|
|
|
1575
2029
|
statement.append(READ_QUERY_SETTINGS);
|
|
1576
2030
|
const dbResult = await RumSessionService.executeQuery(statement);
|
|
1577
2031
|
const response = await dbResult.json();
|
|
1578
|
-
|
|
2032
|
+
const responseRows = (response.data || []).filter((row) => {
|
|
2033
|
+
/*
|
|
2034
|
+
* QUALIFY is authoritative. Its count was computed over every app
|
|
2035
|
+
* before ORDER/LIMIT, so retaining only count=1 is also a fail-closed
|
|
2036
|
+
* guard if a changed driver ever returns a row that should not survive.
|
|
2037
|
+
*/
|
|
2038
|
+
return (!isScopedNonRumOrUnknownException ||
|
|
2039
|
+
readNumber(row, "matchedApplicationCount") === 1);
|
|
2040
|
+
});
|
|
2041
|
+
return responseRows.map((row) => {
|
|
1579
2042
|
return {
|
|
1580
2043
|
sessionId: readString(row, "sessionId"),
|
|
1581
2044
|
rumApplicationId: readString(row, "applicationId"),
|
|
@@ -1604,9 +2067,10 @@ export default class SessionReplayReadService {
|
|
|
1604
2067
|
* session, so a session that started inside the window threw inside
|
|
1605
2068
|
* [startTime, endTime + max session length].
|
|
1606
2069
|
*
|
|
1607
|
-
* Best-effort
|
|
1608
|
-
* a failure
|
|
1609
|
-
*
|
|
2070
|
+
* Best-effort for fully unscoped legacy and typed RUM lookups: there it only
|
|
2071
|
+
* ADDS live sessions, so a failure degrades to finalized headers. Scoped
|
|
2072
|
+
* non-RUM and ID-only lookups rely on it as their sole entity-ownership
|
|
2073
|
+
* proof and therefore fail closed.
|
|
1610
2074
|
*
|
|
1611
2075
|
* A caller-pinned sessionId narrows the lookup rather than bypassing it,
|
|
1612
2076
|
* so the pin can never assert that a session threw something the
|
|
@@ -1634,6 +2098,25 @@ export default class SessionReplayReadService {
|
|
|
1634
2098
|
value: new Date(data.endTime.getTime() + SESSION_REPLAY_MAX_SESSION_MS),
|
|
1635
2099
|
}}
|
|
1636
2100
|
`;
|
|
2101
|
+
if (data.primaryEntityId) {
|
|
2102
|
+
statement.append(SQL ` AND primaryEntityId = ${{
|
|
2103
|
+
type: TableColumnType.ObjectID,
|
|
2104
|
+
value: data.primaryEntityId,
|
|
2105
|
+
}}`);
|
|
2106
|
+
}
|
|
2107
|
+
if (data.primaryEntityType === ServiceType.OpenTelemetry) {
|
|
2108
|
+
/* NULL/empty is the historical discriminator for an OTel service. */
|
|
2109
|
+
statement.append(SQL ` AND (ifNull(primaryEntityType, '') = '' OR primaryEntityType = ${{
|
|
2110
|
+
type: TableColumnType.Text,
|
|
2111
|
+
value: ServiceType.OpenTelemetry,
|
|
2112
|
+
}})`);
|
|
2113
|
+
}
|
|
2114
|
+
else if (data.primaryEntityType) {
|
|
2115
|
+
statement.append(SQL ` AND primaryEntityType = ${{
|
|
2116
|
+
type: TableColumnType.Text,
|
|
2117
|
+
value: data.primaryEntityType,
|
|
2118
|
+
}}`);
|
|
2119
|
+
}
|
|
1637
2120
|
/*
|
|
1638
2121
|
* A pinned sessionId narrows this lookup; it does NOT replace it.
|
|
1639
2122
|
*
|
|
@@ -1674,7 +2157,7 @@ export default class SessionReplayReadService {
|
|
|
1674
2157
|
});
|
|
1675
2158
|
}
|
|
1676
2159
|
catch (err) {
|
|
1677
|
-
logger.warn("SessionReplayReadService: could not look up exception instances by session;
|
|
2160
|
+
logger.warn("SessionReplayReadService: could not look up exception instances by session; scoped non-RUM lookups fail closed and other lookups answer from finalized headers only");
|
|
1678
2161
|
logger.warn(err);
|
|
1679
2162
|
return [];
|
|
1680
2163
|
}
|
|
@@ -2073,6 +2556,12 @@ export default class SessionReplayReadService {
|
|
|
2073
2556
|
statement.append(")");
|
|
2074
2557
|
}
|
|
2075
2558
|
}
|
|
2559
|
+
__decorate([
|
|
2560
|
+
CaptureSpan(),
|
|
2561
|
+
__metadata("design:type", Function),
|
|
2562
|
+
__metadata("design:paramtypes", [Object]),
|
|
2563
|
+
__metadata("design:returntype", Promise)
|
|
2564
|
+
], SessionReplayReadService, "getSessionSummaries", null);
|
|
2076
2565
|
__decorate([
|
|
2077
2566
|
CaptureSpan(),
|
|
2078
2567
|
__metadata("design:type", Function),
|