@oneuptime/common 12.0.32 → 12.0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/Span.ts +14 -0
- package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/Index.ts +10 -0
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +176 -1
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- package/Models/DatabaseModels/TelemetryException.ts +119 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
- package/Server/API/EnterpriseLicenseAPI.ts +391 -64
- package/Server/API/LlmProviderAPI.ts +137 -22
- package/Server/EnvironmentConfig.ts +14 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
- package/Server/Infrastructure/QueueWorker.ts +38 -8
- package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
- package/Server/Middleware/ProjectAuthorization.ts +11 -0
- package/Server/Middleware/SCIMAuthorization.ts +12 -0
- package/Server/Middleware/TelemetryIngest.ts +11 -0
- package/Server/Services/AIBillingService.ts +101 -27
- package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/Index.ts +10 -0
- package/Server/Services/MonitorService.ts +143 -21
- package/Server/Services/MonitorStatusTimelineService.ts +150 -8
- package/Server/Services/MonitorTemplateService.ts +217 -1
- package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
- package/Server/Services/NetworkAlertPolicyService.ts +944 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
- package/Server/Services/NetworkDeviceService.ts +1032 -73
- package/Server/Services/NetworkSiteService.ts +1502 -129
- package/Server/Services/NetworkSiteTypeService.ts +1216 -0
- package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
- package/Server/Services/NotificationService.ts +118 -28
- package/Server/Services/ProjectService.ts +105 -48
- package/Server/Services/StatusPagePrivateUserService.ts +103 -3
- package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
- package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
- package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
- package/Server/Services/UserNotificationSettingService.ts +62 -25
- package/Server/Services/UserService.ts +95 -0
- package/Server/Types/Database/QueryHelper.ts +2 -2
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
- package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
- package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
- package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
- package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
- package/Server/Utils/DataSource/HttpFetch.ts +9 -2
- package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
- package/Server/Utils/LLM/LLMService.ts +78 -0
- package/Server/Utils/LogRedaction.ts +8 -0
- package/Server/Utils/Logger.ts +79 -1
- package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
- package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
- package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
- package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
- package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
- package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
- package/Server/Utils/OutboundUserAgent.ts +152 -0
- package/Server/Utils/StartServer.ts +51 -19
- package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
- package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
- package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
- package/Server/Utils/Telemetry.ts +198 -51
- package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
- package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
- package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
- package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
- package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
- package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
- package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
- package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
- package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
- package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
- package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
- package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
- package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
- package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
- package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
- package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
- package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
- package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
- package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
- package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
- package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
- package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
- package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
- package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
- package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
- package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
- package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
- package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
- package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
- package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
- package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
- package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
- package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +102 -1
- package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
- package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
- package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
- package/Tests/Server/Utils/Captcha.test.ts +422 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
- package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
- package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
- package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
- package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
- package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
- package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
- package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
- package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
- package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
- package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
- package/Tests/Server/Utils/Telemetry.test.ts +456 -66
- package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
- package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
- package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
- package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
- package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
- package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
- package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
- package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
- package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
- package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
- package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
- package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
- package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
- package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
- package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
- package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
- package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
- package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
- package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
- package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
- package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
- package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
- package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
- package/Types/AI/ExceptionAIClassification.ts +10 -24
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
- package/Types/Exception/ApiException.ts +10 -0
- package/Types/Exception/BadDataException.ts +11 -0
- package/Types/Exception/BadRequestException.ts +11 -0
- package/Types/Exception/Exception.ts +65 -0
- package/Types/Exception/ForbiddenException.ts +10 -0
- package/Types/Exception/NotAuthenticatedException.ts +10 -0
- package/Types/Exception/NotAuthorizedException.ts +10 -0
- package/Types/Exception/NotFoundException.ts +11 -0
- package/Types/Exception/PayloadTooLargeException.ts +11 -0
- package/Types/Exception/PaymentRequiredException.ts +10 -0
- package/Types/Exception/ServiceUnavailableException.ts +10 -0
- package/Types/Exception/SsoAuthorizationException.ts +10 -0
- package/Types/Exception/TenantNotFoundException.ts +11 -0
- package/Types/Exception/TimeoutException.ts +10 -0
- package/Types/Exception/TooManyRequestsException.ts +10 -0
- package/Types/Exception/UnableToReachServer.ts +10 -0
- package/Types/Exception/WebsiteRequestException.ts +10 -0
- package/Types/Monitor/CriteriaFilter.ts +60 -2
- package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
- package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
- package/Types/Monitor/MonitorMetricType.ts +71 -0
- package/Types/Monitor/MonitorStep.ts +76 -0
- package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
- package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
- package/Types/Monitor/MonitorType.ts +47 -1
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
- package/Types/Monitor/SqlConnectionConfig.ts +31 -0
- package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
- package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
- package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
- package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
- package/Types/Permission.ts +90 -0
- package/Types/Probe/ProbeMonitorResponse.ts +16 -0
- package/Types/Telemetry/ErrorClass.ts +274 -0
- package/Types/Telemetry/UnitOfWork.ts +59 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
- package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
- package/UI/Components/Modal/Modal.tsx +2 -8
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/SideMenu.tsx +123 -5
- package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
- package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
- package/UI/Components/SideOver/SideOver.tsx +21 -20
- package/UI/Utils/PageScrollLock.ts +79 -3
- package/UI/Utils/PermissionGate.ts +61 -0
- package/UI/Utils/SensitiveUrlToken.ts +112 -0
- package/UI/Utils/TestLLMProvider.ts +11 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
- package/Utils/Monitor/MonitorMetricType.ts +153 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
- package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
- package/build/dist/Models/AnalyticsModels/Span.js +14 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +10 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
- package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/LlmProviderAPI.js +108 -13
- package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +12 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.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/Infrastructure/QueueWorker.js +33 -5
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
- package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
- package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIBillingService.js +70 -16
- package/build/dist/Server/Services/AIBillingService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
- package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
- package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
- package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +10 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +119 -21
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
- package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
- package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
- package/build/dist/Server/Services/NotificationService.js +80 -17
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +66 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
- package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationSettingService.js +46 -20
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +90 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
- package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
- package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
- package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/LogRedaction.js +8 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +63 -1
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
- package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
- package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
- package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
- package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
- package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
- package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
- package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
- package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
- package/build/dist/Server/Utils/StartServer.js +38 -14
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
- package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
- package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
- package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry.js +162 -46
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
- package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
- package/build/dist/Types/Exception/ApiException.js +9 -0
- package/build/dist/Types/Exception/ApiException.js.map +1 -1
- package/build/dist/Types/Exception/BadDataException.js +10 -0
- package/build/dist/Types/Exception/BadDataException.js.map +1 -1
- package/build/dist/Types/Exception/BadRequestException.js +10 -0
- package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
- package/build/dist/Types/Exception/Exception.js +56 -0
- package/build/dist/Types/Exception/Exception.js.map +1 -1
- package/build/dist/Types/Exception/ForbiddenException.js +9 -0
- package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
- package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
- package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
- package/build/dist/Types/Exception/NotFoundException.js +10 -0
- package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
- package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
- package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
- package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
- package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
- package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
- package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
- package/build/dist/Types/Exception/TimeoutException.js +9 -0
- package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
- package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
- package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
- package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
- package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
- package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
- package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
- package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
- package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +54 -0
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
- package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorType.js +45 -1
- package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
- package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
- package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
- package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
- package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
- package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
- package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
- package/build/dist/Types/Permission.js +80 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
- package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
- package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -7
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +31 -3
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +42 -1
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
- package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
- package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
- package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
- package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
- package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,992 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import OneUptimeDate from "../../../Types/Date";
|
|
5
|
+
import NetworkDeviceMonitoringMethod, {
|
|
6
|
+
NetworkDeviceMonitoringMethodUtil,
|
|
7
|
+
} from "../../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
|
|
8
|
+
import { NetworkTopologyNode } from "../../../Types/Monitor/SnmpMonitor/NetworkTopology";
|
|
9
|
+
import DeviceReachabilityUtil, {
|
|
10
|
+
NetworkDeviceReachability,
|
|
11
|
+
} from "../../../Utils/NetworkDevice/DeviceReachabilityUtil";
|
|
12
|
+
import {
|
|
13
|
+
DeviceHealthStateInput,
|
|
14
|
+
NetworkDeviceHealthState,
|
|
15
|
+
deviceHealthState,
|
|
16
|
+
} from "../../../Utils/NetworkDevice/DeviceHealthStateUtil";
|
|
17
|
+
import SiteStatusRollupUtil, {
|
|
18
|
+
DeviceHealthShare,
|
|
19
|
+
DeviceHealthState,
|
|
20
|
+
RollupStatusOption,
|
|
21
|
+
} from "../../../Utils/NetworkSite/SiteStatusRollupUtil";
|
|
22
|
+
import NetworkTopologyUtil, {
|
|
23
|
+
TopologyBuildResult,
|
|
24
|
+
TopologyDeviceInput,
|
|
25
|
+
} from "../../../Utils/Monitor/NetworkTopologyUtil";
|
|
26
|
+
import {
|
|
27
|
+
DeviceHealthGroup,
|
|
28
|
+
deviceHealthInputForGroup,
|
|
29
|
+
deviceRollupStateForGroup,
|
|
30
|
+
} from "../../../Server/Utils/NetworkDevice/DeviceHealthAggregation";
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* Issue #3562 — the monitoring method reaches every classifier, not only
|
|
34
|
+
* the device list.
|
|
35
|
+
*
|
|
36
|
+
* DeviceReachabilityUtil knows the two kinds of NetworkDevice: a
|
|
37
|
+
* PROBE-POLLED one (monitoringMethod "Probe", and equally NULL, "" or the
|
|
38
|
+
* retired "SNMP") is judged by the OUTCOME of its last poll — the probe
|
|
39
|
+
* pings it on its schedule and walks it over SNMP when credentials resolve,
|
|
40
|
+
* and either answering makes it reachable — while a MONITOR-BACKED one is
|
|
41
|
+
* judged ONLY by the status its bound Monitor stamped, and is Pending until
|
|
42
|
+
* one lands. The device list pill goes through that rule with
|
|
43
|
+
* `monitoringMethod` attached and gets the right answer.
|
|
44
|
+
*
|
|
45
|
+
* Three other surfaces build a DeviceReachabilityUtil input of their own —
|
|
46
|
+
* the site card's per-device health (DeviceHealthStateUtil), the site
|
|
47
|
+
* status rollup (SiteStatusRollupUtil) and the topology map
|
|
48
|
+
* (NetworkTopologyUtil) — and none of them used to say what kind of device
|
|
49
|
+
* it was passing. That was survivable while a monitor-backed row had NULL
|
|
50
|
+
* in every poll column, because the rule can only answer Pending for that.
|
|
51
|
+
* It stops being survivable the moment those columns hold anything else:
|
|
52
|
+
*
|
|
53
|
+
* - a device SWITCHED from probe polling to a bound monitor keeps its old
|
|
54
|
+
* lastSeenAt until the switch-over clears it, and `isReachable` NULL +
|
|
55
|
+
* lastSeenAt set is the one branch of the rule where staleness alone
|
|
56
|
+
* decides — so a months-old timestamp reads as Down on the site card
|
|
57
|
+
* while the pill under it reads Pending;
|
|
58
|
+
* - the server keeps `isReachable` on a monitor-backed device in step
|
|
59
|
+
* with its Monitor (true/false, NULL when nothing is bound), and a
|
|
60
|
+
* mirrored outcome beside a stamp that has not landed yet would read as
|
|
61
|
+
* a poll verdict.
|
|
62
|
+
*
|
|
63
|
+
* The field is load-bearing in the OTHER direction too, and that is the half
|
|
64
|
+
* ping-first polling added. A probe-polled device now always has a poll
|
|
65
|
+
* verdict of its own, and it can carry a stamped MonitorStatus at the same
|
|
66
|
+
* time: a Network Device monitor with an "interface down → Offline"
|
|
67
|
+
* criterion stamps one the moment a single port goes dark, and so does the
|
|
68
|
+
* SNMP walk failing on a switch that still answers ping. That stamp is
|
|
69
|
+
* INFORMATIONAL on such a device — its poll decides — because a stamp
|
|
70
|
+
* outranking the poll turned a site of answering devices red while every
|
|
71
|
+
* device row under it read Up.
|
|
72
|
+
*
|
|
73
|
+
* So the field is threaded through all three inputs, and through the
|
|
74
|
+
* bucket-to-input builders that feed two of them. What is pinned here:
|
|
75
|
+
*
|
|
76
|
+
* 1. the field is OPTIONAL, and a caller that omits it — or passes NULL,
|
|
77
|
+
* "SNMP", anything the parser reads as Probe — behaves exactly as
|
|
78
|
+
* before, legacy freshness branch included;
|
|
79
|
+
* 2. an unstamped monitor-backed device is "unknown" on the site card, is
|
|
80
|
+
* skipped by both rollup policies, and is drawn "unknown" on the map,
|
|
81
|
+
* whatever its leftover poll columns say;
|
|
82
|
+
* 3. a stamped monitor-backed device is judged by the stamp on every
|
|
83
|
+
* surface, the same way the pill judges it;
|
|
84
|
+
* 4. a stamped PROBE-POLLED device is judged by its poll on every surface,
|
|
85
|
+
* also the same way the pill judges it — the stamp does not enter;
|
|
86
|
+
* 5. the aggregation buckets carry the field into both classifier
|
|
87
|
+
* inputs, and the topology endpoint selects it, forwards it, and gates
|
|
88
|
+
* the stamp on it.
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
const NOW: Date = OneUptimeDate.fromString("2026-09-01T12:00:00.000Z");
|
|
92
|
+
|
|
93
|
+
function minutesAgo(minutes: number): Date {
|
|
94
|
+
return new Date(NOW.getTime() - minutes * 60 * 1000);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** The poll columns every classifier reads, in their raw column shape. */
|
|
98
|
+
interface PollColumns {
|
|
99
|
+
isReachable: boolean | null;
|
|
100
|
+
lastPolledAt: Date | null;
|
|
101
|
+
lastSeenAt: Date | null;
|
|
102
|
+
pollingIntervalInMinutes: number;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/*
|
|
106
|
+
* What a device switched from probe polling to a bound monitor is left
|
|
107
|
+
* holding: no recorded outcome, and a last successful poll from long before
|
|
108
|
+
* the probe stopped asking. On the legacy branch of the shared rule (no
|
|
109
|
+
* outcome, but seen) staleness alone decides, so this reads as Down through
|
|
110
|
+
* any classifier that forgets to say what kind of device it is.
|
|
111
|
+
*/
|
|
112
|
+
const STALE_LEFTOVERS: PollColumns = {
|
|
113
|
+
isReachable: null,
|
|
114
|
+
lastPolledAt: null,
|
|
115
|
+
lastSeenAt: minutesAgo(60 * 24 * 90),
|
|
116
|
+
pollingIntervalInMinutes: 5,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
// The same leftovers still inside the window, where that branch says Up.
|
|
120
|
+
const FRESH_LEFTOVERS: PollColumns = {
|
|
121
|
+
isReachable: null,
|
|
122
|
+
lastPolledAt: null,
|
|
123
|
+
lastSeenAt: minutesAgo(2),
|
|
124
|
+
pollingIntervalInMinutes: 5,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const NEVER_POLLED: PollColumns = {
|
|
128
|
+
isReachable: null,
|
|
129
|
+
lastPolledAt: null,
|
|
130
|
+
lastSeenAt: null,
|
|
131
|
+
pollingIntervalInMinutes: 5,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const ANSWERED: PollColumns = {
|
|
135
|
+
isReachable: true,
|
|
136
|
+
lastPolledAt: minutesAgo(1),
|
|
137
|
+
lastSeenAt: minutesAgo(1),
|
|
138
|
+
pollingIntervalInMinutes: 5,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const FAILED: PollColumns = {
|
|
142
|
+
isReachable: false,
|
|
143
|
+
lastPolledAt: minutesAgo(1),
|
|
144
|
+
lastSeenAt: minutesAgo(600),
|
|
145
|
+
pollingIntervalInMinutes: 5,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// The real column value, so a renamed enum member fails here and not in prod.
|
|
149
|
+
const MONITOR: string = NetworkDeviceMonitoringMethod.Monitor;
|
|
150
|
+
|
|
151
|
+
// MonitorStatus priority is HIGHER = WORSE (seeded: Operational 1 ... Offline 3).
|
|
152
|
+
const OPERATIONAL: RollupStatusOption = {
|
|
153
|
+
monitorStatusId: "status-operational",
|
|
154
|
+
priority: 1,
|
|
155
|
+
};
|
|
156
|
+
const DEGRADED: RollupStatusOption = {
|
|
157
|
+
monitorStatusId: "status-degraded",
|
|
158
|
+
priority: 2,
|
|
159
|
+
};
|
|
160
|
+
const OFFLINE: RollupStatusOption = {
|
|
161
|
+
monitorStatusId: "status-offline",
|
|
162
|
+
priority: 3,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/*
|
|
166
|
+
* The ladder as each surface reads it. `isOffline` is the flag the site
|
|
167
|
+
* card and the map read (NetworkDeviceTopology.ts: `isOfflineState ? "down"
|
|
168
|
+
* : "up"`); `isOperational` is the one the percent-threshold share reads.
|
|
169
|
+
*/
|
|
170
|
+
interface StampedRung {
|
|
171
|
+
name: string;
|
|
172
|
+
option: RollupStatusOption;
|
|
173
|
+
isOperational: boolean;
|
|
174
|
+
isOffline: boolean;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const RUNGS: Array<StampedRung> = [
|
|
178
|
+
{
|
|
179
|
+
name: "Operational",
|
|
180
|
+
option: OPERATIONAL,
|
|
181
|
+
isOperational: true,
|
|
182
|
+
isOffline: false,
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: "Degraded",
|
|
186
|
+
option: DEGRADED,
|
|
187
|
+
isOperational: false,
|
|
188
|
+
isOffline: false,
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
name: "Offline",
|
|
192
|
+
option: OFFLINE,
|
|
193
|
+
isOperational: false,
|
|
194
|
+
isOffline: true,
|
|
195
|
+
},
|
|
196
|
+
];
|
|
197
|
+
|
|
198
|
+
function healthInput(
|
|
199
|
+
columns: PollColumns,
|
|
200
|
+
overrides?: Partial<DeviceHealthStateInput>,
|
|
201
|
+
): DeviceHealthStateInput {
|
|
202
|
+
return { ...columns, ...overrides };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function rollupState(
|
|
206
|
+
columns: PollColumns,
|
|
207
|
+
overrides?: Partial<DeviceHealthState>,
|
|
208
|
+
): DeviceHealthState {
|
|
209
|
+
return { ...columns, ...overrides };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// TopologyDeviceInput carries `undefined` where a column carries NULL.
|
|
213
|
+
function topologyInput(
|
|
214
|
+
columns: PollColumns,
|
|
215
|
+
overrides?: Partial<TopologyDeviceInput>,
|
|
216
|
+
): TopologyDeviceInput {
|
|
217
|
+
return {
|
|
218
|
+
id: "device-1",
|
|
219
|
+
name: "device-1",
|
|
220
|
+
isReachable: columns.isReachable === null ? undefined : columns.isReachable,
|
|
221
|
+
lastPolledAt:
|
|
222
|
+
columns.lastPolledAt === null ? undefined : columns.lastPolledAt,
|
|
223
|
+
lastSeenAt: columns.lastSeenAt === null ? undefined : columns.lastSeenAt,
|
|
224
|
+
pollingIntervalInMinutes: columns.pollingIntervalInMinutes,
|
|
225
|
+
...overrides,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function topologyStatus(device: TopologyDeviceInput): string {
|
|
230
|
+
const result: TopologyBuildResult = NetworkTopologyUtil.buildTopology(
|
|
231
|
+
[device],
|
|
232
|
+
NOW,
|
|
233
|
+
);
|
|
234
|
+
const node: NetworkTopologyNode | undefined = result.nodes.find(
|
|
235
|
+
(candidate: NetworkTopologyNode): boolean => {
|
|
236
|
+
return candidate.id === device.id;
|
|
237
|
+
},
|
|
238
|
+
);
|
|
239
|
+
expect(node).toBeDefined();
|
|
240
|
+
return node!.status;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function worst(deviceStates: Array<DeviceHealthState>): string | null {
|
|
244
|
+
return SiteStatusRollupUtil.worstStatus({
|
|
245
|
+
deviceStates: deviceStates,
|
|
246
|
+
operationalStatus: OPERATIONAL,
|
|
247
|
+
offlineStatus: OFFLINE,
|
|
248
|
+
now: NOW,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function share(deviceStates: Array<DeviceHealthState>): DeviceHealthShare {
|
|
253
|
+
return SiteStatusRollupUtil.deviceHealthShare({
|
|
254
|
+
deviceStates: deviceStates,
|
|
255
|
+
now: NOW,
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const NOTHING_REPORTED: DeviceHealthShare = {
|
|
260
|
+
reportingDeviceCount: 0,
|
|
261
|
+
nonOperationalDeviceCount: 0,
|
|
262
|
+
nonOperationalPercent: 0,
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const ONE_DOWN: DeviceHealthShare = {
|
|
266
|
+
reportingDeviceCount: 1,
|
|
267
|
+
nonOperationalDeviceCount: 1,
|
|
268
|
+
nonOperationalPercent: 100,
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const ONE_UP: DeviceHealthShare = {
|
|
272
|
+
reportingDeviceCount: 1,
|
|
273
|
+
nonOperationalDeviceCount: 0,
|
|
274
|
+
nonOperationalPercent: 0,
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
/*
|
|
278
|
+
* The field is optional precisely so that nothing that does not pass it can
|
|
279
|
+
* change. Every caller written before it existed — and every test of those
|
|
280
|
+
* callers — must land on the same branch of the shared rule it always did,
|
|
281
|
+
* legacy freshness included.
|
|
282
|
+
*/
|
|
283
|
+
describe("without a monitoring method nothing changes — the legacy path is pinned", () => {
|
|
284
|
+
test("stale leftovers read as down on every surface, as they always did", () => {
|
|
285
|
+
expect(deviceHealthState(healthInput(STALE_LEFTOVERS), NOW)).toBe("down");
|
|
286
|
+
expect(worst([rollupState(STALE_LEFTOVERS)])).toBe(OFFLINE.monitorStatusId);
|
|
287
|
+
expect(share([rollupState(STALE_LEFTOVERS)])).toEqual(ONE_DOWN);
|
|
288
|
+
expect(topologyStatus(topologyInput(STALE_LEFTOVERS))).toBe("down");
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
test("fresh leftovers read as up on every surface, as they always did", () => {
|
|
292
|
+
expect(deviceHealthState(healthInput(FRESH_LEFTOVERS), NOW)).toBe(
|
|
293
|
+
"healthy",
|
|
294
|
+
);
|
|
295
|
+
expect(worst([rollupState(FRESH_LEFTOVERS)])).toBe(
|
|
296
|
+
OPERATIONAL.monitorStatusId,
|
|
297
|
+
);
|
|
298
|
+
expect(share([rollupState(FRESH_LEFTOVERS)])).toEqual(ONE_UP);
|
|
299
|
+
expect(topologyStatus(topologyInput(FRESH_LEFTOVERS))).toBe("up");
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
/*
|
|
303
|
+
* Everything the parser reads as Probe has to land on the same path as an
|
|
304
|
+
* omitted value, or a row written before the column existed (NULL) would
|
|
305
|
+
* classify differently from one written after it ("SNMP"), or from one
|
|
306
|
+
* written today ("Probe").
|
|
307
|
+
*/
|
|
308
|
+
test.each([null, "", "snmp", NetworkDeviceMonitoringMethod.Probe])(
|
|
309
|
+
"a monitoring method of %j is the poll rule, exactly as if omitted",
|
|
310
|
+
(monitoringMethod: string | null) => {
|
|
311
|
+
expect(
|
|
312
|
+
deviceHealthState(
|
|
313
|
+
healthInput(STALE_LEFTOVERS, { monitoringMethod: monitoringMethod }),
|
|
314
|
+
NOW,
|
|
315
|
+
),
|
|
316
|
+
).toBe("down");
|
|
317
|
+
expect(
|
|
318
|
+
worst([
|
|
319
|
+
rollupState(STALE_LEFTOVERS, { monitoringMethod: monitoringMethod }),
|
|
320
|
+
]),
|
|
321
|
+
).toBe(OFFLINE.monitorStatusId);
|
|
322
|
+
expect(
|
|
323
|
+
topologyStatus(
|
|
324
|
+
topologyInput(STALE_LEFTOVERS, {
|
|
325
|
+
monitoringMethod: monitoringMethod,
|
|
326
|
+
}),
|
|
327
|
+
),
|
|
328
|
+
).toBe("down");
|
|
329
|
+
},
|
|
330
|
+
);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
describe("an unstamped monitor-backed device is Pending on every surface", () => {
|
|
334
|
+
test.each([
|
|
335
|
+
["stale leftovers", STALE_LEFTOVERS],
|
|
336
|
+
["fresh leftovers", FRESH_LEFTOVERS],
|
|
337
|
+
["nothing at all", NEVER_POLLED],
|
|
338
|
+
])("with %s in its poll columns", (_label: string, columns: PollColumns) => {
|
|
339
|
+
expect(
|
|
340
|
+
deviceHealthState(
|
|
341
|
+
healthInput(columns, { monitoringMethod: MONITOR }),
|
|
342
|
+
NOW,
|
|
343
|
+
),
|
|
344
|
+
).toBe("unknown");
|
|
345
|
+
expect(
|
|
346
|
+
worst([rollupState(columns, { monitoringMethod: MONITOR })]),
|
|
347
|
+
).toBeNull();
|
|
348
|
+
expect(
|
|
349
|
+
share([rollupState(columns, { monitoringMethod: MONITOR })]),
|
|
350
|
+
).toEqual(NOTHING_REPORTED);
|
|
351
|
+
expect(
|
|
352
|
+
topologyStatus(topologyInput(columns, { monitoringMethod: MONITOR })),
|
|
353
|
+
).toBe("unknown");
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
/*
|
|
357
|
+
* The server keeps `isReachable` on a monitor-backed device in step with
|
|
358
|
+
* its Monitor, so a mirrored true/false can exist beside a stamp that has
|
|
359
|
+
* not landed yet. A mirror is not a verdict: only the stamp is — which is
|
|
360
|
+
* exactly what the pill says about the same row.
|
|
361
|
+
*/
|
|
362
|
+
test.each([true, false])(
|
|
363
|
+
"with a mirrored isReachable of %s and no stamp yet",
|
|
364
|
+
(isReachable: boolean) => {
|
|
365
|
+
const columns: PollColumns = { ...ANSWERED, isReachable: isReachable };
|
|
366
|
+
|
|
367
|
+
expect(
|
|
368
|
+
deviceHealthState(
|
|
369
|
+
healthInput(columns, { monitoringMethod: MONITOR }),
|
|
370
|
+
NOW,
|
|
371
|
+
),
|
|
372
|
+
).toBe("unknown");
|
|
373
|
+
expect(
|
|
374
|
+
worst([rollupState(columns, { monitoringMethod: MONITOR })]),
|
|
375
|
+
).toBeNull();
|
|
376
|
+
expect(
|
|
377
|
+
topologyStatus(topologyInput(columns, { monitoringMethod: MONITOR })),
|
|
378
|
+
).toBe("unknown");
|
|
379
|
+
},
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
test("the column is parsed, not compared: any casing of the word is monitor-backed", () => {
|
|
383
|
+
for (const spelling of ["monitor", "MONITOR", " Monitor "]) {
|
|
384
|
+
expect(
|
|
385
|
+
deviceHealthState(
|
|
386
|
+
healthInput(STALE_LEFTOVERS, { monitoringMethod: spelling }),
|
|
387
|
+
NOW,
|
|
388
|
+
),
|
|
389
|
+
).toBe("unknown");
|
|
390
|
+
expect(
|
|
391
|
+
worst([rollupState(STALE_LEFTOVERS, { monitoringMethod: spelling })]),
|
|
392
|
+
).toBeNull();
|
|
393
|
+
expect(
|
|
394
|
+
topologyStatus(
|
|
395
|
+
topologyInput(STALE_LEFTOVERS, { monitoringMethod: spelling }),
|
|
396
|
+
),
|
|
397
|
+
).toBe("unknown");
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
/*
|
|
402
|
+
* Skipped means skipped from BOTH sides of the share, the same treatment
|
|
403
|
+
* a never-polled probe-polled bucket gets. Four hundred devices awaiting
|
|
404
|
+
* their first monitor evaluation must not dilute the one switch that is
|
|
405
|
+
* genuinely dark beside them into a 0.25% blip...
|
|
406
|
+
*/
|
|
407
|
+
test("a bucket of unstamped monitor-backed devices does not dilute a real outage", () => {
|
|
408
|
+
expect(
|
|
409
|
+
share([
|
|
410
|
+
rollupState(STALE_LEFTOVERS, {
|
|
411
|
+
monitoringMethod: MONITOR,
|
|
412
|
+
deviceCount: 400,
|
|
413
|
+
}),
|
|
414
|
+
rollupState(FAILED),
|
|
415
|
+
]),
|
|
416
|
+
).toEqual(ONE_DOWN);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
test("...and cannot drag a healthy site down either", () => {
|
|
420
|
+
expect(
|
|
421
|
+
worst([
|
|
422
|
+
rollupState(STALE_LEFTOVERS, { monitoringMethod: MONITOR }),
|
|
423
|
+
rollupState(ANSWERED),
|
|
424
|
+
]),
|
|
425
|
+
).toBe(OPERATIONAL.monitorStatusId);
|
|
426
|
+
});
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
describe("a stamped monitor-backed device is judged by the stamp, everywhere", () => {
|
|
430
|
+
test.each(RUNGS)(
|
|
431
|
+
"$name: the site card reads the offline end of the ladder",
|
|
432
|
+
(rung: StampedRung) => {
|
|
433
|
+
expect(
|
|
434
|
+
deviceHealthState(
|
|
435
|
+
healthInput(STALE_LEFTOVERS, {
|
|
436
|
+
monitoringMethod: MONITOR,
|
|
437
|
+
monitorStatusIsOffline: rung.isOffline,
|
|
438
|
+
}),
|
|
439
|
+
NOW,
|
|
440
|
+
),
|
|
441
|
+
).toBe(rung.isOffline ? "down" : "healthy");
|
|
442
|
+
},
|
|
443
|
+
);
|
|
444
|
+
|
|
445
|
+
test.each(RUNGS)(
|
|
446
|
+
"$name: worst-of carries the stamp verbatim",
|
|
447
|
+
(rung: StampedRung) => {
|
|
448
|
+
expect(
|
|
449
|
+
worst([
|
|
450
|
+
rollupState(STALE_LEFTOVERS, {
|
|
451
|
+
monitoringMethod: MONITOR,
|
|
452
|
+
currentMonitorStatusId: rung.option.monitorStatusId,
|
|
453
|
+
monitorStatusPriority: rung.option.priority,
|
|
454
|
+
}),
|
|
455
|
+
]),
|
|
456
|
+
).toBe(rung.option.monitorStatusId);
|
|
457
|
+
},
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
test.each(RUNGS)(
|
|
461
|
+
"$name: the share reads the operational end of the ladder",
|
|
462
|
+
(rung: StampedRung) => {
|
|
463
|
+
expect(
|
|
464
|
+
share([
|
|
465
|
+
rollupState(STALE_LEFTOVERS, {
|
|
466
|
+
monitoringMethod: MONITOR,
|
|
467
|
+
currentMonitorStatusId: rung.option.monitorStatusId,
|
|
468
|
+
monitorStatusIsOperational: rung.isOperational,
|
|
469
|
+
}),
|
|
470
|
+
]),
|
|
471
|
+
).toEqual(rung.isOperational ? ONE_UP : ONE_DOWN);
|
|
472
|
+
},
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
test.each(RUNGS)("$name: the map draws the stamp", (rung: StampedRung) => {
|
|
476
|
+
expect(
|
|
477
|
+
topologyStatus(
|
|
478
|
+
topologyInput(STALE_LEFTOVERS, {
|
|
479
|
+
monitoringMethod: MONITOR,
|
|
480
|
+
monitorStatus: rung.isOffline ? "down" : "up",
|
|
481
|
+
}),
|
|
482
|
+
),
|
|
483
|
+
).toBe(rung.isOffline ? "down" : "up");
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
/*
|
|
487
|
+
* The rollup falls back to reachability when a stamped row cannot be
|
|
488
|
+
* resolved (a deleted status, or a lookup that missed). For a probe-polled
|
|
489
|
+
* device that fallback is a real poll verdict. For a monitor-backed one
|
|
490
|
+
* there is nothing underneath to fall back TO — and the pill, which
|
|
491
|
+
* resolves the same row, reads Pending for it — so it sits out the vote.
|
|
492
|
+
*/
|
|
493
|
+
test("a stamp the rollup cannot resolve leaves a monitor-backed device out of the vote", () => {
|
|
494
|
+
const unresolved: DeviceHealthState = rollupState(STALE_LEFTOVERS, {
|
|
495
|
+
currentMonitorStatusId: "status-deleted",
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
expect(worst([{ ...unresolved, monitoringMethod: MONITOR }])).toBeNull();
|
|
499
|
+
expect(share([{ ...unresolved, monitoringMethod: MONITOR }])).toEqual(
|
|
500
|
+
NOTHING_REPORTED,
|
|
501
|
+
);
|
|
502
|
+
/*
|
|
503
|
+
* Whereas the probe-polled device beside it still has its poll to fall
|
|
504
|
+
* back to — and would have had one even if the row HAD resolved, since
|
|
505
|
+
* its stamp never votes.
|
|
506
|
+
*/
|
|
507
|
+
expect(worst([unresolved])).toBe(OFFLINE.monitorStatusId);
|
|
508
|
+
});
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
/*
|
|
512
|
+
* The other precedence, and the half ping-first polling added (see the
|
|
513
|
+
* header). A probe-polled device carries a stamp and a poll at the same
|
|
514
|
+
* time, and the poll is the verdict on every surface.
|
|
515
|
+
*
|
|
516
|
+
* The concrete regression: an "interface down → Offline" criterion, or an
|
|
517
|
+
* SNMP walk failing on a credential rotation, stamps Offline on a switch
|
|
518
|
+
* that answers every ping. If any of these surfaces read that stamp, the
|
|
519
|
+
* site card and the topology node go red while the device's own row in the
|
|
520
|
+
* list — which reads `isReachable` — says Up, and an operator is sent to
|
|
521
|
+
* find an outage that is not there.
|
|
522
|
+
*/
|
|
523
|
+
describe("a stamped probe-polled device is judged by its poll, everywhere", () => {
|
|
524
|
+
// Every spelling of "probe-polled" a real row can carry.
|
|
525
|
+
const PROBE_POLLED: Array<string | null | undefined> = [
|
|
526
|
+
NetworkDeviceMonitoringMethod.Probe,
|
|
527
|
+
"SNMP",
|
|
528
|
+
"",
|
|
529
|
+
null,
|
|
530
|
+
undefined,
|
|
531
|
+
];
|
|
532
|
+
|
|
533
|
+
test.each(RUNGS)(
|
|
534
|
+
"$name: the site card reads the poll, not the rung",
|
|
535
|
+
(rung: StampedRung) => {
|
|
536
|
+
for (const monitoringMethod of PROBE_POLLED) {
|
|
537
|
+
expect(
|
|
538
|
+
deviceHealthState(
|
|
539
|
+
healthInput(ANSWERED, {
|
|
540
|
+
monitoringMethod: monitoringMethod,
|
|
541
|
+
monitorStatusIsOffline: rung.isOffline,
|
|
542
|
+
}),
|
|
543
|
+
NOW,
|
|
544
|
+
),
|
|
545
|
+
).toBe("healthy");
|
|
546
|
+
expect(
|
|
547
|
+
deviceHealthState(
|
|
548
|
+
healthInput(FAILED, {
|
|
549
|
+
monitoringMethod: monitoringMethod,
|
|
550
|
+
monitorStatusIsOffline: rung.isOffline,
|
|
551
|
+
}),
|
|
552
|
+
NOW,
|
|
553
|
+
),
|
|
554
|
+
).toBe("down");
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
);
|
|
558
|
+
|
|
559
|
+
test.each(RUNGS)(
|
|
560
|
+
"$name: worst-of maps the poll to the project's own rows, ignoring the stamp",
|
|
561
|
+
(rung: StampedRung) => {
|
|
562
|
+
expect(
|
|
563
|
+
worst([
|
|
564
|
+
rollupState(ANSWERED, {
|
|
565
|
+
currentMonitorStatusId: rung.option.monitorStatusId,
|
|
566
|
+
monitorStatusPriority: rung.option.priority,
|
|
567
|
+
}),
|
|
568
|
+
]),
|
|
569
|
+
).toBe(OPERATIONAL.monitorStatusId);
|
|
570
|
+
expect(
|
|
571
|
+
worst([
|
|
572
|
+
rollupState(FAILED, {
|
|
573
|
+
currentMonitorStatusId: rung.option.monitorStatusId,
|
|
574
|
+
monitorStatusPriority: rung.option.priority,
|
|
575
|
+
}),
|
|
576
|
+
]),
|
|
577
|
+
).toBe(OFFLINE.monitorStatusId);
|
|
578
|
+
},
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
test.each(RUNGS)(
|
|
582
|
+
"$name: the share counts the poll, so a stamped fleet that answers is 0% down",
|
|
583
|
+
(rung: StampedRung) => {
|
|
584
|
+
expect(
|
|
585
|
+
share([
|
|
586
|
+
rollupState(ANSWERED, {
|
|
587
|
+
currentMonitorStatusId: rung.option.monitorStatusId,
|
|
588
|
+
monitorStatusIsOperational: rung.isOperational,
|
|
589
|
+
deviceCount: 400,
|
|
590
|
+
}),
|
|
591
|
+
]),
|
|
592
|
+
).toEqual({
|
|
593
|
+
reportingDeviceCount: 400,
|
|
594
|
+
nonOperationalDeviceCount: 0,
|
|
595
|
+
nonOperationalPercent: 0,
|
|
596
|
+
});
|
|
597
|
+
},
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
/*
|
|
601
|
+
* The map's gate is one layer up. NetworkTopologyUtil takes a
|
|
602
|
+
* `monitorStatus` that is PRESENT as the verdict — by design, since the
|
|
603
|
+
* graph is handed nodes rather than rows — so the endpoint that builds
|
|
604
|
+
* those nodes is what withholds the stamp from a probe-polled device. The
|
|
605
|
+
* source assertion at the bottom of this file pins that gate; here we pin
|
|
606
|
+
* what the graph then draws, which is the poll.
|
|
607
|
+
*/
|
|
608
|
+
test("the map draws the poll for a probe-polled device, the stamp having been withheld", () => {
|
|
609
|
+
expect(topologyStatus(topologyInput(ANSWERED))).toBe("up");
|
|
610
|
+
expect(topologyStatus(topologyInput(FAILED))).toBe("down");
|
|
611
|
+
});
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
/*
|
|
615
|
+
* The invariant all of the above serves, stated once over the whole
|
|
616
|
+
* matrix: for every row this change is about, the three surfaces answer
|
|
617
|
+
* what the device list pill answers. The pill IS DeviceReachabilityUtil
|
|
618
|
+
* with the same columns, so it is used as the oracle rather than a
|
|
619
|
+
* hand-written expectation per cell.
|
|
620
|
+
*/
|
|
621
|
+
describe("the site card, the rollup and the map agree with the device list pill", () => {
|
|
622
|
+
interface MatrixCase {
|
|
623
|
+
label: string;
|
|
624
|
+
monitoringMethod: string | null | undefined;
|
|
625
|
+
monitorStatusIsOffline: boolean | undefined;
|
|
626
|
+
columns: PollColumns;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
const METHODS: Array<string | null | undefined> = [
|
|
630
|
+
undefined,
|
|
631
|
+
null,
|
|
632
|
+
"SNMP",
|
|
633
|
+
MONITOR,
|
|
634
|
+
];
|
|
635
|
+
const STAMPS: Array<boolean | undefined> = [undefined, false, true];
|
|
636
|
+
const COLUMN_SETS: Array<[string, PollColumns]> = [
|
|
637
|
+
["stale leftovers", STALE_LEFTOVERS],
|
|
638
|
+
["fresh leftovers", FRESH_LEFTOVERS],
|
|
639
|
+
["never polled", NEVER_POLLED],
|
|
640
|
+
["answered", ANSWERED],
|
|
641
|
+
["failed", FAILED],
|
|
642
|
+
];
|
|
643
|
+
|
|
644
|
+
const cases: Array<MatrixCase> = [];
|
|
645
|
+
|
|
646
|
+
/*
|
|
647
|
+
* The full product, stamped probe-polled devices included. They used to be
|
|
648
|
+
* excluded here on the grounds that the pill judged such a device by its
|
|
649
|
+
* poll while the classifiers judged it by its stamp — a real disagreement
|
|
650
|
+
* at the time, and the one ping-first polling closed. All four surfaces
|
|
651
|
+
* now read a probe-polled device by its poll, so the cell belongs in the
|
|
652
|
+
* matrix and is the strongest single check that they still agree.
|
|
653
|
+
*/
|
|
654
|
+
for (const monitoringMethod of METHODS) {
|
|
655
|
+
for (const monitorStatusIsOffline of STAMPS) {
|
|
656
|
+
for (const [label, columns] of COLUMN_SETS) {
|
|
657
|
+
cases.push({
|
|
658
|
+
label: `${label} / method ${String(monitoringMethod)} / stamp ${String(monitorStatusIsOffline)}`,
|
|
659
|
+
monitoringMethod: monitoringMethod,
|
|
660
|
+
monitorStatusIsOffline: monitorStatusIsOffline,
|
|
661
|
+
columns: columns,
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/*
|
|
668
|
+
* What the topology ENDPOINT hands the graph. NetworkTopologyUtil takes a
|
|
669
|
+
* present `monitorStatus` as the verdict outright, so the isMonitorBacked
|
|
670
|
+
* gate lives where the device row is mapped into a node — reproduced here
|
|
671
|
+
* so the map is compared against the graph it is actually given (the
|
|
672
|
+
* source assertions at the bottom of this file pin that the endpoint
|
|
673
|
+
* really applies it).
|
|
674
|
+
*/
|
|
675
|
+
function stampForGraph(testCase: MatrixCase): "up" | "down" | undefined {
|
|
676
|
+
if (
|
|
677
|
+
testCase.monitorStatusIsOffline === undefined ||
|
|
678
|
+
!NetworkDeviceMonitoringMethodUtil.isMonitorBacked(
|
|
679
|
+
testCase.monitoringMethod,
|
|
680
|
+
)
|
|
681
|
+
) {
|
|
682
|
+
return undefined;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
return testCase.monitorStatusIsOffline ? "down" : "up";
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
function pill(testCase: MatrixCase): NetworkDeviceReachability {
|
|
689
|
+
return DeviceReachabilityUtil.getStatus(
|
|
690
|
+
{
|
|
691
|
+
...testCase.columns,
|
|
692
|
+
monitoringMethod: testCase.monitoringMethod,
|
|
693
|
+
monitorStatusIsOffline: testCase.monitorStatusIsOffline,
|
|
694
|
+
},
|
|
695
|
+
NOW,
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
test("the matrix reaches every verdict the pill can give", () => {
|
|
700
|
+
const seen: Set<NetworkDeviceReachability> =
|
|
701
|
+
new Set<NetworkDeviceReachability>(cases.map(pill));
|
|
702
|
+
|
|
703
|
+
expect(Array.from(seen).sort()).toEqual(
|
|
704
|
+
[
|
|
705
|
+
NetworkDeviceReachability.Down,
|
|
706
|
+
NetworkDeviceReachability.Pending,
|
|
707
|
+
NetworkDeviceReachability.Up,
|
|
708
|
+
].sort(),
|
|
709
|
+
);
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
test("the site card", () => {
|
|
713
|
+
const disagreements: Array<string> = [];
|
|
714
|
+
|
|
715
|
+
for (const testCase of cases) {
|
|
716
|
+
const verdict: NetworkDeviceReachability = pill(testCase);
|
|
717
|
+
const expected: NetworkDeviceHealthState =
|
|
718
|
+
verdict === NetworkDeviceReachability.Pending
|
|
719
|
+
? "unknown"
|
|
720
|
+
: verdict === NetworkDeviceReachability.Up
|
|
721
|
+
? "healthy"
|
|
722
|
+
: "down";
|
|
723
|
+
|
|
724
|
+
const actual: NetworkDeviceHealthState = deviceHealthState(
|
|
725
|
+
healthInput(testCase.columns, {
|
|
726
|
+
monitoringMethod: testCase.monitoringMethod,
|
|
727
|
+
monitorStatusIsOffline: testCase.monitorStatusIsOffline,
|
|
728
|
+
}),
|
|
729
|
+
NOW,
|
|
730
|
+
);
|
|
731
|
+
|
|
732
|
+
if (actual !== expected) {
|
|
733
|
+
disagreements.push(`${testCase.label}: pill=${verdict} card=${actual}`);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
expect(disagreements).toEqual([]);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
test("the worst-of rollup", () => {
|
|
741
|
+
const disagreements: Array<string> = [];
|
|
742
|
+
|
|
743
|
+
for (const testCase of cases) {
|
|
744
|
+
const verdict: NetworkDeviceReachability = pill(testCase);
|
|
745
|
+
const expected: string | null =
|
|
746
|
+
verdict === NetworkDeviceReachability.Pending
|
|
747
|
+
? null
|
|
748
|
+
: verdict === NetworkDeviceReachability.Up
|
|
749
|
+
? OPERATIONAL.monitorStatusId
|
|
750
|
+
: OFFLINE.monitorStatusId;
|
|
751
|
+
|
|
752
|
+
// A stamp reaches the rollup as the status row it resolved to.
|
|
753
|
+
const stamp: RollupStatusOption | undefined =
|
|
754
|
+
testCase.monitorStatusIsOffline === undefined
|
|
755
|
+
? undefined
|
|
756
|
+
: testCase.monitorStatusIsOffline
|
|
757
|
+
? OFFLINE
|
|
758
|
+
: OPERATIONAL;
|
|
759
|
+
|
|
760
|
+
const actual: string | null = worst([
|
|
761
|
+
rollupState(testCase.columns, {
|
|
762
|
+
monitoringMethod: testCase.monitoringMethod,
|
|
763
|
+
currentMonitorStatusId: stamp?.monitorStatusId,
|
|
764
|
+
monitorStatusPriority: stamp?.priority,
|
|
765
|
+
}),
|
|
766
|
+
]);
|
|
767
|
+
|
|
768
|
+
if (actual !== expected) {
|
|
769
|
+
disagreements.push(
|
|
770
|
+
`${testCase.label}: pill=${verdict} rollup=${String(actual)}`,
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
expect(disagreements).toEqual([]);
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
test("the map", () => {
|
|
779
|
+
const disagreements: Array<string> = [];
|
|
780
|
+
|
|
781
|
+
for (const testCase of cases) {
|
|
782
|
+
const verdict: NetworkDeviceReachability = pill(testCase);
|
|
783
|
+
const expected: string =
|
|
784
|
+
verdict === NetworkDeviceReachability.Pending
|
|
785
|
+
? "unknown"
|
|
786
|
+
: verdict === NetworkDeviceReachability.Up
|
|
787
|
+
? "up"
|
|
788
|
+
: "down";
|
|
789
|
+
|
|
790
|
+
const actual: string = topologyStatus(
|
|
791
|
+
topologyInput(testCase.columns, {
|
|
792
|
+
monitoringMethod: testCase.monitoringMethod,
|
|
793
|
+
monitorStatus: stampForGraph(testCase),
|
|
794
|
+
}),
|
|
795
|
+
);
|
|
796
|
+
|
|
797
|
+
if (actual !== expected) {
|
|
798
|
+
disagreements.push(`${testCase.label}: pill=${verdict} map=${actual}`);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
expect(disagreements).toEqual([]);
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
/*
|
|
807
|
+
* The site card and the rollup never see rows — they see buckets, grouped in
|
|
808
|
+
* SQL by the facts the classifiers read and turned back into classifier
|
|
809
|
+
* inputs by DeviceHealthAggregation. The method is one of those facts, so
|
|
810
|
+
* both builders have to carry it or the whole thread above is cut at the
|
|
811
|
+
* database.
|
|
812
|
+
*/
|
|
813
|
+
describe("buckets carry the method into both classifier inputs", () => {
|
|
814
|
+
// An unstamped bucket of stale leftovers: the legacy branch, on purpose.
|
|
815
|
+
function bucket(overrides: Partial<DeviceHealthGroup>): DeviceHealthGroup {
|
|
816
|
+
return {
|
|
817
|
+
siteId: null,
|
|
818
|
+
monitorStatusId: null,
|
|
819
|
+
monitoringMethod: null,
|
|
820
|
+
isReachable: null,
|
|
821
|
+
hasBeenPolled: false,
|
|
822
|
+
hasBeenSeen: true,
|
|
823
|
+
isStale: true,
|
|
824
|
+
hasDownInterfaces: false,
|
|
825
|
+
deviceCount: 1,
|
|
826
|
+
interfacesDownTotal: 0,
|
|
827
|
+
...overrides,
|
|
828
|
+
};
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
test.each([null, "SNMP", MONITOR])(
|
|
832
|
+
"deviceHealthInputForGroup emits %j verbatim",
|
|
833
|
+
(monitoringMethod: string | null) => {
|
|
834
|
+
expect(
|
|
835
|
+
deviceHealthInputForGroup({
|
|
836
|
+
group: bucket({ monitoringMethod: monitoringMethod }),
|
|
837
|
+
now: NOW,
|
|
838
|
+
}).monitoringMethod,
|
|
839
|
+
).toBe(monitoringMethod);
|
|
840
|
+
},
|
|
841
|
+
);
|
|
842
|
+
|
|
843
|
+
test.each([null, "SNMP", MONITOR])(
|
|
844
|
+
"deviceRollupStateForGroup emits %j verbatim",
|
|
845
|
+
(monitoringMethod: string | null) => {
|
|
846
|
+
expect(
|
|
847
|
+
deviceRollupStateForGroup({
|
|
848
|
+
group: bucket({ monitoringMethod: monitoringMethod }),
|
|
849
|
+
now: NOW,
|
|
850
|
+
}).monitoringMethod,
|
|
851
|
+
).toBe(monitoringMethod);
|
|
852
|
+
},
|
|
853
|
+
);
|
|
854
|
+
|
|
855
|
+
test("the same stale bucket is down as probe-polled and unknown as monitor-backed", () => {
|
|
856
|
+
const probePolled: DeviceHealthGroup = bucket({});
|
|
857
|
+
const monitorBacked: DeviceHealthGroup = bucket({
|
|
858
|
+
monitoringMethod: MONITOR,
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
expect(
|
|
862
|
+
deviceHealthState(
|
|
863
|
+
deviceHealthInputForGroup({ group: probePolled, now: NOW }),
|
|
864
|
+
NOW,
|
|
865
|
+
),
|
|
866
|
+
).toBe("down");
|
|
867
|
+
expect(
|
|
868
|
+
deviceHealthState(
|
|
869
|
+
deviceHealthInputForGroup({ group: monitorBacked, now: NOW }),
|
|
870
|
+
NOW,
|
|
871
|
+
),
|
|
872
|
+
).toBe("unknown");
|
|
873
|
+
|
|
874
|
+
expect(
|
|
875
|
+
worst([deviceRollupStateForGroup({ group: probePolled, now: NOW })]),
|
|
876
|
+
).toBe(OFFLINE.monitorStatusId);
|
|
877
|
+
expect(
|
|
878
|
+
worst([deviceRollupStateForGroup({ group: monitorBacked, now: NOW })]),
|
|
879
|
+
).toBeNull();
|
|
880
|
+
});
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
/*
|
|
884
|
+
* The map's endpoint is the one caller that maps device ROWS into
|
|
885
|
+
* TopologyDeviceInput by hand, so it has to select the column and copy it
|
|
886
|
+
* across — and neither omission would fail to compile or throw. It lives in
|
|
887
|
+
* App, which this suite cannot import, so it is asserted against the source
|
|
888
|
+
* the way App's own surface-invariant tests are. Whitespace is squashed
|
|
889
|
+
* first so prettier re-wrapping a line cannot turn this into a red herring.
|
|
890
|
+
*/
|
|
891
|
+
describe("the topology endpoint selects the column and forwards it", () => {
|
|
892
|
+
const source: string = fs
|
|
893
|
+
.readFileSync(
|
|
894
|
+
path.join(
|
|
895
|
+
__dirname,
|
|
896
|
+
"..",
|
|
897
|
+
"..",
|
|
898
|
+
"..",
|
|
899
|
+
"..",
|
|
900
|
+
"App",
|
|
901
|
+
"FeatureSet",
|
|
902
|
+
"BaseAPI",
|
|
903
|
+
"API",
|
|
904
|
+
"NetworkDeviceTopology.ts",
|
|
905
|
+
),
|
|
906
|
+
"utf8",
|
|
907
|
+
)
|
|
908
|
+
.replace(/\s+/g, " ");
|
|
909
|
+
|
|
910
|
+
/*
|
|
911
|
+
* The object literal enclosing the first occurrence of `needle`, found by
|
|
912
|
+
* brace matching outwards — so an assertion about "the device select" is
|
|
913
|
+
* made against that literal and not against the whole file.
|
|
914
|
+
*/
|
|
915
|
+
function enclosingLiteral(needle: string): string {
|
|
916
|
+
const needleAt: number = source.indexOf(needle);
|
|
917
|
+
expect(needleAt).toBeGreaterThanOrEqual(0);
|
|
918
|
+
|
|
919
|
+
let start: number = -1;
|
|
920
|
+
let depth: number = 0;
|
|
921
|
+
|
|
922
|
+
for (let index: number = needleAt; index >= 0; index--) {
|
|
923
|
+
const character: string = source[index]!;
|
|
924
|
+
|
|
925
|
+
if (character === "}") {
|
|
926
|
+
depth++;
|
|
927
|
+
} else if (character === "{") {
|
|
928
|
+
if (depth === 0) {
|
|
929
|
+
start = index;
|
|
930
|
+
break;
|
|
931
|
+
}
|
|
932
|
+
depth--;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
expect(start).toBeGreaterThanOrEqual(0);
|
|
937
|
+
|
|
938
|
+
depth = 0;
|
|
939
|
+
|
|
940
|
+
for (let index: number = start; index < source.length; index++) {
|
|
941
|
+
const character: string = source[index]!;
|
|
942
|
+
|
|
943
|
+
if (character === "{") {
|
|
944
|
+
depth++;
|
|
945
|
+
} else if (character === "}") {
|
|
946
|
+
depth--;
|
|
947
|
+
if (depth === 0) {
|
|
948
|
+
return source.slice(start, index + 1);
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
throw new Error(`Unbalanced literal around ${needle}`);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
test("the device select asks for monitoringMethod beside the poll columns", () => {
|
|
957
|
+
const select: string = enclosingLiteral("isReachable: true,");
|
|
958
|
+
|
|
959
|
+
expect(select).toContain("monitoringMethod: true,");
|
|
960
|
+
// ...and still for the stamp, which is what the method qualifies.
|
|
961
|
+
expect(select).toContain("currentMonitorStatusId: true,");
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
test("the row is forwarded to the graph input with the method attached", () => {
|
|
965
|
+
const mapping: string = enclosingLiteral(
|
|
966
|
+
"isReachable: device.isReachable,",
|
|
967
|
+
);
|
|
968
|
+
|
|
969
|
+
expect(mapping).toContain("monitoringMethod: device.monitoringMethod,");
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
/*
|
|
973
|
+
* And the gate itself. NetworkTopologyUtil.deviceStatus returns a present
|
|
974
|
+
* `monitorStatus` outright — the graph is handed nodes, not rows, and has
|
|
975
|
+
* no business re-deciding what a node's status means — so the endpoint is
|
|
976
|
+
* the only place that can withhold a probe-polled device's stamp. Drop
|
|
977
|
+
* this condition and an "interface down → Offline" criterion paints every
|
|
978
|
+
* answering switch on the map red while its row in the device list reads
|
|
979
|
+
* Up: a silent, compiling, non-throwing regression, which is why it is
|
|
980
|
+
* asserted against the source.
|
|
981
|
+
*/
|
|
982
|
+
test("the stamp reaches the graph only for a monitor-backed device", () => {
|
|
983
|
+
const mapping: string = enclosingLiteral(
|
|
984
|
+
"isReachable: device.isReachable,",
|
|
985
|
+
);
|
|
986
|
+
|
|
987
|
+
expect(mapping).toContain("monitorStatus:");
|
|
988
|
+
expect(mapping).toContain(
|
|
989
|
+
"NetworkDeviceMonitoringMethodUtil.isMonitorBacked( device.monitoringMethod, )",
|
|
990
|
+
);
|
|
991
|
+
});
|
|
992
|
+
});
|