@oneuptime/common 13.0.0 → 13.0.1
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/Alert.ts +55 -0
- package/Models/DatabaseModels/CloudResource.ts +45 -7
- package/Models/DatabaseModels/CodeRepository.ts +85 -0
- package/Models/DatabaseModels/GoogleSecOpsConnection.ts +57 -7
- package/Models/DatabaseModels/GoogleSecOpsConnectionRun.ts +263 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/Index.ts +16 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
- package/Models/DatabaseModels/User.ts +51 -2
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +43 -2
- package/Models/DatabaseModels/UserWebAuthn.ts +17 -0
- package/Models/DatabaseModels/VMwareResource.ts +1149 -0
- package/Models/DatabaseModels/VMwareVCenter.ts +1122 -0
- package/Models/DatabaseModels/VMwareVCenterFeed.ts +625 -0
- package/Models/DatabaseModels/VMwareVCenterLabelRule.ts +514 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerRule.ts +596 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerTeam.ts +485 -0
- package/Models/DatabaseModels/VMwareVCenterOwnerUser.ts +484 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +22 -1
- package/Server/API/AIAgentDataAPI.ts +79 -4
- package/Server/API/AIAgentGitHubAPI.ts +523 -0
- package/Server/API/AIChatAPI.ts +20 -1
- package/Server/API/BillingAPI.ts +33 -0
- package/Server/API/DashboardAPI.ts +10 -0
- package/Server/API/GitHubAPI.ts +47 -5
- package/Server/API/GoogleSecOpsConnectionAPI.ts +79 -0
- package/Server/API/UserWebAuthnAPI.ts +21 -1
- package/Server/API/VMwareResourceAPI.ts +143 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.ts +68 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.ts +636 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.ts +83 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Middleware/IdentityRateLimit.ts +101 -0
- package/Server/Services/AIRunService.ts +13 -0
- package/Server/Services/BillingPaymentMethodService.ts +99 -28
- package/Server/Services/BillingService.ts +287 -20
- package/Server/Services/CloudResourceInstanceService.ts +70 -0
- package/Server/Services/ExceptionAggregationService.ts +1 -0
- package/Server/Services/GoogleSecOpsConnectionRunService.ts +10 -0
- package/Server/Services/GoogleSecOpsConnectionService.ts +12 -0
- package/Server/Services/Index.ts +16 -0
- package/Server/Services/LogAggregationService.ts +1 -0
- package/Server/Services/MetricAggregationService.ts +1 -0
- package/Server/Services/MobilePasskeyLoginService.ts +216 -0
- package/Server/Services/MonitorService.ts +51 -1
- package/Server/Services/MonitorTemplateService.ts +91 -29
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +132 -1
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +176 -2
- package/Server/Services/OpenTelemetryIngestService.ts +17 -0
- package/Server/Services/PayAsYouGoBillingService.ts +446 -0
- package/Server/Services/ProjectService.ts +46 -2
- package/Server/Services/ServerlessFunctionInstanceService.ts +71 -0
- package/Server/Services/TeamMemberService.ts +96 -36
- package/Server/Services/TelemetryIngestionKeyService.ts +80 -10
- package/Server/Services/TelemetryUsageBillingService.ts +95 -5
- package/Server/Services/TraceAggregationService.ts +5 -4
- package/Server/Services/UserWebAuthnService.ts +592 -133
- package/Server/Services/VMwareResourceService.ts +648 -0
- package/Server/Services/VMwareVCenterFeedService.ts +99 -0
- package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +240 -0
- package/Server/Services/VMwareVCenterLabelRuleService.ts +14 -0
- package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +252 -0
- package/Server/Services/VMwareVCenterOwnerRuleService.ts +14 -0
- package/Server/Services/VMwareVCenterOwnerTeamService.ts +139 -0
- package/Server/Services/VMwareVCenterOwnerUserService.ts +133 -0
- package/Server/Services/VMwareVCenterService.ts +629 -0
- package/Server/Services/WorkflowVariableService.ts +203 -0
- package/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.ts +17 -0
- package/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.ts +31 -1
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +7 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.ts +341 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.ts +274 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.ts +375 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubConversation.ts +846 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.ts +360 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubRunReply.ts +421 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.ts +140 -0
- package/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.ts +906 -0
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +143 -0
- package/Server/Utils/DataSource/EgressGuard.ts +160 -15
- package/Server/Utils/Database/TruncateColumnValue.ts +1 -1
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +2 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +33 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +44 -0
- package/Server/Utils/LogRedaction.ts +2 -1
- package/Server/Utils/Monitor/MonitorAlert.ts +1 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +302 -3
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +26 -4
- package/Server/Utils/Monitor/MonitorResourceContext.ts +5 -3
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +14 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +1 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +26 -0
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +28 -5
- package/Server/Utils/ResourceFeed/ResourceFeedUtil.ts +3 -3
- package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +14 -9
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +116 -84
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +594 -195
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +466 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +5 -0
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +2 -1
- package/Server/Utils/Telemetry/TelemetryEntity.ts +181 -1
- package/Server/Utils/Telemetry/VMwareSnapshotScan.ts +1352 -0
- package/Tests/App/Accounts/LoginPasskey.test.tsx +529 -0
- package/Tests/App/Accounts/MobilePasskey.test.tsx +620 -0
- package/Tests/App/Accounts/PasswordRequirements.test.tsx +254 -0
- package/Tests/App/Accounts/RegisterPassword.test.tsx +553 -0
- package/Tests/App/Dashboard/AskAiAvailability.test.ts +224 -0
- package/Tests/App/Dashboard/AskAiDisabled.test.tsx +432 -0
- package/Tests/App/Dashboard/BackupCodes.test.tsx +414 -0
- package/Tests/App/Dashboard/BillingPaidUsageFlow.test.tsx +530 -0
- package/Tests/App/Dashboard/BillingPaymentMethodForm.test.tsx +195 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +199 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +198 -0
- package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +215 -0
- package/Tests/App/Dashboard/CloudFleetSummary.test.ts +183 -0
- package/Tests/App/Dashboard/CloudFleetSummaryComponent.test.tsx +248 -0
- package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +215 -0
- package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +3 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +441 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +458 -0
- package/Tests/App/Dashboard/DashboardToolbarPopupLayering.test.tsx +566 -0
- package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +376 -0
- package/Tests/App/Dashboard/DiscoveryScanLiveUpdates.test.tsx +642 -0
- package/Tests/App/Dashboard/DiscoveryScanProgress.test.tsx +267 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +69 -231
- package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +244 -0
- package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +724 -0
- package/Tests/App/Dashboard/MonitorTemplateSyncFields.test.tsx +539 -0
- package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +24 -7
- package/Tests/App/Dashboard/OnCallOverridePresentation.test.ts +496 -0
- package/Tests/App/Dashboard/OnCallScheduleOverrideClarity.test.tsx +677 -0
- package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +31 -3
- package/Tests/App/Dashboard/PaidUsageConsent.test.tsx +180 -0
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +1220 -0
- package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +176 -275
- package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +380 -233
- package/Tests/App/Dashboard/ProductMenuBreadcrumbs.test.tsx +3 -23
- package/Tests/App/Dashboard/ResourceFeed.test.tsx +1 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/TwoFactorStatus.test.tsx +260 -0
- package/Tests/App/Dashboard/VMwareDashboardWidgets.test.ts +573 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +2 -0
- package/Tests/App/Dashboard/WorkflowVariablesTable.test.tsx +768 -0
- package/Tests/App/StatusPage/StatusPageOverviewLiveAndSearch.test.tsx +532 -40
- package/Tests/App/StatusPage/StatusPageResourceSearchBox.test.tsx +19 -2
- package/Tests/Fixtures/MobilePasskeyUser.json +8 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +25 -6
- package/Tests/Models/DatabaseModels/VMwareModels.test.ts +1134 -0
- package/Tests/Models/RunnerVersionLabel.test.ts +4 -2
- package/Tests/Server/API/AIChatProvidersAIEnabled.test.ts +259 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +31 -2
- package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +116 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +29 -1
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +13 -2
- package/Tests/Server/API/GitHubWebhookSignature.test.ts +368 -0
- package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +248 -0
- package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +330 -0
- package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +172 -0
- package/Tests/Server/API/VMwareResourceAPI.test.ts +546 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupMetadataMigration.test.ts +85 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +34 -3
- package/Tests/Server/Middleware/PasskeyRateLimit.test.ts +141 -0
- package/Tests/Server/Services/AutoImportRuleRearmRecentScans.test.ts +343 -0
- package/Tests/Server/Services/AutoImportRuleWriteRearmsScans.test.ts +381 -0
- package/Tests/Server/Services/BillingPaymentMethodServiceSync.test.ts +175 -0
- package/Tests/Server/Services/BillingService.test.ts +26 -11
- package/Tests/Server/Services/BillingServiceMeteredPaymentAuthorization.test.ts +245 -0
- package/Tests/Server/Services/BillingServicePaymentMethodReads.test.ts +362 -0
- package/Tests/Server/Services/CloudResourceInstanceStalePrune.test.ts +188 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +16 -2
- package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +153 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +13 -0
- package/Tests/Server/Services/InventoryItemPromotionGate.test.ts +5 -0
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +36 -0
- package/Tests/Server/Services/InventoryUpsertTruncationGuard.test.ts +151 -0
- package/Tests/Server/Services/MobilePasskeyLoginIntegration.test.ts +231 -0
- package/Tests/Server/Services/MobilePasskeyLoginService.test.ts +315 -0
- package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +302 -0
- package/Tests/Server/Services/MonitorTemplateServiceFieldSync.test.ts +994 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +22 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
- package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +857 -0
- package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +379 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +99 -1
- package/Tests/Server/Services/ProjectServiceSubscriptionSeats.test.ts +134 -0
- package/Tests/Server/Services/ResourceFeedServices.test.ts +3 -2
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +32 -6
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +363 -175
- package/Tests/Server/Services/ServerlessFunctionInstanceStalePrune.test.ts +200 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +3 -0
- package/Tests/Server/Services/TeamMemberBillingSeatSync.test.ts +762 -0
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +3 -0
- package/Tests/Server/Services/TelemetryIngestionKeyPolicyResolution.test.ts +72 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +17 -4
- package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +355 -0
- package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +41 -4
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +37 -0
- package/Tests/Server/Services/UserWebAuthnPasskeyIntegration.test.ts +401 -0
- package/Tests/Server/Services/UserWebAuthnPasskeyService.test.ts +769 -0
- package/Tests/Server/Services/UserWebAuthnUserVerification.test.ts +649 -0
- package/Tests/Server/Services/VMwareResourceService.test.ts +945 -0
- package/Tests/Server/Services/VMwareVCenterService.test.ts +722 -0
- package/Tests/Server/Services/WorkflowVariableRenameUniqueness.test.ts +842 -0
- package/Tests/Server/TestingUtils/PasskeyHttpIntegration.ts +102 -0
- package/Tests/Server/TestingUtils/SecurityKey.ts +464 -0
- package/Tests/Server/TestingUtils/WebAuthnServiceMocks.ts +60 -0
- package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +573 -0
- package/Tests/Server/Types/Database/Permissions/ProjectCustomerSupportAccessColumn.test.ts +261 -0
- package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +95 -0
- package/Tests/Server/Utils/CodeRepository/GitHubAgentTaskTrigger.test.ts +2101 -0
- package/Tests/Server/Utils/CodeRepository/GitHubCommandAuthorizer.test.ts +883 -0
- package/Tests/Server/Utils/CodeRepository/GitHubCommandParser.test.ts +1474 -0
- package/Tests/Server/Utils/CodeRepository/GitHubConversation.test.ts +1526 -0
- package/Tests/Server/Utils/CodeRepository/GitHubReplyComposer.test.ts +1389 -0
- package/Tests/Server/Utils/CodeRepository/GitHubRunReply.test.ts +1707 -0
- package/Tests/Server/Utils/CodeRepository/GitHubWebhookHandler.test.ts +2202 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +345 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +896 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupMetadataIntegration.test.ts +246 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +299 -1
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +6 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +185 -0
- package/Tests/Server/Utils/LogRedaction.test.ts +33 -0
- package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +2 -1
- package/Tests/Server/Utils/Monitor/Criteria/TelemetryStepMetricAlias.test.ts +10 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +66 -1
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +362 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +60 -1
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +60 -0
- package/Tests/Server/Utils/Monitor/MonitorRootCauseTargetResolution.test.ts +423 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +6 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +46 -2
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +81 -45
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +711 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClickhouseIntegration.test.ts +223 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +69 -1
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +838 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsErrorHandling.test.ts +241 -28
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsHttpIntegration.test.ts +651 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +11 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +13 -12
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +112 -127
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsRequestContract.test.ts +12 -18
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsResponseParsing.test.ts +43 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +580 -0
- package/Tests/Server/Utils/Telemetry/VMwareSnapshotScan.test.ts +1748 -0
- package/Tests/Types/Cloud/CloudPlatform.test.ts +574 -0
- package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +2 -0
- package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +9 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorStepInfraMonitorUtils.test.ts +53 -8
- package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +97 -0
- package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorStepTemplateSyncFields.test.ts +107 -0
- package/Tests/Types/Monitor/MonitorTemplateSyncField.test.ts +172 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +2 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationAlertDebuggability.test.ts +1 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +9 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/SeriesContext/SeriesDebugHints.test.ts +131 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +10 -0
- package/Tests/Types/Monitor/VMwareAlertTemplates.test.ts +1608 -0
- package/Tests/Types/Monitor/VMwareMetricCatalog.test.ts +488 -0
- package/Tests/Types/OnCallDutyPolicy/OverrideProvenance.test.ts +295 -0
- package/Tests/Types/Runner/RunnerLiveStatus.test.ts +2 -2
- package/Tests/Types/SignupPassword.test.ts +205 -0
- package/Tests/Types/StatusPage/StatusPageLanguage.test.ts +44 -0
- package/Tests/Types/SupportedLanguages.test.ts +119 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +19 -0
- package/Tests/UI/ColorPickerBuild.test.ts +86 -0
- package/Tests/UI/Components/Breadcrumbs.test.tsx +32 -0
- package/Tests/UI/Components/Forms/ModelFormPreservesUserInput.test.tsx +937 -0
- package/Tests/UI/Components/Forms/ModelFormWriteOnlyColumnSelect.test.tsx +230 -0
- package/Tests/UI/Components/Forms/ValidationFormSteps.test.ts +3 -4
- package/Tests/UI/Components/LabelRuleImportExport.test.tsx +907 -0
- package/Tests/UI/Components/ModelTable/ModelTableCreateAfterEdit.test.tsx +514 -0
- package/Tests/UI/Components/MonitorGraphs/Uptime.test.tsx +301 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +2 -1
- package/Tests/UI/Components/TooltipLazyContent.test.tsx +373 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsMessagingEndpointGuidance.test.tsx +43 -12
- package/Tests/UI/ReactDomBuild.test.ts +104 -0
- package/Tests/UI/ReactRouterSingletonBuild.test.ts +11 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +148 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +29 -0
- package/Tests/UI/Utils/DashboardStackingLayers.test.ts +197 -0
- package/Tests/UI/Utils/LabelRuleImportExport.test.ts +546 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +109 -2
- package/Tests/UI/Utils/UseDashboardGridDnd.test.tsx +7 -2
- package/Tests/UI/Utils/UserEmailRegistrationStatus.test.tsx +295 -0
- package/Tests/UI/Utils/WebAuthn.test.ts +265 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentDefaults.test.ts +5 -0
- package/Tests/Utils/Dashboard/Components/DashboardVMwareListComponents.test.ts +548 -0
- package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +17 -3
- package/Tests/Utils/LabelRuleImportExport.test.ts +583 -0
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/MonitorTemplateSyncUtil.test.ts +590 -0
- package/Tests/Utils/RequestFailedDetails.test.ts +325 -0
- package/Tests/Utils/Telemetry/CloudInstanceIdentity.test.ts +255 -0
- package/Tests/Utils/Telemetry/EntityRelationship.test.ts +167 -0
- package/Tests/Utils/WebAuthnTestUtil.ts +79 -0
- package/Tests/__mocks__/simplewebauthn.js +33 -4
- package/Types/AI/CodeFixTaskContext.ts +122 -0
- package/Types/AI/CodeFixTaskType.ts +62 -0
- package/Types/Accounts/AccountsLanguage.ts +1 -0
- package/Types/AdminDashboard/AdminDashboardLanguage.ts +1 -0
- package/Types/Calendar/CalendarEvent.ts +16 -0
- package/Types/Cloud/CloudPlatform.ts +372 -0
- package/Types/CodeRepository/GitHubCommand.ts +69 -0
- package/Types/Dashboard/DashboardComponentType.ts +2 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.ts +23 -0
- package/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.ts +30 -0
- package/Types/Dashboard/DashboardLanguage.ts +1 -0
- package/Types/Dashboard/DashboardTemplates.ts +314 -0
- package/Types/Docs/DocsLanguage.ts +1 -0
- package/Types/Exception/EgressGuardException.ts +65 -0
- package/Types/Icon/IconProp.ts +1 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +36 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +1 -0
- package/Types/Monitor/MonitorStep.ts +78 -17
- package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +1 -0
- package/Types/Monitor/MonitorStepVMwareMonitor.ts +127 -0
- package/Types/Monitor/MonitorTemplateSyncField.ts +291 -0
- package/Types/Monitor/MonitorType.ts +24 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +33 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +2 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +3 -0
- package/Types/Monitor/SeriesContext/SeriesDebugHints.ts +158 -0
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +61 -0
- package/Types/Monitor/VMwareAlertTemplates.ts +1070 -0
- package/Types/Monitor/VMwareMetricCatalog.ts +914 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +29 -0
- package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +16 -0
- package/Types/Password.ts +84 -5
- package/Types/Permission.ts +265 -0
- package/Types/Probe/RequestFailedDetails.ts +7 -0
- package/Types/Runner/RunnerLiveStatus.ts +1 -1
- package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +56 -0
- package/Types/StatusPage/StatusPageLanguage.ts +1 -0
- package/Types/Telemetry/EntityType.ts +21 -0
- package/Types/Telemetry/ServiceType.ts +1 -0
- package/Typings/Index.d.ts +63 -0
- package/UI/Components/Breadcrumbs/Breadcrumbs.tsx +2 -2
- package/UI/Components/Calendar/Calendar.css +78 -0
- package/UI/Components/Calendar/Calendar.tsx +28 -3
- package/UI/Components/Forms/BasicForm.tsx +44 -2
- package/UI/Components/Forms/Fields/ColorPicker.tsx +2 -1
- package/UI/Components/Forms/Fields/FormField.tsx +16 -3
- package/UI/Components/Forms/ModelForm.tsx +159 -5
- package/UI/Components/Forms/Types/Field.ts +8 -1
- package/UI/Components/Graphs/DayUptimeGraph.tsx +8 -10
- package/UI/Components/Icon/Icon.tsx +16 -0
- package/UI/Components/Input/Input.tsx +42 -7
- package/UI/Components/LabelRule/ImportLabelRulesModal.tsx +441 -0
- package/UI/Components/LabelRule/LabelRuleTable.tsx +142 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +22 -5
- package/UI/Components/ModelTable/ModelTable.tsx +14 -6
- package/UI/Components/MonitorGraphs/Uptime.tsx +17 -27
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +3 -1
- package/UI/Components/Tooltip/Tooltip.tsx +52 -6
- package/UI/Utils/DashboardStackingLayers.ts +85 -0
- package/UI/Utils/LabelRuleImportExport.ts +310 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +4 -3
- package/UI/Utils/TelemetryService.ts +4 -3
- package/UI/Utils/UseDashboardGridDnd.ts +4 -1
- package/UI/Utils/UserEmailRegistrationStatus.ts +33 -5
- package/UI/Utils/WebAuthn.ts +220 -0
- package/UI/esbuild-config.js +4 -0
- package/Utils/API.ts +34 -0
- package/Utils/Dashboard/Components/DashboardVMwareHostListComponent.ts +38 -0
- package/Utils/Dashboard/Components/DashboardVMwareResourceListShared.ts +70 -0
- package/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.ts +76 -0
- package/Utils/Dashboard/Components/Index.ts +16 -0
- package/Utils/LabelRuleImportExport.ts +496 -0
- package/Utils/Monitor/MonitorTemplateSyncUtil.ts +164 -0
- package/Utils/NetworkDiscovery/DiscoveryScanStatus.ts +8 -0
- package/Utils/Telemetry/CloudInstanceIdentity.ts +94 -0
- package/Utils/Telemetry/EntityKey.ts +19 -0
- package/Utils/Telemetry/EntityRelationship.ts +19 -0
- package/build/dist/Models/DatabaseModels/Alert.js +54 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +44 -7
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CodeRepository.js +87 -0
- package/build/dist/Models/DatabaseModels/CodeRepository.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +60 -7
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js +287 -0
- package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Incident.js +54 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +57 -4
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +47 -2
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js +18 -0
- package/build/dist/Models/DatabaseModels/UserWebAuthn.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareResource.js +1201 -0
- package/build/dist/Models/DatabaseModels/VMwareResource.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +1149 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js +503 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js +502 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +22 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AIAgentDataAPI.js +63 -3
- package/build/dist/Server/API/AIAgentDataAPI.js.map +1 -1
- package/build/dist/Server/API/AIAgentGitHubAPI.js +363 -0
- package/build/dist/Server/API/AIAgentGitHubAPI.js.map +1 -0
- package/build/dist/Server/API/AIChatAPI.js +19 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/BillingAPI.js +22 -0
- package/build/dist/Server/API/BillingAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +10 -0
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/GitHubAPI.js +33 -5
- package/build/dist/Server/API/GitHubAPI.js.map +1 -1
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +56 -0
- package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +1 -0
- package/build/dist/Server/API/UserWebAuthnAPI.js +17 -1
- package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
- package/build/dist/Server/API/VMwareResourceAPI.js +106 -0
- package/build/dist/Server/API/VMwareResourceAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791800000000-SplitWebAuthnChallengeByPurpose.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791900000000-AddSeverityAndStateToNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.js +241 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792000000000-AddVMwareTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792100000000-AddGitHubCommandSettingsToCodeRepository.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792200000000-AddUserWebAuthnPurpose.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792300000000-AddGoogleSecOpsDiagnostics.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +80 -0
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Services/AIRunService.js +14 -1
- package/build/dist/Server/Services/AIRunService.js.map +1 -1
- package/build/dist/Server/Services/BillingPaymentMethodService.js +71 -21
- package/build/dist/Server/Services/BillingPaymentMethodService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +210 -22
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceInstanceService.js +66 -0
- package/build/dist/Server/Services/CloudResourceInstanceService.js.map +1 -1
- package/build/dist/Server/Services/ExceptionAggregationService.js +1 -0
- package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js +9 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +1 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +7 -0
- package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +16 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +1 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +1 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MobilePasskeyLoginService.js +137 -0
- package/build/dist/Server/Services/MobilePasskeyLoginService.js.map +1 -0
- package/build/dist/Server/Services/MonitorService.js +34 -1
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +64 -26
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +124 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +142 -2
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +28 -13
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PayAsYouGoBillingService.js +297 -0
- package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -0
- package/build/dist/Server/Services/ProjectService.js +38 -2
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionInstanceService.js +66 -0
- package/build/dist/Server/Services/ServerlessFunctionInstanceService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +85 -28
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +61 -10
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +62 -5
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceAggregationService.js +5 -4
- package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
- package/build/dist/Server/Services/UserWebAuthnService.js +345 -113
- package/build/dist/Server/Services/UserWebAuthnService.js.map +1 -1
- package/build/dist/Server/Services/VMwareResourceService.js +395 -0
- package/build/dist/Server/Services/VMwareResourceService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterFeedService.js +89 -0
- package/build/dist/Server/Services/VMwareVCenterFeedService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +197 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleService.js +13 -0
- package/build/dist/Server/Services/VMwareVCenterLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +214 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerTeamService.js +129 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerUserService.js +122 -0
- package/build/dist/Server/Services/VMwareVCenterOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/VMwareVCenterService.js +533 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -0
- package/build/dist/Server/Services/WorkflowVariableService.js +169 -0
- package/build/dist/Server/Services/WorkflowVariableService.js.map +1 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.js +12 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/ActiveMonitoringMeteredPlan.js.map +1 -1
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js +25 -2
- package/build/dist/Server/Types/Billing/MeteredPlan/TelemetryMeteredPlan.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.js +275 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubAgentTaskTrigger.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.js +226 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandAuthorizer.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.js +297 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubCommandParser.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubConversation.js +582 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubConversation.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.js +275 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubReplyComposer.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubRunReply.js +365 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubRunReply.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.js +103 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookEvents.js.map +1 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.js +661 -0
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHubWebhookHandler.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +113 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +99 -15
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +2 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +18 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +31 -2
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +2 -1
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +219 -4
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +12 -4
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +5 -3
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +22 -9
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +21 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +21 -6
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/ResourceFeed/ResourceFeedUtil.js +3 -3
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +9 -9
- package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +92 -71
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +428 -143
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +376 -0
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +136 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/VMwareSnapshotScan.js +933 -0
- package/build/dist/Server/Utils/Telemetry/VMwareSnapshotScan.js.map +1 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js +40 -0
- package/build/dist/Types/AI/CodeFixTaskContext.js.map +1 -1
- package/build/dist/Types/AI/CodeFixTaskType.js +57 -0
- package/build/dist/Types/AI/CodeFixTaskType.js.map +1 -1
- package/build/dist/Types/Accounts/AccountsLanguage.js +1 -0
- package/build/dist/Types/Accounts/AccountsLanguage.js.map +1 -1
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js +1 -0
- package/build/dist/Types/AdminDashboard/AdminDashboardLanguage.js.map +1 -1
- package/build/dist/Types/Cloud/CloudPlatform.js +277 -0
- package/build/dist/Types/Cloud/CloudPlatform.js.map +1 -0
- package/build/dist/Types/CodeRepository/GitHubCommand.js +52 -0
- package/build/dist/Types/CodeRepository/GitHubCommand.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareHostListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardVMwareVirtualMachineListComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardLanguage.js +1 -0
- package/build/dist/Types/Dashboard/DashboardLanguage.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +286 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Docs/DocsLanguage.js +1 -0
- package/build/dist/Types/Docs/DocsLanguage.js.map +1 -1
- package/build/dist/Types/Exception/EgressGuardException.js +59 -0
- package/build/dist/Types/Exception/EgressGuardException.js.map +1 -0
- package/build/dist/Types/Icon/IconProp.js +1 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +61 -18
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +1 -0
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepVMwareMonitor.js +71 -0
- package/build/dist/Types/Monitor/MonitorStepVMwareMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorTemplateSyncField.js +211 -0
- package/build/dist/Types/Monitor/MonitorTemplateSyncField.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorType.js +23 -0
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +28 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +2 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js +120 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +60 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/Monitor/VMwareAlertTemplates.js +775 -0
- package/build/dist/Types/Monitor/VMwareAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/VMwareMetricCatalog.js +799 -0
- package/build/dist/Types/Monitor/VMwareMetricCatalog.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +25 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +5 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -1
- package/build/dist/Types/Password.js +63 -5
- package/build/dist/Types/Password.js.map +1 -1
- package/build/dist/Types/Permission.js +234 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Probe/RequestFailedDetails.js +7 -0
- package/build/dist/Types/Probe/RequestFailedDetails.js.map +1 -1
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js +2 -0
- package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js +1 -0
- package/build/dist/Types/StatusPage/StatusPageLanguage.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +21 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +1 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Breadcrumbs/Breadcrumbs.js +2 -2
- package/build/dist/UI/Components/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js +24 -4
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +28 -3
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +89 -6
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +5 -6
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +14 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +37 -8
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js +228 -0
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js.map +1 -0
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js +102 -0
- package/build/dist/UI/Components/LabelRule/LabelRuleTable.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +15 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +13 -5
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +14 -15
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +2 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +33 -4
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Utils/DashboardStackingLayers.js +44 -0
- package/build/dist/UI/Utils/DashboardStackingLayers.js.map +1 -0
- package/build/dist/UI/Utils/LabelRuleImportExport.js +195 -0
- package/build/dist/UI/Utils/LabelRuleImportExport.js.map +1 -0
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +4 -4
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +3 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js +2 -1
- package/build/dist/UI/Utils/UseDashboardGridDnd.js.map +1 -1
- package/build/dist/UI/Utils/UserEmailRegistrationStatus.js +21 -4
- package/build/dist/UI/Utils/UserEmailRegistrationStatus.js.map +1 -1
- package/build/dist/UI/Utils/WebAuthn.js +121 -0
- package/build/dist/UI/Utils/WebAuthn.js.map +1 -0
- package/build/dist/Utils/API.js +29 -0
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareHostListComponent.js +33 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareHostListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareResourceListShared.js +54 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareResourceListShared.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.js +60 -0
- package/build/dist/Utils/Dashboard/Components/DashboardVMwareVirtualMachineListComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +8 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/LabelRuleImportExport.js +356 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorTemplateSyncUtil.js +110 -0
- package/build/dist/Utils/Monitor/MonitorTemplateSyncUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js +6 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js.map +1 -1
- package/build/dist/Utils/Telemetry/CloudInstanceIdentity.js +88 -0
- package/build/dist/Utils/Telemetry/CloudInstanceIdentity.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +15 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +13 -0
- package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,1608 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VMwareAlertTemplate,
|
|
3
|
+
VMwareAlertTemplateArgs,
|
|
4
|
+
VMwareGroupByKey,
|
|
5
|
+
getAllVMwareAlertTemplates,
|
|
6
|
+
getVMwareAlertTemplateById,
|
|
7
|
+
getVMwareAlertTemplatesByCategory,
|
|
8
|
+
} from "../../../Types/Monitor/VMwareAlertTemplates";
|
|
9
|
+
import {
|
|
10
|
+
VMwareMetricDefinition,
|
|
11
|
+
getVMwareMetricByMetricName,
|
|
12
|
+
} from "../../../Types/Monitor/VMwareMetricCatalog";
|
|
13
|
+
import { getRecoveryThreshold } from "../../../Types/Monitor/Recommendation/RecommendationCriteriaBuilder";
|
|
14
|
+
import {
|
|
15
|
+
getComplementFilterType,
|
|
16
|
+
hasRecoveryDeadBand,
|
|
17
|
+
} from "./Utils/RecommendationCriteriaAssertions";
|
|
18
|
+
import MonitorStep from "../../../Types/Monitor/MonitorStep";
|
|
19
|
+
import MonitorStepVMwareMonitor from "../../../Types/Monitor/MonitorStepVMwareMonitor";
|
|
20
|
+
import MonitorCriteriaInstance from "../../../Types/Monitor/MonitorCriteriaInstance";
|
|
21
|
+
import {
|
|
22
|
+
EvaluateOverTimeType,
|
|
23
|
+
FilterType,
|
|
24
|
+
} from "../../../Types/Monitor/CriteriaFilter";
|
|
25
|
+
import MetricsAggregationType from "../../../Types/Metrics/MetricsAggregationType";
|
|
26
|
+
import RollingTime from "../../../Types/RollingTime/RollingTime";
|
|
27
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
28
|
+
import SeriesLabelDisplay from "../../../Types/Monitor/SeriesContext/SeriesLabelDisplay";
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* Lock in the VMware alert-template contracts (design spec §6). Two layers:
|
|
32
|
+
*
|
|
33
|
+
* 1. ENUMERATED invariants run over getAllVMwareAlertTemplates(), so a
|
|
34
|
+
* newly added template is automatically covered: it must build a
|
|
35
|
+
* valid MonitorStep, reference only catalog metrics, resolve every
|
|
36
|
+
* criteria alias, group by a `resource.vcenter.*` RESOURCE attribute
|
|
37
|
+
* (the OTel vcenter receiver's identity lives in resource attributes —
|
|
38
|
+
* the inverse of the Proxmox rule), and use disjoint fire/recover
|
|
39
|
+
* thresholds on the same alias.
|
|
40
|
+
*
|
|
41
|
+
* 2. A per-template expectation table pins the spec'd metric /
|
|
42
|
+
* aggregation / threshold / attribute-filter / group-by decisions.
|
|
43
|
+
* The table is exhaustive both ways — adding a template without a
|
|
44
|
+
* row here fails loudly, which is the point.
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
interface QueryExpectation {
|
|
48
|
+
metricName: string;
|
|
49
|
+
aggregation: MetricsAggregationType;
|
|
50
|
+
attributes: Record<string, string>;
|
|
51
|
+
legendUnit: string | undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface ThresholdExpectation {
|
|
55
|
+
alias: string;
|
|
56
|
+
filterType: FilterType;
|
|
57
|
+
value: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface TemplateExpectation {
|
|
61
|
+
id: string;
|
|
62
|
+
category: string;
|
|
63
|
+
severity: string;
|
|
64
|
+
rollingTime: RollingTime;
|
|
65
|
+
queries: Array<QueryExpectation>;
|
|
66
|
+
groupBy: string;
|
|
67
|
+
fire: ThresholdExpectation;
|
|
68
|
+
recover: ThresholdExpectation;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const HOST: string = "resource.vcenter.host.name";
|
|
72
|
+
const VM: string = "resource.vcenter.vm.name";
|
|
73
|
+
const DATASTORE: string = "resource.vcenter.datastore.name";
|
|
74
|
+
const CLUSTER: string = "resource.vcenter.cluster.name";
|
|
75
|
+
const DATACENTER: string = "resource.vcenter.datacenter.name";
|
|
76
|
+
const RESOURCE_POOL: string = "resource.vcenter.resource_pool.inventory_path";
|
|
77
|
+
|
|
78
|
+
const EXPECTED_TEMPLATES: Array<TemplateExpectation> = [
|
|
79
|
+
{
|
|
80
|
+
id: "vmware-host-cpu-saturation",
|
|
81
|
+
category: "Host",
|
|
82
|
+
severity: "Warning",
|
|
83
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
84
|
+
queries: [
|
|
85
|
+
{
|
|
86
|
+
metricName: "vcenter.host.cpu.utilization",
|
|
87
|
+
aggregation: MetricsAggregationType.Avg,
|
|
88
|
+
attributes: {},
|
|
89
|
+
legendUnit: "%",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
groupBy: HOST,
|
|
93
|
+
fire: {
|
|
94
|
+
alias: "host_cpu_utilization",
|
|
95
|
+
filterType: FilterType.GreaterThan,
|
|
96
|
+
value: 90,
|
|
97
|
+
},
|
|
98
|
+
recover: {
|
|
99
|
+
alias: "host_cpu_utilization",
|
|
100
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
101
|
+
value: 90,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: "vmware-host-memory-saturation",
|
|
106
|
+
category: "Host",
|
|
107
|
+
severity: "Warning",
|
|
108
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
109
|
+
queries: [
|
|
110
|
+
{
|
|
111
|
+
metricName: "vcenter.host.memory.utilization",
|
|
112
|
+
aggregation: MetricsAggregationType.Avg,
|
|
113
|
+
attributes: {},
|
|
114
|
+
legendUnit: "%",
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
groupBy: HOST,
|
|
118
|
+
fire: {
|
|
119
|
+
alias: "host_memory_utilization",
|
|
120
|
+
filterType: FilterType.GreaterThan,
|
|
121
|
+
value: 90,
|
|
122
|
+
},
|
|
123
|
+
recover: {
|
|
124
|
+
alias: "host_memory_utilization",
|
|
125
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
126
|
+
value: 90,
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
/*
|
|
131
|
+
* Max, not Avg: the metric is itself the worst latency across the
|
|
132
|
+
* host's disks, and the threshold is in the receiver's native ms.
|
|
133
|
+
*/
|
|
134
|
+
id: "vmware-host-disk-latency-high",
|
|
135
|
+
category: "Host",
|
|
136
|
+
severity: "Warning",
|
|
137
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
138
|
+
queries: [
|
|
139
|
+
{
|
|
140
|
+
metricName: "vcenter.host.disk.latency.max",
|
|
141
|
+
aggregation: MetricsAggregationType.Max,
|
|
142
|
+
attributes: {},
|
|
143
|
+
legendUnit: "ms",
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
groupBy: HOST,
|
|
147
|
+
fire: {
|
|
148
|
+
alias: "host_disk_latency_max",
|
|
149
|
+
filterType: FilterType.GreaterThan,
|
|
150
|
+
value: 50,
|
|
151
|
+
},
|
|
152
|
+
recover: {
|
|
153
|
+
alias: "host_disk_latency_max",
|
|
154
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
155
|
+
value: 50,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: "vmware-host-network-packet-errors",
|
|
160
|
+
category: "Host",
|
|
161
|
+
severity: "Warning",
|
|
162
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
163
|
+
queries: [
|
|
164
|
+
{
|
|
165
|
+
metricName: "vcenter.host.network.packet.error.rate",
|
|
166
|
+
aggregation: MetricsAggregationType.Max,
|
|
167
|
+
attributes: {},
|
|
168
|
+
legendUnit: undefined,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
groupBy: HOST,
|
|
172
|
+
fire: {
|
|
173
|
+
alias: "host_packet_error_rate",
|
|
174
|
+
filterType: FilterType.GreaterThan,
|
|
175
|
+
value: 0,
|
|
176
|
+
},
|
|
177
|
+
recover: {
|
|
178
|
+
alias: "host_packet_error_rate",
|
|
179
|
+
filterType: FilterType.EqualTo,
|
|
180
|
+
value: 0,
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
id: "vmware-host-network-packet-drops",
|
|
185
|
+
category: "Host",
|
|
186
|
+
severity: "Warning",
|
|
187
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
188
|
+
queries: [
|
|
189
|
+
{
|
|
190
|
+
metricName: "vcenter.host.network.packet.drop.rate",
|
|
191
|
+
aggregation: MetricsAggregationType.Max,
|
|
192
|
+
attributes: {},
|
|
193
|
+
legendUnit: undefined,
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
groupBy: HOST,
|
|
197
|
+
fire: {
|
|
198
|
+
alias: "host_packet_drop_rate",
|
|
199
|
+
filterType: FilterType.GreaterThan,
|
|
200
|
+
value: 0,
|
|
201
|
+
},
|
|
202
|
+
recover: {
|
|
203
|
+
alias: "host_packet_drop_rate",
|
|
204
|
+
filterType: FilterType.EqualTo,
|
|
205
|
+
value: 0,
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
/*
|
|
210
|
+
* The only 15-minute window: a VM is entitled to spend its vCPUs, so
|
|
211
|
+
* only sustained saturation is worth a page (see the asymmetry suite).
|
|
212
|
+
*/
|
|
213
|
+
id: "vmware-vm-cpu-saturation",
|
|
214
|
+
category: "Virtual Machine",
|
|
215
|
+
severity: "Warning",
|
|
216
|
+
rollingTime: RollingTime.Past15Minutes,
|
|
217
|
+
queries: [
|
|
218
|
+
{
|
|
219
|
+
metricName: "vcenter.vm.cpu.utilization",
|
|
220
|
+
aggregation: MetricsAggregationType.Avg,
|
|
221
|
+
attributes: {},
|
|
222
|
+
legendUnit: "%",
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
groupBy: VM,
|
|
226
|
+
fire: {
|
|
227
|
+
alias: "vm_cpu_utilization",
|
|
228
|
+
filterType: FilterType.GreaterThan,
|
|
229
|
+
value: 90,
|
|
230
|
+
},
|
|
231
|
+
recover: {
|
|
232
|
+
alias: "vm_cpu_utilization",
|
|
233
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
234
|
+
value: 90,
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: "vmware-vm-cpu-ready-contention",
|
|
239
|
+
category: "Virtual Machine",
|
|
240
|
+
severity: "Warning",
|
|
241
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
242
|
+
queries: [
|
|
243
|
+
{
|
|
244
|
+
metricName: "vcenter.vm.cpu.readiness",
|
|
245
|
+
aggregation: MetricsAggregationType.Avg,
|
|
246
|
+
attributes: {},
|
|
247
|
+
legendUnit: "%",
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
groupBy: VM,
|
|
251
|
+
fire: {
|
|
252
|
+
alias: "vm_cpu_ready",
|
|
253
|
+
filterType: FilterType.GreaterThan,
|
|
254
|
+
value: 10,
|
|
255
|
+
},
|
|
256
|
+
recover: {
|
|
257
|
+
alias: "vm_cpu_ready",
|
|
258
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
259
|
+
value: 10,
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
id: "vmware-vm-memory-saturation",
|
|
264
|
+
category: "Virtual Machine",
|
|
265
|
+
severity: "Warning",
|
|
266
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
267
|
+
queries: [
|
|
268
|
+
{
|
|
269
|
+
metricName: "vcenter.vm.memory.utilization",
|
|
270
|
+
aggregation: MetricsAggregationType.Avg,
|
|
271
|
+
attributes: {},
|
|
272
|
+
legendUnit: "%",
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
groupBy: VM,
|
|
276
|
+
fire: {
|
|
277
|
+
alias: "vm_memory_utilization",
|
|
278
|
+
filterType: FilterType.GreaterThan,
|
|
279
|
+
value: 90,
|
|
280
|
+
},
|
|
281
|
+
recover: {
|
|
282
|
+
alias: "vm_memory_utilization",
|
|
283
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
284
|
+
value: 90,
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: "vmware-vm-memory-ballooning",
|
|
289
|
+
category: "Virtual Machine",
|
|
290
|
+
severity: "Warning",
|
|
291
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
292
|
+
queries: [
|
|
293
|
+
{
|
|
294
|
+
metricName: "vcenter.vm.memory.ballooned",
|
|
295
|
+
aggregation: MetricsAggregationType.Max,
|
|
296
|
+
attributes: {},
|
|
297
|
+
legendUnit: undefined,
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
groupBy: VM,
|
|
301
|
+
fire: {
|
|
302
|
+
alias: "vm_memory_ballooned",
|
|
303
|
+
filterType: FilterType.GreaterThan,
|
|
304
|
+
value: 0,
|
|
305
|
+
},
|
|
306
|
+
recover: {
|
|
307
|
+
alias: "vm_memory_ballooned",
|
|
308
|
+
filterType: FilterType.EqualTo,
|
|
309
|
+
value: 0,
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
id: "vmware-vm-memory-swapping",
|
|
314
|
+
category: "Virtual Machine",
|
|
315
|
+
severity: "Critical",
|
|
316
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
317
|
+
queries: [
|
|
318
|
+
{
|
|
319
|
+
metricName: "vcenter.vm.memory.swapped",
|
|
320
|
+
aggregation: MetricsAggregationType.Max,
|
|
321
|
+
attributes: {},
|
|
322
|
+
legendUnit: undefined,
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
groupBy: VM,
|
|
326
|
+
fire: {
|
|
327
|
+
alias: "vm_memory_swapped",
|
|
328
|
+
filterType: FilterType.GreaterThan,
|
|
329
|
+
value: 0,
|
|
330
|
+
},
|
|
331
|
+
recover: {
|
|
332
|
+
alias: "vm_memory_swapped",
|
|
333
|
+
filterType: FilterType.EqualTo,
|
|
334
|
+
value: 0,
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
id: "vmware-vm-disk-latency-high",
|
|
339
|
+
category: "Virtual Machine",
|
|
340
|
+
severity: "Warning",
|
|
341
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
342
|
+
queries: [
|
|
343
|
+
{
|
|
344
|
+
metricName: "vcenter.vm.disk.latency.max",
|
|
345
|
+
aggregation: MetricsAggregationType.Max,
|
|
346
|
+
attributes: {},
|
|
347
|
+
legendUnit: "ms",
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
groupBy: VM,
|
|
351
|
+
fire: {
|
|
352
|
+
alias: "vm_disk_latency_max",
|
|
353
|
+
filterType: FilterType.GreaterThan,
|
|
354
|
+
value: 50,
|
|
355
|
+
},
|
|
356
|
+
recover: {
|
|
357
|
+
alias: "vm_disk_latency_max",
|
|
358
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
359
|
+
value: 50,
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
id: "vmware-vm-disk-usage-high",
|
|
364
|
+
category: "Virtual Machine",
|
|
365
|
+
severity: "Warning",
|
|
366
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
367
|
+
queries: [
|
|
368
|
+
{
|
|
369
|
+
metricName: "vcenter.vm.disk.utilization",
|
|
370
|
+
aggregation: MetricsAggregationType.Avg,
|
|
371
|
+
attributes: {},
|
|
372
|
+
legendUnit: "%",
|
|
373
|
+
},
|
|
374
|
+
],
|
|
375
|
+
groupBy: VM,
|
|
376
|
+
fire: {
|
|
377
|
+
alias: "vm_disk_utilization",
|
|
378
|
+
filterType: FilterType.GreaterThan,
|
|
379
|
+
value: 90,
|
|
380
|
+
},
|
|
381
|
+
recover: {
|
|
382
|
+
alias: "vm_disk_utilization",
|
|
383
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
384
|
+
value: 90,
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
id: "vmware-datastore-capacity-warning",
|
|
389
|
+
category: "Datastore",
|
|
390
|
+
severity: "Warning",
|
|
391
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
392
|
+
queries: [
|
|
393
|
+
{
|
|
394
|
+
metricName: "vcenter.datastore.disk.utilization",
|
|
395
|
+
aggregation: MetricsAggregationType.Avg,
|
|
396
|
+
attributes: {},
|
|
397
|
+
legendUnit: "%",
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
groupBy: DATASTORE,
|
|
401
|
+
fire: {
|
|
402
|
+
alias: "datastore_utilization",
|
|
403
|
+
filterType: FilterType.GreaterThan,
|
|
404
|
+
value: 80,
|
|
405
|
+
},
|
|
406
|
+
recover: {
|
|
407
|
+
alias: "datastore_utilization",
|
|
408
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
409
|
+
value: 80,
|
|
410
|
+
},
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
id: "vmware-datastore-capacity-critical",
|
|
414
|
+
category: "Datastore",
|
|
415
|
+
severity: "Critical",
|
|
416
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
417
|
+
queries: [
|
|
418
|
+
{
|
|
419
|
+
metricName: "vcenter.datastore.disk.utilization",
|
|
420
|
+
aggregation: MetricsAggregationType.Avg,
|
|
421
|
+
attributes: {},
|
|
422
|
+
legendUnit: "%",
|
|
423
|
+
},
|
|
424
|
+
],
|
|
425
|
+
groupBy: DATASTORE,
|
|
426
|
+
fire: {
|
|
427
|
+
alias: "datastore_utilization",
|
|
428
|
+
filterType: FilterType.GreaterThan,
|
|
429
|
+
value: 90,
|
|
430
|
+
},
|
|
431
|
+
recover: {
|
|
432
|
+
alias: "datastore_utilization",
|
|
433
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
434
|
+
value: 90,
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
/*
|
|
439
|
+
* The receiver's boolean `effective` attribute is stored as the
|
|
440
|
+
* STRING "false" — the filter must use the string, not a boolean.
|
|
441
|
+
*/
|
|
442
|
+
id: "vmware-cluster-host-not-effective",
|
|
443
|
+
category: "Cluster",
|
|
444
|
+
severity: "Critical",
|
|
445
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
446
|
+
queries: [
|
|
447
|
+
{
|
|
448
|
+
metricName: "vcenter.cluster.host.count",
|
|
449
|
+
aggregation: MetricsAggregationType.Max,
|
|
450
|
+
attributes: { effective: "false" },
|
|
451
|
+
legendUnit: undefined,
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
groupBy: CLUSTER,
|
|
455
|
+
fire: {
|
|
456
|
+
alias: "cluster_hosts_not_effective",
|
|
457
|
+
filterType: FilterType.GreaterThan,
|
|
458
|
+
value: 0,
|
|
459
|
+
},
|
|
460
|
+
recover: {
|
|
461
|
+
alias: "cluster_hosts_not_effective",
|
|
462
|
+
filterType: FilterType.EqualTo,
|
|
463
|
+
value: 0,
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
id: "vmware-datacenter-hosts-unhealthy",
|
|
468
|
+
category: "Datacenter",
|
|
469
|
+
severity: "Critical",
|
|
470
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
471
|
+
queries: [
|
|
472
|
+
{
|
|
473
|
+
metricName: "vcenter.datacenter.host.count",
|
|
474
|
+
aggregation: MetricsAggregationType.Max,
|
|
475
|
+
attributes: { status: "red" },
|
|
476
|
+
legendUnit: undefined,
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
groupBy: DATACENTER,
|
|
480
|
+
fire: {
|
|
481
|
+
alias: "datacenter_hosts_red",
|
|
482
|
+
filterType: FilterType.GreaterThan,
|
|
483
|
+
value: 0,
|
|
484
|
+
},
|
|
485
|
+
recover: {
|
|
486
|
+
alias: "datacenter_hosts_red",
|
|
487
|
+
filterType: FilterType.EqualTo,
|
|
488
|
+
value: 0,
|
|
489
|
+
},
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
id: "vmware-datacenter-hosts-degraded",
|
|
493
|
+
category: "Datacenter",
|
|
494
|
+
severity: "Warning",
|
|
495
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
496
|
+
queries: [
|
|
497
|
+
{
|
|
498
|
+
metricName: "vcenter.datacenter.host.count",
|
|
499
|
+
aggregation: MetricsAggregationType.Max,
|
|
500
|
+
attributes: { status: "yellow" },
|
|
501
|
+
legendUnit: undefined,
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
groupBy: DATACENTER,
|
|
505
|
+
fire: {
|
|
506
|
+
alias: "datacenter_hosts_yellow",
|
|
507
|
+
filterType: FilterType.GreaterThan,
|
|
508
|
+
value: 0,
|
|
509
|
+
},
|
|
510
|
+
recover: {
|
|
511
|
+
alias: "datacenter_hosts_yellow",
|
|
512
|
+
filterType: FilterType.EqualTo,
|
|
513
|
+
value: 0,
|
|
514
|
+
},
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
id: "vmware-datacenter-hosts-powered-off",
|
|
518
|
+
category: "Datacenter",
|
|
519
|
+
severity: "Warning",
|
|
520
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
521
|
+
queries: [
|
|
522
|
+
{
|
|
523
|
+
metricName: "vcenter.datacenter.host.count",
|
|
524
|
+
aggregation: MetricsAggregationType.Max,
|
|
525
|
+
attributes: { power_state: "off" },
|
|
526
|
+
legendUnit: undefined,
|
|
527
|
+
},
|
|
528
|
+
],
|
|
529
|
+
groupBy: DATACENTER,
|
|
530
|
+
fire: {
|
|
531
|
+
alias: "datacenter_hosts_powered_off",
|
|
532
|
+
filterType: FilterType.GreaterThan,
|
|
533
|
+
value: 0,
|
|
534
|
+
},
|
|
535
|
+
recover: {
|
|
536
|
+
alias: "datacenter_hosts_powered_off",
|
|
537
|
+
filterType: FilterType.EqualTo,
|
|
538
|
+
value: 0,
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
id: "vmware-datacenter-vms-unhealthy",
|
|
543
|
+
category: "Datacenter",
|
|
544
|
+
severity: "Warning",
|
|
545
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
546
|
+
queries: [
|
|
547
|
+
{
|
|
548
|
+
metricName: "vcenter.datacenter.vm.count",
|
|
549
|
+
aggregation: MetricsAggregationType.Max,
|
|
550
|
+
attributes: { status: "red" },
|
|
551
|
+
legendUnit: undefined,
|
|
552
|
+
},
|
|
553
|
+
],
|
|
554
|
+
groupBy: DATACENTER,
|
|
555
|
+
fire: {
|
|
556
|
+
alias: "datacenter_vms_red",
|
|
557
|
+
filterType: FilterType.GreaterThan,
|
|
558
|
+
value: 0,
|
|
559
|
+
},
|
|
560
|
+
recover: {
|
|
561
|
+
alias: "datacenter_vms_red",
|
|
562
|
+
filterType: FilterType.EqualTo,
|
|
563
|
+
value: 0,
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: "vmware-datacenter-clusters-unhealthy",
|
|
568
|
+
category: "Datacenter",
|
|
569
|
+
severity: "Critical",
|
|
570
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
571
|
+
queries: [
|
|
572
|
+
{
|
|
573
|
+
metricName: "vcenter.datacenter.cluster.count",
|
|
574
|
+
aggregation: MetricsAggregationType.Max,
|
|
575
|
+
attributes: { status: "red" },
|
|
576
|
+
legendUnit: undefined,
|
|
577
|
+
},
|
|
578
|
+
],
|
|
579
|
+
groupBy: DATACENTER,
|
|
580
|
+
fire: {
|
|
581
|
+
alias: "datacenter_clusters_red",
|
|
582
|
+
filterType: FilterType.GreaterThan,
|
|
583
|
+
value: 0,
|
|
584
|
+
},
|
|
585
|
+
recover: {
|
|
586
|
+
alias: "datacenter_clusters_red",
|
|
587
|
+
filterType: FilterType.EqualTo,
|
|
588
|
+
value: 0,
|
|
589
|
+
},
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
/*
|
|
593
|
+
* vSAN latency is reported in MICROseconds by the receiver; the
|
|
594
|
+
* 20 ms threshold is written in the native unit (20 000 us) and pinned.
|
|
595
|
+
*/
|
|
596
|
+
id: "vmware-vsan-latency-high",
|
|
597
|
+
category: "vSAN",
|
|
598
|
+
severity: "Warning",
|
|
599
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
600
|
+
queries: [
|
|
601
|
+
{
|
|
602
|
+
metricName: "vcenter.cluster.vsan.latency.avg",
|
|
603
|
+
aggregation: MetricsAggregationType.Avg,
|
|
604
|
+
attributes: {},
|
|
605
|
+
legendUnit: "us",
|
|
606
|
+
},
|
|
607
|
+
],
|
|
608
|
+
groupBy: CLUSTER,
|
|
609
|
+
fire: {
|
|
610
|
+
alias: "vsan_latency_avg",
|
|
611
|
+
filterType: FilterType.GreaterThan,
|
|
612
|
+
value: 20000,
|
|
613
|
+
},
|
|
614
|
+
recover: {
|
|
615
|
+
alias: "vsan_latency_avg",
|
|
616
|
+
filterType: FilterType.LessThanOrEqualTo,
|
|
617
|
+
value: 20000,
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
id: "vmware-vsan-congestion",
|
|
622
|
+
category: "vSAN",
|
|
623
|
+
severity: "Warning",
|
|
624
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
625
|
+
queries: [
|
|
626
|
+
{
|
|
627
|
+
metricName: "vcenter.cluster.vsan.congestions",
|
|
628
|
+
aggregation: MetricsAggregationType.Max,
|
|
629
|
+
attributes: {},
|
|
630
|
+
legendUnit: undefined,
|
|
631
|
+
},
|
|
632
|
+
],
|
|
633
|
+
groupBy: CLUSTER,
|
|
634
|
+
fire: {
|
|
635
|
+
alias: "vsan_congestions",
|
|
636
|
+
filterType: FilterType.GreaterThan,
|
|
637
|
+
value: 0,
|
|
638
|
+
},
|
|
639
|
+
recover: {
|
|
640
|
+
alias: "vsan_congestions",
|
|
641
|
+
filterType: FilterType.EqualTo,
|
|
642
|
+
value: 0,
|
|
643
|
+
},
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
/*
|
|
647
|
+
* Grouped by the pool's inventory PATH, not its name: pool names are
|
|
648
|
+
* only unique within their parent.
|
|
649
|
+
*/
|
|
650
|
+
id: "vmware-resource-pool-memory-swapped",
|
|
651
|
+
category: "Cluster",
|
|
652
|
+
severity: "Warning",
|
|
653
|
+
rollingTime: RollingTime.Past5Minutes,
|
|
654
|
+
queries: [
|
|
655
|
+
{
|
|
656
|
+
metricName: "vcenter.resource_pool.memory.swapped",
|
|
657
|
+
aggregation: MetricsAggregationType.Max,
|
|
658
|
+
attributes: {},
|
|
659
|
+
legendUnit: undefined,
|
|
660
|
+
},
|
|
661
|
+
],
|
|
662
|
+
groupBy: RESOURCE_POOL,
|
|
663
|
+
fire: {
|
|
664
|
+
alias: "resource_pool_memory_swapped",
|
|
665
|
+
filterType: FilterType.GreaterThan,
|
|
666
|
+
value: 0,
|
|
667
|
+
},
|
|
668
|
+
recover: {
|
|
669
|
+
alias: "resource_pool_memory_swapped",
|
|
670
|
+
filterType: FilterType.EqualTo,
|
|
671
|
+
value: 0,
|
|
672
|
+
},
|
|
673
|
+
},
|
|
674
|
+
];
|
|
675
|
+
|
|
676
|
+
function buildArgs(): VMwareAlertTemplateArgs {
|
|
677
|
+
return {
|
|
678
|
+
vcenterIdentifier: "vcsa-prod",
|
|
679
|
+
onlineMonitorStatusId: ObjectID.generate(),
|
|
680
|
+
offlineMonitorStatusId: ObjectID.generate(),
|
|
681
|
+
defaultIncidentSeverityId: ObjectID.generate(),
|
|
682
|
+
defaultAlertSeverityId: ObjectID.generate(),
|
|
683
|
+
monitorName: "Test Monitor",
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function getVMwareMonitor(step: MonitorStep): MonitorStepVMwareMonitor {
|
|
688
|
+
const vmwareMonitor: MonitorStepVMwareMonitor | undefined =
|
|
689
|
+
step.data?.vmwareMonitor;
|
|
690
|
+
if (!vmwareMonitor) {
|
|
691
|
+
throw new Error("vmwareMonitor missing from monitor step");
|
|
692
|
+
}
|
|
693
|
+
return vmwareMonitor;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
function getCriteriaInstances(
|
|
697
|
+
step: MonitorStep,
|
|
698
|
+
): Array<MonitorCriteriaInstance> {
|
|
699
|
+
const instances: Array<MonitorCriteriaInstance> | undefined =
|
|
700
|
+
step.data?.monitorCriteria.data?.monitorCriteriaInstanceArray;
|
|
701
|
+
if (!instances || instances.length === 0) {
|
|
702
|
+
throw new Error("monitorCriteria missing from monitor step");
|
|
703
|
+
}
|
|
704
|
+
return instances;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// Aliases a criteria filter may legally reference: query + formula variables.
|
|
708
|
+
function getReferencableAliases(
|
|
709
|
+
monitor: MonitorStepVMwareMonitor,
|
|
710
|
+
): Set<string> {
|
|
711
|
+
const aliases: Set<string> = new Set<string>();
|
|
712
|
+
for (const queryConfig of monitor.metricViewConfig
|
|
713
|
+
.queryConfigs as Array<any>) {
|
|
714
|
+
aliases.add(queryConfig.metricAliasData.metricVariable);
|
|
715
|
+
}
|
|
716
|
+
for (const formulaConfig of (monitor.metricViewConfig.formulaConfigs ||
|
|
717
|
+
[]) as Array<any>) {
|
|
718
|
+
aliases.add(formulaConfig.metricAliasData.metricVariable);
|
|
719
|
+
}
|
|
720
|
+
return aliases;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
/*
|
|
724
|
+
* No VMware template thresholds a strictly 0/1 gauge (the vcenter
|
|
725
|
+
* receiver emits no up/down boolean — power state is inferred from metric
|
|
726
|
+
* presence at ingest), so every pair is checked with the shared dead-band
|
|
727
|
+
* assertion; the `> 0` / `= 0` count pairs are accepted by it as-is.
|
|
728
|
+
*/
|
|
729
|
+
function expectedRecoveryValue(recover: {
|
|
730
|
+
filterType: FilterType;
|
|
731
|
+
value: number;
|
|
732
|
+
}): number {
|
|
733
|
+
return (
|
|
734
|
+
getRecoveryThreshold({
|
|
735
|
+
filterType: getComplementFilterType(recover.filterType)!,
|
|
736
|
+
value: recover.value,
|
|
737
|
+
}) ?? recover.value
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
const ALL_TEMPLATES: Array<VMwareAlertTemplate> = getAllVMwareAlertTemplates();
|
|
742
|
+
|
|
743
|
+
describe("VMwareAlertTemplates - registry", () => {
|
|
744
|
+
test("template ids are unique and match the expectation table exactly", () => {
|
|
745
|
+
const ids: Array<string> = ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
746
|
+
return t.id;
|
|
747
|
+
});
|
|
748
|
+
expect(new Set(ids).size).toBe(ids.length);
|
|
749
|
+
// Exhaustive both ways: a new template must get an expectation row.
|
|
750
|
+
expect([...ids].sort()).toEqual(
|
|
751
|
+
EXPECTED_TEMPLATES.map((t: TemplateExpectation) => {
|
|
752
|
+
return t.id;
|
|
753
|
+
}).sort(),
|
|
754
|
+
);
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
test("ships the 23 templates the design spec lists", () => {
|
|
758
|
+
expect(ALL_TEMPLATES).toHaveLength(23);
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
test("every template id carries the vmware- prefix", () => {
|
|
762
|
+
/*
|
|
763
|
+
* Template ids are only guaranteed unique within a module; the
|
|
764
|
+
* registry canary asserts they happen to be globally unique. A
|
|
765
|
+
* distinct prefix is what keeps that true against pve-/k8s-/ceph-.
|
|
766
|
+
*/
|
|
767
|
+
for (const template of ALL_TEMPLATES) {
|
|
768
|
+
expect(template.id).toMatch(/^vmware-[a-z0-9-]+$/);
|
|
769
|
+
}
|
|
770
|
+
});
|
|
771
|
+
|
|
772
|
+
test("template names are unique within the module", () => {
|
|
773
|
+
const names: Array<string> = ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
774
|
+
return t.name;
|
|
775
|
+
});
|
|
776
|
+
expect(new Set(names).size).toBe(names.length);
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
test("getVMwareAlertTemplateById round-trips every template and misses unknown ids", () => {
|
|
780
|
+
for (const template of ALL_TEMPLATES) {
|
|
781
|
+
expect(getVMwareAlertTemplateById(template.id)).toBe(template);
|
|
782
|
+
}
|
|
783
|
+
expect(getVMwareAlertTemplateById("pve-node-offline")).toBeUndefined();
|
|
784
|
+
expect(getVMwareAlertTemplateById("")).toBeUndefined();
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
test("getVMwareAlertTemplatesByCategory partitions the registry", () => {
|
|
788
|
+
const categories: Array<string> = [
|
|
789
|
+
"Host",
|
|
790
|
+
"Virtual Machine",
|
|
791
|
+
"Datastore",
|
|
792
|
+
"Cluster",
|
|
793
|
+
"Datacenter",
|
|
794
|
+
"vSAN",
|
|
795
|
+
];
|
|
796
|
+
|
|
797
|
+
let total: number = 0;
|
|
798
|
+
for (const category of categories) {
|
|
799
|
+
const templates: Array<VMwareAlertTemplate> =
|
|
800
|
+
getVMwareAlertTemplatesByCategory(category as any);
|
|
801
|
+
expect(templates.length).toBeGreaterThan(0);
|
|
802
|
+
for (const template of templates) {
|
|
803
|
+
expect(template.category).toBe(category);
|
|
804
|
+
}
|
|
805
|
+
total += templates.length;
|
|
806
|
+
}
|
|
807
|
+
expect(total).toBe(ALL_TEMPLATES.length);
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
test("severities are the two-member vocabulary the recommendation mapper understands", () => {
|
|
811
|
+
for (const template of ALL_TEMPLATES) {
|
|
812
|
+
expect(["Critical", "Warning"]).toContain(template.severity);
|
|
813
|
+
}
|
|
814
|
+
});
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
describe("VMwareAlertTemplates - enumerated invariants (every template)", () => {
|
|
818
|
+
test.each(
|
|
819
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
820
|
+
return [t.id, t];
|
|
821
|
+
}),
|
|
822
|
+
)("%s builds a valid MonitorStep", (_id: unknown, template: unknown) => {
|
|
823
|
+
const args: VMwareAlertTemplateArgs = buildArgs();
|
|
824
|
+
const step: MonitorStep = (template as VMwareAlertTemplate).getMonitorStep(
|
|
825
|
+
args,
|
|
826
|
+
);
|
|
827
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
828
|
+
|
|
829
|
+
// The vCenter identity is injected from the template args.
|
|
830
|
+
expect(monitor.vcenterIdentifier).toBe(args.vcenterIdentifier);
|
|
831
|
+
expect(monitor.resourceFilters).toEqual({});
|
|
832
|
+
expect(monitor.metricViewConfig.queryConfigs.length).toBeGreaterThan(0);
|
|
833
|
+
|
|
834
|
+
// Only the VMware sub-config is populated; no sibling leaks through.
|
|
835
|
+
expect(step.data?.proxmoxMonitor).toBeUndefined();
|
|
836
|
+
expect(step.data?.kubernetesMonitor).toBeUndefined();
|
|
837
|
+
expect(step.data?.metricMonitor).toBeUndefined();
|
|
838
|
+
|
|
839
|
+
const instances: Array<MonitorCriteriaInstance> =
|
|
840
|
+
getCriteriaInstances(step);
|
|
841
|
+
expect(instances.length).toBeGreaterThanOrEqual(2);
|
|
842
|
+
|
|
843
|
+
/*
|
|
844
|
+
* Criteria are evaluated first-match-wins: every instance before
|
|
845
|
+
* the last is an unhealthy tier (creates incidents + alerts,
|
|
846
|
+
* flips to the offline status); the LAST is the recover instance
|
|
847
|
+
* (no incidents, flips to the online status).
|
|
848
|
+
*/
|
|
849
|
+
const offlineInstances: Array<MonitorCriteriaInstance> = instances.slice(
|
|
850
|
+
0,
|
|
851
|
+
-1,
|
|
852
|
+
);
|
|
853
|
+
const onlineInstance: MonitorCriteriaInstance =
|
|
854
|
+
instances[instances.length - 1]!;
|
|
855
|
+
|
|
856
|
+
for (const offline of offlineInstances) {
|
|
857
|
+
expect(offline.data?.monitorStatusId).toBe(args.offlineMonitorStatusId);
|
|
858
|
+
expect(offline.data?.createIncidents).toBe(true);
|
|
859
|
+
expect(offline.data?.createAlerts).toBe(true);
|
|
860
|
+
expect(offline.data?.incidents).toHaveLength(1);
|
|
861
|
+
expect(offline.data?.alerts).toHaveLength(1);
|
|
862
|
+
expect(offline.data?.incidents?.[0]?.autoResolveIncident).toBe(true);
|
|
863
|
+
expect(offline.data?.alerts?.[0]?.autoResolveAlert).toBe(true);
|
|
864
|
+
expect(offline.data?.incidents?.[0]?.incidentSeverityId).toBe(
|
|
865
|
+
args.defaultIncidentSeverityId,
|
|
866
|
+
);
|
|
867
|
+
expect(offline.data?.alerts?.[0]?.alertSeverityId).toBe(
|
|
868
|
+
args.defaultAlertSeverityId,
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
expect(onlineInstance.data?.monitorStatusId).toBe(
|
|
873
|
+
args.onlineMonitorStatusId,
|
|
874
|
+
);
|
|
875
|
+
expect(onlineInstance.data?.createIncidents).toBe(false);
|
|
876
|
+
expect(onlineInstance.data?.createAlerts).toBe(false);
|
|
877
|
+
expect(onlineInstance.data?.name).toBe("Healthy");
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
test.each(
|
|
881
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
882
|
+
return [t.id, t];
|
|
883
|
+
}),
|
|
884
|
+
)(
|
|
885
|
+
"%s references only catalog metrics and resolvable aliases",
|
|
886
|
+
(_id: unknown, template: unknown) => {
|
|
887
|
+
const step: MonitorStep = (
|
|
888
|
+
template as VMwareAlertTemplate
|
|
889
|
+
).getMonitorStep(buildArgs());
|
|
890
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
891
|
+
|
|
892
|
+
for (const queryConfig of monitor.metricViewConfig
|
|
893
|
+
.queryConfigs as Array<any>) {
|
|
894
|
+
const metricName: string =
|
|
895
|
+
queryConfig.metricQueryData.filterData.metricName;
|
|
896
|
+
expect(getVMwareMetricByMetricName(metricName)).toBeDefined();
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
const aliases: Set<string> = getReferencableAliases(monitor);
|
|
900
|
+
for (const instance of getCriteriaInstances(step)) {
|
|
901
|
+
for (const filter of instance.data?.filters || []) {
|
|
902
|
+
expect(aliases).toContain(
|
|
903
|
+
(filter as any).metricMonitorOptions.metricAlias,
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
},
|
|
908
|
+
);
|
|
909
|
+
|
|
910
|
+
test.each(
|
|
911
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
912
|
+
return [t.id, t];
|
|
913
|
+
}),
|
|
914
|
+
)(
|
|
915
|
+
"%s groups by a resource.vcenter.* attribute the display layer can name",
|
|
916
|
+
(_id: unknown, template: unknown) => {
|
|
917
|
+
const step: MonitorStep = (
|
|
918
|
+
template as VMwareAlertTemplate
|
|
919
|
+
).getMonitorStep(buildArgs());
|
|
920
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
921
|
+
|
|
922
|
+
for (const queryConfig of monitor.metricViewConfig
|
|
923
|
+
.queryConfigs as Array<any>) {
|
|
924
|
+
const groupBys: Array<string> =
|
|
925
|
+
queryConfig.metricQueryData.groupByAttributeKeys || [];
|
|
926
|
+
|
|
927
|
+
/*
|
|
928
|
+
* Every VMware template is per-object: one incident per host /
|
|
929
|
+
* VM / datastore / cluster / datacenter / pool. An ungrouped
|
|
930
|
+
* template would collapse the whole vCenter into one alert that
|
|
931
|
+
* cannot say which object broke.
|
|
932
|
+
*/
|
|
933
|
+
expect(groupBys).toHaveLength(1);
|
|
934
|
+
|
|
935
|
+
for (const key of groupBys) {
|
|
936
|
+
/*
|
|
937
|
+
* The vcenter receiver's identity lives in OTel RESOURCE
|
|
938
|
+
* attributes, stored `resource.`-prefixed in ClickHouse. A bare
|
|
939
|
+
* `vcenter.host.name` would match nothing and collapse every
|
|
940
|
+
* host into one mislabeled series — the inverse of the Proxmox
|
|
941
|
+
* rule, where identity is an unprefixed datapoint label.
|
|
942
|
+
*/
|
|
943
|
+
expect(key).toMatch(/^resource\.vcenter\./);
|
|
944
|
+
expect(Object.values(VMwareGroupByKey)).toContain(key);
|
|
945
|
+
expect(SeriesLabelDisplay.isKnownLabelKey(key)).toBe(true);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
},
|
|
949
|
+
);
|
|
950
|
+
|
|
951
|
+
test.each(
|
|
952
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
953
|
+
return [t.id, t];
|
|
954
|
+
}),
|
|
955
|
+
)(
|
|
956
|
+
"%s groups by the identity attribute of the object its metric describes",
|
|
957
|
+
(_id: unknown, template: unknown) => {
|
|
958
|
+
/*
|
|
959
|
+
* A host metric grouped by the VM name would fan out on an attribute
|
|
960
|
+
* the series does not carry. The catalog's defaultResourceScope says
|
|
961
|
+
* which object a metric belongs to; the group-by must agree.
|
|
962
|
+
*/
|
|
963
|
+
const scopeToGroupBy: Record<string, string> = {
|
|
964
|
+
datacenter: VMwareGroupByKey.Datacenter,
|
|
965
|
+
cluster: VMwareGroupByKey.Cluster,
|
|
966
|
+
host: VMwareGroupByKey.Host,
|
|
967
|
+
vm: VMwareGroupByKey.VirtualMachine,
|
|
968
|
+
datastore: VMwareGroupByKey.Datastore,
|
|
969
|
+
resource_pool: VMwareGroupByKey.ResourcePool,
|
|
970
|
+
};
|
|
971
|
+
|
|
972
|
+
const step: MonitorStep = (
|
|
973
|
+
template as VMwareAlertTemplate
|
|
974
|
+
).getMonitorStep(buildArgs());
|
|
975
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
976
|
+
|
|
977
|
+
for (const queryConfig of monitor.metricViewConfig
|
|
978
|
+
.queryConfigs as Array<any>) {
|
|
979
|
+
const definition: VMwareMetricDefinition | undefined =
|
|
980
|
+
getVMwareMetricByMetricName(
|
|
981
|
+
queryConfig.metricQueryData.filterData.metricName,
|
|
982
|
+
);
|
|
983
|
+
expect(definition).toBeDefined();
|
|
984
|
+
|
|
985
|
+
expect(queryConfig.metricQueryData.groupByAttributeKeys).toEqual([
|
|
986
|
+
scopeToGroupBy[definition!.defaultResourceScope],
|
|
987
|
+
]);
|
|
988
|
+
}
|
|
989
|
+
},
|
|
990
|
+
);
|
|
991
|
+
|
|
992
|
+
test.each(
|
|
993
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
994
|
+
return [t.id, t];
|
|
995
|
+
}),
|
|
996
|
+
)(
|
|
997
|
+
"%s filters only on bare datapoint attributes, never resource.-prefixed ones",
|
|
998
|
+
(_id: unknown, template: unknown) => {
|
|
999
|
+
/*
|
|
1000
|
+
* `status`, `power_state` and `effective` are DATAPOINT attributes
|
|
1001
|
+
* and are stored bare. Prefixing one would make the filter match
|
|
1002
|
+
* nothing, and the template would never fire — silently.
|
|
1003
|
+
*/
|
|
1004
|
+
const step: MonitorStep = (
|
|
1005
|
+
template as VMwareAlertTemplate
|
|
1006
|
+
).getMonitorStep(buildArgs());
|
|
1007
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
1008
|
+
|
|
1009
|
+
for (const queryConfig of monitor.metricViewConfig
|
|
1010
|
+
.queryConfigs as Array<any>) {
|
|
1011
|
+
const attributes: Record<string, string> =
|
|
1012
|
+
queryConfig.metricQueryData.filterData.attributes;
|
|
1013
|
+
|
|
1014
|
+
for (const key of Object.keys(attributes)) {
|
|
1015
|
+
expect(key.startsWith("resource.")).toBe(false);
|
|
1016
|
+
expect(["status", "power_state", "effective"]).toContain(key);
|
|
1017
|
+
expect(typeof attributes[key]).toBe("string");
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
);
|
|
1022
|
+
|
|
1023
|
+
test.each(
|
|
1024
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
1025
|
+
return [t.id, t];
|
|
1026
|
+
}),
|
|
1027
|
+
)(
|
|
1028
|
+
"%s has disjoint fire/recover thresholds on the same alias",
|
|
1029
|
+
(_id: unknown, template: unknown) => {
|
|
1030
|
+
const step: MonitorStep = (
|
|
1031
|
+
template as VMwareAlertTemplate
|
|
1032
|
+
).getMonitorStep(buildArgs());
|
|
1033
|
+
const instances: Array<MonitorCriteriaInstance> =
|
|
1034
|
+
getCriteriaInstances(step);
|
|
1035
|
+
const onlineFilters: Array<any> = (instances[instances.length - 1]!.data
|
|
1036
|
+
?.filters || []) as Array<any>;
|
|
1037
|
+
|
|
1038
|
+
for (const offline of instances.slice(0, -1)) {
|
|
1039
|
+
for (const fireFilter of (offline.data?.filters || []) as Array<any>) {
|
|
1040
|
+
const recoverFilter: any = onlineFilters.find((f: any) => {
|
|
1041
|
+
return (
|
|
1042
|
+
f.metricMonitorOptions.metricAlias ===
|
|
1043
|
+
fireFilter.metricMonitorOptions.metricAlias
|
|
1044
|
+
);
|
|
1045
|
+
});
|
|
1046
|
+
expect(recoverFilter).toBeDefined();
|
|
1047
|
+
expect(
|
|
1048
|
+
hasRecoveryDeadBand(
|
|
1049
|
+
{
|
|
1050
|
+
filterType: fireFilter.filterType,
|
|
1051
|
+
value: fireFilter.value as number,
|
|
1052
|
+
},
|
|
1053
|
+
{
|
|
1054
|
+
filterType: recoverFilter.filterType,
|
|
1055
|
+
value: recoverFilter.value as number,
|
|
1056
|
+
},
|
|
1057
|
+
),
|
|
1058
|
+
).toBe(true);
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
},
|
|
1062
|
+
);
|
|
1063
|
+
|
|
1064
|
+
test.each(
|
|
1065
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
1066
|
+
return [t.id, t];
|
|
1067
|
+
}),
|
|
1068
|
+
)(
|
|
1069
|
+
"%s evaluates sustained over the whole window, not on a single sample",
|
|
1070
|
+
(_id: unknown, template: unknown) => {
|
|
1071
|
+
/*
|
|
1072
|
+
* The rolling window is only the alert's patience because the
|
|
1073
|
+
* quantifier is "every sample". With AnyValue a 15-minute and a
|
|
1074
|
+
* 1-minute window are identical for anything that spikes.
|
|
1075
|
+
*/
|
|
1076
|
+
const step: MonitorStep = (
|
|
1077
|
+
template as VMwareAlertTemplate
|
|
1078
|
+
).getMonitorStep(buildArgs());
|
|
1079
|
+
|
|
1080
|
+
for (const instance of getCriteriaInstances(step)) {
|
|
1081
|
+
for (const filter of (instance.data?.filters || []) as Array<any>) {
|
|
1082
|
+
expect(filter.metricMonitorOptions.metricAggregationType).toBe(
|
|
1083
|
+
EvaluateOverTimeType.AllValues,
|
|
1084
|
+
);
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
},
|
|
1088
|
+
);
|
|
1089
|
+
|
|
1090
|
+
test.each(
|
|
1091
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
1092
|
+
return [t.id, t];
|
|
1093
|
+
}),
|
|
1094
|
+
)(
|
|
1095
|
+
"%s pins the display unit whenever the threshold is written in a unit",
|
|
1096
|
+
(_id: unknown, template: unknown) => {
|
|
1097
|
+
/*
|
|
1098
|
+
* A percentage / latency threshold only means what it says if the
|
|
1099
|
+
* query's samples are in that unit. The vcenter receiver's native
|
|
1100
|
+
* unit matches, so the pin is a no-op today — it is there so the
|
|
1101
|
+
* threshold does not silently change meaning if a receiver build
|
|
1102
|
+
* ever ships a different unit string. Zero-thresholded counts and
|
|
1103
|
+
* rates need no unit.
|
|
1104
|
+
*/
|
|
1105
|
+
const step: MonitorStep = (
|
|
1106
|
+
template as VMwareAlertTemplate
|
|
1107
|
+
).getMonitorStep(buildArgs());
|
|
1108
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
1109
|
+
const fireFilter: any = (
|
|
1110
|
+
getCriteriaInstances(step)[0]!.data?.filters as Array<any>
|
|
1111
|
+
)[0];
|
|
1112
|
+
|
|
1113
|
+
for (const queryConfig of monitor.metricViewConfig
|
|
1114
|
+
.queryConfigs as Array<any>) {
|
|
1115
|
+
const definition: VMwareMetricDefinition | undefined =
|
|
1116
|
+
getVMwareMetricByMetricName(
|
|
1117
|
+
queryConfig.metricQueryData.filterData.metricName,
|
|
1118
|
+
);
|
|
1119
|
+
const legendUnit: string | undefined =
|
|
1120
|
+
queryConfig.metricAliasData.legendUnit;
|
|
1121
|
+
|
|
1122
|
+
if (fireFilter.value === 0) {
|
|
1123
|
+
expect(legendUnit).toBeUndefined();
|
|
1124
|
+
} else {
|
|
1125
|
+
expect(legendUnit).toBeDefined();
|
|
1126
|
+
// ...and it is the receiver's own unit, so no conversion happens.
|
|
1127
|
+
expect(legendUnit).toBe(definition!.unit);
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
},
|
|
1131
|
+
);
|
|
1132
|
+
|
|
1133
|
+
test.each(
|
|
1134
|
+
ALL_TEMPLATES.map((t: VMwareAlertTemplate) => {
|
|
1135
|
+
return [t.id, t];
|
|
1136
|
+
}),
|
|
1137
|
+
)(
|
|
1138
|
+
"%s names the vSphere object kind in its title and tells the reader where to look",
|
|
1139
|
+
(_id: unknown, template: unknown) => {
|
|
1140
|
+
const step: MonitorStep = (
|
|
1141
|
+
template as VMwareAlertTemplate
|
|
1142
|
+
).getMonitorStep(buildArgs());
|
|
1143
|
+
const fireInstance: MonitorCriteriaInstance =
|
|
1144
|
+
getCriteriaInstances(step)[0]!;
|
|
1145
|
+
const incident: any = fireInstance.data?.incidents?.[0];
|
|
1146
|
+
const alert: any = fireInstance.data?.alerts?.[0];
|
|
1147
|
+
|
|
1148
|
+
expect(incident.title).toMatch(/^\[VMware\] /);
|
|
1149
|
+
expect(incident.title).toContain("Test Monitor");
|
|
1150
|
+
expect(alert.title).toBe(incident.title);
|
|
1151
|
+
expect(alert.description).toBe(incident.description);
|
|
1152
|
+
|
|
1153
|
+
// The description tells the engineer to read the affected resource.
|
|
1154
|
+
expect(incident.description).toMatch(/affected resource on this alert/i);
|
|
1155
|
+
|
|
1156
|
+
// Named criteria, not the builder's generic fallback.
|
|
1157
|
+
expect(fireInstance.data?.name).not.toMatch(/Unhealthy$/);
|
|
1158
|
+
expect(fireInstance.data?.description).toMatch(/^Triggers when /);
|
|
1159
|
+
|
|
1160
|
+
// Never leaks Proxmox vocabulary into a vSphere alert.
|
|
1161
|
+
for (const text of [
|
|
1162
|
+
(template as VMwareAlertTemplate).description,
|
|
1163
|
+
incident.title,
|
|
1164
|
+
incident.description,
|
|
1165
|
+
fireInstance.data?.name || "",
|
|
1166
|
+
fireInstance.data?.description || "",
|
|
1167
|
+
]) {
|
|
1168
|
+
expect(text).not.toMatch(/proxmox|pve|lxc|qemu|guest agent/i);
|
|
1169
|
+
}
|
|
1170
|
+
},
|
|
1171
|
+
);
|
|
1172
|
+
|
|
1173
|
+
test("Critical templates announce themselves in the incident title", () => {
|
|
1174
|
+
for (const template of ALL_TEMPLATES) {
|
|
1175
|
+
const step: MonitorStep = template.getMonitorStep(buildArgs());
|
|
1176
|
+
const title: string =
|
|
1177
|
+
getCriteriaInstances(step)[0]!.data?.incidents?.[0]?.title || "";
|
|
1178
|
+
|
|
1179
|
+
if (template.severity === "Critical") {
|
|
1180
|
+
expect(title).toContain("CRITICAL:");
|
|
1181
|
+
} else {
|
|
1182
|
+
expect(title).not.toContain("CRITICAL:");
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
});
|
|
1187
|
+
|
|
1188
|
+
describe("VMwareAlertTemplates - spec table expectations", () => {
|
|
1189
|
+
test.each(
|
|
1190
|
+
EXPECTED_TEMPLATES.map((t: TemplateExpectation) => {
|
|
1191
|
+
return [t.id, t];
|
|
1192
|
+
}),
|
|
1193
|
+
)(
|
|
1194
|
+
"%s matches the spec'd metric/aggregation/threshold contract",
|
|
1195
|
+
(_id: unknown, expected: unknown) => {
|
|
1196
|
+
const tc: TemplateExpectation = expected as TemplateExpectation;
|
|
1197
|
+
const template: VMwareAlertTemplate | undefined =
|
|
1198
|
+
getVMwareAlertTemplateById(tc.id);
|
|
1199
|
+
expect(template).toBeDefined();
|
|
1200
|
+
|
|
1201
|
+
expect(template!.category).toBe(tc.category);
|
|
1202
|
+
expect(template!.severity).toBe(tc.severity);
|
|
1203
|
+
|
|
1204
|
+
const step: MonitorStep = template!.getMonitorStep(buildArgs());
|
|
1205
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
1206
|
+
|
|
1207
|
+
expect(monitor.rollingTime).toBe(tc.rollingTime);
|
|
1208
|
+
|
|
1209
|
+
const queryConfigs: Array<any> = monitor.metricViewConfig
|
|
1210
|
+
.queryConfigs as Array<any>;
|
|
1211
|
+
expect(queryConfigs).toHaveLength(tc.queries.length);
|
|
1212
|
+
|
|
1213
|
+
for (let i: number = 0; i < tc.queries.length; i++) {
|
|
1214
|
+
const expectedQuery: QueryExpectation = tc.queries[i]!;
|
|
1215
|
+
const filterData: any = queryConfigs[i].metricQueryData.filterData;
|
|
1216
|
+
expect(filterData.metricName).toBe(expectedQuery.metricName);
|
|
1217
|
+
expect(filterData.aggegationType).toBe(expectedQuery.aggregation);
|
|
1218
|
+
expect(filterData.attributes).toEqual(expectedQuery.attributes);
|
|
1219
|
+
expect(queryConfigs[i].metricAliasData.legendUnit).toBe(
|
|
1220
|
+
expectedQuery.legendUnit,
|
|
1221
|
+
);
|
|
1222
|
+
|
|
1223
|
+
const groupBys: Array<string> =
|
|
1224
|
+
queryConfigs[i].metricQueryData.groupByAttributeKeys || [];
|
|
1225
|
+
expect(groupBys).toEqual([tc.groupBy]);
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
// No ratio formulas: the receiver ships ready-made percentages.
|
|
1229
|
+
expect(monitor.metricViewConfig.formulaConfigs || []).toHaveLength(0);
|
|
1230
|
+
|
|
1231
|
+
const instances: Array<MonitorCriteriaInstance> =
|
|
1232
|
+
getCriteriaInstances(step);
|
|
1233
|
+
expect(instances).toHaveLength(2);
|
|
1234
|
+
|
|
1235
|
+
const fireFilter: any = (instances[0]!.data?.filters as Array<any>)[0];
|
|
1236
|
+
expect(fireFilter.metricMonitorOptions.metricAlias).toBe(tc.fire.alias);
|
|
1237
|
+
expect(fireFilter.filterType).toBe(tc.fire.filterType);
|
|
1238
|
+
expect(fireFilter.value).toBe(tc.fire.value);
|
|
1239
|
+
|
|
1240
|
+
const recoverFilter: any = (instances[1]!.data?.filters as Array<any>)[0];
|
|
1241
|
+
expect(recoverFilter.metricMonitorOptions.metricAlias).toBe(
|
|
1242
|
+
tc.recover.alias,
|
|
1243
|
+
);
|
|
1244
|
+
expect(recoverFilter.filterType).toBe(tc.recover.filterType);
|
|
1245
|
+
/*
|
|
1246
|
+
* The spec table states the FIRING threshold; the recovery threshold
|
|
1247
|
+
* is derived from it so the dead band lives in one place rather than
|
|
1248
|
+
* being restated in every spec table.
|
|
1249
|
+
*/
|
|
1250
|
+
expect(recoverFilter.value).toBe(expectedRecoveryValue(tc.recover));
|
|
1251
|
+
},
|
|
1252
|
+
);
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1255
|
+
/*
|
|
1256
|
+
* Regression suites below. Each pins a decision that is easy to "tidy up"
|
|
1257
|
+
* into a defect: reverting it must turn one of these red.
|
|
1258
|
+
*/
|
|
1259
|
+
|
|
1260
|
+
function getTemplate(id: string): VMwareAlertTemplate {
|
|
1261
|
+
const template: VMwareAlertTemplate | undefined =
|
|
1262
|
+
getVMwareAlertTemplateById(id);
|
|
1263
|
+
if (!template) {
|
|
1264
|
+
throw new Error(`template ${id} is not registered`);
|
|
1265
|
+
}
|
|
1266
|
+
return template;
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
function findFilterByAlias(
|
|
1270
|
+
instance: MonitorCriteriaInstance,
|
|
1271
|
+
alias: string,
|
|
1272
|
+
): any {
|
|
1273
|
+
return ((instance.data?.filters || []) as Array<any>).find((filter: any) => {
|
|
1274
|
+
return filter.metricMonitorOptions.metricAlias === alias;
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
describe("VMwareAlertTemplates - VM vs host CPU asymmetry (regression)", () => {
|
|
1279
|
+
const ROLLING_MINUTES: Record<string, number> = {
|
|
1280
|
+
[RollingTime.Past5Minutes]: 5,
|
|
1281
|
+
[RollingTime.Past15Minutes]: 15,
|
|
1282
|
+
};
|
|
1283
|
+
|
|
1284
|
+
/*
|
|
1285
|
+
* `vcenter.vm.cpu.utilization` is usage as a fraction of the VM's OWN
|
|
1286
|
+
* vCPU allocation, which the VM is entitled to spend. A right-sized
|
|
1287
|
+
* 2-vCPU VM running a build sits at 100% by design, so the host's
|
|
1288
|
+
* 5-minute window pages for a workload doing exactly what it was
|
|
1289
|
+
* provisioned to do. The asymmetry IS the fix; assert the relationship,
|
|
1290
|
+
* not only the numbers.
|
|
1291
|
+
*/
|
|
1292
|
+
test("the VM template waits longer than the host one", () => {
|
|
1293
|
+
const hostStep: MonitorStep = getTemplate(
|
|
1294
|
+
"vmware-host-cpu-saturation",
|
|
1295
|
+
).getMonitorStep(buildArgs());
|
|
1296
|
+
const vmStep: MonitorStep = getTemplate(
|
|
1297
|
+
"vmware-vm-cpu-saturation",
|
|
1298
|
+
).getMonitorStep(buildArgs());
|
|
1299
|
+
|
|
1300
|
+
const hostWindow: number =
|
|
1301
|
+
ROLLING_MINUTES[getVMwareMonitor(hostStep).rollingTime as string]!;
|
|
1302
|
+
const vmWindow: number =
|
|
1303
|
+
ROLLING_MINUTES[getVMwareMonitor(vmStep).rollingTime as string]!;
|
|
1304
|
+
expect(vmWindow).toBeGreaterThan(hostWindow);
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
test("vmware-vm-cpu-saturation is 90% sustained across a 15-minute window", () => {
|
|
1308
|
+
const step: MonitorStep = getTemplate(
|
|
1309
|
+
"vmware-vm-cpu-saturation",
|
|
1310
|
+
).getMonitorStep(buildArgs());
|
|
1311
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
1312
|
+
|
|
1313
|
+
expect(monitor.rollingTime).toBe(RollingTime.Past15Minutes);
|
|
1314
|
+
|
|
1315
|
+
const fire: any = findFilterByAlias(
|
|
1316
|
+
getCriteriaInstances(step)[0]!,
|
|
1317
|
+
"vm_cpu_utilization",
|
|
1318
|
+
);
|
|
1319
|
+
expect(fire.filterType).toBe(FilterType.GreaterThan);
|
|
1320
|
+
expect(fire.value).toBe(90);
|
|
1321
|
+
expect(fire.metricMonitorOptions.metricAggregationType).toBe(
|
|
1322
|
+
EvaluateOverTimeType.AllValues,
|
|
1323
|
+
);
|
|
1324
|
+
});
|
|
1325
|
+
|
|
1326
|
+
test("vmware-vm-cpu-saturation recovers at 81, strictly inside its firing threshold", () => {
|
|
1327
|
+
const step: MonitorStep = getTemplate(
|
|
1328
|
+
"vmware-vm-cpu-saturation",
|
|
1329
|
+
).getMonitorStep(buildArgs());
|
|
1330
|
+
const instances: Array<MonitorCriteriaInstance> =
|
|
1331
|
+
getCriteriaInstances(step);
|
|
1332
|
+
const recover: any = findFilterByAlias(
|
|
1333
|
+
instances[instances.length - 1]!,
|
|
1334
|
+
"vm_cpu_utilization",
|
|
1335
|
+
);
|
|
1336
|
+
|
|
1337
|
+
expect(recover.filterType).toBe(FilterType.LessThanOrEqualTo);
|
|
1338
|
+
// 90% minus the shared 10% dead band. A VM parked at 90 cannot toggle.
|
|
1339
|
+
expect(recover.value).toBeCloseTo(81, 10);
|
|
1340
|
+
expect(recover.value).toBeLessThan(90);
|
|
1341
|
+
});
|
|
1342
|
+
|
|
1343
|
+
test("every other template uses the 5-minute window", () => {
|
|
1344
|
+
for (const template of ALL_TEMPLATES) {
|
|
1345
|
+
if (template.id === "vmware-vm-cpu-saturation") {
|
|
1346
|
+
continue;
|
|
1347
|
+
}
|
|
1348
|
+
expect(
|
|
1349
|
+
getVMwareMonitor(template.getMonitorStep(buildArgs())).rollingTime,
|
|
1350
|
+
).toBe(RollingTime.Past5Minutes);
|
|
1351
|
+
}
|
|
1352
|
+
});
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
describe("VMwareAlertTemplates - datastore warning/critical tiering (regression)", () => {
|
|
1356
|
+
/*
|
|
1357
|
+
* Two templates on ONE metric with different thresholds and severities.
|
|
1358
|
+
* They must stay ordered (warning strictly below critical), their
|
|
1359
|
+
* recovery bands must not overlap the other tier's firing threshold, and
|
|
1360
|
+
* they must fingerprint differently or the recommendation diff would
|
|
1361
|
+
* treat creating one as covering both.
|
|
1362
|
+
*/
|
|
1363
|
+
test("the warning tier fires below the critical tier and the bands do not cross", () => {
|
|
1364
|
+
const warningStep: MonitorStep = getTemplate(
|
|
1365
|
+
"vmware-datastore-capacity-warning",
|
|
1366
|
+
).getMonitorStep(buildArgs());
|
|
1367
|
+
const criticalStep: MonitorStep = getTemplate(
|
|
1368
|
+
"vmware-datastore-capacity-critical",
|
|
1369
|
+
).getMonitorStep(buildArgs());
|
|
1370
|
+
|
|
1371
|
+
const warningFire: any = findFilterByAlias(
|
|
1372
|
+
getCriteriaInstances(warningStep)[0]!,
|
|
1373
|
+
"datastore_utilization",
|
|
1374
|
+
);
|
|
1375
|
+
const criticalFire: any = findFilterByAlias(
|
|
1376
|
+
getCriteriaInstances(criticalStep)[0]!,
|
|
1377
|
+
"datastore_utilization",
|
|
1378
|
+
);
|
|
1379
|
+
const criticalRecover: any = findFilterByAlias(
|
|
1380
|
+
getCriteriaInstances(criticalStep)[1]!,
|
|
1381
|
+
"datastore_utilization",
|
|
1382
|
+
);
|
|
1383
|
+
|
|
1384
|
+
expect(warningFire.value).toBe(80);
|
|
1385
|
+
expect(criticalFire.value).toBe(90);
|
|
1386
|
+
expect(warningFire.value).toBeLessThan(criticalFire.value);
|
|
1387
|
+
// Critical recovers at 81 — still above the warning tier's 80.
|
|
1388
|
+
expect(criticalRecover.value).toBeCloseTo(81, 10);
|
|
1389
|
+
expect(criticalRecover.value).toBeGreaterThan(warningFire.value);
|
|
1390
|
+
|
|
1391
|
+
expect(getTemplate("vmware-datastore-capacity-warning").severity).toBe(
|
|
1392
|
+
"Warning",
|
|
1393
|
+
);
|
|
1394
|
+
expect(getTemplate("vmware-datastore-capacity-critical").severity).toBe(
|
|
1395
|
+
"Critical",
|
|
1396
|
+
);
|
|
1397
|
+
});
|
|
1398
|
+
});
|
|
1399
|
+
|
|
1400
|
+
describe("VMwareAlertTemplates - attribute-filtered count templates (regression)", () => {
|
|
1401
|
+
/*
|
|
1402
|
+
* The datacenter / cluster count metrics fan out over `status`,
|
|
1403
|
+
* `power_state` and `effective`. Without the equality filter the
|
|
1404
|
+
* template would count EVERY host (green ones included) and fire on
|
|
1405
|
+
* any datacenter with a host in it.
|
|
1406
|
+
*/
|
|
1407
|
+
test.each([
|
|
1408
|
+
["vmware-cluster-host-not-effective", { effective: "false" }],
|
|
1409
|
+
["vmware-datacenter-hosts-unhealthy", { status: "red" }],
|
|
1410
|
+
["vmware-datacenter-hosts-degraded", { status: "yellow" }],
|
|
1411
|
+
["vmware-datacenter-hosts-powered-off", { power_state: "off" }],
|
|
1412
|
+
["vmware-datacenter-vms-unhealthy", { status: "red" }],
|
|
1413
|
+
["vmware-datacenter-clusters-unhealthy", { status: "red" }],
|
|
1414
|
+
])(
|
|
1415
|
+
"%s narrows the count to the unhealthy attribute value",
|
|
1416
|
+
(id: string, attributes: Record<string, string>) => {
|
|
1417
|
+
const step: MonitorStep = getTemplate(id).getMonitorStep(buildArgs());
|
|
1418
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(step);
|
|
1419
|
+
const queryConfig: any = monitor.metricViewConfig.queryConfigs[0];
|
|
1420
|
+
|
|
1421
|
+
expect(queryConfig.metricQueryData.filterData.attributes).toEqual(
|
|
1422
|
+
attributes,
|
|
1423
|
+
);
|
|
1424
|
+
// Max — one collection reporting an unhealthy object trips it.
|
|
1425
|
+
expect(queryConfig.metricQueryData.filterData.aggegationType).toBe(
|
|
1426
|
+
MetricsAggregationType.Max,
|
|
1427
|
+
);
|
|
1428
|
+
|
|
1429
|
+
const fire: any = (
|
|
1430
|
+
getCriteriaInstances(step)[0]!.data?.filters as Array<any>
|
|
1431
|
+
)[0];
|
|
1432
|
+
expect(fire.filterType).toBe(FilterType.GreaterThan);
|
|
1433
|
+
expect(fire.value).toBe(0);
|
|
1434
|
+
},
|
|
1435
|
+
);
|
|
1436
|
+
|
|
1437
|
+
test('the effective filter is the string "false", never a boolean', () => {
|
|
1438
|
+
/*
|
|
1439
|
+
* The receiver declares `effective` as a bool, but attribute values
|
|
1440
|
+
* are stored as strings, so a boolean `false` here would compare a
|
|
1441
|
+
* string column against a boolean and match nothing.
|
|
1442
|
+
*/
|
|
1443
|
+
const step: MonitorStep = getTemplate(
|
|
1444
|
+
"vmware-cluster-host-not-effective",
|
|
1445
|
+
).getMonitorStep(buildArgs());
|
|
1446
|
+
const attributes: Record<string, unknown> = (
|
|
1447
|
+
getVMwareMonitor(step).metricViewConfig.queryConfigs[0] as any
|
|
1448
|
+
).metricQueryData.filterData.attributes;
|
|
1449
|
+
|
|
1450
|
+
expect(attributes["effective"]).toBe("false");
|
|
1451
|
+
expect(typeof attributes["effective"]).toBe("string");
|
|
1452
|
+
});
|
|
1453
|
+
|
|
1454
|
+
test("every template that filters on a count metric names the datacenter or cluster, not the counted object", () => {
|
|
1455
|
+
/*
|
|
1456
|
+
* `vcenter.datacenter.host.count` is a property of the DATACENTER: the
|
|
1457
|
+
* series carries only `vcenter.datacenter.name`. Grouping it by host
|
|
1458
|
+
* would key on an attribute the series never has.
|
|
1459
|
+
*/
|
|
1460
|
+
for (const template of ALL_TEMPLATES) {
|
|
1461
|
+
const monitor: MonitorStepVMwareMonitor = getVMwareMonitor(
|
|
1462
|
+
template.getMonitorStep(buildArgs()),
|
|
1463
|
+
);
|
|
1464
|
+
const queryConfig: any = monitor.metricViewConfig.queryConfigs[0];
|
|
1465
|
+
const metricName: string = queryConfig.metricQueryData.filterData
|
|
1466
|
+
.metricName as string;
|
|
1467
|
+
|
|
1468
|
+
if (metricName.startsWith("vcenter.datacenter.")) {
|
|
1469
|
+
expect(queryConfig.metricQueryData.groupByAttributeKeys).toEqual([
|
|
1470
|
+
VMwareGroupByKey.Datacenter,
|
|
1471
|
+
]);
|
|
1472
|
+
}
|
|
1473
|
+
if (metricName.startsWith("vcenter.cluster.")) {
|
|
1474
|
+
expect(queryConfig.metricQueryData.groupByAttributeKeys).toEqual([
|
|
1475
|
+
VMwareGroupByKey.Cluster,
|
|
1476
|
+
]);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
});
|
|
1480
|
+
});
|
|
1481
|
+
|
|
1482
|
+
describe("VMwareAlertTemplates - vSAN latency unit (regression)", () => {
|
|
1483
|
+
/*
|
|
1484
|
+
* Host and VM disk latency are milliseconds; vSAN latency is
|
|
1485
|
+
* MICROseconds. A copy-pasted "50" from the disk templates would be
|
|
1486
|
+
* 50 µs and page constantly. The threshold must be 20 000 in the native
|
|
1487
|
+
* unit, pinned as "us".
|
|
1488
|
+
*/
|
|
1489
|
+
test("thresholds 20 000 µs with the unit pinned, not 20 or 50 ms", () => {
|
|
1490
|
+
const step: MonitorStep = getTemplate(
|
|
1491
|
+
"vmware-vsan-latency-high",
|
|
1492
|
+
).getMonitorStep(buildArgs());
|
|
1493
|
+
const queryConfig: any =
|
|
1494
|
+
getVMwareMonitor(step).metricViewConfig.queryConfigs[0];
|
|
1495
|
+
const fire: any = (
|
|
1496
|
+
getCriteriaInstances(step)[0]!.data?.filters as Array<any>
|
|
1497
|
+
)[0];
|
|
1498
|
+
|
|
1499
|
+
expect(queryConfig.metricAliasData.legendUnit).toBe("us");
|
|
1500
|
+
expect(
|
|
1501
|
+
getVMwareMetricByMetricName("vcenter.cluster.vsan.latency.avg")?.unit,
|
|
1502
|
+
).toBe("us");
|
|
1503
|
+
expect(fire.value).toBe(20000);
|
|
1504
|
+
expect(fire.value).not.toBe(20);
|
|
1505
|
+
expect(fire.value).not.toBe(50);
|
|
1506
|
+
});
|
|
1507
|
+
|
|
1508
|
+
test("disk latency templates threshold in milliseconds", () => {
|
|
1509
|
+
for (const id of [
|
|
1510
|
+
"vmware-host-disk-latency-high",
|
|
1511
|
+
"vmware-vm-disk-latency-high",
|
|
1512
|
+
]) {
|
|
1513
|
+
const step: MonitorStep = getTemplate(id).getMonitorStep(buildArgs());
|
|
1514
|
+
const queryConfig: any =
|
|
1515
|
+
getVMwareMonitor(step).metricViewConfig.queryConfigs[0];
|
|
1516
|
+
const fire: any = (
|
|
1517
|
+
getCriteriaInstances(step)[0]!.data?.filters as Array<any>
|
|
1518
|
+
)[0];
|
|
1519
|
+
|
|
1520
|
+
expect(queryConfig.metricAliasData.legendUnit).toBe("ms");
|
|
1521
|
+
expect(fire.value).toBe(50);
|
|
1522
|
+
}
|
|
1523
|
+
});
|
|
1524
|
+
});
|
|
1525
|
+
|
|
1526
|
+
describe("VMwareAlertTemplates - memory pressure ladder (regression)", () => {
|
|
1527
|
+
/*
|
|
1528
|
+
* Ballooning precedes swapping in ESXi's reclamation order, so
|
|
1529
|
+
* swapping is the more severe signal. A later "harmonisation" that made
|
|
1530
|
+
* both Warning would lose the escalation.
|
|
1531
|
+
*/
|
|
1532
|
+
test("swapping is Critical, ballooning is Warning", () => {
|
|
1533
|
+
expect(getTemplate("vmware-vm-memory-swapping").severity).toBe("Critical");
|
|
1534
|
+
expect(getTemplate("vmware-vm-memory-ballooning").severity).toBe("Warning");
|
|
1535
|
+
expect(getTemplate("vmware-resource-pool-memory-swapped").severity).toBe(
|
|
1536
|
+
"Warning",
|
|
1537
|
+
);
|
|
1538
|
+
});
|
|
1539
|
+
|
|
1540
|
+
test("zero-thresholded count pairs recover at exactly 0, with no dead band", () => {
|
|
1541
|
+
for (const id of [
|
|
1542
|
+
"vmware-vm-memory-ballooning",
|
|
1543
|
+
"vmware-vm-memory-swapping",
|
|
1544
|
+
"vmware-resource-pool-memory-swapped",
|
|
1545
|
+
"vmware-vsan-congestion",
|
|
1546
|
+
"vmware-host-network-packet-errors",
|
|
1547
|
+
"vmware-host-network-packet-drops",
|
|
1548
|
+
]) {
|
|
1549
|
+
const step: MonitorStep = getTemplate(id).getMonitorStep(buildArgs());
|
|
1550
|
+
const instances: Array<MonitorCriteriaInstance> =
|
|
1551
|
+
getCriteriaInstances(step);
|
|
1552
|
+
const fire: any = (instances[0]!.data?.filters as Array<any>)[0];
|
|
1553
|
+
const recover: any = (instances[1]!.data?.filters as Array<any>)[0];
|
|
1554
|
+
|
|
1555
|
+
expect(fire.filterType).toBe(FilterType.GreaterThan);
|
|
1556
|
+
expect(fire.value).toBe(0);
|
|
1557
|
+
expect(recover.filterType).toBe(FilterType.EqualTo);
|
|
1558
|
+
expect(recover.value).toBe(0);
|
|
1559
|
+
}
|
|
1560
|
+
});
|
|
1561
|
+
});
|
|
1562
|
+
|
|
1563
|
+
describe("VMwareAlertTemplates - coverage fingerprints", () => {
|
|
1564
|
+
/*
|
|
1565
|
+
* The recommendation coverage diff resolves "already created" by
|
|
1566
|
+
* fingerprint (metric names + query attributes + criteria thresholds).
|
|
1567
|
+
* Two templates that fingerprint identically would make creating one
|
|
1568
|
+
* grey out the other. Every template must therefore differ from every
|
|
1569
|
+
* other in at least (metric, attribute filter, firing threshold) — and
|
|
1570
|
+
* the module as a whole must watch many metrics, so the coverage test's
|
|
1571
|
+
* "two templates with different fingerprints" precondition can never
|
|
1572
|
+
* degrade into threshold-only variants of one metric.
|
|
1573
|
+
*/
|
|
1574
|
+
test("every template has a distinct (metric, attributes, threshold) signature", () => {
|
|
1575
|
+
const signatures: Array<string> = ALL_TEMPLATES.map(
|
|
1576
|
+
(template: VMwareAlertTemplate) => {
|
|
1577
|
+
const step: MonitorStep = template.getMonitorStep(buildArgs());
|
|
1578
|
+
const queryConfig: any =
|
|
1579
|
+
getVMwareMonitor(step).metricViewConfig.queryConfigs[0];
|
|
1580
|
+
const fire: any = (
|
|
1581
|
+
getCriteriaInstances(step)[0]!.data?.filters as Array<any>
|
|
1582
|
+
)[0];
|
|
1583
|
+
|
|
1584
|
+
return [
|
|
1585
|
+
queryConfig.metricQueryData.filterData.metricName,
|
|
1586
|
+
JSON.stringify(queryConfig.metricQueryData.filterData.attributes),
|
|
1587
|
+
fire.filterType,
|
|
1588
|
+
fire.value,
|
|
1589
|
+
].join("|");
|
|
1590
|
+
},
|
|
1591
|
+
);
|
|
1592
|
+
|
|
1593
|
+
expect(new Set(signatures).size).toBe(signatures.length);
|
|
1594
|
+
});
|
|
1595
|
+
|
|
1596
|
+
test("the module watches well over a dozen distinct metrics", () => {
|
|
1597
|
+
const metricNames: Set<string> = new Set<string>(
|
|
1598
|
+
ALL_TEMPLATES.map((template: VMwareAlertTemplate) => {
|
|
1599
|
+
const queryConfig: any = getVMwareMonitor(
|
|
1600
|
+
template.getMonitorStep(buildArgs()),
|
|
1601
|
+
).metricViewConfig.queryConfigs[0];
|
|
1602
|
+
return queryConfig.metricQueryData.filterData.metricName as string;
|
|
1603
|
+
}),
|
|
1604
|
+
);
|
|
1605
|
+
|
|
1606
|
+
expect(metricNames.size).toBeGreaterThanOrEqual(15);
|
|
1607
|
+
});
|
|
1608
|
+
});
|