@oneuptime/common 14.0.10 → 14.0.11
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/AIConversation.ts +127 -1
- package/Models/DatabaseModels/CephCluster.ts +12 -0
- package/Models/DatabaseModels/CloudResource.ts +12 -0
- package/Models/DatabaseModels/DatabaseServer.ts +12 -0
- package/Models/DatabaseModels/DockerHost.ts +12 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +12 -0
- package/Models/DatabaseModels/GlobalOidc.ts +0 -4
- package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
- package/Models/DatabaseModels/GlobalSso.ts +0 -4
- package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
- package/Models/DatabaseModels/Host.ts +12 -0
- package/Models/DatabaseModels/IncidentForm.ts +594 -0
- package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
- package/Models/DatabaseModels/Index.ts +14 -0
- package/Models/DatabaseModels/IoTFleet.ts +12 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
- package/Models/DatabaseModels/MessageQueue.ts +1102 -0
- package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
- package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
- package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
- package/Models/DatabaseModels/PodmanHost.ts +12 -0
- package/Models/DatabaseModels/Project.ts +59 -0
- package/Models/DatabaseModels/ProjectOidc.ts +0 -4
- package/Models/DatabaseModels/ProjectSso.ts +0 -4
- package/Models/DatabaseModels/ProxmoxCluster.ts +12 -0
- package/Models/DatabaseModels/RumApplication.ts +12 -0
- package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
- package/Models/DatabaseModels/Service.ts +12 -0
- package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
- package/Models/DatabaseModels/StatusPageSso.ts +0 -4
- package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
- package/Models/DatabaseModels/VMwareVCenter.ts +12 -0
- package/Server/API/AIChatAPI.ts +13 -114
- package/Server/API/AIInvestigationAPI.ts +3 -3
- package/Server/API/AIInvestigationConversationAPI.ts +266 -0
- package/Server/API/IncidentFormAPI.ts +376 -0
- package/Server/API/ProjectOIDC.ts +16 -25
- package/Server/API/ProjectSSO.ts +16 -24
- package/Server/API/StatusPageAPI.ts +42 -77
- package/Server/Enterprise/EnterpriseEdition.ts +93 -28
- package/Server/Enterprise/EnterpriseFeature.ts +25 -3
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
- package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
- package/Server/EnvironmentConfig.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
- package/Server/Middleware/UserAuthorization.ts +16 -38
- package/Server/Services/AIService.ts +10 -13
- package/Server/Services/IncidentCustomFieldService.ts +112 -2
- package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
- package/Server/Services/IncidentEpisodeService.ts +10 -1
- package/Server/Services/IncidentFormService.ts +1566 -0
- package/Server/Services/IncidentFormSubmissionService.ts +97 -0
- package/Server/Services/IncidentGroupingEngineService.ts +45 -8
- package/Server/Services/IncidentService.ts +123 -5
- package/Server/Services/IncidentTemplateService.ts +22 -0
- package/Server/Services/Index.ts +14 -0
- package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
- package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
- package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
- package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
- package/Server/Services/MessageQueueService.ts +1463 -0
- package/Server/Services/OpenTelemetryIngestService.ts +37 -4
- package/Server/Services/ProjectService.ts +0 -59
- package/Server/Services/StatusPagePrivateUserService.ts +1 -4
- package/Server/Services/StatusPageService.ts +1 -51
- package/Server/Services/TeamComplianceSettingService.ts +163 -42
- package/Server/Services/UserNotificationRuleService.ts +8 -1
- package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
- package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
- package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
- package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
- package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
- package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
- package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +7 -1
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +34 -14
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +69 -24
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +9 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +53 -10
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +27 -10
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +27 -10
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
- package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
- package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
- package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
- package/Server/Utils/EditionEnforcement.ts +19 -202
- package/Server/Utils/LLM/LLMService.ts +259 -63
- package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/SameOriginRequest.ts +203 -0
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
- package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
- package/Server/Utils/VendorAssets.ts +3 -3
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +3 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +3 -1
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +10 -1
- package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
- package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
- package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
- package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
- package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
- package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
- package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
- package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
- package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +174 -12
- package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
- package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
- package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +5 -0
- package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
- package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
- package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
- package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
- package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
- package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
- package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
- package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
- package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
- package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
- package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
- package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
- package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
- package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
- package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
- package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
- package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
- package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
- package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
- package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
- package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
- package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
- package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
- package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
- package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
- package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
- package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
- package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
- package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
- package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
- package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
- package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
- package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
- package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
- package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
- package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
- package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
- package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
- package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
- package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
- package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
- package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
- package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
- package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
- package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
- package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
- package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +298 -9
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +453 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
- package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
- package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
- package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
- package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
- package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
- package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
- package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
- package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
- package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
- package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
- package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
- package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
- package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
- package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +28 -9
- package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
- package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
- package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
- package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
- package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
- package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
- package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
- package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
- package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
- package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
- package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
- package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
- package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
- package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
- package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
- package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
- package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
- package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
- package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
- package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
- package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
- package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
- package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
- package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
- package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
- package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
- package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
- package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
- package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
- package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
- package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
- package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
- package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
- package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
- package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
- package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
- package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
- package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
- package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
- package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +266 -25
- package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
- package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
- package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
- package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
- package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +2 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +297 -15
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +10 -6
- package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
- package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
- package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
- package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
- package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
- package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
- package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
- package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
- package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
- package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
- package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
- package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
- package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
- package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
- package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
- package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
- package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
- package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
- package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
- package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +5 -3
- package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
- package/Tests/Types/XML.test.ts +51 -0
- package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
- package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
- package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
- package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
- package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
- package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
- package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
- package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
- package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
- package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
- package/Tests/UI/Components/Icon.test.tsx +32 -0
- package/Tests/UI/Components/Input.test.tsx +31 -0
- package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
- package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
- package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
- package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
- package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
- package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
- package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
- package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
- package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
- package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
- package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
- package/Tests/UI/Components/TextArea.test.tsx +19 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
- package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
- package/Tests/UI/EsbuildConfig.test.ts +115 -39
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
- package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
- package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
- package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
- package/Types/AI/AIAgentRunLimits.ts +146 -0
- package/Types/Code/CodeType.ts +2 -0
- package/Types/Code/JsonSyntax.ts +923 -0
- package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
- package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
- package/Types/Icon/IconProp.ts +2 -0
- package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
- package/Types/Incident/IncidentFormPublic.ts +1145 -0
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
- package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
- package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
- package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
- package/Types/MessageQueue/MessagingSystem.ts +518 -0
- package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
- package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
- package/Types/Permission.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +10 -4
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/Types/Team/ComplianceNotificationChannel.ts +4 -3
- package/Types/Team/ComplianceRule.ts +71 -18
- package/Types/Team/ComplianceRuleType.ts +2 -2
- package/Types/Team/TeamComplianceStatus.ts +6 -2
- package/Types/Telemetry/EntityType.ts +16 -0
- package/Types/Telemetry/LockedFilterDetail.ts +22 -0
- package/Types/XML.ts +26 -0
- package/UI/Components/CodeEditor/CodeEditor.css +379 -0
- package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
- package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
- package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
- package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
- package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
- package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
- package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
- package/UI/Components/Forms/Fields/FormField.tsx +8 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Icon/Icon.tsx +18 -0
- package/UI/Components/Input/Input.tsx +11 -4
- package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
- package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
- package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
- package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
- package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
- package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
- package/UI/Components/Table/EmptyTableMessage.ts +81 -0
- package/UI/Components/Table/Table.tsx +50 -21
- package/UI/Components/Table/TableRow.tsx +9 -1
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
- package/UI/Components/TextArea/TextArea.tsx +9 -2
- package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
- package/UI/Styles/Theme.css +8 -0
- package/UI/esbuild-config.js +2 -32
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
- package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
- package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
- package/Utils/Telemetry/EntityKey.ts +48 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +12 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +12 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
- package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +14 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
- package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
- package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js +12 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +61 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +12 -0
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +12 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +9 -103
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
- package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
- package/build/dist/Server/API/IncidentFormAPI.js +245 -0
- package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
- package/build/dist/Server/API/ProjectOIDC.js +16 -24
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +16 -24
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +42 -75
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +10 -13
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFormService.js +1202 -0
- package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +106 -4
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +14 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueService.js +1140 -0
- package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +0 -54
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +0 -46
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +7 -2
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +29 -14
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +38 -14
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +2 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +40 -10
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +19 -7
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +19 -7
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
- package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
- package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +3 -3
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +3 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +3 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +10 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
- package/build/dist/Types/Code/CodeType.js +2 -0
- package/build/dist/Types/Code/CodeType.js.map +1 -1
- package/build/dist/Types/Code/JsonSyntax.js +604 -0
- package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
- package/build/dist/Types/Icon/IconProp.js +2 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
- package/build/dist/Types/Permission.js +274 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +10 -4
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRule.js +48 -14
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
- package/build/dist/Types/Telemetry/EntityType.js +16 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/XML.js +23 -0
- package/build/dist/Types/XML.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
- package/build/dist/UI/Components/CodeEditor/YamlEditor.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/CustomFieldModelFormFields.js +5 -14
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +8 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +11 -3
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
- package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
- package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +30 -11
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +9 -2
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
- package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/package.json +1 -3
- package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
- package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
- package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
- package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
- package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
- package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
- package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
- package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
- package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
- package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
|
@@ -0,0 +1,1207 @@
|
|
|
1
|
+
import Includes from "../BaseDatabase/Includes";
|
|
2
|
+
import MonitorStep from "./MonitorStep";
|
|
3
|
+
import MonitorCriteria from "./MonitorCriteria";
|
|
4
|
+
import { EvaluateOverTimeType, FilterType } from "./CriteriaFilter";
|
|
5
|
+
import MonitorType from "./MonitorType";
|
|
6
|
+
import RollingTime from "../RollingTime/RollingTime";
|
|
7
|
+
import RollingTimeUtil from "../RollingTime/RollingTimeUtil";
|
|
8
|
+
import MetricsAggregationType from "../Metrics/MetricsAggregationType";
|
|
9
|
+
import MetricUnitUtil from "../../Utils/MetricUnitUtil";
|
|
10
|
+
import { MESSAGE_QUEUE_METRICS, getMessageQueueMetricId, } from "../MessageQueue/MessageQueueMetricCatalog";
|
|
11
|
+
import { resolveMessagingMetricDatapoint, } from "../MessageQueue/MessagingTelemetryResolver";
|
|
12
|
+
import { buildMessageQueueIdentifier, toMessageQueueIdentity, } from "../MessageQueue/MessageQueueIdentity";
|
|
13
|
+
import { buildHealthyCriteriaInstance, buildUnhealthyCriteriaInstance, getRecoveryFilterType, } from "./Recommendation/RecommendationCriteriaBuilder";
|
|
14
|
+
/*
|
|
15
|
+
* The signals a static "at or above" threshold means something for (see
|
|
16
|
+
* WHICH METRICS GET A TEMPLATE in the header). published, consumed and
|
|
17
|
+
* consumers are the rest of MessageQueueSignal.
|
|
18
|
+
*/
|
|
19
|
+
export const MESSAGE_QUEUE_THRESHOLDABLE_SIGNALS = [
|
|
20
|
+
"backlog",
|
|
21
|
+
"consumerLag",
|
|
22
|
+
"oldestMessageAge",
|
|
23
|
+
"deadLetter",
|
|
24
|
+
"errors",
|
|
25
|
+
"throttled",
|
|
26
|
+
];
|
|
27
|
+
export function getMessageQueueAlertMeasure(descriptor) {
|
|
28
|
+
return descriptor.aggregation === MetricsAggregationType.Sum
|
|
29
|
+
? "count"
|
|
30
|
+
: "level";
|
|
31
|
+
}
|
|
32
|
+
export const MESSAGE_QUEUE_ALERT_POLICIES = [
|
|
33
|
+
/*
|
|
34
|
+
* A thousand messages held for ten minutes. A work queue that keeps up
|
|
35
|
+
* drains to near empty between bursts, so a thousand waiting messages
|
|
36
|
+
* that do not go away within ten minutes means the queue fills faster
|
|
37
|
+
* than it drains, or nothing drains it; a burst that drains inside the
|
|
38
|
+
* window never fires. For the brokers that track each message
|
|
39
|
+
* (RabbitMQ, ActiveMQ, SQS, Service Bus, Pub/Sub subscriptions) and the
|
|
40
|
+
* ready count of RocketMQ and Pulsar's topic backlog.
|
|
41
|
+
*/
|
|
42
|
+
{
|
|
43
|
+
signal: "backlog",
|
|
44
|
+
measure: "level",
|
|
45
|
+
threshold: 1000,
|
|
46
|
+
thresholdUnit: null,
|
|
47
|
+
evaluation: EvaluateOverTimeType.AllValues,
|
|
48
|
+
rollingTime: RollingTime.Past10Minutes,
|
|
49
|
+
severity: "Warning",
|
|
50
|
+
category: "Backlog",
|
|
51
|
+
nameSuffix: "High",
|
|
52
|
+
metricAlias: "queue_backlog",
|
|
53
|
+
meaning: "Messages are arriving faster than consumers take them, or nothing is consuming them. A healthy queue drains to near empty between bursts, so retune to a few times this queue's normal peak.",
|
|
54
|
+
incidentDescription: "Messages are piling up in the queue. Check that its consumers are running and connected, whether they are failing and returning messages to the queue, and whether they need more instances to keep up with the publish rate.",
|
|
55
|
+
},
|
|
56
|
+
/*
|
|
57
|
+
* Ten thousand messages held for ten minutes — ten times the backlog
|
|
58
|
+
* default, because a consumer group's lag is measured against the offset
|
|
59
|
+
* it last COMMITTED: a healthy Kafka consumer commits every few seconds
|
|
60
|
+
* (five by default), so on a topic taking a few thousand messages a
|
|
61
|
+
* second it trails by thousands between commits, all the time. The same
|
|
62
|
+
* default serves Pulsar's subscription backlog and RocketMQ's lag, the
|
|
63
|
+
* other log-based brokers.
|
|
64
|
+
*/
|
|
65
|
+
{
|
|
66
|
+
signal: "consumerLag",
|
|
67
|
+
measure: "level",
|
|
68
|
+
threshold: 10000,
|
|
69
|
+
thresholdUnit: null,
|
|
70
|
+
evaluation: EvaluateOverTimeType.AllValues,
|
|
71
|
+
rollingTime: RollingTime.Past10Minutes,
|
|
72
|
+
severity: "Warning",
|
|
73
|
+
category: "Consumer Lag",
|
|
74
|
+
nameSuffix: "High",
|
|
75
|
+
metricAlias: "consumer_lag",
|
|
76
|
+
meaning: "Consumers are falling behind what is produced. A healthy consumer group that commits its offsets every few seconds already trails a busy topic by thousands of messages, so retune to a few times this topic's normal lag.",
|
|
77
|
+
incidentDescription: "The consumer group is falling behind its producers. Check that every consumer is running and not stuck rebalancing, whether one partition is stuck on a message its consumer cannot process, and whether the group needs more consumers (up to one per partition).",
|
|
78
|
+
},
|
|
79
|
+
/*
|
|
80
|
+
* Ten minutes of waiting, held for five. A consumer that keeps up takes a
|
|
81
|
+
* message within seconds, so a message ten minutes old means consumers
|
|
82
|
+
* are stopped or far behind, or keep failing on one message that is
|
|
83
|
+
* received and returned until its dead-letter policy moves it aside. An
|
|
84
|
+
* age already is a duration, so a shorter sustain (five minutes) is
|
|
85
|
+
* enough to ignore one late sample.
|
|
86
|
+
*/
|
|
87
|
+
{
|
|
88
|
+
signal: "oldestMessageAge",
|
|
89
|
+
measure: "level",
|
|
90
|
+
threshold: 600,
|
|
91
|
+
thresholdUnit: "s",
|
|
92
|
+
evaluation: EvaluateOverTimeType.AllValues,
|
|
93
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
94
|
+
severity: "Warning",
|
|
95
|
+
category: "Message Age",
|
|
96
|
+
nameSuffix: "High",
|
|
97
|
+
metricAlias: "oldest_message_age",
|
|
98
|
+
meaning: "Messages are waiting far longer than a working consumer takes: consumers are stopped or far behind, or keep failing on a message that is received and returned again and again. Retune to how long a message may wait before it is late.",
|
|
99
|
+
incidentDescription: "The oldest message has waited longer than a working consumer takes. Check that consumers are running; a message that fails every time it is processed is received and returned until the dead-letter policy moves it aside, so look at its receive count.",
|
|
100
|
+
},
|
|
101
|
+
/*
|
|
102
|
+
* Any dead-lettered message, held for five minutes: each one failed
|
|
103
|
+
* every delivery attempt and waits for a person. It stays open until
|
|
104
|
+
* the dead-letter queue is drained, which is the point.
|
|
105
|
+
*/
|
|
106
|
+
{
|
|
107
|
+
signal: "deadLetter",
|
|
108
|
+
measure: "level",
|
|
109
|
+
threshold: 1,
|
|
110
|
+
thresholdUnit: null,
|
|
111
|
+
evaluation: EvaluateOverTimeType.AllValues,
|
|
112
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
113
|
+
severity: "Warning",
|
|
114
|
+
category: "Dead Letters",
|
|
115
|
+
nameSuffix: "",
|
|
116
|
+
metricAlias: "dead_letters",
|
|
117
|
+
meaning: "Messages that failed every delivery attempt are waiting in the dead-letter queue for someone to inspect them. Raise the threshold if the dead-letter queue is drained on a schedule.",
|
|
118
|
+
incidentDescription: "Messages failed every delivery attempt and were moved to the dead-letter queue. Inspect them to find the failing handler or the malformed payload, fix the cause, then resubmit or discard them.",
|
|
119
|
+
},
|
|
120
|
+
// Any message dead-lettered in any one minute.
|
|
121
|
+
{
|
|
122
|
+
signal: "deadLetter",
|
|
123
|
+
measure: "count",
|
|
124
|
+
threshold: 1,
|
|
125
|
+
thresholdUnit: null,
|
|
126
|
+
evaluation: EvaluateOverTimeType.AnyValue,
|
|
127
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
128
|
+
severity: "Warning",
|
|
129
|
+
category: "Dead Letters",
|
|
130
|
+
nameSuffix: "",
|
|
131
|
+
metricAlias: "dead_letters",
|
|
132
|
+
meaning: "Messages are being moved to a dead-letter queue after failing every delivery attempt.",
|
|
133
|
+
incidentDescription: "Messages failed every delivery attempt and were moved to a dead-letter queue. Inspect them to find the failing handler or the malformed payload, fix the cause, then resubmit or discard them.",
|
|
134
|
+
},
|
|
135
|
+
/*
|
|
136
|
+
* Ten in any one minute. Clients retry a failed request and brokers
|
|
137
|
+
* redeliver a failed message, so one failure goes unnoticed; ten in a
|
|
138
|
+
* minute is a pattern, not a blip.
|
|
139
|
+
*/
|
|
140
|
+
{
|
|
141
|
+
signal: "errors",
|
|
142
|
+
measure: "count",
|
|
143
|
+
threshold: 10,
|
|
144
|
+
thresholdUnit: null,
|
|
145
|
+
evaluation: EvaluateOverTimeType.AnyValue,
|
|
146
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
147
|
+
severity: "Warning",
|
|
148
|
+
category: "Errors",
|
|
149
|
+
nameSuffix: "",
|
|
150
|
+
metricAlias: "failures",
|
|
151
|
+
meaning: "Failures are recurring rather than occasional: clients retry a failed request and brokers redeliver a failed message, so a single failure goes unnoticed, while a burst like this is a pattern, not a blip. Retune to this queue's volume.",
|
|
152
|
+
incidentDescription: "Operations on the queue are failing. The broker's own diagnostics name the operation and the error: failures the broker causes point at the service itself (check its health status), while failures its clients cause usually follow a deployment, a credential or permission change, a consumer that crashes on a message, or an entity that was deleted or disabled.",
|
|
153
|
+
},
|
|
154
|
+
/*
|
|
155
|
+
* Ten in any one minute: a throttled client backs off before it retries,
|
|
156
|
+
* so a few throttled requests at a peak are absorbed, while ten a minute
|
|
157
|
+
* means the namespace is out of capacity.
|
|
158
|
+
*/
|
|
159
|
+
{
|
|
160
|
+
signal: "throttled",
|
|
161
|
+
measure: "count",
|
|
162
|
+
threshold: 10,
|
|
163
|
+
thresholdUnit: null,
|
|
164
|
+
evaluation: EvaluateOverTimeType.AnyValue,
|
|
165
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
166
|
+
severity: "Warning",
|
|
167
|
+
category: "Throttling",
|
|
168
|
+
nameSuffix: "",
|
|
169
|
+
metricAlias: "throttled_requests",
|
|
170
|
+
meaning: "The broker is refusing requests because the namespace is out of capacity, and every throttled client backs off before it retries, which slows everything on the namespace. If it persists, add capacity (Service Bus Premium messaging units, Event Hubs throughput or processing units).",
|
|
171
|
+
incidentDescription: "The broker is throttling requests because the namespace is out of capacity. Look for a traffic spike or a new heavy client; if throttling persists, scale the namespace up.",
|
|
172
|
+
},
|
|
173
|
+
];
|
|
174
|
+
export const MESSAGE_QUEUE_ALERT_POLICY_OVERRIDES = [
|
|
175
|
+
{
|
|
176
|
+
system: "aws_sqs",
|
|
177
|
+
metricNames: [
|
|
178
|
+
"amazonaws.com/aws/sqs/approximatenumberofmessagesnotvisible",
|
|
179
|
+
"approximatenumberofmessagesnotvisible",
|
|
180
|
+
],
|
|
181
|
+
/*
|
|
182
|
+
* 90% of the in-flight quota of a standard queue (about 120,000
|
|
183
|
+
* messages received but not yet deleted): early enough to act before
|
|
184
|
+
* receives start failing, and far above what a busy queue that is
|
|
185
|
+
* draining keeps in flight.
|
|
186
|
+
*/
|
|
187
|
+
threshold: 108000,
|
|
188
|
+
/*
|
|
189
|
+
* Critical, and held for five minutes rather than a backlog's ten: the
|
|
190
|
+
* last 10% of the quota is what stands between the queue and receives
|
|
191
|
+
* that fail.
|
|
192
|
+
*/
|
|
193
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
194
|
+
severity: "Critical",
|
|
195
|
+
name: "Messages In Flight Near Quota",
|
|
196
|
+
meaning: "A standard queue keeps about 120,000 messages in flight (received but not yet deleted) at most; past that, short-polling receives fail with OverLimit and long polls return nothing, so every consumer stalls. This fires at 90% of that quota; for a FIFO queue, retune to 90% of its own quota.",
|
|
197
|
+
incidentDescription: "Close to 120,000 messages are received but not yet deleted, so receives are about to fail. Check that consumers delete messages once they have processed them, and whether a long visibility timeout keeps failed messages in flight.",
|
|
198
|
+
reason: "Messages in flight are not a backlog: a busy queue keeps thousands in flight while it drains, and the one level that matters is the queue's in-flight quota.",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
system: "aws_sqs",
|
|
202
|
+
metricNames: [
|
|
203
|
+
"amazonaws.com/aws/sqs/approximateageofoldestmessage",
|
|
204
|
+
"approximateageofoldestmessage",
|
|
205
|
+
],
|
|
206
|
+
recoverOnNoData: true,
|
|
207
|
+
reason: "CloudWatch reports this metric only while the queue holds a message, so a silent window is an empty queue: recovery reads it as an age of zero.",
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
/*
|
|
211
|
+
* Catalog gauges with a thresholdable signal that deliberately get no
|
|
212
|
+
* template. The queue page still charts them, and its "Create monitor" link
|
|
213
|
+
* still builds a monitor on them for a team that wants one.
|
|
214
|
+
*/
|
|
215
|
+
export const UNTEMPLATED_MESSAGE_QUEUE_GAUGES = [
|
|
216
|
+
{
|
|
217
|
+
system: "kafka",
|
|
218
|
+
metricName: "kafka.consumer_group.lag",
|
|
219
|
+
reason: "Every partition's lag is part of its consumer group's lag, so at Consumer lag's threshold it could only fire after that template has, and no fixed lower threshold tells one stuck partition from a busy one: a healthy group that commits every few seconds trails each busy partition by thousands of messages.",
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
system: "activemq",
|
|
223
|
+
metricName: "activemq.message.enqueue.average_duration",
|
|
224
|
+
reason: "It is a running average the broker keeps from its start (AverageEnqueueTime), so after one stall it stays high long after the destination has drained, and on a destination with a long history a new stall barely moves it: a threshold on it fires late and does not clear. Queue size catches a stall directly.",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
system: "activemq",
|
|
228
|
+
metricName: "activemq.message.wait_time.avg",
|
|
229
|
+
reason: "It is the same running average the broker keeps from its start (AverageEnqueueTime), under the JMX Scraper's legacy name, so a threshold on it fires late and does not clear. Queue size (legacy names) catches a stall directly.",
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
system: "pulsar",
|
|
233
|
+
metricName: "pulsar_storage_backlog_age_seconds",
|
|
234
|
+
reason: "It read -1 (unknown) on topics that held a backlog in a live capture from Pulsar 4.2.4 on its default configuration, so a threshold on it would watch nothing there. Subscription backlog catches a subscription that stopped acknowledging.",
|
|
235
|
+
},
|
|
236
|
+
];
|
|
237
|
+
/*
|
|
238
|
+
* What each counter would be tempting to alert on, by signal: the catalog
|
|
239
|
+
* marks every cumulative total `kind: "counter"`, and the monitor path has
|
|
240
|
+
* no rate to threshold it with.
|
|
241
|
+
*/
|
|
242
|
+
const COUNTER_TEMPTATION_BY_SIGNAL = {
|
|
243
|
+
published: "publishing stopping or spiking",
|
|
244
|
+
consumed: "consumers stopping",
|
|
245
|
+
errors: "a rise in failed or expired messages",
|
|
246
|
+
deadLetter: "messages being dead-lettered",
|
|
247
|
+
backlog: "a growing backlog",
|
|
248
|
+
consumerLag: "a growing lag",
|
|
249
|
+
oldestMessageAge: "messages getting old",
|
|
250
|
+
throttled: "throttling",
|
|
251
|
+
consumers: "consumers leaving",
|
|
252
|
+
};
|
|
253
|
+
/*
|
|
254
|
+
* Every catalog counter, which no template reads, and what a team would
|
|
255
|
+
* reach for it for. The honest workaround for a team that needs one alerted
|
|
256
|
+
* today is a `cumulative_to_delta` processor in its collector pipeline
|
|
257
|
+
* (`cumulativetodelta`, its old name, is a deprecated alias in
|
|
258
|
+
* collector-contrib 0.161.0) converting a COPY of the counter, made under a
|
|
259
|
+
* name of its own, into per-scrape deltas that a Sum over the window
|
|
260
|
+
* thresholds correctly; `initial_value: drop` keeps back the copy's first
|
|
261
|
+
* point after a collector start, the counter's whole running total. The
|
|
262
|
+
* config is at /docs/telemetry/queues#alerting. Never convert the counter
|
|
263
|
+
* itself: the queue page reads each counter as a running total and charts
|
|
264
|
+
* how fast it grows, so a counter converted in place charts about 0/s for
|
|
265
|
+
* steady traffic. The processor only converts sums, so it leaves Kafka's
|
|
266
|
+
* offsets and Pulsar's totals, which reach the collector as gauges, as they
|
|
267
|
+
* are.
|
|
268
|
+
*/
|
|
269
|
+
export const UNALERTABLE_MESSAGE_QUEUE_COUNTERS = MESSAGE_QUEUE_METRICS.filter((descriptor) => {
|
|
270
|
+
return descriptor.kind === "counter";
|
|
271
|
+
}).map((descriptor) => {
|
|
272
|
+
return {
|
|
273
|
+
system: descriptor.system,
|
|
274
|
+
metricName: descriptor.metricName,
|
|
275
|
+
wouldAlertOn: COUNTER_TEMPTATION_BY_SIGNAL[descriptor.signal],
|
|
276
|
+
};
|
|
277
|
+
});
|
|
278
|
+
export const MESSAGE_QUEUE_SOURCE_WINDOW_FLOORS = [
|
|
279
|
+
{
|
|
280
|
+
receiver: "aws_cloudwatch",
|
|
281
|
+
/*
|
|
282
|
+
* The newest point is up to delay + 2 × period + collection_interval
|
|
283
|
+
* old: 17 minutes under the documented configuration, 25 under the
|
|
284
|
+
* receiver's defaults. Thirty is the shortest RollingTime above both.
|
|
285
|
+
*/
|
|
286
|
+
minimumRollingTime: RollingTime.Past30Minutes,
|
|
287
|
+
reason: "The collector's `aws_cloudwatch` receiver fetches CloudWatch's periods `delay` (ten minutes) after they end, `collection_interval` (five minutes) at a time, so its points arrive 11 to 17 minutes late, and up to 25 minutes late with the receiver's default five-minute `period`: the window is thirty minutes so that it always holds some.",
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
receiver: "googlecloudmonitoring",
|
|
291
|
+
/*
|
|
292
|
+
* A sample arrives up to ingestDelay + collection_interval late: nine
|
|
293
|
+
* minutes for dead_letter_message_count (240 seconds) with the
|
|
294
|
+
* receiver's default five-minute interval, and the next one-minute
|
|
295
|
+
* evaluation reads it up to ten minutes after it was taken — the very
|
|
296
|
+
* edge of a Past10Minutes window, which any export delay tips over.
|
|
297
|
+
* Fifteen leaves a margin.
|
|
298
|
+
*/
|
|
299
|
+
minimumRollingTime: RollingTime.Past15Minutes,
|
|
300
|
+
reason: "Cloud Monitoring makes a Pub/Sub sample visible two to four minutes after it is taken, and the collector's `googlecloudmonitoring` receiver fetches what has become visible once per `collection_interval`, so a point arrives up to nine minutes late with the receiver's default five-minute interval: the window is fifteen minutes so that it always holds some and reads every point.",
|
|
301
|
+
},
|
|
302
|
+
];
|
|
303
|
+
/**
|
|
304
|
+
* The window floor of a catalog entry's source, or null when its points
|
|
305
|
+
* arrive live.
|
|
306
|
+
*/
|
|
307
|
+
export function getMessageQueueSourceWindowFloor(descriptor) {
|
|
308
|
+
if (!descriptor) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
for (const floor of MESSAGE_QUEUE_SOURCE_WINDOW_FLOORS) {
|
|
312
|
+
if (floor.receiver === descriptor.receiver) {
|
|
313
|
+
return floor;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
function getRollingTimeSeconds(rollingTime) {
|
|
319
|
+
const window = RollingTimeUtil.convertToStartAndEndDate(rollingTime);
|
|
320
|
+
return (window.endValue.getTime() - window.startValue.getTime()) / 1000;
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* The window a monitor on this catalog entry reads: `preferred`, widened to
|
|
324
|
+
* the entry's source floor when that is longer. The templates read their
|
|
325
|
+
* signal's window through it, and the "Create monitor" link its default.
|
|
326
|
+
*/
|
|
327
|
+
export function getMessageQueueMetricMonitorRollingTime(descriptor, preferred) {
|
|
328
|
+
const floor = getMessageQueueSourceWindowFloor(descriptor);
|
|
329
|
+
if (floor &&
|
|
330
|
+
getRollingTimeSeconds(floor.minimumRollingTime) >
|
|
331
|
+
getRollingTimeSeconds(preferred)) {
|
|
332
|
+
return floor.minimumRollingTime;
|
|
333
|
+
}
|
|
334
|
+
return preferred;
|
|
335
|
+
}
|
|
336
|
+
export const MESSAGE_QUEUE_SERIES_TOTALS = [
|
|
337
|
+
{
|
|
338
|
+
system: "rabbitmq",
|
|
339
|
+
metricName: "rabbitmq.message.current",
|
|
340
|
+
seriesKey: "state",
|
|
341
|
+
values: ["ready", "unacknowledged"],
|
|
342
|
+
reason: "The rabbitmq receiver records both states of every queue on every scrape, under the scrape's one timestamp (collectQueue in receiver/rabbitmqreceiver scraper.go@v0.161.0), so the average of each state over a bucket, added together, is the queue's average depth.",
|
|
343
|
+
},
|
|
344
|
+
];
|
|
345
|
+
function getSeriesTotalDefinition(descriptor) {
|
|
346
|
+
const seriesKeys = descriptor.seriesKeys || [];
|
|
347
|
+
for (const definition of MESSAGE_QUEUE_SERIES_TOTALS) {
|
|
348
|
+
if (definition.system === descriptor.system &&
|
|
349
|
+
definition.metricName === descriptor.metricName &&
|
|
350
|
+
seriesKeys.length === 1 &&
|
|
351
|
+
seriesKeys[0] === definition.seriesKey) {
|
|
352
|
+
return definition;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
// --- the shared query builder (templates and the "Create monitor" link) ---
|
|
358
|
+
/*
|
|
359
|
+
* Whether a monitor can evaluate this catalog entry at all: a gauge, whose
|
|
360
|
+
* series are all part of the queue. A counter only grows (see the header),
|
|
361
|
+
* and an entry with `excludeSeriesWithAttributes` needs "this attribute is
|
|
362
|
+
* absent" to leave out its finer-grained repeats, which an equality filter
|
|
363
|
+
* cannot say — both are refused rather than built into a monitor that
|
|
364
|
+
* compares the wrong number.
|
|
365
|
+
*/
|
|
366
|
+
export function isMessageQueueMetricMonitorable(descriptor) {
|
|
367
|
+
if (!descriptor || descriptor.kind !== "gauge") {
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
return !(descriptor.excludeSeriesWithAttributes &&
|
|
371
|
+
descriptor.excludeSeriesWithAttributes.length > 0);
|
|
372
|
+
}
|
|
373
|
+
function aggregationLabel(aggregationType) {
|
|
374
|
+
return aggregationType === MetricsAggregationType.Avg
|
|
375
|
+
? "Average"
|
|
376
|
+
: String(aggregationType);
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* The query shape that evaluates what the queue page shows for this entry
|
|
380
|
+
* (see AGGREGATION CONTRACT in the header), or null for an entry no monitor
|
|
381
|
+
* can evaluate (isMessageQueueMetricMonitorable).
|
|
382
|
+
*/
|
|
383
|
+
export function getMessageQueueMetricMonitorSeed(descriptor) {
|
|
384
|
+
if (!isMessageQueueMetricMonitorable(descriptor)) {
|
|
385
|
+
return null;
|
|
386
|
+
}
|
|
387
|
+
const aggregation = descriptor.aggregation;
|
|
388
|
+
const seriesKeys = [...(descriptor.seriesKeys || [])];
|
|
389
|
+
const floor = getMessageQueueSourceWindowFloor(descriptor);
|
|
390
|
+
const shape = getMonitorShape({
|
|
391
|
+
descriptor: descriptor,
|
|
392
|
+
aggregation: aggregation,
|
|
393
|
+
seriesKeys: seriesKeys,
|
|
394
|
+
});
|
|
395
|
+
return Object.assign(Object.assign({}, shape), { minimumRollingTime: floor ? floor.minimumRollingTime : null });
|
|
396
|
+
}
|
|
397
|
+
function getMonitorShape(data) {
|
|
398
|
+
const aggregation = data.aggregation;
|
|
399
|
+
const seriesKeys = data.seriesKeys;
|
|
400
|
+
switch (data.descriptor.seriesCombine) {
|
|
401
|
+
case "max":
|
|
402
|
+
if (aggregation === MetricsAggregationType.Sum) {
|
|
403
|
+
/*
|
|
404
|
+
* A per-period count: the Sum of a bucket is one series' count for
|
|
405
|
+
* its period, never Max, which on a CloudWatch Summary reads the
|
|
406
|
+
* period's Average (see AGGREGATION CONTRACT). With series keys, the
|
|
407
|
+
* worst series crossing is the highest one crossing.
|
|
408
|
+
*/
|
|
409
|
+
return {
|
|
410
|
+
aggregationType: MetricsAggregationType.Sum,
|
|
411
|
+
groupByAttributeKeys: seriesKeys,
|
|
412
|
+
seriesTotal: null,
|
|
413
|
+
note: seriesKeys.length > 0
|
|
414
|
+
? `The chart shows the highest of this metric's series (one per ${seriesKeys.join(" / ")}). A monitor would add them up, so this one alerts on each series separately, which fires exactly when the highest one crosses the threshold.`
|
|
415
|
+
: null,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
return {
|
|
419
|
+
aggregationType: MetricsAggregationType.Max,
|
|
420
|
+
groupByAttributeKeys: [],
|
|
421
|
+
seriesTotal: null,
|
|
422
|
+
note: aggregation === MetricsAggregationType.Max
|
|
423
|
+
? null
|
|
424
|
+
: `The chart shows the highest of this metric's series. A monitor folds every series and sample into one number, so this one takes their Max instead of each series' ${aggregationLabel(aggregation)}.`,
|
|
425
|
+
};
|
|
426
|
+
case "avg":
|
|
427
|
+
return {
|
|
428
|
+
aggregationType: aggregation,
|
|
429
|
+
groupByAttributeKeys: [],
|
|
430
|
+
seriesTotal: null,
|
|
431
|
+
note: null,
|
|
432
|
+
};
|
|
433
|
+
default: {
|
|
434
|
+
// "sum".
|
|
435
|
+
if (aggregation === MetricsAggregationType.Sum) {
|
|
436
|
+
return {
|
|
437
|
+
aggregationType: MetricsAggregationType.Sum,
|
|
438
|
+
groupByAttributeKeys: [],
|
|
439
|
+
seriesTotal: null,
|
|
440
|
+
note: null,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
const total = getSeriesTotalDefinition(data.descriptor);
|
|
444
|
+
if (total) {
|
|
445
|
+
// The page's own total: one query per part, added up by a formula.
|
|
446
|
+
return {
|
|
447
|
+
aggregationType: aggregation,
|
|
448
|
+
groupByAttributeKeys: [],
|
|
449
|
+
seriesTotal: { key: total.seriesKey, values: [...total.values] },
|
|
450
|
+
note: null,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
return {
|
|
454
|
+
aggregationType: aggregation,
|
|
455
|
+
groupByAttributeKeys: seriesKeys,
|
|
456
|
+
seriesTotal: null,
|
|
457
|
+
note: seriesKeys.length > 0
|
|
458
|
+
? `The chart adds this metric's series up (one per ${seriesKeys.join(" / ")}). They are not a fixed set, so a monitor cannot add them together the way the chart does: this one alerts on each series separately. Set a threshold for one series, not for the total.`
|
|
459
|
+
: null,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Every stored key a monitor filter on this entry can pin: its destination,
|
|
466
|
+
* broker-scope and required attributes. The attributes a series of the
|
|
467
|
+
* metric has to be read with to build its filter.
|
|
468
|
+
*/
|
|
469
|
+
export function getMessageQueueMetricFilterAttributeKeys(descriptor) {
|
|
470
|
+
const keys = [];
|
|
471
|
+
for (const key of [
|
|
472
|
+
...descriptor.destinationAttributes,
|
|
473
|
+
...(descriptor.scopeAttributes || []),
|
|
474
|
+
...Object.keys(descriptor.requiredAttributes || {}),
|
|
475
|
+
]) {
|
|
476
|
+
if (!keys.includes(key)) {
|
|
477
|
+
keys.push(key);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return keys;
|
|
481
|
+
}
|
|
482
|
+
function readObserved(series, key) {
|
|
483
|
+
return Object.prototype.hasOwnProperty.call(series, key)
|
|
484
|
+
? series[key]
|
|
485
|
+
: undefined;
|
|
486
|
+
}
|
|
487
|
+
/*
|
|
488
|
+
* The text a value is stored as, which is what an equality filter has to
|
|
489
|
+
* match: a string exactly as it is — surrounding whitespace included — and a
|
|
490
|
+
* number or boolean as its String() form. Null for a value that is absent,
|
|
491
|
+
* blank or not a scalar, which the resolver does not read a destination,
|
|
492
|
+
* scope or required value from either.
|
|
493
|
+
*/
|
|
494
|
+
function observedText(value) {
|
|
495
|
+
let text = null;
|
|
496
|
+
if (typeof value === "string") {
|
|
497
|
+
text = value;
|
|
498
|
+
}
|
|
499
|
+
else if (typeof value === "number") {
|
|
500
|
+
text = Number.isFinite(value) ? String(value) : null;
|
|
501
|
+
}
|
|
502
|
+
else if (typeof value === "boolean" || typeof value === "bigint") {
|
|
503
|
+
text = String(value);
|
|
504
|
+
}
|
|
505
|
+
return text !== null && text.trim().length > 0 ? text : null;
|
|
506
|
+
}
|
|
507
|
+
/*
|
|
508
|
+
* The (key, stored value) pairs that pin one series to its queue: the first
|
|
509
|
+
* destination key with a value (the resolver's own "first non-empty wins"),
|
|
510
|
+
* the first broker-scope key with one, and every required key. Null when the
|
|
511
|
+
* series lacks a destination or a required attribute.
|
|
512
|
+
*/
|
|
513
|
+
function getSeriesFilter(descriptor, series) {
|
|
514
|
+
const firstWithValue = (keys) => {
|
|
515
|
+
for (const key of keys) {
|
|
516
|
+
const text = observedText(readObserved(series, key));
|
|
517
|
+
if (text !== null) {
|
|
518
|
+
return [key, text];
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return null;
|
|
522
|
+
};
|
|
523
|
+
const destination = firstWithValue(descriptor.destinationAttributes);
|
|
524
|
+
if (!destination) {
|
|
525
|
+
return null;
|
|
526
|
+
}
|
|
527
|
+
const entries = [destination];
|
|
528
|
+
const scope = descriptor.scopeAttributes
|
|
529
|
+
? firstWithValue(descriptor.scopeAttributes)
|
|
530
|
+
: null;
|
|
531
|
+
if (scope) {
|
|
532
|
+
entries.push(scope);
|
|
533
|
+
}
|
|
534
|
+
for (const key of Object.keys(descriptor.requiredAttributes || {})) {
|
|
535
|
+
const text = observedText(readObserved(series, key));
|
|
536
|
+
if (text === null) {
|
|
537
|
+
return null;
|
|
538
|
+
}
|
|
539
|
+
entries.push([key, text]);
|
|
540
|
+
}
|
|
541
|
+
return entries;
|
|
542
|
+
}
|
|
543
|
+
/*
|
|
544
|
+
* The identifier of the queue a series of this entry belongs to, through the
|
|
545
|
+
* same resolver ingest stamps entity keys with — or null when the series
|
|
546
|
+
* resolves to nothing, or to another system's entry (a Service Bus name
|
|
547
|
+
* observed on an Event Hubs series).
|
|
548
|
+
*/
|
|
549
|
+
function getSeriesQueueIdentifier(descriptor, series) {
|
|
550
|
+
const resolved = resolveMessagingMetricDatapoint({
|
|
551
|
+
metricName: descriptor.metricName,
|
|
552
|
+
getAttribute: (key) => {
|
|
553
|
+
return readObserved(series, key);
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
if (!resolved || resolved.system !== descriptor.system) {
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
const identity = toMessageQueueIdentity({
|
|
560
|
+
system: resolved.system,
|
|
561
|
+
brokerScope: resolved.brokerScope,
|
|
562
|
+
destination: resolved.destination,
|
|
563
|
+
});
|
|
564
|
+
return identity ? buildMessageQueueIdentifier(identity) : null;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* The metric monitor query that watches one queue through one catalog
|
|
568
|
+
* entry, built from the stored attributes of the series observed for it —
|
|
569
|
+
* the code path the queue page's "Create monitor" link and getMonitorStep
|
|
570
|
+
* share. Null when the entry cannot be monitored
|
|
571
|
+
* (isMessageQueueMetricMonitorable) or no observed series resolves to the
|
|
572
|
+
* queue.
|
|
573
|
+
*
|
|
574
|
+
* A series is used only when the resolver maps it to the queue under this
|
|
575
|
+
* entry — `identity`'s queue when given, else the first series that
|
|
576
|
+
* resolves — and when it pins the same keys as the first series used (one
|
|
577
|
+
* spelling of Azure's entity key, not two: an AND of equalities cannot say
|
|
578
|
+
* "this key or that one"). Values are kept exactly as stored, and a key the
|
|
579
|
+
* used series disagree on (a Pulsar topic's partitions) becomes an Includes
|
|
580
|
+
* of every value, sorted. A queue whose destination is templated from many
|
|
581
|
+
* raw names (a UUID) is watched under the names observed.
|
|
582
|
+
*/
|
|
583
|
+
export function buildMessageQueueMetricMonitorQuery(data) {
|
|
584
|
+
if (!data || !data.descriptor) {
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
const descriptor = data.descriptor;
|
|
588
|
+
const seed = getMessageQueueMetricMonitorSeed(descriptor);
|
|
589
|
+
if (!seed) {
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
let queueIdentifier = null;
|
|
593
|
+
if (data.identity) {
|
|
594
|
+
queueIdentifier = buildMessageQueueIdentifier(data.identity);
|
|
595
|
+
if (!queueIdentifier) {
|
|
596
|
+
return null;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
let keys = null;
|
|
600
|
+
const valuesByKey = new Map();
|
|
601
|
+
const observedSeries = Array.isArray(data.observedSeries)
|
|
602
|
+
? data.observedSeries
|
|
603
|
+
: [];
|
|
604
|
+
for (const candidate of observedSeries) {
|
|
605
|
+
if (!candidate ||
|
|
606
|
+
typeof candidate !== "object" ||
|
|
607
|
+
Array.isArray(candidate)) {
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
const series = candidate;
|
|
611
|
+
const entries = getSeriesFilter(descriptor, series);
|
|
612
|
+
if (!entries) {
|
|
613
|
+
continue;
|
|
614
|
+
}
|
|
615
|
+
const identifier = getSeriesQueueIdentifier(descriptor, series);
|
|
616
|
+
if (!identifier) {
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
if (queueIdentifier === null) {
|
|
620
|
+
queueIdentifier = identifier;
|
|
621
|
+
}
|
|
622
|
+
else if (identifier !== queueIdentifier) {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
const seriesKeys = entries.map((entry) => {
|
|
626
|
+
return entry[0];
|
|
627
|
+
});
|
|
628
|
+
if (keys === null) {
|
|
629
|
+
keys = seriesKeys;
|
|
630
|
+
}
|
|
631
|
+
else if (keys.join("\n") !== seriesKeys.join("\n")) {
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
for (const [key, value] of entries) {
|
|
635
|
+
const values = valuesByKey.get(key) || [];
|
|
636
|
+
if (!values.includes(value)) {
|
|
637
|
+
values.push(value);
|
|
638
|
+
}
|
|
639
|
+
valuesByKey.set(key, values);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (keys === null) {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
const attributes = {};
|
|
646
|
+
for (const key of keys) {
|
|
647
|
+
const values = [...(valuesByKey.get(key) || [])].sort();
|
|
648
|
+
attributes[key] = values.length === 1 ? values[0] : new Includes(values);
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
metricId: getMessageQueueMetricId(descriptor),
|
|
652
|
+
metricName: descriptor.metricName,
|
|
653
|
+
attributes: attributes,
|
|
654
|
+
aggregationType: seed.aggregationType,
|
|
655
|
+
groupByAttributeKeys: [...seed.groupByAttributeKeys],
|
|
656
|
+
seriesTotal: seed.seriesTotal
|
|
657
|
+
? { key: seed.seriesTotal.key, values: [...seed.seriesTotal.values] }
|
|
658
|
+
: null,
|
|
659
|
+
unit: descriptor.unit,
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
// "unacknowledged" → "unacknowledged"; any other character → "_".
|
|
663
|
+
function toAliasPart(value) {
|
|
664
|
+
return (value
|
|
665
|
+
.toLowerCase()
|
|
666
|
+
.replace(/[^a-z0-9]+/g, "_")
|
|
667
|
+
.replace(/^_+|_+$/g, "") || "part");
|
|
668
|
+
}
|
|
669
|
+
// A copy, so a config edited in the explorer never edits the query.
|
|
670
|
+
function copyAttributes(attributes) {
|
|
671
|
+
const copy = {};
|
|
672
|
+
for (const key of Object.keys(attributes)) {
|
|
673
|
+
const value = attributes[key];
|
|
674
|
+
if (value instanceof Includes) {
|
|
675
|
+
copy[key] = new Includes([...value.values]);
|
|
676
|
+
}
|
|
677
|
+
else if (value !== undefined) {
|
|
678
|
+
copy[key] = value;
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
return copy;
|
|
682
|
+
}
|
|
683
|
+
function buildQueryConfig(data) {
|
|
684
|
+
const query = data.query;
|
|
685
|
+
return {
|
|
686
|
+
metricAliasData: {
|
|
687
|
+
metricVariable: data.metricVariable,
|
|
688
|
+
title: data.title,
|
|
689
|
+
description: data.description,
|
|
690
|
+
legend: data.title,
|
|
691
|
+
legendUnit: query.unit || undefined,
|
|
692
|
+
},
|
|
693
|
+
metricQueryData: Object.assign({ filterData: {
|
|
694
|
+
metricName: query.metricName,
|
|
695
|
+
attributes: data.attributes,
|
|
696
|
+
aggegationType: query.aggregationType,
|
|
697
|
+
aggregateBy: {},
|
|
698
|
+
} }, (query.groupByAttributeKeys.length > 0
|
|
699
|
+
? { groupByAttributeKeys: [...query.groupByAttributeKeys] }
|
|
700
|
+
: {})),
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* The metric monitor view for a queue query — what the "Create monitor"
|
|
705
|
+
* link pre-seeds Monitor Create with, and what getMonitorStep builds: the
|
|
706
|
+
* exact filters, the fold, the grouping, and the catalog's unit as the legend
|
|
707
|
+
* unit. A plain query is one query config, aliased `metricVariable`. A
|
|
708
|
+
* series total is one query per part, each also filtered on its value and
|
|
709
|
+
* aliased `<metricVariable>_<value>`, plus the formula adding them up,
|
|
710
|
+
* aliased `metricVariable` — the alias a criteria compares either way.
|
|
711
|
+
* `metricVariable` must be a formula identifier (letters, digits, "_").
|
|
712
|
+
*/
|
|
713
|
+
export function buildMessageQueueMetricMonitorViewConfig(data) {
|
|
714
|
+
const query = data.query;
|
|
715
|
+
const description = data.description || data.title;
|
|
716
|
+
const total = query.seriesTotal;
|
|
717
|
+
if (!total || total.values.length === 0) {
|
|
718
|
+
return {
|
|
719
|
+
metricViewConfig: {
|
|
720
|
+
queryConfigs: [
|
|
721
|
+
buildQueryConfig({
|
|
722
|
+
query: query,
|
|
723
|
+
attributes: copyAttributes(query.attributes),
|
|
724
|
+
metricVariable: data.metricVariable,
|
|
725
|
+
title: data.title,
|
|
726
|
+
description: description,
|
|
727
|
+
}),
|
|
728
|
+
],
|
|
729
|
+
formulaConfigs: [],
|
|
730
|
+
},
|
|
731
|
+
criteriaAlias: data.metricVariable,
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
const partAliases = total.values.map((value) => {
|
|
735
|
+
return `${data.metricVariable}_${toAliasPart(value)}`;
|
|
736
|
+
});
|
|
737
|
+
const queryConfigs = total.values.map((value, index) => {
|
|
738
|
+
return buildQueryConfig({
|
|
739
|
+
query: query,
|
|
740
|
+
attributes: Object.assign(Object.assign({}, copyAttributes(query.attributes)), { [total.key]: value }),
|
|
741
|
+
metricVariable: partAliases[index],
|
|
742
|
+
title: `${data.title} (${value})`,
|
|
743
|
+
description: description,
|
|
744
|
+
});
|
|
745
|
+
});
|
|
746
|
+
const formulaConfig = {
|
|
747
|
+
metricAliasData: {
|
|
748
|
+
metricVariable: data.metricVariable,
|
|
749
|
+
title: data.title,
|
|
750
|
+
description: description,
|
|
751
|
+
legend: data.title,
|
|
752
|
+
legendUnit: query.unit || undefined,
|
|
753
|
+
},
|
|
754
|
+
metricFormulaData: {
|
|
755
|
+
metricFormula: partAliases.join(" + "),
|
|
756
|
+
},
|
|
757
|
+
};
|
|
758
|
+
return {
|
|
759
|
+
metricViewConfig: {
|
|
760
|
+
queryConfigs: queryConfigs,
|
|
761
|
+
formulaConfigs: [formulaConfig],
|
|
762
|
+
},
|
|
763
|
+
criteriaAlias: data.metricVariable,
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
function getUntemplatedReason(descriptor) {
|
|
767
|
+
for (const entry of UNTEMPLATED_MESSAGE_QUEUE_GAUGES) {
|
|
768
|
+
if (entry.system === descriptor.system &&
|
|
769
|
+
entry.metricName === descriptor.metricName) {
|
|
770
|
+
return entry.reason;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
function getPolicyDefault(signal, measure) {
|
|
776
|
+
for (const policy of MESSAGE_QUEUE_ALERT_POLICIES) {
|
|
777
|
+
if (policy.signal === signal && policy.measure === measure) {
|
|
778
|
+
return policy;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return null;
|
|
782
|
+
}
|
|
783
|
+
function getPolicyOverride(descriptor) {
|
|
784
|
+
for (const override of MESSAGE_QUEUE_ALERT_POLICY_OVERRIDES) {
|
|
785
|
+
if (override.system === descriptor.system &&
|
|
786
|
+
override.metricNames.includes(descriptor.metricName)) {
|
|
787
|
+
return override;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return null;
|
|
791
|
+
}
|
|
792
|
+
// "1000" → "1,000"; a fraction to at most two decimals.
|
|
793
|
+
function formatNumber(value) {
|
|
794
|
+
if (!Number.isInteger(value)) {
|
|
795
|
+
return String(Number(value.toFixed(2)));
|
|
796
|
+
}
|
|
797
|
+
return String(value).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
798
|
+
}
|
|
799
|
+
function formatDuration(seconds) {
|
|
800
|
+
if (seconds > 0 && seconds % 3600 === 0) {
|
|
801
|
+
const hours = seconds / 3600;
|
|
802
|
+
return `${formatNumber(hours)} ${hours === 1 ? "hour" : "hours"}`;
|
|
803
|
+
}
|
|
804
|
+
if (seconds > 0 && seconds % 60 === 0) {
|
|
805
|
+
const minutes = seconds / 60;
|
|
806
|
+
return `${formatNumber(minutes)} ${minutes === 1 ? "minute" : "minutes"}`;
|
|
807
|
+
}
|
|
808
|
+
return `${formatNumber(seconds)} ${seconds === 1 ? "second" : "seconds"}`;
|
|
809
|
+
}
|
|
810
|
+
/*
|
|
811
|
+
* A threshold in words, in the metric's own unit: "1,000 messages",
|
|
812
|
+
* "1 message", "10 minutes".
|
|
813
|
+
*/
|
|
814
|
+
export function formatMessageQueueThreshold(value, unit) {
|
|
815
|
+
const trimmedUnit = (unit || "").trim();
|
|
816
|
+
if (trimmedUnit === "s") {
|
|
817
|
+
return formatDuration(value);
|
|
818
|
+
}
|
|
819
|
+
if (trimmedUnit === "ms") {
|
|
820
|
+
return value % 1000 === 0
|
|
821
|
+
? formatDuration(value / 1000)
|
|
822
|
+
: `${formatNumber(value)} milliseconds`;
|
|
823
|
+
}
|
|
824
|
+
if (!trimmedUnit) {
|
|
825
|
+
return formatNumber(value);
|
|
826
|
+
}
|
|
827
|
+
const singular = value === 1 && trimmedUnit.length > 1 && trimmedUnit.endsWith("s")
|
|
828
|
+
? trimmedUnit.substring(0, trimmedUnit.length - 1)
|
|
829
|
+
: trimmedUnit;
|
|
830
|
+
return `${formatNumber(value)} ${singular}`;
|
|
831
|
+
}
|
|
832
|
+
// "Dead-lettered messages" → "Dead-Lettered Messages"; small words stay small.
|
|
833
|
+
const TITLE_CASE_SMALL_WORDS = [
|
|
834
|
+
"a",
|
|
835
|
+
"an",
|
|
836
|
+
"and",
|
|
837
|
+
"at",
|
|
838
|
+
"by",
|
|
839
|
+
"for",
|
|
840
|
+
"in",
|
|
841
|
+
"of",
|
|
842
|
+
"on",
|
|
843
|
+
"or",
|
|
844
|
+
"the",
|
|
845
|
+
"to",
|
|
846
|
+
];
|
|
847
|
+
function toTitleCase(value) {
|
|
848
|
+
return value
|
|
849
|
+
.split(" ")
|
|
850
|
+
.map((word, index) => {
|
|
851
|
+
if (index > 0 && TITLE_CASE_SMALL_WORDS.includes(word.toLowerCase())) {
|
|
852
|
+
return word.toLowerCase();
|
|
853
|
+
}
|
|
854
|
+
return word
|
|
855
|
+
.split("-")
|
|
856
|
+
.map((part) => {
|
|
857
|
+
return part.length > 0
|
|
858
|
+
? `${part.charAt(0).toUpperCase()}${part.substring(1)}`
|
|
859
|
+
: part;
|
|
860
|
+
})
|
|
861
|
+
.join("-");
|
|
862
|
+
})
|
|
863
|
+
.join(" ");
|
|
864
|
+
}
|
|
865
|
+
/*
|
|
866
|
+
* A catalog title split into its name and a trailing qualifier:
|
|
867
|
+
* "Messages visible (JSON stream)" → "Messages visible", "(JSON stream)".
|
|
868
|
+
*/
|
|
869
|
+
function splitTitle(title) {
|
|
870
|
+
const match = title.match(/^(.*?)\s*(\([^()]*\))$/);
|
|
871
|
+
if (!match) {
|
|
872
|
+
return { base: title, qualifier: "" };
|
|
873
|
+
}
|
|
874
|
+
return { base: match[1] || title, qualifier: match[2] || "" };
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* The alert a catalog entry gets, or null when it gets none: not a
|
|
878
|
+
* monitorable gauge, a signal no static threshold means anything for, no
|
|
879
|
+
* default for its (signal, measure), or a deliberately untemplated gauge.
|
|
880
|
+
* The threshold is in the metric's own unit (an age of 600 s reads 600000 on
|
|
881
|
+
* a metric reported in milliseconds).
|
|
882
|
+
*/
|
|
883
|
+
export function getMessageQueueAlertPolicy(descriptor) {
|
|
884
|
+
var _a, _b;
|
|
885
|
+
if (!isMessageQueueMetricMonitorable(descriptor) ||
|
|
886
|
+
!MESSAGE_QUEUE_THRESHOLDABLE_SIGNALS.includes(descriptor.signal) ||
|
|
887
|
+
getUntemplatedReason(descriptor) !== null) {
|
|
888
|
+
return null;
|
|
889
|
+
}
|
|
890
|
+
const measure = getMessageQueueAlertMeasure(descriptor);
|
|
891
|
+
const defaults = getPolicyDefault(descriptor.signal, measure);
|
|
892
|
+
if (!defaults) {
|
|
893
|
+
return null;
|
|
894
|
+
}
|
|
895
|
+
const override = getPolicyOverride(descriptor);
|
|
896
|
+
const defaultThreshold = defaults.thresholdUnit
|
|
897
|
+
? MetricUnitUtil.convertToMetricUnit({
|
|
898
|
+
value: defaults.threshold,
|
|
899
|
+
fromUnit: defaults.thresholdUnit,
|
|
900
|
+
metricUnit: descriptor.unit,
|
|
901
|
+
})
|
|
902
|
+
: defaults.threshold;
|
|
903
|
+
// Clears the binary noise a unit conversion leaves (600 / 0.001).
|
|
904
|
+
const threshold = Number(((_a = override === null || override === void 0 ? void 0 : override.threshold) !== null && _a !== void 0 ? _a : defaultThreshold).toPrecision(12));
|
|
905
|
+
const title = splitTitle(descriptor.title);
|
|
906
|
+
const generatedName = defaults.nameSuffix
|
|
907
|
+
? `${toTitleCase(title.base)} ${defaults.nameSuffix}`
|
|
908
|
+
: toTitleCase(title.base);
|
|
909
|
+
// A late source's points never land in a window shorter than their lag.
|
|
910
|
+
const signalWindow = (override === null || override === void 0 ? void 0 : override.rollingTime) || defaults.rollingTime;
|
|
911
|
+
const rollingTime = getMessageQueueMetricMonitorRollingTime(descriptor, signalWindow);
|
|
912
|
+
return {
|
|
913
|
+
threshold: threshold,
|
|
914
|
+
thresholdLabel: `at or above ${formatMessageQueueThreshold(threshold, descriptor.unit)}`,
|
|
915
|
+
filterType: FilterType.GreaterThanOrEqualTo,
|
|
916
|
+
evaluation: defaults.evaluation,
|
|
917
|
+
rollingTime: rollingTime,
|
|
918
|
+
windowFloor: rollingTime === signalWindow
|
|
919
|
+
? null
|
|
920
|
+
: getMessageQueueSourceWindowFloor(descriptor),
|
|
921
|
+
severity: (override === null || override === void 0 ? void 0 : override.severity) || defaults.severity,
|
|
922
|
+
category: defaults.category,
|
|
923
|
+
// A count's silent window is a window without events (see THRESHOLDS).
|
|
924
|
+
recoverOnNoData: (_b = override === null || override === void 0 ? void 0 : override.recoverOnNoData) !== null && _b !== void 0 ? _b : measure === "count",
|
|
925
|
+
metricAlias: defaults.metricAlias,
|
|
926
|
+
meaning: (override === null || override === void 0 ? void 0 : override.meaning) || defaults.meaning,
|
|
927
|
+
incidentDescription: (override === null || override === void 0 ? void 0 : override.incidentDescription) || defaults.incidentDescription,
|
|
928
|
+
baseName: (override === null || override === void 0 ? void 0 : override.name) || generatedName,
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
// --- template builders ---
|
|
932
|
+
const ROLLING_TIME_WORDS = {
|
|
933
|
+
[RollingTime.Past5Minutes]: {
|
|
934
|
+
noun: "five minutes",
|
|
935
|
+
adjective: "five-minute",
|
|
936
|
+
},
|
|
937
|
+
[RollingTime.Past10Minutes]: {
|
|
938
|
+
noun: "ten minutes",
|
|
939
|
+
adjective: "ten-minute",
|
|
940
|
+
},
|
|
941
|
+
[RollingTime.Past15Minutes]: {
|
|
942
|
+
noun: "fifteen minutes",
|
|
943
|
+
adjective: "fifteen-minute",
|
|
944
|
+
},
|
|
945
|
+
[RollingTime.Past30Minutes]: {
|
|
946
|
+
noun: "thirty minutes",
|
|
947
|
+
adjective: "thirty-minute",
|
|
948
|
+
},
|
|
949
|
+
};
|
|
950
|
+
// ["ready", "unacknowledged"] → "ready and unacknowledged".
|
|
951
|
+
function joinWords(values) {
|
|
952
|
+
if (values.length <= 1) {
|
|
953
|
+
return values.join("");
|
|
954
|
+
}
|
|
955
|
+
return `${values.slice(0, -1).join(", ")} and ${values[values.length - 1]}`;
|
|
956
|
+
}
|
|
957
|
+
function getWindowWords(rollingTime) {
|
|
958
|
+
return (ROLLING_TIME_WORDS[rollingTime] || {
|
|
959
|
+
noun: rollingTime.toLowerCase(),
|
|
960
|
+
adjective: rollingTime.toLowerCase(),
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
// A collector component type: "googlecloudmonitoring", "kafka_metrics".
|
|
964
|
+
const COLLECTOR_COMPONENT_PATTERN = /^[a-z0-9_]+$/;
|
|
965
|
+
/*
|
|
966
|
+
* "the collector's `googlecloudmonitoring` receiver" — how a sentence names
|
|
967
|
+
* the component, which the catalog spells as a receiver type,
|
|
968
|
+
* "prometheus" or a product name.
|
|
969
|
+
*/
|
|
970
|
+
function describeReceiver(receiver) {
|
|
971
|
+
return COLLECTOR_COMPONENT_PATTERN.test(receiver)
|
|
972
|
+
? `the collector's \`${receiver}\` receiver`
|
|
973
|
+
: receiver;
|
|
974
|
+
}
|
|
975
|
+
function buildTemplateDescription(data) {
|
|
976
|
+
const descriptor = data.descriptor;
|
|
977
|
+
const policy = data.policy;
|
|
978
|
+
const window = getWindowWords(policy.rollingTime);
|
|
979
|
+
const subject = `"${splitTitle(descriptor.title).base}"`;
|
|
980
|
+
const perSeries = data.seed.groupByAttributeKeys.length > 0
|
|
981
|
+
? `any one ${data.seed.groupByAttributeKeys.join(" / ")} series of `
|
|
982
|
+
: "";
|
|
983
|
+
/*
|
|
984
|
+
* A late source's window holds less than its length of data (see WINDOWS
|
|
985
|
+
* AND LATE SOURCES), so its breach is worded by points, not by minutes.
|
|
986
|
+
*/
|
|
987
|
+
let breach;
|
|
988
|
+
if (policy.evaluation === EvaluateOverTimeType.AnyValue) {
|
|
989
|
+
breach = policy.windowFloor
|
|
990
|
+
? `Alert when ${perSeries}${subject} reads ${policy.thresholdLabel} at any point of a ${window.adjective} window.`
|
|
991
|
+
: `Alert when ${perSeries}${subject} reads ${policy.thresholdLabel} in any single minute of a ${window.adjective} window.`;
|
|
992
|
+
}
|
|
993
|
+
else {
|
|
994
|
+
breach = policy.windowFloor
|
|
995
|
+
? `Alert when ${perSeries}${subject} reads ${policy.thresholdLabel} at every point of a ${window.adjective} window.`
|
|
996
|
+
: `Alert when ${perSeries}${subject} stays ${policy.thresholdLabel} for ${window.noun}.`;
|
|
997
|
+
}
|
|
998
|
+
const sentences = [breach, policy.meaning];
|
|
999
|
+
if (policy.windowFloor) {
|
|
1000
|
+
sentences.push(policy.windowFloor.reason);
|
|
1001
|
+
}
|
|
1002
|
+
sentences.push(`Reads ${descriptor.metricName}. ${descriptor.description}`);
|
|
1003
|
+
if (data.seed.seriesTotal) {
|
|
1004
|
+
sentences.push(`The monitor reads the ${joinWords(data.seed.seriesTotal.values)} series with one query each and adds them up with a formula, the total the queue page shows.`);
|
|
1005
|
+
}
|
|
1006
|
+
if (data.seed.groupByAttributeKeys.length > 0) {
|
|
1007
|
+
sentences.push("Its series are not a fixed set, so the monitor cannot add them up the way the queue page does: it watches each series on its own, and the threshold is for one series, not for the total.");
|
|
1008
|
+
}
|
|
1009
|
+
if (!descriptor.enabledByDefault) {
|
|
1010
|
+
sentences.push(`${capitalizeFirst(describeReceiver(descriptor.receiver))} only reports ${descriptor.metricName} once it is enabled in the collector's configuration${descriptor.receiver === "googlecloudmonitoring"
|
|
1011
|
+
? " (listed under the receiver's `metrics_list`)"
|
|
1012
|
+
: ""}.`);
|
|
1013
|
+
}
|
|
1014
|
+
return sentences.join(" ");
|
|
1015
|
+
}
|
|
1016
|
+
function capitalizeFirst(value) {
|
|
1017
|
+
return value.length > 0
|
|
1018
|
+
? `${value.charAt(0).toUpperCase()}${value.substring(1)}`
|
|
1019
|
+
: value;
|
|
1020
|
+
}
|
|
1021
|
+
/*
|
|
1022
|
+
* "rabbitmq.message.current (resource.rabbitmq.queue.name = orders), state
|
|
1023
|
+
* ready + unacknowledged" or "…, per broker" — the query as the criteria
|
|
1024
|
+
* description names it.
|
|
1025
|
+
*/
|
|
1026
|
+
function describeQuery(query) {
|
|
1027
|
+
const filters = Object.keys(query.attributes).map((key) => {
|
|
1028
|
+
const value = query.attributes[key];
|
|
1029
|
+
if (value instanceof Includes) {
|
|
1030
|
+
const values = value.values;
|
|
1031
|
+
return `${key} in [${values
|
|
1032
|
+
.map((item) => {
|
|
1033
|
+
return String(item);
|
|
1034
|
+
})
|
|
1035
|
+
.join(", ")}]`;
|
|
1036
|
+
}
|
|
1037
|
+
return `${key} = ${String(value)}`;
|
|
1038
|
+
});
|
|
1039
|
+
let series = "";
|
|
1040
|
+
if (query.seriesTotal) {
|
|
1041
|
+
series = `, ${query.seriesTotal.key} ${query.seriesTotal.values.join(" + ")}`;
|
|
1042
|
+
}
|
|
1043
|
+
else if (query.groupByAttributeKeys.length > 0) {
|
|
1044
|
+
series = `, per ${query.groupByAttributeKeys.join(" / ")}`;
|
|
1045
|
+
}
|
|
1046
|
+
return `${query.metricName} (${filters.join(", ")})${series}`;
|
|
1047
|
+
}
|
|
1048
|
+
function describeCriteria(data) {
|
|
1049
|
+
if (data.policy.evaluation === EvaluateOverTimeType.AnyValue) {
|
|
1050
|
+
return `Triggers when ${data.subject} reads ${data.policy.thresholdLabel} at any point in the evaluation window.`;
|
|
1051
|
+
}
|
|
1052
|
+
return `Triggers when ${data.subject} stays ${data.policy.thresholdLabel} for the whole evaluation window.`;
|
|
1053
|
+
}
|
|
1054
|
+
function buildCriteria(data) {
|
|
1055
|
+
const policy = data.policy;
|
|
1056
|
+
const unhealthy = buildUnhealthyCriteriaInstance({
|
|
1057
|
+
offlineMonitorStatusId: data.args.offlineMonitorStatusId,
|
|
1058
|
+
incidentSeverityId: data.args.defaultIncidentSeverityId,
|
|
1059
|
+
alertSeverityId: data.args.defaultAlertSeverityId,
|
|
1060
|
+
monitorName: data.args.monitorName,
|
|
1061
|
+
metricAlias: data.criteriaAlias,
|
|
1062
|
+
filterType: policy.filterType,
|
|
1063
|
+
value: policy.threshold,
|
|
1064
|
+
incidentTitle: `[Queue] ${data.templateName} - ${data.args.monitorName}`,
|
|
1065
|
+
incidentDescription: policy.incidentDescription,
|
|
1066
|
+
criteriaName: `${data.templateName} - ${policy.thresholdLabel}`,
|
|
1067
|
+
criteriaDescription: describeCriteria({
|
|
1068
|
+
subject: describeQuery(data.query),
|
|
1069
|
+
policy: policy,
|
|
1070
|
+
}),
|
|
1071
|
+
resourceNoun: "queue",
|
|
1072
|
+
metricAggregationType: policy.evaluation,
|
|
1073
|
+
});
|
|
1074
|
+
/*
|
|
1075
|
+
* Recovery mirrors the breach: the complementary comparison below a dead
|
|
1076
|
+
* band, held for the whole window — also for a count, which breaches on
|
|
1077
|
+
* any one minute — and, where a silent window means zero, met by one.
|
|
1078
|
+
*/
|
|
1079
|
+
const healthy = buildHealthyCriteriaInstance({
|
|
1080
|
+
onlineMonitorStatusId: data.args.onlineMonitorStatusId,
|
|
1081
|
+
metricAlias: data.criteriaAlias,
|
|
1082
|
+
filterType: getRecoveryFilterType(policy.filterType),
|
|
1083
|
+
value: policy.threshold,
|
|
1084
|
+
metricAggregationType: policy.evaluation === EvaluateOverTimeType.AnyValue
|
|
1085
|
+
? EvaluateOverTimeType.AllValues
|
|
1086
|
+
: policy.evaluation,
|
|
1087
|
+
treatNoDataAsZero: policy.recoverOnNoData,
|
|
1088
|
+
});
|
|
1089
|
+
const monitorCriteria = new MonitorCriteria();
|
|
1090
|
+
monitorCriteria.data = {
|
|
1091
|
+
monitorCriteriaInstanceArray: [unhealthy, healthy],
|
|
1092
|
+
};
|
|
1093
|
+
return monitorCriteria;
|
|
1094
|
+
}
|
|
1095
|
+
// "aws_sqs" + "amazonaws.com/aws/sqs/x" → "aws-sqs-amazonaws-com-aws-sqs-x".
|
|
1096
|
+
function toIdSlug(value) {
|
|
1097
|
+
return value
|
|
1098
|
+
.toLowerCase()
|
|
1099
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
1100
|
+
.replace(/^-+|-+$/g, "");
|
|
1101
|
+
}
|
|
1102
|
+
function buildTemplate(descriptor) {
|
|
1103
|
+
const policy = getMessageQueueAlertPolicy(descriptor);
|
|
1104
|
+
const seed = getMessageQueueMetricMonitorSeed(descriptor);
|
|
1105
|
+
if (!policy || !seed) {
|
|
1106
|
+
return null;
|
|
1107
|
+
}
|
|
1108
|
+
const qualifier = splitTitle(descriptor.title).qualifier;
|
|
1109
|
+
const name = qualifier
|
|
1110
|
+
? `${policy.baseName} ${qualifier}`
|
|
1111
|
+
: policy.baseName;
|
|
1112
|
+
return {
|
|
1113
|
+
id: `message-queue-${toIdSlug(descriptor.system)}-${toIdSlug(descriptor.metricName)}`,
|
|
1114
|
+
name: name,
|
|
1115
|
+
description: buildTemplateDescription({
|
|
1116
|
+
descriptor: descriptor,
|
|
1117
|
+
policy: policy,
|
|
1118
|
+
seed: seed,
|
|
1119
|
+
}),
|
|
1120
|
+
category: policy.category,
|
|
1121
|
+
severity: policy.severity,
|
|
1122
|
+
monitorType: MonitorType.Metrics,
|
|
1123
|
+
system: descriptor.system,
|
|
1124
|
+
receiver: descriptor.receiver,
|
|
1125
|
+
signal: descriptor.signal,
|
|
1126
|
+
metricId: getMessageQueueMetricId(descriptor),
|
|
1127
|
+
metricName: descriptor.metricName,
|
|
1128
|
+
metricNames: [descriptor.metricName],
|
|
1129
|
+
unit: descriptor.unit,
|
|
1130
|
+
aggregationType: seed.aggregationType,
|
|
1131
|
+
groupByAttributeKeys: [...seed.groupByAttributeKeys],
|
|
1132
|
+
seriesTotal: seed.seriesTotal
|
|
1133
|
+
? { key: seed.seriesTotal.key, values: [...seed.seriesTotal.values] }
|
|
1134
|
+
: null,
|
|
1135
|
+
filterType: policy.filterType,
|
|
1136
|
+
threshold: policy.threshold,
|
|
1137
|
+
thresholdLabel: policy.thresholdLabel,
|
|
1138
|
+
evaluation: policy.evaluation,
|
|
1139
|
+
rollingTime: policy.rollingTime,
|
|
1140
|
+
recoverOnNoData: policy.recoverOnNoData,
|
|
1141
|
+
getMonitorStep: (args) => {
|
|
1142
|
+
if (!args) {
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
const query = buildMessageQueueMetricMonitorQuery({
|
|
1146
|
+
descriptor: descriptor,
|
|
1147
|
+
observedSeries: args.observedSeries,
|
|
1148
|
+
identity: args.identity,
|
|
1149
|
+
});
|
|
1150
|
+
if (!query) {
|
|
1151
|
+
return null;
|
|
1152
|
+
}
|
|
1153
|
+
const step = MonitorStep.getDefaultMonitorStep({
|
|
1154
|
+
monitorName: args.monitorName,
|
|
1155
|
+
monitorType: MonitorType.Metrics,
|
|
1156
|
+
onlineMonitorStatusId: args.onlineMonitorStatusId,
|
|
1157
|
+
offlineMonitorStatusId: args.offlineMonitorStatusId,
|
|
1158
|
+
defaultIncidentSeverityId: args.defaultIncidentSeverityId,
|
|
1159
|
+
defaultAlertSeverityId: args.defaultAlertSeverityId,
|
|
1160
|
+
});
|
|
1161
|
+
const view = buildMessageQueueMetricMonitorViewConfig({
|
|
1162
|
+
query: query,
|
|
1163
|
+
metricVariable: policy.metricAlias,
|
|
1164
|
+
title: name,
|
|
1165
|
+
description: descriptor.description,
|
|
1166
|
+
});
|
|
1167
|
+
step.setMetricMonitor({
|
|
1168
|
+
rollingTime: policy.rollingTime,
|
|
1169
|
+
metricViewConfig: view.metricViewConfig,
|
|
1170
|
+
});
|
|
1171
|
+
step.setMonitorCriteria(buildCriteria({
|
|
1172
|
+
args: args,
|
|
1173
|
+
templateName: name,
|
|
1174
|
+
query: query,
|
|
1175
|
+
policy: policy,
|
|
1176
|
+
criteriaAlias: view.criteriaAlias,
|
|
1177
|
+
}));
|
|
1178
|
+
return step;
|
|
1179
|
+
},
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
/*
|
|
1183
|
+
* Every catalog entry's template, in catalog order, built once. The product
|
|
1184
|
+
* reads them one at a time, by catalog entry, and never as a list (see WHO
|
|
1185
|
+
* READS THEM).
|
|
1186
|
+
*/
|
|
1187
|
+
const ALL_MESSAGE_QUEUE_ALERT_TEMPLATES = MESSAGE_QUEUE_METRICS.map((descriptor) => {
|
|
1188
|
+
return buildTemplate(descriptor);
|
|
1189
|
+
}).filter((template) => {
|
|
1190
|
+
return template !== null;
|
|
1191
|
+
});
|
|
1192
|
+
/**
|
|
1193
|
+
* The template of one catalog entry, or undefined when the entry has none:
|
|
1194
|
+
* where the "Create monitor" link reads its starting threshold, comparison,
|
|
1195
|
+
* severity and window. Keyed by the entry (getMessageQueueMetricId), not the
|
|
1196
|
+
* metric name, which Service Bus and Event Hubs share.
|
|
1197
|
+
*/
|
|
1198
|
+
export function getMessageQueueAlertTemplateForMetric(descriptor) {
|
|
1199
|
+
if (!descriptor) {
|
|
1200
|
+
return undefined;
|
|
1201
|
+
}
|
|
1202
|
+
const metricId = getMessageQueueMetricId(descriptor);
|
|
1203
|
+
return ALL_MESSAGE_QUEUE_ALERT_TEMPLATES.find((template) => {
|
|
1204
|
+
return template.metricId === metricId;
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
//# sourceMappingURL=MessageQueueAlertTemplates.js.map
|