@oneuptime/common 12.0.3 → 12.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/AIRun.ts +38 -1
- package/Models/DatabaseModels/AlertFeed.ts +30 -0
- package/Models/DatabaseModels/CephCluster.ts +14 -0
- package/Models/DatabaseModels/CodeRepository.ts +14 -6
- package/Models/DatabaseModels/Dashboard.ts +28 -0
- package/Models/DatabaseModels/DockerHost.ts +14 -0
- package/Models/DatabaseModels/GlobalOidcProject.ts +18 -0
- package/Models/DatabaseModels/GlobalSsoProject.ts +18 -0
- package/Models/DatabaseModels/Incident.ts +2 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentFeed.ts +30 -0
- package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IoTFleet.ts +14 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +14 -0
- package/Models/DatabaseModels/LogSavedView.ts +33 -0
- package/Models/DatabaseModels/NetworkDevice.ts +14 -0
- package/Models/DatabaseModels/NetworkInterface.ts +18 -0
- package/Models/DatabaseModels/Project.ts +247 -11
- package/Models/DatabaseModels/ProxmoxCluster.ts +14 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +4 -4
- package/Models/DatabaseModels/Service.ts +30 -0
- package/Models/DatabaseModels/StatusPage.ts +28 -0
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
- package/Models/DatabaseModels/StatusPagePrivateUser.ts +30 -0
- package/Models/DatabaseModels/User.ts +30 -0
- package/Server/API/AIAgentDataAPI.ts +75 -55
- package/Server/API/AIInvestigationAPI.ts +175 -17
- package/Server/API/DashboardAPI.ts +429 -22
- package/Server/API/GitHubAPI.ts +119 -283
- package/Server/API/StatusPageAPI.ts +38 -19
- package/Server/API/UserAPI.ts +263 -1
- package/Server/EnvironmentConfig.ts +23 -3
- package/Server/Infrastructure/ClickhouseConfig.ts +15 -1
- package/Server/Infrastructure/ClickhouseDatabase.ts +1 -1
- package/Server/Infrastructure/GlobalCache.ts +37 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.ts +21 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.ts +68 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +100 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.ts +89 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.ts +27 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +214 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.ts +69 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
- package/Server/Services/AIRunService.ts +78 -10
- package/Server/Services/AIService.ts +94 -22
- package/Server/Services/AlertFeedService.ts +5 -0
- package/Server/Services/AnalyticsDatabaseService.ts +101 -1
- package/Server/Services/CodeRepositoryService.ts +105 -2
- package/Server/Services/DatabaseService.ts +227 -3
- package/Server/Services/IncidentFeedService.ts +5 -0
- package/Server/Services/LlmLogService.ts +46 -2
- package/Server/Services/OpenTelemetryIngestService.ts +230 -26
- package/Server/Services/UserService.ts +184 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +6 -0
- package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +4 -0
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +8 -5
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +90 -16
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +2 -0
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +2 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +223 -22
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/ConfidenceSignal.ts +182 -71
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +252 -43
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +25 -24
- package/Server/Utils/AI/SRE/InstrumentationTaskTrigger.ts +47 -13
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +9 -5
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +141 -24
- package/Server/Utils/AI/SRE/InvestigationSubjectLock.ts +66 -0
- package/Server/Utils/AI/SRE/PostedRootCause.ts +94 -3
- package/Server/Utils/AI/SRE/README.md +1 -1
- package/Server/Utils/AI/SRE/SubjectCodeFixRun.ts +132 -10
- package/Server/Utils/AI/Toolbox/CodeTools.ts +45 -4
- package/Server/Utils/AnalyticsDatabase/ClusterConfig.ts +24 -0
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +13 -0
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +157 -4
- package/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.ts +130 -0
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +29 -0
- package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +56 -0
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +46 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
- package/Server/Utils/PasswordHash.ts +330 -0
- package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +251 -0
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +747 -0
- package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +480 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1184 -0
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +500 -0
- package/Tests/App/Dashboard/OverviewCustomFields.test.tsx +333 -0
- package/Tests/App/Dashboard/PortMonitorCriteriaFilter.test.ts +93 -0
- package/Tests/App/Dashboard/UserCustomFields.test.tsx +392 -0
- package/Tests/App/StatusPage/PublicStatusPageAPIErrorHandling.test.ts +117 -0
- package/Tests/App/StatusPage/StatusPageModelAPIPolymorphism.test.ts +223 -0
- package/Tests/Models/DatabaseModels/PermissionCatalogueCoverage.test.ts +243 -0
- package/Tests/Server/API/AIAgentDataFixFromIncidentContext.test.ts +266 -0
- package/Tests/Server/API/AIAgentDataRepositoryToken.test.ts +381 -0
- package/Tests/Server/API/AIInvestigationAPI.test.ts +594 -0
- package/Tests/Server/API/AIInvestigationCreateFixTask.test.ts +80 -0
- package/Tests/Server/API/DashboardMasterPasswordAPI.test.ts +172 -1
- package/Tests/Server/API/DashboardPublicAttributeValuesAPI.test.ts +943 -0
- package/Tests/Server/API/DashboardPublicMetricsAggregateAPI.test.ts +1296 -0
- package/Tests/Server/API/DashboardPublicTemplatePayloads.test.ts +598 -0
- package/Tests/Server/API/GitHubAppInstallationBindingAPI.test.ts +539 -0
- package/Tests/Server/API/Helpers.ts +6 -1
- package/Tests/Server/API/StatusPageMasterPasswordAPI.test.ts +335 -0
- package/Tests/Server/API/UserProjectsAPI.test.ts +852 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +128 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +215 -0
- package/Tests/Server/Services/AIRunCodeFixClaim.test.ts +59 -5
- package/Tests/Server/Services/AIRunHumanVerdict.test.ts +127 -58
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +396 -20
- package/Tests/Server/Services/AddMasterPasswordSaltMigration.test.ts +283 -0
- package/Tests/Server/Services/AddPerUserPasswordSaltMigration.test.ts +178 -0
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +582 -0
- package/Tests/Server/Services/AnalyticsDatabaseService.test.ts +30 -1
- package/Tests/Server/Services/CodeRepositoryInstallationBinding.test.ts +305 -0
- package/Tests/Server/Services/CodeRepositoryResolutionBinding.test.ts +147 -0
- package/Tests/Server/Services/DatabaseServicePerUserPasswordSalt.test.ts +880 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsWithoutHooks.test.ts +54 -0
- package/Tests/Server/Services/FeedAIRunAssociation.test.ts +125 -0
- package/Tests/Server/Services/FixFromIncidentTaskTrigger.test.ts +418 -57
- package/Tests/Server/Services/InstrumentationTaskTrigger.test.ts +173 -14
- package/Tests/Server/Services/MasterPasswordScrypt.test.ts +567 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +568 -0
- package/Tests/Server/Services/RestoreDroppedUniqueIndexesMigration.test.ts +386 -0
- package/Tests/Server/Services/RestoreServiceLowerNameIndexMigration.test.ts +240 -0
- package/Tests/Server/Services/SeparateIncidentAlertAiSettingsMigration.test.ts +194 -0
- package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +885 -0
- package/Tests/Server/Services/WidenHashedStringColumnsForScryptMigration.test.ts +220 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +37 -4
- package/Tests/Server/Utils/AI/AIConfidenceSignal.test.ts +330 -29
- package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +25 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +293 -5
- package/Tests/Server/Utils/AI/CodeFixAgentCompletion.test.ts +59 -1
- package/Tests/Server/Utils/AI/CodeTools.test.ts +47 -1
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +10 -0
- package/Tests/Server/Utils/AI/FixFromIncidentAutoTrigger.test.ts +342 -19
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +214 -30
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationGrader.test.ts +65 -17
- package/Tests/Server/Utils/AI/InvestigationQueueRemediationExecution.test.ts +3 -0
- package/Tests/Server/Utils/AI/InvestigationSettlement.test.ts +313 -20
- package/Tests/Server/Utils/AI/PostedRootCause.test.ts +254 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +4 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +2 -0
- package/Tests/Server/Utils/AI/SubjectCodeFixRunDedupe.test.ts +44 -0
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterAwareSchema.test.ts +30 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +120 -0
- package/Tests/Server/Utils/CodeRepository/GitHubInstallationBinding.test.ts +292 -0
- package/Tests/Server/Utils/GitHubInstallationOwnershipVerification.test.ts +340 -0
- package/Tests/Server/Utils/GitHubWebhookAndTreeCacheIsolation.test.ts +250 -0
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +212 -0
- package/Tests/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.test.ts +401 -0
- package/Tests/Server/Utils/Monitor/MonitorMetricUtilPortTimings.test.ts +243 -0
- package/Tests/Server/Utils/PasswordHash.test.ts +585 -0
- package/Tests/Types/Dashboard/DashboardTemplates.test.ts +111 -0
- package/Tests/Types/Database/ColumnLength.test.ts +7 -1
- package/Tests/Types/HashedStringPerUserSalt.test.ts +476 -0
- package/Tests/Types/Monitor/CephMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/CriteriaFilter.test.ts +4 -0
- package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +293 -0
- package/Tests/Types/Monitor/DockerMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/DockerSwarmMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/HostAlertTemplates.test.ts +249 -0
- package/Tests/Types/Monitor/HostMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/IotAlertTemplates.test.ts +320 -0
- package/Tests/Types/Monitor/IotMetricCatalog.test.ts +104 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +118 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +42 -0
- package/Tests/Types/Monitor/MonitorStep.test.ts +38 -0
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +75 -0
- package/Tests/Types/Monitor/PodmanAlertTemplates.test.ts +271 -0
- package/Tests/Types/Monitor/PodmanMetricCatalog.test.ts +109 -0
- package/Tests/Types/Monitor/ProxmoxMetricCatalog.test.ts +107 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVendorTemplate.test.ts +151 -0
- package/Tests/Types/Permission.test.ts +137 -0
- package/Tests/Types/Rum/SessionReplayMaskingMode.test.ts +101 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +5 -5
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +3 -5
- package/Tests/UI/Components/CustomFields/CustomFieldsDetail.test.tsx +696 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +158 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +74 -0
- package/Tests/UI/Components/MoreMenu.test.tsx +756 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +62 -0
- package/Tests/UI/Monitor/PortMonitorView.test.tsx +237 -0
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +91 -0
- package/Tests/UI/Utils/DownloadFile.test.ts +103 -0
- package/Tests/UI/Utils/ErrorSupportBundle.test.ts +582 -0
- package/Tests/UI/Utils/Project.test.ts +31 -0
- package/Tests/UI/Utils/StatusPageModelAPIInjection.test.ts +245 -0
- package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +820 -0
- package/Tests/UI/Utils/UserProjectsModelAPI.test.ts +714 -0
- package/Tests/Utils/Dashboard/DashboardViewConfig.test.ts +329 -0
- package/Tests/Utils/Dashboard/GridLayout.test.ts +951 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +117 -0
- package/Tests/Utils/RecordingRuleExpression.test.ts +327 -0
- package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +186 -0
- package/Tests/Utils/StatusPage/GroupTree.test.ts +456 -0
- package/Tests/Utils/StatusPage/OverviewGroupHierarchyVisibility.test.ts +588 -0
- package/Tests/Utils/TeamMembersByProject.test.ts +655 -0
- package/Tests/Utils/Telemetry/SavedViewTimeRange.test.ts +244 -0
- package/Tests/Utils/Telemetry/TelemetryQueryTimeRange.test.ts +825 -0
- package/Types/AI/AIRunCodeFixRecommendation.ts +17 -0
- package/Types/AI/CodeFixTaskContext.ts +63 -3
- package/Types/AI/CodeFixTaskType.ts +3 -3
- package/Types/Database/ColumnLength.ts +9 -1
- package/Types/Database/TableColumn.ts +11 -0
- package/Types/Database/UnsynchronizedIndex.ts +48 -0
- package/Types/HashedString.ts +140 -4
- package/Types/Monitor/CriteriaFilter.ts +4 -0
- package/Types/Monitor/DomainMonitor/DomainLookupMethod.ts +23 -0
- package/Types/Monitor/DomainMonitor/DomainMonitorResponse.ts +7 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +24 -7
- package/Types/Monitor/MonitorMetricType.ts +8 -0
- package/Types/Monitor/MonitorStep.ts +10 -1
- package/Types/Monitor/MonitorStepDomainMonitor.ts +21 -0
- package/Types/Monitor/PortMonitor/PortMonitorTimings.ts +10 -0
- package/Types/Permission.ts +23 -175
- package/Types/Probe/ProbeMonitorResponse.ts +6 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +2 -3
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +85 -11
- package/UI/Components/ErrorBoundary.tsx +138 -11
- package/UI/Components/Feed/FeedItem.tsx +9 -2
- package/UI/Components/ModelDetail/CardModelDetail.tsx +0 -12
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +12 -2
- package/UI/Components/MoreMenu/MoreMenu.tsx +285 -97
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +8 -5
- package/UI/Components/Navbar/NavBar.tsx +12 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +19 -7
- package/UI/Utils/DownloadFile.ts +16 -8
- package/UI/Utils/ErrorSupportBundle.ts +805 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +19 -8
- package/UI/Utils/ModelAPI/UserProjectsModelAPI.ts +257 -0
- package/UI/Utils/Project.ts +4 -0
- package/UI/Utils/StatusPage.ts +8 -2
- package/UI/Utils/UseDashboardGridDnd.ts +917 -0
- package/Utils/Dashboard/DashboardViewConfig.ts +80 -36
- package/Utils/Dashboard/GridLayout.ts +523 -0
- package/Utils/Metrics/RecordingRuleExpression.ts +19 -17
- package/Utils/Monitor/MonitorMetricType.ts +44 -2
- package/Utils/StatusPage/GroupNestingLayout.ts +69 -0
- package/Utils/StatusPage/GroupTree.ts +157 -66
- package/Utils/StatusPage/ResourceUptime.ts +37 -2
- package/Utils/TeamMembersByProject.ts +237 -0
- package/Utils/Telemetry/SavedViewTimeRange.ts +114 -0
- package/Utils/Telemetry/TelemetryQueryTimeRange.ts +334 -0
- package/build/dist/Models/DatabaseModels/AIRun.js +39 -1
- package/build/dist/Models/DatabaseModels/AIRun.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +14 -6
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Dashboard.js +29 -0
- package/build/dist/Models/DatabaseModels/Dashboard.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +16 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +16 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +16 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js +2 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentFeed.js +32 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js +16 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogSavedView.js +33 -0
- package/build/dist/Models/DatabaseModels/LogSavedView.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +16 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkInterface.js +16 -1
- package/build/dist/Models/DatabaseModels/NetworkInterface.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +257 -13
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +16 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +4 -4
- package/build/dist/Models/DatabaseModels/Service.js +28 -1
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +29 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +32 -0
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +32 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +49 -48
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +111 -11
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +312 -15
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GitHubAPI.js +94 -167
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +29 -11
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +187 -2
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +21 -3
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js +12 -1
- package/build/dist/Server/Infrastructure/ClickhouseConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js +1 -1
- package/build/dist/Server/Infrastructure/ClickhouseDatabase.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +29 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786018109307-AddPerUserPasswordSalt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.js +59 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786023262402-WidenHashedStringColumnsForScrypt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786096660558-AddTimeRangeToLogSavedView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +93 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786101798351-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786105470826-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.js +101 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.js +66 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786300000000-QuarantineUnboundGitHubInstallations.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786400000000-AddMasterPasswordSalt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786500000000-AddInvestigationCodeFixRecommendation.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +58 -12
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +74 -21
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertFeedService.js +3 -0
- package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +86 -2
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/CodeRepositoryService.js +90 -2
- package/build/dist/Server/Services/CodeRepositoryService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +180 -3
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFeedService.js +3 -0
- package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
- package/build/dist/Server/Services/LlmLogService.js +22 -1
- package/build/dist/Server/Services/LlmLogService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +155 -25
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +165 -0
- package/build/dist/Server/Services/UserService.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/CodeFix/CodeFixAgentCompletion.js +4 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +8 -5
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +63 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +2 -0
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +156 -28
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js +128 -49
- package/build/dist/Server/Utils/AI/SRE/ConfidenceSignal.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js +170 -31
- package/build/dist/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +21 -19
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js +33 -9
- package/build/dist/Server/Utils/AI/SRE/InstrumentationTaskTrigger.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +9 -5
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +121 -41
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js +46 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationSubjectLock.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js +61 -14
- package/build/dist/Server/Utils/AI/SRE/PostedRootCause.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js +79 -1
- package/build/dist/Server/Utils/AI/SRE/SubjectCodeFixRun.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js +31 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js +21 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/ClusterConfig.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +13 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +126 -4
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.js +136 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubInstallationBinding.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +20 -3
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +43 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/PasswordHash.js +258 -0
- package/build/dist/Server/Utils/PasswordHash.js.map +1 -0
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js +18 -0
- package/build/dist/Types/AI/AIRunCodeFixRecommendation.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js +23 -3
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskType.js +3 -3
- package/build/dist/Types/Database/ColumnLength.js +9 -1
- package/build/dist/Types/Database/ColumnLength.js.map +1 -1
- package/build/dist/Types/Database/TableColumn.js.map +1 -1
- package/build/dist/Types/Database/UnsynchronizedIndex.js +46 -0
- package/build/dist/Types/Database/UnsynchronizedIndex.js.map +1 -0
- package/build/dist/Types/HashedString.js +96 -5
- package/build/dist/Types/HashedString.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +4 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js +24 -0
- package/build/dist/Types/Monitor/DomainMonitor/DomainLookupMethod.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +24 -7
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +7 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +6 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +15 -0
- package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js +2 -0
- package/build/dist/Types/Monitor/PortMonitor/PortMonitorTimings.js.map +1 -0
- package/build/dist/Types/Permission.js +23 -155
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +2 -5
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +51 -10
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +67 -8
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +2 -2
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +0 -12
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +12 -2
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +193 -65
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +3 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +19 -7
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Utils/DownloadFile.js +15 -8
- package/build/dist/UI/Utils/DownloadFile.js.map +1 -1
- package/build/dist/UI/Utils/ErrorSupportBundle.js +476 -0
- package/build/dist/UI/Utils/ErrorSupportBundle.js.map +1 -0
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -8
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/UserProjectsModelAPI.js +156 -0
- package/build/dist/UI/Utils/ModelAPI/UserProjectsModelAPI.js.map +1 -0
- package/build/dist/UI/Utils/Project.js +3 -0
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/UI/Utils/StatusPage.js +4 -4
- package/build/dist/UI/Utils/StatusPage.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js +551 -0
- package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js +42 -26
- package/build/dist/Utils/Dashboard/DashboardViewConfig.js.map +1 -1
- package/build/dist/Utils/Dashboard/GridLayout.js +338 -0
- package/build/dist/Utils/Dashboard/GridLayout.js.map +1 -0
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js +19 -17
- package/build/dist/Utils/Metrics/RecordingRuleExpression.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +38 -6
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js +46 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -1
- package/build/dist/Utils/StatusPage/GroupTree.js +79 -34
- package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js +22 -1
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/TeamMembersByProject.js +145 -0
- package/build/dist/Utils/TeamMembersByProject.js.map +1 -0
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js +79 -0
- package/build/dist/Utils/Telemetry/SavedViewTimeRange.js.map +1 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js +236 -0
- package/build/dist/Utils/Telemetry/TelemetryQueryTimeRange.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
import ExceptionInstance from "../../../Models/AnalyticsModels/ExceptionInstance";
|
|
2
|
+
import Log from "../../../Models/AnalyticsModels/Log";
|
|
3
|
+
import Span from "../../../Models/AnalyticsModels/Span";
|
|
4
|
+
import InBetween from "../../../Types/BaseDatabase/InBetween";
|
|
5
|
+
import Includes from "../../../Types/BaseDatabase/Includes";
|
|
6
|
+
import Query from "../../../Types/BaseDatabase/Query";
|
|
7
|
+
import Search from "../../../Types/BaseDatabase/Search";
|
|
8
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
9
|
+
import JSONFunctions from "../../../Types/JSONFunctions";
|
|
10
|
+
import LogSeverity from "../../../Types/Log/LogSeverity";
|
|
11
|
+
import MetricViewData from "../../../Types/Metrics/MetricViewData";
|
|
12
|
+
import { MonitorStepExceptionMonitorUtil } from "../../../Types/Monitor/MonitorStepExceptionMonitor";
|
|
13
|
+
import { MonitorStepLogMonitorUtil } from "../../../Types/Monitor/MonitorStepLogMonitor";
|
|
14
|
+
import { MonitorStepTraceMonitorUtil } from "../../../Types/Monitor/MonitorStepTraceMonitor";
|
|
15
|
+
import { TelemetryQuery } from "../../../Types/Telemetry/TelemetryQuery";
|
|
16
|
+
import TelemetryType from "../../../Types/Telemetry/TelemetryType";
|
|
17
|
+
import RangeStartAndEndDateTime, {
|
|
18
|
+
RangeStartAndEndDateTimeUtil,
|
|
19
|
+
} from "../../../Types/Time/RangeStartAndEndDateTime";
|
|
20
|
+
import TimeRange from "../../../Types/Time/TimeRange";
|
|
21
|
+
import TelemetryQueryTimeRange from "../../../Utils/Telemetry/TelemetryQueryTimeRange";
|
|
22
|
+
import { describe, expect, test } from "@jest/globals";
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* When a telemetry monitor opens an incident it stamps the window it just
|
|
26
|
+
* evaluated over onto the query it stores on the row. The incident page is
|
|
27
|
+
* supposed to render that exact window — "the logs at the moment this fired" —
|
|
28
|
+
* but the logs viewer was substituting a rolling "past 1 hour" over it, so an
|
|
29
|
+
* incident from last Tuesday showed the last hour of unrelated traffic under
|
|
30
|
+
* the heading "Logs for this incident".
|
|
31
|
+
*
|
|
32
|
+
* The root cause that let it go unnoticed for so long is in these tests'
|
|
33
|
+
* crosshairs: the window survives storage by VALUE but not by TYPE. It is
|
|
34
|
+
* persisted through JSON.stringify, which calls InBetween.toJSON() and then
|
|
35
|
+
* flattens each Date bound to an ISO string; InBetween.fromJSON hands those
|
|
36
|
+
* strings straight to the constructor. So a restored window is a real
|
|
37
|
+
* InBetween whose `startValue` is a `string`, even though the type says Date —
|
|
38
|
+
* and every consumer guarding on `instanceof Date` silently did nothing.
|
|
39
|
+
*
|
|
40
|
+
* These tests pin both halves: the coercion itself, and the full
|
|
41
|
+
* monitor -> store -> load round trip that produces the awkward shape.
|
|
42
|
+
*/
|
|
43
|
+
describe("TelemetryQueryTimeRange", () => {
|
|
44
|
+
const START_ISO: string = "2026-08-04T10:00:00.000Z";
|
|
45
|
+
const END_ISO: string = "2026-08-04T10:01:00.000Z";
|
|
46
|
+
const START_DATE: Date = new Date(START_ISO);
|
|
47
|
+
const END_DATE: Date = new Date(END_ISO);
|
|
48
|
+
|
|
49
|
+
describe("toDateWindow", () => {
|
|
50
|
+
test("returns Date bounds unchanged when they are already Dates", () => {
|
|
51
|
+
const window: InBetween<Date> | null =
|
|
52
|
+
TelemetryQueryTimeRange.toDateWindow(
|
|
53
|
+
new InBetween<Date>(START_DATE, END_DATE),
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(window).not.toBeNull();
|
|
57
|
+
expect(window!.startValue).toBeInstanceOf(Date);
|
|
58
|
+
expect(window!.startValue.getTime()).toBe(START_DATE.getTime());
|
|
59
|
+
expect(window!.endValue.getTime()).toBe(END_DATE.getTime());
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("hands back the same instance when nothing needs coercing", () => {
|
|
63
|
+
/*
|
|
64
|
+
* Identity is the signal callers use to decide whether anything changed;
|
|
65
|
+
* an equal-but-fresh object would churn React state on every load.
|
|
66
|
+
*/
|
|
67
|
+
const already: InBetween<Date> = new InBetween<Date>(
|
|
68
|
+
START_DATE,
|
|
69
|
+
END_DATE,
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
expect(TelemetryQueryTimeRange.toDateWindow(already)).toBe(already);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test("coerces ISO string bounds back to Dates — the shape storage actually returns", () => {
|
|
76
|
+
/*
|
|
77
|
+
* This is the exact value InBetween.fromJSON produces for a stored
|
|
78
|
+
* window: the right class, the wrong bound type.
|
|
79
|
+
*/
|
|
80
|
+
const restored: InBetween<Date> = new InBetween<Date>(
|
|
81
|
+
START_ISO as unknown as Date,
|
|
82
|
+
END_ISO as unknown as Date,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
expect(restored.startValue).not.toBeInstanceOf(Date);
|
|
86
|
+
|
|
87
|
+
const window: InBetween<Date> | null =
|
|
88
|
+
TelemetryQueryTimeRange.toDateWindow(restored);
|
|
89
|
+
|
|
90
|
+
expect(window!.startValue).toBeInstanceOf(Date);
|
|
91
|
+
expect(window!.endValue).toBeInstanceOf(Date);
|
|
92
|
+
expect(window!.startValue.toISOString()).toBe(START_ISO);
|
|
93
|
+
expect(window!.endValue.toISOString()).toBe(END_ISO);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("coerces epoch-number bounds", () => {
|
|
97
|
+
const window: InBetween<Date> | null =
|
|
98
|
+
TelemetryQueryTimeRange.toDateWindow(
|
|
99
|
+
new InBetween<Date>(
|
|
100
|
+
START_DATE.getTime() as unknown as Date,
|
|
101
|
+
END_DATE.getTime() as unknown as Date,
|
|
102
|
+
),
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
expect(window!.startValue.getTime()).toBe(START_DATE.getTime());
|
|
106
|
+
expect(window!.endValue.getTime()).toBe(END_DATE.getTime());
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test("accepts the plain tagged object, for callers that skipped deserialize", () => {
|
|
110
|
+
const window: InBetween<Date> | null =
|
|
111
|
+
TelemetryQueryTimeRange.toDateWindow({
|
|
112
|
+
_type: "InBetween",
|
|
113
|
+
startValue: START_ISO,
|
|
114
|
+
endValue: END_ISO,
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
expect(window!.startValue.getTime()).toBe(START_DATE.getTime());
|
|
118
|
+
expect(window!.endValue.getTime()).toBe(END_DATE.getTime());
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("returns null for absent, non-object and untagged values", () => {
|
|
122
|
+
expect(TelemetryQueryTimeRange.toDateWindow(null)).toBeNull();
|
|
123
|
+
expect(TelemetryQueryTimeRange.toDateWindow(undefined)).toBeNull();
|
|
124
|
+
expect(TelemetryQueryTimeRange.toDateWindow(START_ISO)).toBeNull();
|
|
125
|
+
expect(TelemetryQueryTimeRange.toDateWindow(12345)).toBeNull();
|
|
126
|
+
expect(
|
|
127
|
+
TelemetryQueryTimeRange.toDateWindow({
|
|
128
|
+
startValue: START_ISO,
|
|
129
|
+
endValue: END_ISO,
|
|
130
|
+
}),
|
|
131
|
+
).toBeNull();
|
|
132
|
+
// A different operator must not be mistaken for a window.
|
|
133
|
+
expect(
|
|
134
|
+
TelemetryQueryTimeRange.toDateWindow(new Search("boom")),
|
|
135
|
+
).toBeNull();
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test("returns null when either bound is unparseable, rather than an Invalid Date", () => {
|
|
139
|
+
expect(
|
|
140
|
+
TelemetryQueryTimeRange.toDateWindow(
|
|
141
|
+
new InBetween<Date>("not-a-date" as unknown as Date, END_DATE),
|
|
142
|
+
),
|
|
143
|
+
).toBeNull();
|
|
144
|
+
expect(
|
|
145
|
+
TelemetryQueryTimeRange.toDateWindow(
|
|
146
|
+
new InBetween<Date>(START_DATE, "" as unknown as Date),
|
|
147
|
+
),
|
|
148
|
+
).toBeNull();
|
|
149
|
+
expect(
|
|
150
|
+
TelemetryQueryTimeRange.toDateWindow(
|
|
151
|
+
new InBetween<Date>(
|
|
152
|
+
START_DATE,
|
|
153
|
+
new Date("nonsense") as unknown as Date,
|
|
154
|
+
),
|
|
155
|
+
),
|
|
156
|
+
).toBeNull();
|
|
157
|
+
expect(
|
|
158
|
+
TelemetryQueryTimeRange.toDateWindow({
|
|
159
|
+
_type: "InBetween",
|
|
160
|
+
startValue: null,
|
|
161
|
+
endValue: END_ISO,
|
|
162
|
+
}),
|
|
163
|
+
).toBeNull();
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("preserves an inverted window instead of falling back", () => {
|
|
167
|
+
/*
|
|
168
|
+
* A start after the end is a server-side bug. Rendering it makes that
|
|
169
|
+
* visible; quietly reverting to a rolling default would reintroduce the
|
|
170
|
+
* exact failure this whole helper exists to stop — unrelated data shown
|
|
171
|
+
* under an incident's heading with nothing to indicate it.
|
|
172
|
+
*/
|
|
173
|
+
const window: InBetween<Date> | null =
|
|
174
|
+
TelemetryQueryTimeRange.toDateWindow(
|
|
175
|
+
new InBetween<Date>(END_DATE, START_DATE),
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
expect(window!.startValue.getTime()).toBe(END_DATE.getTime());
|
|
179
|
+
expect(window!.endValue.getTime()).toBe(START_DATE.getTime());
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe("getWindowFieldName", () => {
|
|
184
|
+
test("maps each telemetry type to the field its monitor stamps", () => {
|
|
185
|
+
expect(
|
|
186
|
+
TelemetryQueryTimeRange.getWindowFieldName(TelemetryType.Log),
|
|
187
|
+
).toBe("time");
|
|
188
|
+
expect(
|
|
189
|
+
TelemetryQueryTimeRange.getWindowFieldName(TelemetryType.Exception),
|
|
190
|
+
).toBe("time");
|
|
191
|
+
expect(
|
|
192
|
+
TelemetryQueryTimeRange.getWindowFieldName(TelemetryType.Trace),
|
|
193
|
+
).toBe("startTime");
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("returns null for types that carry no query window", () => {
|
|
197
|
+
expect(
|
|
198
|
+
TelemetryQueryTimeRange.getWindowFieldName(TelemetryType.Metric),
|
|
199
|
+
).toBeNull();
|
|
200
|
+
expect(
|
|
201
|
+
TelemetryQueryTimeRange.getWindowFieldName(TelemetryType.Profile),
|
|
202
|
+
).toBeNull();
|
|
203
|
+
expect(TelemetryQueryTimeRange.getWindowFieldName(undefined)).toBeNull();
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
describe("getQueryWindow", () => {
|
|
208
|
+
test("reads the field named by the telemetry type", () => {
|
|
209
|
+
const spanQuery: JSONObject = {
|
|
210
|
+
startTime: new InBetween<Date>(START_DATE, END_DATE),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
expect(
|
|
214
|
+
TelemetryQueryTimeRange.getQueryWindow(
|
|
215
|
+
spanQuery,
|
|
216
|
+
TelemetryType.Trace,
|
|
217
|
+
)!.startValue.getTime(),
|
|
218
|
+
).toBe(START_DATE.getTime());
|
|
219
|
+
|
|
220
|
+
// Spans keep theirs on startTime, so looking for `time` must find nothing.
|
|
221
|
+
expect(
|
|
222
|
+
TelemetryQueryTimeRange.getQueryWindow(spanQuery, TelemetryType.Log),
|
|
223
|
+
).toBeNull();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
test("tries both known fields when the type is unknown", () => {
|
|
227
|
+
expect(
|
|
228
|
+
TelemetryQueryTimeRange.getQueryWindow({
|
|
229
|
+
time: new InBetween<Date>(START_DATE, END_DATE),
|
|
230
|
+
}),
|
|
231
|
+
).not.toBeNull();
|
|
232
|
+
|
|
233
|
+
expect(
|
|
234
|
+
TelemetryQueryTimeRange.getQueryWindow({
|
|
235
|
+
startTime: new InBetween<Date>(START_DATE, END_DATE),
|
|
236
|
+
}),
|
|
237
|
+
).not.toBeNull();
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
test("returns null for an empty or absent query, and for a query with no window", () => {
|
|
241
|
+
expect(TelemetryQueryTimeRange.getQueryWindow(null)).toBeNull();
|
|
242
|
+
expect(TelemetryQueryTimeRange.getQueryWindow(undefined)).toBeNull();
|
|
243
|
+
expect(TelemetryQueryTimeRange.getQueryWindow({})).toBeNull();
|
|
244
|
+
expect(
|
|
245
|
+
TelemetryQueryTimeRange.getQueryWindow({
|
|
246
|
+
body: new Search("boom"),
|
|
247
|
+
severityText: new Includes([LogSeverity.Error]),
|
|
248
|
+
}),
|
|
249
|
+
).toBeNull();
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
describe("round trip from a real monitor evaluation", () => {
|
|
254
|
+
/*
|
|
255
|
+
* The regression that matters. These walk the actual production path —
|
|
256
|
+
* build the query the way the worker does, persist it the way the worker
|
|
257
|
+
* does, restore it the way the page does — instead of hand-writing a
|
|
258
|
+
* fixture of what that is assumed to look like. A hand-written fixture is
|
|
259
|
+
* how the previous attempt at covering this drifted into asserting
|
|
260
|
+
* nothing.
|
|
261
|
+
*/
|
|
262
|
+
type StoreAndRestoreFunction = (query: JSONObject) => JSONObject;
|
|
263
|
+
|
|
264
|
+
const storeAndRestore: StoreAndRestoreFunction = (
|
|
265
|
+
query: JSONObject,
|
|
266
|
+
): JSONObject => {
|
|
267
|
+
// Exactly what the worker writes, then what the client reads back.
|
|
268
|
+
const stored: JSONObject = JSONFunctions.anyObjectToJSONObject(query);
|
|
269
|
+
|
|
270
|
+
return JSONFunctions.deserialize(stored);
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
test("log monitor: the stored window is flat ISO strings, and is recovered as Dates", () => {
|
|
274
|
+
const query: Query<Log> = MonitorStepLogMonitorUtil.toQuery({
|
|
275
|
+
...MonitorStepLogMonitorUtil.getDefault(),
|
|
276
|
+
body: "boom",
|
|
277
|
+
lastXSecondsOfLogs: 60,
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
const evaluated: InBetween<Date> = (query as JSONObject)[
|
|
281
|
+
"time"
|
|
282
|
+
] as InBetween<Date>;
|
|
283
|
+
expect(evaluated.startValue).toBeInstanceOf(Date);
|
|
284
|
+
|
|
285
|
+
const stored: JSONObject = JSONFunctions.anyObjectToJSONObject(query);
|
|
286
|
+
|
|
287
|
+
/*
|
|
288
|
+
* Pin the on-disk shape. It is FLAT — `{_type, startValue, endValue}`,
|
|
289
|
+
* with no `value` wrapper and no `{_type:"DateTime"}` tagging of the
|
|
290
|
+
* bounds. Any fixture that models it otherwise deserializes to an empty
|
|
291
|
+
* InBetween and silently asserts nothing.
|
|
292
|
+
*/
|
|
293
|
+
expect(stored["time"]).toEqual({
|
|
294
|
+
_type: "InBetween",
|
|
295
|
+
startValue: evaluated.startValue.toISOString(),
|
|
296
|
+
endValue: evaluated.endValue.toISOString(),
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
const restored: JSONObject = JSONFunctions.deserialize(stored);
|
|
300
|
+
const restoredWindow: InBetween<Date> = restored[
|
|
301
|
+
"time"
|
|
302
|
+
] as InBetween<Date>;
|
|
303
|
+
|
|
304
|
+
// The class survives; the bound type does not. This is the whole trap.
|
|
305
|
+
expect(restoredWindow).toBeInstanceOf(InBetween);
|
|
306
|
+
expect(typeof restoredWindow.startValue).toBe("string");
|
|
307
|
+
|
|
308
|
+
const recovered: InBetween<Date> | null =
|
|
309
|
+
TelemetryQueryTimeRange.getQueryWindow(restored, TelemetryType.Log);
|
|
310
|
+
|
|
311
|
+
expect(recovered!.startValue).toBeInstanceOf(Date);
|
|
312
|
+
expect(recovered!.startValue.getTime()).toBe(
|
|
313
|
+
evaluated.startValue.getTime(),
|
|
314
|
+
);
|
|
315
|
+
expect(recovered!.endValue.getTime()).toBe(evaluated.endValue.getTime());
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("log monitor: the window is exactly lastXSecondsOfLogs wide", () => {
|
|
319
|
+
const query: Query<Log> = MonitorStepLogMonitorUtil.toQuery({
|
|
320
|
+
...MonitorStepLogMonitorUtil.getDefault(),
|
|
321
|
+
lastXSecondsOfLogs: 300,
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
const window: InBetween<Date> | null =
|
|
325
|
+
TelemetryQueryTimeRange.getQueryWindow(
|
|
326
|
+
storeAndRestore(query as JSONObject),
|
|
327
|
+
TelemetryType.Log,
|
|
328
|
+
);
|
|
329
|
+
|
|
330
|
+
expect(window!.endValue.getTime() - window!.startValue.getTime()).toBe(
|
|
331
|
+
300 * 1000,
|
|
332
|
+
);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
test("trace monitor: the window round-trips off startTime", () => {
|
|
336
|
+
const query: Query<Span> = MonitorStepTraceMonitorUtil.toQuery({
|
|
337
|
+
...MonitorStepTraceMonitorUtil.getDefault(),
|
|
338
|
+
lastXSecondsOfSpans: 120,
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const evaluated: InBetween<Date> = (query as JSONObject)[
|
|
342
|
+
"startTime"
|
|
343
|
+
] as InBetween<Date>;
|
|
344
|
+
|
|
345
|
+
const window: InBetween<Date> | null =
|
|
346
|
+
TelemetryQueryTimeRange.getQueryWindow(
|
|
347
|
+
storeAndRestore(query as JSONObject),
|
|
348
|
+
TelemetryType.Trace,
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
expect(window!.startValue).toBeInstanceOf(Date);
|
|
352
|
+
expect(window!.startValue.getTime()).toBe(evaluated.startValue.getTime());
|
|
353
|
+
expect(window!.endValue.getTime() - window!.startValue.getTime()).toBe(
|
|
354
|
+
120 * 1000,
|
|
355
|
+
);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
test("exception monitor: the window round-trips off time", () => {
|
|
359
|
+
const query: Query<ExceptionInstance> =
|
|
360
|
+
MonitorStepExceptionMonitorUtil.toAnalyticsQuery({
|
|
361
|
+
...MonitorStepExceptionMonitorUtil.getDefault(),
|
|
362
|
+
lastXSecondsOfExceptions: 90,
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const window: InBetween<Date> | null =
|
|
366
|
+
TelemetryQueryTimeRange.getQueryWindow(
|
|
367
|
+
storeAndRestore(query as JSONObject),
|
|
368
|
+
TelemetryType.Exception,
|
|
369
|
+
);
|
|
370
|
+
|
|
371
|
+
expect(window!.startValue).toBeInstanceOf(Date);
|
|
372
|
+
expect(window!.endValue.getTime() - window!.startValue.getTime()).toBe(
|
|
373
|
+
90 * 1000,
|
|
374
|
+
);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test("a monitor configured with no window stores none, and none is recovered", () => {
|
|
378
|
+
// Backwards compatibility: older incidents, and monitors with the window off.
|
|
379
|
+
const query: Query<Log> = MonitorStepLogMonitorUtil.toQuery({
|
|
380
|
+
...MonitorStepLogMonitorUtil.getDefault(),
|
|
381
|
+
body: "boom",
|
|
382
|
+
lastXSecondsOfLogs: 0,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
expect((query as JSONObject)["time"]).toBeUndefined();
|
|
386
|
+
|
|
387
|
+
expect(
|
|
388
|
+
TelemetryQueryTimeRange.getQueryWindow(
|
|
389
|
+
storeAndRestore(query as JSONObject),
|
|
390
|
+
TelemetryType.Log,
|
|
391
|
+
),
|
|
392
|
+
).toBeNull();
|
|
393
|
+
});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
describe("getSnapshotWindow", () => {
|
|
397
|
+
test("finds the window for each telemetry type", () => {
|
|
398
|
+
const logWindow: InBetween<Date> | null =
|
|
399
|
+
TelemetryQueryTimeRange.getSnapshotWindow({
|
|
400
|
+
telemetryType: TelemetryType.Log,
|
|
401
|
+
telemetryQuery: {
|
|
402
|
+
time: new InBetween<Date>(
|
|
403
|
+
START_ISO as unknown as Date,
|
|
404
|
+
END_ISO as unknown as Date,
|
|
405
|
+
),
|
|
406
|
+
} as Query<Log>,
|
|
407
|
+
metricViewData: null,
|
|
408
|
+
});
|
|
409
|
+
expect(logWindow!.startValue.getTime()).toBe(START_DATE.getTime());
|
|
410
|
+
|
|
411
|
+
const traceWindow: InBetween<Date> | null =
|
|
412
|
+
TelemetryQueryTimeRange.getSnapshotWindow({
|
|
413
|
+
telemetryType: TelemetryType.Trace,
|
|
414
|
+
telemetryQuery: {
|
|
415
|
+
startTime: new InBetween<Date>(
|
|
416
|
+
START_ISO as unknown as Date,
|
|
417
|
+
END_ISO as unknown as Date,
|
|
418
|
+
),
|
|
419
|
+
} as Query<Span>,
|
|
420
|
+
metricViewData: null,
|
|
421
|
+
});
|
|
422
|
+
expect(traceWindow!.startValue.getTime()).toBe(START_DATE.getTime());
|
|
423
|
+
|
|
424
|
+
const exceptionWindow: InBetween<Date> | null =
|
|
425
|
+
TelemetryQueryTimeRange.getSnapshotWindow({
|
|
426
|
+
telemetryType: TelemetryType.Exception,
|
|
427
|
+
telemetryQuery: {
|
|
428
|
+
time: new InBetween<Date>(
|
|
429
|
+
START_ISO as unknown as Date,
|
|
430
|
+
END_ISO as unknown as Date,
|
|
431
|
+
),
|
|
432
|
+
} as Query<ExceptionInstance>,
|
|
433
|
+
metricViewData: null,
|
|
434
|
+
});
|
|
435
|
+
expect(exceptionWindow!.startValue.getTime()).toBe(START_DATE.getTime());
|
|
436
|
+
|
|
437
|
+
const metricWindow: InBetween<Date> | null =
|
|
438
|
+
TelemetryQueryTimeRange.getSnapshotWindow({
|
|
439
|
+
telemetryType: TelemetryType.Metric,
|
|
440
|
+
telemetryQuery: null,
|
|
441
|
+
metricViewData: {
|
|
442
|
+
startAndEndDate: new InBetween<Date>(
|
|
443
|
+
START_ISO as unknown as Date,
|
|
444
|
+
END_ISO as unknown as Date,
|
|
445
|
+
),
|
|
446
|
+
queryConfigs: [],
|
|
447
|
+
formulaConfigs: [],
|
|
448
|
+
} as MetricViewData,
|
|
449
|
+
});
|
|
450
|
+
expect(metricWindow!.startValue).toBeInstanceOf(Date);
|
|
451
|
+
expect(metricWindow!.startValue.getTime()).toBe(START_DATE.getTime());
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
test("returns null for no telemetry query and for one carrying no window", () => {
|
|
455
|
+
expect(TelemetryQueryTimeRange.getSnapshotWindow(null)).toBeNull();
|
|
456
|
+
expect(TelemetryQueryTimeRange.getSnapshotWindow(undefined)).toBeNull();
|
|
457
|
+
expect(
|
|
458
|
+
TelemetryQueryTimeRange.getSnapshotWindow({
|
|
459
|
+
telemetryType: TelemetryType.Log,
|
|
460
|
+
telemetryQuery: { body: new Search("boom") } as Query<Log>,
|
|
461
|
+
metricViewData: null,
|
|
462
|
+
}),
|
|
463
|
+
).toBeNull();
|
|
464
|
+
expect(
|
|
465
|
+
TelemetryQueryTimeRange.getSnapshotWindow({
|
|
466
|
+
telemetryType: TelemetryType.Metric,
|
|
467
|
+
telemetryQuery: null,
|
|
468
|
+
metricViewData: {
|
|
469
|
+
startAndEndDate: null,
|
|
470
|
+
queryConfigs: [],
|
|
471
|
+
formulaConfigs: [],
|
|
472
|
+
} as MetricViewData,
|
|
473
|
+
}),
|
|
474
|
+
).toBeNull();
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
describe("toRangeStartAndEndDateTime / getPinnedRangeForQuery", () => {
|
|
479
|
+
test("resolves to CUSTOM so the window cannot re-anchor to now", () => {
|
|
480
|
+
const range: RangeStartAndEndDateTime | null =
|
|
481
|
+
TelemetryQueryTimeRange.toRangeStartAndEndDateTime(
|
|
482
|
+
new InBetween<Date>(START_DATE, END_DATE),
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
expect(range!.range).toBe(TimeRange.CUSTOM);
|
|
486
|
+
expect(range!.startAndEndDate!.startValue.getTime()).toBe(
|
|
487
|
+
START_DATE.getTime(),
|
|
488
|
+
);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
test("survives the picker's own resolution unchanged", () => {
|
|
492
|
+
/*
|
|
493
|
+
* The property the whole fix rests on: the logs viewer stores this value
|
|
494
|
+
* as picker state and every downstream request (list, histogram, facets)
|
|
495
|
+
* re-resolves it through RangeStartAndEndDateTimeUtil. A relative range
|
|
496
|
+
* would slide to "now" on each of those calls; CUSTOM must come back
|
|
497
|
+
* byte-identical every time.
|
|
498
|
+
*/
|
|
499
|
+
const range: RangeStartAndEndDateTime | null =
|
|
500
|
+
TelemetryQueryTimeRange.toRangeStartAndEndDateTime(
|
|
501
|
+
new InBetween<Date>(START_DATE, END_DATE),
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
const resolved: InBetween<Date> =
|
|
505
|
+
RangeStartAndEndDateTimeUtil.getStartAndEndDate(range!);
|
|
506
|
+
|
|
507
|
+
expect(resolved.startValue.getTime()).toBe(START_DATE.getTime());
|
|
508
|
+
expect(resolved.endValue.getTime()).toBe(END_DATE.getTime());
|
|
509
|
+
|
|
510
|
+
// And again — resolving twice must not move it.
|
|
511
|
+
const resolvedAgain: InBetween<Date> =
|
|
512
|
+
RangeStartAndEndDateTimeUtil.getStartAndEndDate(range!);
|
|
513
|
+
expect(resolvedAgain.startValue.getTime()).toBe(START_DATE.getTime());
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
test("resolved bounds are real Dates, which downstream callers require", () => {
|
|
517
|
+
/*
|
|
518
|
+
* The facets request calls `.toISOString()` on these bounds directly. A
|
|
519
|
+
* string-valued bound would throw, so coercion is load-bearing, not
|
|
520
|
+
* cosmetic.
|
|
521
|
+
*/
|
|
522
|
+
const range: RangeStartAndEndDateTime | null =
|
|
523
|
+
TelemetryQueryTimeRange.getPinnedRangeForQuery(
|
|
524
|
+
{
|
|
525
|
+
time: new InBetween<Date>(
|
|
526
|
+
START_ISO as unknown as Date,
|
|
527
|
+
END_ISO as unknown as Date,
|
|
528
|
+
),
|
|
529
|
+
},
|
|
530
|
+
TelemetryType.Log,
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
const resolved: InBetween<Date> =
|
|
534
|
+
RangeStartAndEndDateTimeUtil.getStartAndEndDate(range!);
|
|
535
|
+
|
|
536
|
+
expect(() => {
|
|
537
|
+
return resolved.startValue.toISOString();
|
|
538
|
+
}).not.toThrow();
|
|
539
|
+
expect(resolved.startValue.toISOString()).toBe(START_ISO);
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
test("returns null when there is nothing to pin, so hosts keep their own default", () => {
|
|
543
|
+
expect(
|
|
544
|
+
TelemetryQueryTimeRange.toRangeStartAndEndDateTime(null),
|
|
545
|
+
).toBeNull();
|
|
546
|
+
expect(
|
|
547
|
+
TelemetryQueryTimeRange.getPinnedRangeForQuery({}, TelemetryType.Log),
|
|
548
|
+
).toBeNull();
|
|
549
|
+
expect(
|
|
550
|
+
TelemetryQueryTimeRange.getPinnedRangeForQuery(
|
|
551
|
+
undefined,
|
|
552
|
+
TelemetryType.Log,
|
|
553
|
+
),
|
|
554
|
+
).toBeNull();
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
describe("isSameRange", () => {
|
|
559
|
+
test("compares by value, not identity", () => {
|
|
560
|
+
const a: RangeStartAndEndDateTime = {
|
|
561
|
+
range: TimeRange.CUSTOM,
|
|
562
|
+
startAndEndDate: new InBetween<Date>(START_DATE, END_DATE),
|
|
563
|
+
};
|
|
564
|
+
const b: RangeStartAndEndDateTime = {
|
|
565
|
+
range: TimeRange.CUSTOM,
|
|
566
|
+
startAndEndDate: new InBetween<Date>(
|
|
567
|
+
new Date(START_ISO),
|
|
568
|
+
new Date(END_ISO),
|
|
569
|
+
),
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
expect(a.startAndEndDate).not.toBe(b.startAndEndDate);
|
|
573
|
+
expect(TelemetryQueryTimeRange.isSameRange(a, b)).toBe(true);
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
test("treats string-valued and Date-valued bounds for the same instant as equal", () => {
|
|
577
|
+
// A host rebuilding its query from stored JSON must not look like a change.
|
|
578
|
+
expect(
|
|
579
|
+
TelemetryQueryTimeRange.isSameRange(
|
|
580
|
+
{
|
|
581
|
+
range: TimeRange.CUSTOM,
|
|
582
|
+
startAndEndDate: new InBetween<Date>(START_DATE, END_DATE),
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
range: TimeRange.CUSTOM,
|
|
586
|
+
startAndEndDate: new InBetween<Date>(
|
|
587
|
+
START_ISO as unknown as Date,
|
|
588
|
+
END_ISO as unknown as Date,
|
|
589
|
+
),
|
|
590
|
+
},
|
|
591
|
+
),
|
|
592
|
+
).toBe(true);
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
test("detects a different window and a different range kind", () => {
|
|
596
|
+
const base: RangeStartAndEndDateTime = {
|
|
597
|
+
range: TimeRange.CUSTOM,
|
|
598
|
+
startAndEndDate: new InBetween<Date>(START_DATE, END_DATE),
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
expect(
|
|
602
|
+
TelemetryQueryTimeRange.isSameRange(base, {
|
|
603
|
+
range: TimeRange.CUSTOM,
|
|
604
|
+
startAndEndDate: new InBetween<Date>(
|
|
605
|
+
START_DATE,
|
|
606
|
+
new Date("2026-08-04T10:05:00.000Z"),
|
|
607
|
+
),
|
|
608
|
+
}),
|
|
609
|
+
).toBe(false);
|
|
610
|
+
|
|
611
|
+
expect(
|
|
612
|
+
TelemetryQueryTimeRange.isSameRange(base, {
|
|
613
|
+
range: TimeRange.PAST_ONE_HOUR,
|
|
614
|
+
}),
|
|
615
|
+
).toBe(false);
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
test("handles absent values", () => {
|
|
619
|
+
expect(TelemetryQueryTimeRange.isSameRange(null, null)).toBe(true);
|
|
620
|
+
expect(TelemetryQueryTimeRange.isSameRange(undefined, null)).toBe(true);
|
|
621
|
+
expect(
|
|
622
|
+
TelemetryQueryTimeRange.isSameRange(null, {
|
|
623
|
+
range: TimeRange.PAST_ONE_HOUR,
|
|
624
|
+
}),
|
|
625
|
+
).toBe(false);
|
|
626
|
+
expect(
|
|
627
|
+
TelemetryQueryTimeRange.isSameRange(
|
|
628
|
+
{ range: TimeRange.PAST_ONE_HOUR },
|
|
629
|
+
{ range: TimeRange.PAST_ONE_HOUR },
|
|
630
|
+
),
|
|
631
|
+
).toBe(true);
|
|
632
|
+
});
|
|
633
|
+
});
|
|
634
|
+
|
|
635
|
+
describe("hydrate", () => {
|
|
636
|
+
test("gives the metric view real Date bounds", () => {
|
|
637
|
+
/*
|
|
638
|
+
* The metric chart gates bucket-grid alignment and exemplar fetching on
|
|
639
|
+
* `instanceof Date`. Until this runs, both are switched off on every
|
|
640
|
+
* incident and alert page.
|
|
641
|
+
*/
|
|
642
|
+
const telemetryQuery: TelemetryQuery = {
|
|
643
|
+
telemetryType: TelemetryType.Metric,
|
|
644
|
+
telemetryQuery: null,
|
|
645
|
+
metricViewData: {
|
|
646
|
+
startAndEndDate: new InBetween<Date>(
|
|
647
|
+
START_ISO as unknown as Date,
|
|
648
|
+
END_ISO as unknown as Date,
|
|
649
|
+
),
|
|
650
|
+
queryConfigs: [],
|
|
651
|
+
formulaConfigs: [],
|
|
652
|
+
rangeToken: undefined,
|
|
653
|
+
} as MetricViewData,
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const hydrated: TelemetryQuery | null =
|
|
657
|
+
TelemetryQueryTimeRange.hydrate(telemetryQuery);
|
|
658
|
+
|
|
659
|
+
expect(
|
|
660
|
+
hydrated!.metricViewData!.startAndEndDate!.startValue,
|
|
661
|
+
).toBeInstanceOf(Date);
|
|
662
|
+
expect(
|
|
663
|
+
hydrated!.metricViewData!.startAndEndDate!.startValue.getTime(),
|
|
664
|
+
).toBe(START_DATE.getTime());
|
|
665
|
+
expect(
|
|
666
|
+
hydrated!.metricViewData!.startAndEndDate!.endValue.getTime(),
|
|
667
|
+
).toBe(END_DATE.getTime());
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
test("gives log, trace and exception queries real Date bounds on the right field", () => {
|
|
671
|
+
const log: TelemetryQuery | null = TelemetryQueryTimeRange.hydrate({
|
|
672
|
+
telemetryType: TelemetryType.Log,
|
|
673
|
+
telemetryQuery: {
|
|
674
|
+
time: new InBetween<Date>(
|
|
675
|
+
START_ISO as unknown as Date,
|
|
676
|
+
END_ISO as unknown as Date,
|
|
677
|
+
),
|
|
678
|
+
} as Query<Log>,
|
|
679
|
+
metricViewData: null,
|
|
680
|
+
});
|
|
681
|
+
expect(
|
|
682
|
+
((log!.telemetryQuery as JSONObject)["time"] as InBetween<Date>)
|
|
683
|
+
.startValue,
|
|
684
|
+
).toBeInstanceOf(Date);
|
|
685
|
+
|
|
686
|
+
const trace: TelemetryQuery | null = TelemetryQueryTimeRange.hydrate({
|
|
687
|
+
telemetryType: TelemetryType.Trace,
|
|
688
|
+
telemetryQuery: {
|
|
689
|
+
startTime: new InBetween<Date>(
|
|
690
|
+
START_ISO as unknown as Date,
|
|
691
|
+
END_ISO as unknown as Date,
|
|
692
|
+
),
|
|
693
|
+
} as Query<Span>,
|
|
694
|
+
metricViewData: null,
|
|
695
|
+
});
|
|
696
|
+
expect(
|
|
697
|
+
((trace!.telemetryQuery as JSONObject)["startTime"] as InBetween<Date>)
|
|
698
|
+
.startValue,
|
|
699
|
+
).toBeInstanceOf(Date);
|
|
700
|
+
|
|
701
|
+
const exception: TelemetryQuery | null = TelemetryQueryTimeRange.hydrate({
|
|
702
|
+
telemetryType: TelemetryType.Exception,
|
|
703
|
+
telemetryQuery: {
|
|
704
|
+
time: new InBetween<Date>(
|
|
705
|
+
START_ISO as unknown as Date,
|
|
706
|
+
END_ISO as unknown as Date,
|
|
707
|
+
),
|
|
708
|
+
} as Query<ExceptionInstance>,
|
|
709
|
+
metricViewData: null,
|
|
710
|
+
});
|
|
711
|
+
expect(
|
|
712
|
+
((exception!.telemetryQuery as JSONObject)["time"] as InBetween<Date>)
|
|
713
|
+
.startValue,
|
|
714
|
+
).toBeInstanceOf(Date);
|
|
715
|
+
});
|
|
716
|
+
|
|
717
|
+
test("leaves every other filter on the query untouched", () => {
|
|
718
|
+
const body: Search<string> = new Search("boom");
|
|
719
|
+
const severity: Includes = new Includes([LogSeverity.Error]);
|
|
720
|
+
|
|
721
|
+
const hydrated: TelemetryQuery | null = TelemetryQueryTimeRange.hydrate({
|
|
722
|
+
telemetryType: TelemetryType.Log,
|
|
723
|
+
telemetryQuery: {
|
|
724
|
+
body: body,
|
|
725
|
+
severityText: severity,
|
|
726
|
+
time: new InBetween<Date>(
|
|
727
|
+
START_ISO as unknown as Date,
|
|
728
|
+
END_ISO as unknown as Date,
|
|
729
|
+
),
|
|
730
|
+
} as unknown as Query<Log>,
|
|
731
|
+
metricViewData: null,
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
const query: JSONObject = hydrated!.telemetryQuery as JSONObject;
|
|
735
|
+
expect(query["body"]).toBe(body);
|
|
736
|
+
expect(query["severityText"]).toBe(severity);
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
test("leaves the rest of the metric view untouched, including rangeToken", () => {
|
|
740
|
+
const queryConfigs: MetricViewData["queryConfigs"] = [];
|
|
741
|
+
const metricViewData: MetricViewData = {
|
|
742
|
+
startAndEndDate: new InBetween<Date>(
|
|
743
|
+
START_ISO as unknown as Date,
|
|
744
|
+
END_ISO as unknown as Date,
|
|
745
|
+
),
|
|
746
|
+
queryConfigs: queryConfigs,
|
|
747
|
+
formulaConfigs: [],
|
|
748
|
+
rangeToken: TimeRange.PAST_ONE_HOUR,
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
const hydrated: TelemetryQuery | null = TelemetryQueryTimeRange.hydrate({
|
|
752
|
+
telemetryType: TelemetryType.Metric,
|
|
753
|
+
telemetryQuery: null,
|
|
754
|
+
metricViewData: metricViewData,
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
expect(hydrated!.metricViewData!.queryConfigs).toBe(queryConfigs);
|
|
758
|
+
expect(hydrated!.metricViewData!.rangeToken).toBe(
|
|
759
|
+
TimeRange.PAST_ONE_HOUR,
|
|
760
|
+
);
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
test("returns the same reference when there is nothing to fix", () => {
|
|
764
|
+
/*
|
|
765
|
+
* React hosts call this on every load; handing back a fresh-but-equal
|
|
766
|
+
* object would churn state and refetch.
|
|
767
|
+
*/
|
|
768
|
+
const alreadyDates: TelemetryQuery = {
|
|
769
|
+
telemetryType: TelemetryType.Log,
|
|
770
|
+
telemetryQuery: {
|
|
771
|
+
time: new InBetween<Date>(START_DATE, END_DATE),
|
|
772
|
+
} as Query<Log>,
|
|
773
|
+
metricViewData: null,
|
|
774
|
+
};
|
|
775
|
+
expect(TelemetryQueryTimeRange.hydrate(alreadyDates)).toBe(alreadyDates);
|
|
776
|
+
|
|
777
|
+
const noWindow: TelemetryQuery = {
|
|
778
|
+
telemetryType: TelemetryType.Log,
|
|
779
|
+
telemetryQuery: { body: new Search("boom") } as Query<Log>,
|
|
780
|
+
metricViewData: null,
|
|
781
|
+
};
|
|
782
|
+
expect(TelemetryQueryTimeRange.hydrate(noWindow)).toBe(noWindow);
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
test("returns null for no telemetry query", () => {
|
|
786
|
+
expect(TelemetryQueryTimeRange.hydrate(null)).toBeNull();
|
|
787
|
+
expect(TelemetryQueryTimeRange.hydrate(undefined)).toBeNull();
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
test("hydrating a stored blob end to end yields a chart-ready window", () => {
|
|
791
|
+
// The full production path for a metric incident, in one assertion chain.
|
|
792
|
+
const evaluated: InBetween<Date> = new InBetween<Date>(
|
|
793
|
+
START_DATE,
|
|
794
|
+
END_DATE,
|
|
795
|
+
);
|
|
796
|
+
|
|
797
|
+
const restored: TelemetryQuery = JSONFunctions.deserialize(
|
|
798
|
+
JSONFunctions.anyObjectToJSONObject({
|
|
799
|
+
telemetryType: TelemetryType.Metric,
|
|
800
|
+
telemetryQuery: null,
|
|
801
|
+
metricViewData: {
|
|
802
|
+
startAndEndDate: evaluated,
|
|
803
|
+
queryConfigs: [],
|
|
804
|
+
formulaConfigs: [],
|
|
805
|
+
},
|
|
806
|
+
}),
|
|
807
|
+
) as unknown as TelemetryQuery;
|
|
808
|
+
|
|
809
|
+
// Before hydration the guard downstream would reject this.
|
|
810
|
+
expect(
|
|
811
|
+
restored.metricViewData!.startAndEndDate!.startValue,
|
|
812
|
+
).not.toBeInstanceOf(Date);
|
|
813
|
+
|
|
814
|
+
const hydrated: TelemetryQuery | null =
|
|
815
|
+
TelemetryQueryTimeRange.hydrate(restored);
|
|
816
|
+
|
|
817
|
+
expect(
|
|
818
|
+
hydrated!.metricViewData!.startAndEndDate!.startValue,
|
|
819
|
+
).toBeInstanceOf(Date);
|
|
820
|
+
expect(
|
|
821
|
+
hydrated!.metricViewData!.startAndEndDate!.startValue.getTime(),
|
|
822
|
+
).toBe(START_DATE.getTime());
|
|
823
|
+
});
|
|
824
|
+
});
|
|
825
|
+
});
|