@oneuptime/common 12.0.31 → 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/AlertState.ts +0 -2
- package/Models/DatabaseModels/Domain.ts +1 -1
- package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/Incident.ts +1 -1
- package/Models/DatabaseModels/IncidentTemplate.ts +1 -1
- package/Models/DatabaseModels/Index.ts +12 -0
- package/Models/DatabaseModels/MetricType.ts +0 -2
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/MonitorStatusTimeline.ts +0 -2
- package/Models/DatabaseModels/MonitorTest.ts +0 -2
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +297 -3
- package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +3 -1
- package/Models/DatabaseModels/NetworkDeviceRole.ts +648 -0
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -1
- package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -1
- package/Models/DatabaseModels/StatusPageAnnouncement.ts +0 -2
- package/Models/DatabaseModels/StatusPageAnnouncementTemplate.ts +0 -2
- package/Models/DatabaseModels/StatusPagePrivateUser.ts +0 -2
- package/Models/DatabaseModels/StatusPageResource.ts +0 -2
- package/Models/DatabaseModels/StatusPageSubscriber.ts +0 -2
- 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/1790800000000-AddNetworkDeviceRoleTable.ts +72 -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 +14 -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/DatabaseService.ts +39 -9
- package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/Index.ts +12 -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/NetworkDeviceRoleService.ts +90 -0
- 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 +186 -44
- 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 -31
- 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 +158 -27
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +35 -8
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +107 -3
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
- package/Tests/App/Dashboard/DashboardWideChartZoom.test.tsx +401 -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/MonitorTemplateColumnAndFacet.test.tsx +318 -0
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
- package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +357 -0
- 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 +626 -0
- 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/SideMenuHarness.tsx +11 -3
- 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/DatabaseModels/ModelRegistryInvariants.test.ts +115 -41
- 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/NetworkDeviceRoleTableMigration.test.ts +476 -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/DatabaseServiceGenerateSlug.test.ts +215 -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/NetworkDeviceRoleModel.test.ts +672 -0
- package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +1 -1
- 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/ProjectServiceCreateSubscriptionStarted.test.ts +67 -4
- package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberEndTime.test.ts +369 -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/UserNotificationSettingMonitorDefaults.test.ts +248 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +145 -3
- 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/BasicCron.test.ts +283 -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/IncomingCallPhoneNumber.test.ts +174 -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/DefaultNetworkDeviceRole.test.ts +417 -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/Charts/ChartClickDoubleClickDisambiguation.test.tsx +221 -0
- package/Tests/UI/Components/Charts/ChartDoubleClickReset.test.tsx +220 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +751 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +475 -43
- package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +89 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +103 -8
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/SideMenuItem.test.tsx +256 -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/UI/Utils/TableColumnsToCsv.test.ts +30 -0
- package/Tests/UI/Utils/UseDashboardTimeRangeZoom.test.tsx +187 -0
- package/Tests/Utils/Dashboard/DashboardResourceListSharedArgs.test.ts +302 -0
- package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +242 -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/NetworkDeviceRoleCatalog.test.ts +981 -0
- package/Tests/Utils/Monitor/NetworkTopologyRoleCatalog.test.ts +865 -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/DeviceRoleKeyUtil.test.ts +538 -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/Slo/SloEvaluation.test.ts +171 -0
- package/Tests/Utils/Slug.test.ts +61 -1
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
- package/Tests/jest.setup.ts +19 -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/SnmpMonitor/NetworkTopology.ts +61 -0
- package/Types/Monitor/SqlConnectionConfig.ts +31 -0
- package/Types/NetworkDevice/DefaultNetworkDeviceRole.ts +145 -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 +135 -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/Charts/Area/AreaChart.tsx +7 -0
- package/UI/Components/Charts/Bar/BarChart.tsx +6 -0
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +9 -1
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +97 -35
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +14 -0
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +97 -35
- package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +13 -0
- package/UI/Components/Charts/Line/LineChart.tsx +7 -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/ModelTable/BaseModelTable.tsx +50 -15
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
- package/UI/Components/Navbar/NavBar.tsx +62 -13
- package/UI/Components/Navbar/NavBarMenuModal.tsx +7 -2
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +2 -0
- package/UI/Components/SideMenu/SideMenu.tsx +135 -7
- package/UI/Components/SideMenu/SideMenuItem.tsx +80 -85
- package/UI/Components/SideMenu/SideMenuSection.tsx +69 -25
- 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/UI/Utils/UseDashboardTimeRangeZoom.ts +77 -0
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +118 -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/NetworkDeviceRoleCatalog.ts +232 -0
- package/Utils/Monitor/NetworkDeviceRoleUtil.ts +2 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +139 -36
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- package/Utils/NetworkDevice/DeviceRoleKeyUtil.ts +137 -0
- 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/Utils/Rules/RulePatternMatchUtil.ts +1 -1
- package/Utils/Slug.ts +34 -1
- package/build/dist/Models/AnalyticsModels/Span.js +14 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertState.js +0 -2
- package/build/dist/Models/DatabaseModels/AlertState.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Domain.js +1 -1
- package/build/dist/Models/DatabaseModels/Domain.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/Incident.js +1 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +12 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MetricType.js +0 -2
- package/build/dist/Models/DatabaseModels/MetricType.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/MonitorStatusTimeline.js +0 -2
- package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTest.js +0 -2
- package/build/dist/Models/DatabaseModels/MonitorTest.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 +304 -4
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +3 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js +677 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceRole.js.map +1 -0
- 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/ScheduledMaintenance.js +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageAnnouncementTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPagePrivateUser.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageResource.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +0 -2
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
- 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/1790800000000-AddNetworkDeviceRoleTable.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790800000000-AddNetworkDeviceRoleTable.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 +14 -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/DatabaseService.js +31 -5
- package/build/dist/Server/Services/DatabaseService.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 +12 -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/NetworkDeviceRoleService.js +70 -0
- package/build/dist/Server/Services/NetworkDeviceRoleService.js.map +1 -0
- 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 +131 -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 -21
- 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/DefaultNetworkDeviceRole.js +105 -0
- package/build/dist/Types/NetworkDevice/DefaultNetworkDeviceRole.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 +120 -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/Charts/Area/AreaChart.js +1 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +6 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +79 -31
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +7 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +79 -31
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +14 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -0
- package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- 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/ModelTable/BaseModelTable.js +39 -13
- package/build/dist/UI/Components/ModelTable/BaseModelTable.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/Navbar/NavBar.js +44 -9
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.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/CountModelSideMenuItem.js +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +76 -11
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +50 -54
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +32 -9
- 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/UI/Utils/UseDashboardTimeRangeZoom.js +42 -0
- package/build/dist/UI/Utils/UseDashboardTimeRangeZoom.js.map +1 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +74 -0
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -0
- 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/NetworkDeviceRoleCatalog.js +126 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleCatalog.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +2 -1
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +75 -35
- 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/DeviceRoleKeyUtil.js +114 -0
- package/build/dist/Utils/NetworkDevice/DeviceRoleKeyUtil.js.map +1 -0
- 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/build/dist/Utils/Rules/RulePatternMatchUtil.js +1 -1
- package/build/dist/Utils/Slug.js +31 -1
- package/build/dist/Utils/Slug.js.map +1 -1
- package/package.json +2 -2
|
@@ -9,10 +9,13 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import DatabaseService from "./DatabaseService";
|
|
11
11
|
import MonitorService from "./MonitorService";
|
|
12
|
+
import NetworkAlertPolicyEngineService, { MAX_INLINE_RECONCILE_DEVICES, } from "./NetworkAlertPolicyEngineService";
|
|
12
13
|
import NetworkDeviceLabelRuleEngineService from "./NetworkDeviceLabelRuleEngineService";
|
|
13
14
|
import NetworkDeviceOwnerRuleEngineService from "./NetworkDeviceOwnerRuleEngineService";
|
|
14
15
|
import NetworkSiteAssignmentRuleService from "./NetworkSiteAssignmentRuleService";
|
|
15
16
|
import NetworkSiteService from "./NetworkSiteService";
|
|
17
|
+
import NetworkSnmpCredentialProfileService from "./NetworkSnmpCredentialProfileService";
|
|
18
|
+
import ProbeService from "./ProbeService";
|
|
16
19
|
import Model from "../../Models/DatabaseModels/NetworkDevice";
|
|
17
20
|
import Monitor from "../../Models/DatabaseModels/Monitor";
|
|
18
21
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
@@ -91,8 +94,96 @@ function readOidTemplateIdFromData(data) {
|
|
|
91
94
|
*/
|
|
92
95
|
return RelationIdUtil.readConsistent(data, OID_TEMPLATE_KEYS, "OID Collection Template");
|
|
93
96
|
}
|
|
97
|
+
/*
|
|
98
|
+
* readConsistent for the same reason as the OID template above: the create
|
|
99
|
+
* and update guards validate the id this returns, and TypeORM's precedence
|
|
100
|
+
* between `monitorId` and `monitor` is not a security boundary. A payload
|
|
101
|
+
* that writes both spellings with different ids would have one of them
|
|
102
|
+
* validated and the other persisted, so the contradiction is refused
|
|
103
|
+
* instead of picked from.
|
|
104
|
+
*/
|
|
94
105
|
function readMonitorIdFromData(data) {
|
|
95
|
-
return RelationIdUtil.
|
|
106
|
+
return RelationIdUtil.readConsistent(data, MONITOR_KEYS, "Monitor");
|
|
107
|
+
}
|
|
108
|
+
/*
|
|
109
|
+
* Both spellings of "the probe that polls this device", and of "the SNMP
|
|
110
|
+
* credentials it is walked with".
|
|
111
|
+
*
|
|
112
|
+
* These two are the tenancy boundary of device polling. The probe decides
|
|
113
|
+
* WHO reaches into the customer's network on this device's behalf, and the
|
|
114
|
+
* credential profile decides WHAT is put on the wire when it gets there —
|
|
115
|
+
* so a cross-project value in either is not a mislabelled row, it is one
|
|
116
|
+
* project's infrastructure being pointed at another's. Both are read
|
|
117
|
+
* through readConsistent for the reason the monitor reference above is: a
|
|
118
|
+
* payload writing the FK and the relation at different rows would otherwise
|
|
119
|
+
* have one validated and the other persisted.
|
|
120
|
+
*/
|
|
121
|
+
const PROBE_KEYS = ["probeId", "probe"];
|
|
122
|
+
const PROFILE_KEYS = [
|
|
123
|
+
"snmpCredentialProfileId",
|
|
124
|
+
"snmpCredentialProfile",
|
|
125
|
+
];
|
|
126
|
+
/*
|
|
127
|
+
* Both spellings of "what kind of thing this device is". A role is one of
|
|
128
|
+
* the three axes a Network Alert Policy's scope selects on, so a write to it
|
|
129
|
+
* can add a device to a policy or take it out of one.
|
|
130
|
+
*/
|
|
131
|
+
const ROLE_KEYS = ["networkDeviceRoleId", "networkDeviceRole"];
|
|
132
|
+
/*
|
|
133
|
+
* Every write that can change which Network Alert Policies cover a device,
|
|
134
|
+
* or whether it may carry a policy monitor at all.
|
|
135
|
+
*
|
|
136
|
+
* The first three are the scope axes (site, role, labels); the last three
|
|
137
|
+
* are provisionability — an archived device, a monitor-backed device and a
|
|
138
|
+
* device with no probe each keep no policy monitors (see the engine).
|
|
139
|
+
*
|
|
140
|
+
* Writing any of them makes onUpdateSuccess reconcile, and reconciling needs
|
|
141
|
+
* each matched device's PROJECT, which only the pre-write snapshot carries
|
|
142
|
+
* for a root caller with no tenant in props. That is why these are named in
|
|
143
|
+
* onBeforeUpdate's early return as well: without them a bulk re-label would
|
|
144
|
+
* skip the snapshot and the success hook would have no project to reconcile
|
|
145
|
+
* against.
|
|
146
|
+
*/
|
|
147
|
+
function isAlertPolicyRelevantWrite(dataKeys) {
|
|
148
|
+
return (isSiteWrite(dataKeys) ||
|
|
149
|
+
RelationIdUtil.isWritten(dataKeys, ROLE_KEYS) ||
|
|
150
|
+
dataKeys.includes("labels") ||
|
|
151
|
+
dataKeys.includes("isArchived") ||
|
|
152
|
+
dataKeys.includes("monitoringMethod") ||
|
|
153
|
+
RelationIdUtil.isWritten(dataKeys, PROBE_KEYS));
|
|
154
|
+
}
|
|
155
|
+
function readProbeIdFromData(data) {
|
|
156
|
+
return RelationIdUtil.readConsistent(data, PROBE_KEYS, "Probe");
|
|
157
|
+
}
|
|
158
|
+
function readSnmpCredentialProfileIdFromData(data) {
|
|
159
|
+
return RelationIdUtil.readConsistent(data, PROFILE_KEYS, "SNMP Credential Profile");
|
|
160
|
+
}
|
|
161
|
+
/*
|
|
162
|
+
* The poll columns a probe's poll writes and nothing else ever should. On a
|
|
163
|
+
* device switched to monitor-backed they are residue — the last thing a
|
|
164
|
+
* probe found before it stopped asking — and left in place they keep
|
|
165
|
+
* describing a device nothing polls: DeviceReachabilityUtil's legacy branch
|
|
166
|
+
* judges a row with `lastSeenAt` and no `isReachable` by freshness, and the
|
|
167
|
+
* network summary's "degraded" query is `isReachable = true AND
|
|
168
|
+
* interfacesDown > 0`. The SNMP pair goes with them: a monitor-backed device
|
|
169
|
+
* has no walk, so `isSnmpReachable` and `lastSnmpSeenAt` can only ever be
|
|
170
|
+
* what the last walk left behind. Cleared on the Probe -> Monitor transition
|
|
171
|
+
* (onUpdateSuccess) and once on upgrade
|
|
172
|
+
* (BackfillMonitorBackedDeviceReachability), as a root write in both places:
|
|
173
|
+
* these columns are updatable by fewer roles than `monitoringMethod` is, so
|
|
174
|
+
* putting them on the caller's own payload would refuse a project member's
|
|
175
|
+
* legitimate switch.
|
|
176
|
+
*/
|
|
177
|
+
function pollResidueReset() {
|
|
178
|
+
return {
|
|
179
|
+
lastSeenAt: null,
|
|
180
|
+
lastPolledAt: null,
|
|
181
|
+
isReachable: null,
|
|
182
|
+
isSnmpReachable: null,
|
|
183
|
+
lastSnmpSeenAt: null,
|
|
184
|
+
interfacesUp: null,
|
|
185
|
+
interfacesDown: null,
|
|
186
|
+
};
|
|
96
187
|
}
|
|
97
188
|
/*
|
|
98
189
|
* How many devices a single manual "Run now" of an assignment rule walks.
|
|
@@ -511,6 +602,14 @@ export class Service extends DatabaseService {
|
|
|
511
602
|
* first, then deletes their automatic monitors through MonitorService so
|
|
512
603
|
* Monitor delete permissions, workspace cleanup, workflows, audit,
|
|
513
604
|
* realtime, and billing hooks all run before the devices are removed.
|
|
605
|
+
*
|
|
606
|
+
* POLICY-OWNED MONITORS ARE HANDLED SEPARATELY, and deliberately so. A
|
|
607
|
+
* monitor a Network Alert Policy provisioned is system-managed — the API
|
|
608
|
+
* can neither set nor clear its `networkAlertPolicyId` — so nobody chose
|
|
609
|
+
* it individually and nobody should need monitor-delete permission on it
|
|
610
|
+
* individually to remove the device it describes. They are excluded from
|
|
611
|
+
* the caller-authorized preflight below and removed as root by the engine,
|
|
612
|
+
* once every device in the request has cleared that preflight.
|
|
514
613
|
*/
|
|
515
614
|
async onBeforeDelete(deleteBy) {
|
|
516
615
|
const authorizedQuery = await ModelPermission.checkDeleteQueryPermission(Model, deleteBy.query, deleteBy.props);
|
|
@@ -543,6 +642,13 @@ export class Service extends DatabaseService {
|
|
|
543
642
|
const automaticMonitorQuery = {
|
|
544
643
|
projectId: device.projectId,
|
|
545
644
|
autoProvisionedNetworkDeviceId: device.id,
|
|
645
|
+
/*
|
|
646
|
+
* Rule-provisioned and hand-made monitors only. A policy's monitors
|
|
647
|
+
* go through the engine as root (see the hook comment), so requiring
|
|
648
|
+
* the caller's permission on them here would refuse a device delete
|
|
649
|
+
* over rows the caller never chose to own.
|
|
650
|
+
*/
|
|
651
|
+
networkAlertPolicyId: QueryHelper.isNull(),
|
|
546
652
|
};
|
|
547
653
|
const monitorDeleteProps = Object.assign(Object.assign({}, deleteBy.props), { tenantId: device.projectId });
|
|
548
654
|
const monitorCount = await countAutomaticMonitors(automaticMonitorQuery);
|
|
@@ -568,6 +674,30 @@ export class Service extends DatabaseService {
|
|
|
568
674
|
monitorCount,
|
|
569
675
|
});
|
|
570
676
|
}
|
|
677
|
+
/*
|
|
678
|
+
* Every device in the request has now proved the caller may delete its
|
|
679
|
+
* ordinary automatic monitors, so nothing after this point can throw for
|
|
680
|
+
* an authorization reason. That is the moment to remove the policy-owned
|
|
681
|
+
* monitors: doing it earlier would let a later device's failed preflight
|
|
682
|
+
* abort the request after a policy's monitors — and their incident
|
|
683
|
+
* history — were already gone from devices that then survived.
|
|
684
|
+
*/
|
|
685
|
+
const devicesByProjectId = new Map();
|
|
686
|
+
for (const device of devices) {
|
|
687
|
+
if (!device.id || !device.projectId) {
|
|
688
|
+
continue;
|
|
689
|
+
}
|
|
690
|
+
const key = device.projectId.toString();
|
|
691
|
+
const deviceIds = devicesByProjectId.get(key) || [];
|
|
692
|
+
deviceIds.push(device.id);
|
|
693
|
+
devicesByProjectId.set(key, deviceIds);
|
|
694
|
+
}
|
|
695
|
+
for (const [projectIdString, deviceIds] of devicesByProjectId) {
|
|
696
|
+
await NetworkAlertPolicyEngineService.deletePolicyMonitorsForDevices({
|
|
697
|
+
projectId: new ObjectID(projectIdString),
|
|
698
|
+
deviceIds: deviceIds,
|
|
699
|
+
});
|
|
700
|
+
}
|
|
571
701
|
for (const cleanupPlan of cleanupPlans) {
|
|
572
702
|
/*
|
|
573
703
|
* LIMIT_MAX is a per-service-call cap, not a lifecycle cap. Always
|
|
@@ -661,6 +791,99 @@ export class Service extends DatabaseService {
|
|
|
661
791
|
throw new BadDataException("OID Collection Template must belong to the same project.");
|
|
662
792
|
}
|
|
663
793
|
}
|
|
794
|
+
/*
|
|
795
|
+
* The FK behind `probeId` only requires the Probe row to exist. Probe ids
|
|
796
|
+
* reach the server from the browser — the device create form, the settings
|
|
797
|
+
* page and the bulk "Set probe" action all post one — so without this
|
|
798
|
+
* check a device can be pointed at another project's probe, and that probe
|
|
799
|
+
* then claims it on its next poll: it reads the device's hostname and its
|
|
800
|
+
* SNMP credentials, and reports status back into this project. That is a
|
|
801
|
+
* cross-tenant read of both configuration and network position.
|
|
802
|
+
*
|
|
803
|
+
* A GLOBAL probe has no project and is attachable anywhere, so this
|
|
804
|
+
* delegates to ProbeService rather than comparing projectIds — the same
|
|
805
|
+
* predicate that decides which probes a monitor may use.
|
|
806
|
+
*
|
|
807
|
+
* `claimDevicesForPolling` re-checks the pairing in SQL as a backstop, for
|
|
808
|
+
* rows written before this guard existed. Both halves are load-bearing:
|
|
809
|
+
* this one gives the operator an error at the point of the mistake, the
|
|
810
|
+
* other one makes a stale row unpollable rather than merely unwritable.
|
|
811
|
+
*/
|
|
812
|
+
async assertProbeIsAttachableToProject(data) {
|
|
813
|
+
if (!data.projectId) {
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
const isAttachable = await ProbeService.isProbeAttachableToProject({
|
|
817
|
+
probeId: data.probeId,
|
|
818
|
+
projectId: data.projectId,
|
|
819
|
+
});
|
|
820
|
+
if (!isAttachable) {
|
|
821
|
+
throw new BadDataException("Probe not found or it does not belong to this project.");
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
/*
|
|
825
|
+
* Same hole as the probe, on the other half of the poll: a credential
|
|
826
|
+
* profile is read LIVE at poll time
|
|
827
|
+
* (NetworkDeviceHydrationUtil.resolveSnmpCredentials), so a device pointed
|
|
828
|
+
* at another project's profile would be walked with that project's
|
|
829
|
+
* community string or v3 credentials — put on the wire, inside this
|
|
830
|
+
* project's network, by this project's probe.
|
|
831
|
+
*
|
|
832
|
+
* The resolver drops a mismatched reference as a backstop and pings the
|
|
833
|
+
* device instead. This is the half that stops the reference being written
|
|
834
|
+
* at all, and it is the half that tells the operator why.
|
|
835
|
+
*/
|
|
836
|
+
async assertSnmpCredentialProfileBelongsToProject(data) {
|
|
837
|
+
if (!data.projectId) {
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
const profile = await NetworkSnmpCredentialProfileService.findOneById({
|
|
841
|
+
id: data.snmpCredentialProfileId,
|
|
842
|
+
select: {
|
|
843
|
+
_id: true,
|
|
844
|
+
projectId: true,
|
|
845
|
+
},
|
|
846
|
+
props: {
|
|
847
|
+
isRoot: true,
|
|
848
|
+
},
|
|
849
|
+
});
|
|
850
|
+
if (!profile) {
|
|
851
|
+
throw new BadDataException("SNMP Credential Profile not found.");
|
|
852
|
+
}
|
|
853
|
+
if (profile.projectId &&
|
|
854
|
+
profile.projectId.toString() !== data.projectId.toString()) {
|
|
855
|
+
throw new BadDataException("SNMP Credential Profile must belong to the same project.");
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
/*
|
|
859
|
+
* The site's default probe, resolved for a device that is landing in that
|
|
860
|
+
* site without one of its own — this site's `probeId`, or the nearest
|
|
861
|
+
* ancestor that has one.
|
|
862
|
+
*
|
|
863
|
+
* Returns null rather than throwing when the inherited probe is not
|
|
864
|
+
* attachable to the device's project. A site row written before the
|
|
865
|
+
* tenancy guards existed must not be able to fail an unrelated device
|
|
866
|
+
* write; the honest outcome is that the device is created with NO probe
|
|
867
|
+
* (it reads Pending, and the operator picks one) rather than silently
|
|
868
|
+
* copying another project's probe onto it.
|
|
869
|
+
*/
|
|
870
|
+
async resolveInheritedSiteProbeId(data) {
|
|
871
|
+
const inheritedProbeId = await NetworkSiteService.resolveDefaultProbeIdForSite(data.siteId);
|
|
872
|
+
if (!inheritedProbeId) {
|
|
873
|
+
return null;
|
|
874
|
+
}
|
|
875
|
+
for (const projectId of data.projectIds) {
|
|
876
|
+
const isAttachable = await ProbeService.isProbeAttachableToProject({
|
|
877
|
+
probeId: inheritedProbeId,
|
|
878
|
+
projectId: projectId,
|
|
879
|
+
});
|
|
880
|
+
if (!isAttachable) {
|
|
881
|
+
logger.error(`Network site ${data.siteId.toString()} names default probe ${inheritedProbeId.toString()}, which is not attachable to project ${projectId.toString()}. Not inheriting it; the device is left without a probe.`);
|
|
882
|
+
return null;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return inheritedProbeId;
|
|
886
|
+
}
|
|
664
887
|
/*
|
|
665
888
|
* onBeforeUpdate runs before DatabaseService permission-checks the query,
|
|
666
889
|
* so reading the raw client query as root would hand the hook rows from
|
|
@@ -673,6 +896,7 @@ export class Service extends DatabaseService {
|
|
|
673
896
|
return Object.assign(Object.assign({}, query), { projectId: props.tenantId });
|
|
674
897
|
}
|
|
675
898
|
async onBeforeCreate(createBy) {
|
|
899
|
+
var _a;
|
|
676
900
|
/*
|
|
677
901
|
* Read both spellings: the dashboard posts the `site` relation, not the
|
|
678
902
|
* `siteId` column, so guarding only `siteId` let a UI-created device
|
|
@@ -685,6 +909,31 @@ export class Service extends DatabaseService {
|
|
|
685
909
|
projectId: createBy.data.projectId,
|
|
686
910
|
});
|
|
687
911
|
}
|
|
912
|
+
/*
|
|
913
|
+
* DatabaseService stamps the tenant column AFTER this hook runs, so a
|
|
914
|
+
* device created from the dashboard reaches here with `projectId` still
|
|
915
|
+
* unset and only `props.tenantId` to go on. The guards below are the
|
|
916
|
+
* tenancy boundary of polling, so they must not be skipped for the one
|
|
917
|
+
* write shape every UI create takes.
|
|
918
|
+
*/
|
|
919
|
+
const createProjectId = createBy.data.projectId ||
|
|
920
|
+
((_a = createBy.data.project) === null || _a === void 0 ? void 0 : _a.id) ||
|
|
921
|
+
createBy.props.tenantId ||
|
|
922
|
+
undefined;
|
|
923
|
+
const createProbeId = readProbeIdFromData(createBy.data);
|
|
924
|
+
if (createProbeId) {
|
|
925
|
+
await this.assertProbeIsAttachableToProject({
|
|
926
|
+
probeId: createProbeId,
|
|
927
|
+
projectId: createProjectId,
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
const createSnmpCredentialProfileId = readSnmpCredentialProfileIdFromData(createBy.data);
|
|
931
|
+
if (createSnmpCredentialProfileId) {
|
|
932
|
+
await this.assertSnmpCredentialProfileBelongsToProject({
|
|
933
|
+
snmpCredentialProfileId: createSnmpCredentialProfileId,
|
|
934
|
+
projectId: createProjectId,
|
|
935
|
+
});
|
|
936
|
+
}
|
|
688
937
|
const createOidTemplateId = readOidTemplateIdFromData(createBy.data);
|
|
689
938
|
if (createOidTemplateId) {
|
|
690
939
|
await this.assertOidTemplateBelongsToProject({
|
|
@@ -701,29 +950,67 @@ export class Service extends DatabaseService {
|
|
|
701
950
|
label: "Device-Specific Health OIDs",
|
|
702
951
|
});
|
|
703
952
|
}
|
|
953
|
+
const monitorId = readMonitorIdFromData(createBy.data);
|
|
954
|
+
/*
|
|
955
|
+
* The monitor is NOT required. Discovery import is why: a subnet sweep
|
|
956
|
+
* finds ping-only hosts in bulk and there is no monitor to bind them to
|
|
957
|
+
* yet. Such a device is still worth recording — it belongs to a site,
|
|
958
|
+
* carries labels, and appears on the topology map — and its status reads
|
|
959
|
+
* Pending, tagged "No monitor", which is exactly true until somebody
|
|
960
|
+
* points a monitor at it.
|
|
961
|
+
*
|
|
962
|
+
* But any binding that IS supplied is tenant-checked, whatever the
|
|
963
|
+
* monitoring method. This guard used to sit inside the monitor-backed
|
|
964
|
+
* branch below, which left a Probe-method create (or one with the method
|
|
965
|
+
* omitted) free to persist another project's monitor FK: the FK only
|
|
966
|
+
* proves the Monitor row exists, a Probe device may legitimately carry a
|
|
967
|
+
* monitorId (NetworkSiteService.onMonitorStatusChanged stamps from it),
|
|
968
|
+
* and a nested select through the relation reads that monitor's
|
|
969
|
+
* configuration. The update path runs the same check.
|
|
970
|
+
*/
|
|
971
|
+
if (monitorId) {
|
|
972
|
+
await this.assertMonitorBelongsToProject({
|
|
973
|
+
monitorId: monitorId,
|
|
974
|
+
projectId: createBy.data.projectId,
|
|
975
|
+
});
|
|
976
|
+
}
|
|
704
977
|
if (NetworkDeviceMonitoringMethodUtil.isMonitorBacked(createBy.data.monitoringMethod)) {
|
|
705
|
-
const monitorId = readMonitorIdFromData(createBy.data);
|
|
706
978
|
/*
|
|
707
|
-
*
|
|
708
|
-
*
|
|
709
|
-
*
|
|
710
|
-
*
|
|
711
|
-
*
|
|
712
|
-
* is exactly true until somebody points a monitor at it.
|
|
979
|
+
* Not a preference: nothing polls a monitor-backed device — its bound
|
|
980
|
+
* monitor's status is its status — so leaving polling on would queue
|
|
981
|
+
* a poll whose verdict nothing may read. claimDevicesForPolling
|
|
982
|
+
* refuses these rows too — this is the half that keeps the column
|
|
983
|
+
* honest for anything reading it.
|
|
713
984
|
*/
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
projectId: createBy.data.projectId,
|
|
718
|
-
});
|
|
719
|
-
}
|
|
985
|
+
createBy.data.isPollingEnabled = false;
|
|
986
|
+
}
|
|
987
|
+
else if (siteId && !createProbeId) {
|
|
720
988
|
/*
|
|
721
|
-
*
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
*
|
|
989
|
+
* Site default probe, COPIED AT WRITE.
|
|
990
|
+
*
|
|
991
|
+
* This is what lets an operator register a device with a name and an
|
|
992
|
+
* address and nothing else: the site (or the nearest ancestor site
|
|
993
|
+
* that names one) supplies the probe, and the device polls from its
|
|
994
|
+
* first cycle instead of sitting Pending until somebody notices the
|
|
995
|
+
* empty field.
|
|
996
|
+
*
|
|
997
|
+
* Copied, not read through, and that distinction is the whole design.
|
|
998
|
+
* Nothing re-reads the site later, so editing a site's default probe
|
|
999
|
+
* decides where FUTURE devices poll from and never re-points a fleet
|
|
1000
|
+
* that is already polling — a read-through default would turn one
|
|
1001
|
+
* dropdown change into a silent migration of every device in the
|
|
1002
|
+
* subtree onto a probe that may not even reach them.
|
|
1003
|
+
*
|
|
1004
|
+
* A device that names its own probe keeps it: `createProbeId` above is
|
|
1005
|
+
* the caller's explicit choice and always wins.
|
|
725
1006
|
*/
|
|
726
|
-
|
|
1007
|
+
const inheritedProbeId = await this.resolveInheritedSiteProbeId({
|
|
1008
|
+
siteId: siteId,
|
|
1009
|
+
projectIds: createProjectId ? [createProjectId] : [],
|
|
1010
|
+
});
|
|
1011
|
+
if (inheritedProbeId) {
|
|
1012
|
+
createBy.data.probeId = inheritedProbeId;
|
|
1013
|
+
}
|
|
727
1014
|
}
|
|
728
1015
|
return { createBy, carryForward: null };
|
|
729
1016
|
}
|
|
@@ -784,8 +1071,8 @@ export class Service extends DatabaseService {
|
|
|
784
1071
|
/*
|
|
785
1072
|
* A device created monitor-backed adopts its monitor's CURRENT
|
|
786
1073
|
* status right away rather than waiting for that monitor's next
|
|
787
|
-
* status CHANGE. Skipped for
|
|
788
|
-
* their own
|
|
1074
|
+
* status CHANGE. Skipped for Probe devices, which are judged by
|
|
1075
|
+
* their own poll.
|
|
789
1076
|
*/
|
|
790
1077
|
if (NetworkDeviceMonitoringMethodUtil.isMonitorBacked(createdItem.monitoringMethod)) {
|
|
791
1078
|
await this.refreshStampedMonitorStatus({
|
|
@@ -793,6 +1080,21 @@ export class Service extends DatabaseService {
|
|
|
793
1080
|
clearWhenNotMonitorBacked: false,
|
|
794
1081
|
});
|
|
795
1082
|
}
|
|
1083
|
+
})
|
|
1084
|
+
.then(async () => {
|
|
1085
|
+
/*
|
|
1086
|
+
* LAST, and that ordering is the whole point. A Network Alert
|
|
1087
|
+
* Policy can be scoped by site, by role and by LABEL, and the
|
|
1088
|
+
* label and site links above are what put those on a newly
|
|
1089
|
+
* imported device — a discovery import arrives with neither. Asking
|
|
1090
|
+
* the policy engine before they land would reconcile the device
|
|
1091
|
+
* against a scope it does not match yet, provision nothing, and
|
|
1092
|
+
* leave the device uncovered until the five-minute sweep.
|
|
1093
|
+
*/
|
|
1094
|
+
await NetworkAlertPolicyEngineService.reconcileDevice({
|
|
1095
|
+
projectId: createdItem.projectId,
|
|
1096
|
+
deviceId: createdItem.id,
|
|
1097
|
+
});
|
|
796
1098
|
})
|
|
797
1099
|
.catch((error) => {
|
|
798
1100
|
var _a, _b;
|
|
@@ -807,23 +1109,29 @@ export class Service extends DatabaseService {
|
|
|
807
1109
|
/*
|
|
808
1110
|
* Capture the previous state of every matched device when an update
|
|
809
1111
|
* touches siteId (so onUpdateSuccess can refresh the OLD site's rollup as
|
|
810
|
-
* well as the new one)
|
|
1112
|
+
* well as the new one), touches one of the columns site assignment rules
|
|
811
1113
|
* match on (so onUpdateSuccess can tell a real rename from the identical
|
|
812
|
-
* sysName the SNMP walk rewrites on every poll)
|
|
1114
|
+
* sysName the SNMP walk rewrites on every poll), or touches
|
|
1115
|
+
* monitoringMethod (so onUpdateSuccess can tell a real Monitor -> Probe
|
|
1116
|
+
* transition from a form re-sending the method the device already has).
|
|
1117
|
+
* The same read feeds the tenancy guards on the site, monitor and OID
|
|
1118
|
+
* template references.
|
|
813
1119
|
*/
|
|
814
1120
|
async onBeforeUpdate(updateBy) {
|
|
815
1121
|
const dataKeys = Object.keys(updateBy.data || {});
|
|
816
1122
|
/*
|
|
817
1123
|
* Switching a device to monitor-backed turns polling off with it. The
|
|
818
|
-
* two are one decision, not two: a device
|
|
819
|
-
*
|
|
820
|
-
*
|
|
1124
|
+
* two are one decision, not two: a monitor-backed device's health is
|
|
1125
|
+
* its bound monitor's, so leaving the flag on would queue a poll per
|
|
1126
|
+
* interval whose verdict nothing may read. The way back is the mirror
|
|
1127
|
+
* image — onUpdateSuccess restores polling on a real Monitor -> Probe
|
|
1128
|
+
* transition, per device, once the write has committed.
|
|
821
1129
|
*/
|
|
822
1130
|
const isMethodWrite = dataKeys.includes("monitoringMethod");
|
|
823
1131
|
/*
|
|
824
1132
|
* An update payload is a QueryDeepPartialEntity, so a column can hold a
|
|
825
1133
|
* raw value OR a SQL-expression function. Only a plain string is a
|
|
826
|
-
* method we can reason about; anything else falls through to the
|
|
1134
|
+
* method we can reason about; anything else falls through to the Probe
|
|
827
1135
|
* default, which changes nothing.
|
|
828
1136
|
*/
|
|
829
1137
|
const writtenMethod = updateBy.data["monitoringMethod"];
|
|
@@ -831,6 +1139,16 @@ export class Service extends DatabaseService {
|
|
|
831
1139
|
typeof writtenMethod === "string" &&
|
|
832
1140
|
NetworkDeviceMonitoringMethodUtil.isMonitorBacked(writtenMethod);
|
|
833
1141
|
if (becomesMonitorBacked) {
|
|
1142
|
+
/*
|
|
1143
|
+
* Only the polling flag is forced onto the payload, deliberately. The
|
|
1144
|
+
* poll residue the device carries over from its probe-polled days has to go
|
|
1145
|
+
* too, but the column-permission check runs on this payload AFTER the
|
|
1146
|
+
* hook, and those columns are updatable by fewer roles than
|
|
1147
|
+
* monitoringMethod is — so adding them here would turn a project
|
|
1148
|
+
* member's legitimate switch into a permission failure.
|
|
1149
|
+
* onUpdateSuccess clears them as root once the transition has
|
|
1150
|
+
* committed; see pollResidueReset.
|
|
1151
|
+
*/
|
|
834
1152
|
updateBy.data.isPollingEnabled = false;
|
|
835
1153
|
}
|
|
836
1154
|
/*
|
|
@@ -841,29 +1159,26 @@ export class Service extends DatabaseService {
|
|
|
841
1159
|
* nothing ever polled it. Only checked when the payload actually asks
|
|
842
1160
|
* for it, so the ordinary update path costs no extra query.
|
|
843
1161
|
*/
|
|
844
|
-
|
|
1162
|
+
const isPollingTurnOn = !becomesMonitorBacked &&
|
|
845
1163
|
dataKeys.includes("isPollingEnabled") &&
|
|
846
|
-
updateBy.data.isPollingEnabled === true
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
throw new BadDataException("This device is monitor-backed, so there is nothing to poll — it has no probe and no SNMP credentials. Switch its monitoring method to SNMP first.");
|
|
865
|
-
}
|
|
866
|
-
}
|
|
1164
|
+
updateBy.data.isPollingEnabled === true;
|
|
1165
|
+
/*
|
|
1166
|
+
* Read — and, for conflicting spellings, refused — before the early
|
|
1167
|
+
* return below, so a payload that points `monitorId` and `monitor` at
|
|
1168
|
+
* different rows is rejected on every write shape rather than only on
|
|
1169
|
+
* the ones that happen to need the snapshot. Null means the write
|
|
1170
|
+
* unbinds the monitor, or does not mention it; neither needs a lookup.
|
|
1171
|
+
*/
|
|
1172
|
+
const newMonitorId = readMonitorIdFromData(updateBy.data);
|
|
1173
|
+
/*
|
|
1174
|
+
* Read here, above the early return, for the same reason the monitor id
|
|
1175
|
+
* is: a payload that points `probeId` and `probe` (or the two credential
|
|
1176
|
+
* profile spellings) at different rows is a contradiction, and it is
|
|
1177
|
+
* refused on every write shape rather than only on the ones that happen
|
|
1178
|
+
* to need the snapshot below.
|
|
1179
|
+
*/
|
|
1180
|
+
const newProbeId = readProbeIdFromData(updateBy.data);
|
|
1181
|
+
const newSnmpCredentialProfileId = readSnmpCredentialProfileIdFromData(updateBy.data);
|
|
867
1182
|
const isSiteChange = isSiteWrite(dataKeys);
|
|
868
1183
|
const isIdentityChange = SITE_RULE_IDENTITY_COLUMNS.some((column) => {
|
|
869
1184
|
return dataKeys.includes(column);
|
|
@@ -886,10 +1201,42 @@ export class Service extends DatabaseService {
|
|
|
886
1201
|
*/
|
|
887
1202
|
const isOidTemplateChange = RelationIdUtil.isWritten(dataKeys, OID_TEMPLATE_KEYS);
|
|
888
1203
|
const isDeviceOidsChange = updateBy.data.snmpOids !== undefined;
|
|
889
|
-
|
|
1204
|
+
/*
|
|
1205
|
+
* The polling tenancy pair, named in the early return for exactly the
|
|
1206
|
+
* reason the OID template is: assigning a probe or a credential profile
|
|
1207
|
+
* changes neither site nor identity, so a guard placed below the return
|
|
1208
|
+
* would be dead code on the only writes it exists for — the settings
|
|
1209
|
+
* page's Monitoring section and the device-list bulk actions, which post
|
|
1210
|
+
* precisely these columns and nothing else.
|
|
1211
|
+
*/
|
|
1212
|
+
const isProbeChange = RelationIdUtil.isWritten(dataKeys, PROBE_KEYS);
|
|
1213
|
+
const isSnmpCredentialProfileChange = RelationIdUtil.isWritten(dataKeys, PROFILE_KEYS);
|
|
1214
|
+
/*
|
|
1215
|
+
* One snapshot read serves every guard and carry-forward below, and the
|
|
1216
|
+
* SNMP walk's per-poll column writes — the hot path through here — need
|
|
1217
|
+
* none of them. Binding a monitor is on the list for the same reason the
|
|
1218
|
+
* OID template is: it is exactly the write shape that changes neither
|
|
1219
|
+
* site nor identity, so a tenancy guard placed below a narrower return
|
|
1220
|
+
* would never run on the only write it exists for.
|
|
1221
|
+
*/
|
|
1222
|
+
/*
|
|
1223
|
+
* The alert-policy axes ride the same return, and for the same reason
|
|
1224
|
+
* the OID template does: re-labelling a device or moving it to a role
|
|
1225
|
+
* changes neither its site nor its identity, so a snapshot taken below a
|
|
1226
|
+
* narrower return would be absent on exactly the writes onUpdateSuccess
|
|
1227
|
+
* needs it for. See isAlertPolicyRelevantWrite.
|
|
1228
|
+
*/
|
|
1229
|
+
const isAlertPolicyChange = isAlertPolicyRelevantWrite(dataKeys);
|
|
1230
|
+
if (!isMethodWrite &&
|
|
1231
|
+
!isPollingTurnOn &&
|
|
1232
|
+
!newMonitorId &&
|
|
1233
|
+
!isSiteChange &&
|
|
890
1234
|
!isIdentityChange &&
|
|
891
1235
|
!isOidTemplateChange &&
|
|
892
|
-
!isDeviceOidsChange
|
|
1236
|
+
!isDeviceOidsChange &&
|
|
1237
|
+
!isProbeChange &&
|
|
1238
|
+
!isSnmpCredentialProfileChange &&
|
|
1239
|
+
!isAlertPolicyChange) {
|
|
893
1240
|
return { updateBy, carryForward: null };
|
|
894
1241
|
}
|
|
895
1242
|
const previousDevices = await this.findBy({
|
|
@@ -901,9 +1248,18 @@ export class Service extends DatabaseService {
|
|
|
901
1248
|
hostname: true,
|
|
902
1249
|
name: true,
|
|
903
1250
|
sysName: true,
|
|
1251
|
+
/*
|
|
1252
|
+
* Whether the device already has a probe. The site-default
|
|
1253
|
+
* inheritance below must never overwrite one, and this column is
|
|
1254
|
+
* the only way to tell "no probe yet" from "a probe the operator
|
|
1255
|
+
* chose" once the write has committed.
|
|
1256
|
+
*/
|
|
1257
|
+
probeId: true,
|
|
904
1258
|
// Decide which OID budget applies below, and whether a link would truncate.
|
|
905
1259
|
oidTemplateId: true,
|
|
906
1260
|
snmpOids: true,
|
|
1261
|
+
// The polling guard and the method transition both need the OLD method.
|
|
1262
|
+
monitoringMethod: true,
|
|
907
1263
|
},
|
|
908
1264
|
limit: LIMIT_MAX,
|
|
909
1265
|
skip: 0,
|
|
@@ -911,6 +1267,32 @@ export class Service extends DatabaseService {
|
|
|
911
1267
|
isRoot: true,
|
|
912
1268
|
},
|
|
913
1269
|
});
|
|
1270
|
+
if (isPollingTurnOn) {
|
|
1271
|
+
const isTargetMonitorBacked = previousDevices.some((target) => {
|
|
1272
|
+
return NetworkDeviceMonitoringMethodUtil.isMonitorBacked(target.monitoringMethod);
|
|
1273
|
+
});
|
|
1274
|
+
// Unless the same write is moving it back to Probe, which is allowed.
|
|
1275
|
+
if (isTargetMonitorBacked && !(isMethodWrite && !becomesMonitorBacked)) {
|
|
1276
|
+
throw new BadDataException("This device is monitor-backed, so there is nothing to poll — its bound monitor's status is its status. Switch its monitoring method to Probe first.");
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
/*
|
|
1280
|
+
* Which of the matched devices were monitor-backed BEFORE this write.
|
|
1281
|
+
* Only recorded on a method write, because only a method write can be a
|
|
1282
|
+
* transition; see DeviceUpdateCarryForward for what onUpdateSuccess does
|
|
1283
|
+
* with it and why the payload alone is not enough.
|
|
1284
|
+
*/
|
|
1285
|
+
let wasMonitorBackedByDeviceId = undefined;
|
|
1286
|
+
if (isMethodWrite) {
|
|
1287
|
+
wasMonitorBackedByDeviceId = {};
|
|
1288
|
+
for (const previousDevice of previousDevices) {
|
|
1289
|
+
if (!previousDevice.id) {
|
|
1290
|
+
continue;
|
|
1291
|
+
}
|
|
1292
|
+
wasMonitorBackedByDeviceId[previousDevice.id.toString()] =
|
|
1293
|
+
NetworkDeviceMonitoringMethodUtil.isMonitorBacked(previousDevice.monitoringMethod);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
914
1296
|
const newSiteId = readSiteIdFromData(updateBy.data);
|
|
915
1297
|
if (newSiteId) {
|
|
916
1298
|
const checkedProjectIds = new Set();
|
|
@@ -926,6 +1308,29 @@ export class Service extends DatabaseService {
|
|
|
926
1308
|
});
|
|
927
1309
|
}
|
|
928
1310
|
}
|
|
1311
|
+
/*
|
|
1312
|
+
* The monitor guard on the UPDATE path. Until this existed only
|
|
1313
|
+
* onBeforeCreate checked the binding, so a device could be created
|
|
1314
|
+
* clean and then re-pointed at another project's monitor with a plain
|
|
1315
|
+
* update — and read that monitor's status through the device, since
|
|
1316
|
+
* refreshStampedMonitorStatus stamps whatever `monitorId` names. One
|
|
1317
|
+
* check per distinct project in the matched set, like the site guard
|
|
1318
|
+
* above. An unbind (null) has nothing to check.
|
|
1319
|
+
*/
|
|
1320
|
+
if (newMonitorId) {
|
|
1321
|
+
const checkedMonitorProjectIds = new Set();
|
|
1322
|
+
for (const previousDevice of previousDevices) {
|
|
1323
|
+
if (!previousDevice.projectId ||
|
|
1324
|
+
checkedMonitorProjectIds.has(previousDevice.projectId.toString())) {
|
|
1325
|
+
continue;
|
|
1326
|
+
}
|
|
1327
|
+
checkedMonitorProjectIds.add(previousDevice.projectId.toString());
|
|
1328
|
+
await this.assertMonitorBelongsToProject({
|
|
1329
|
+
monitorId: newMonitorId,
|
|
1330
|
+
projectId: previousDevice.projectId,
|
|
1331
|
+
});
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
929
1334
|
const newOidTemplateId = readOidTemplateIdFromData(updateBy.data);
|
|
930
1335
|
/*
|
|
931
1336
|
* Same shape as the site guard above: one check per distinct project in
|
|
@@ -946,6 +1351,49 @@ export class Service extends DatabaseService {
|
|
|
946
1351
|
});
|
|
947
1352
|
}
|
|
948
1353
|
}
|
|
1354
|
+
/*
|
|
1355
|
+
* The polling tenancy guards on the UPDATE path. A device created clean
|
|
1356
|
+
* and then re-pointed with a plain update is the same breach as one
|
|
1357
|
+
* created that way, so both hooks check both references. One check per
|
|
1358
|
+
* distinct project in the matched set, like the guards above — a single
|
|
1359
|
+
* updateBy can span projects when a root caller issues it, and the
|
|
1360
|
+
* payload names ONE probe and ONE profile for all of them.
|
|
1361
|
+
*
|
|
1362
|
+
* A clear (null) points at nothing and has nothing to check.
|
|
1363
|
+
*/
|
|
1364
|
+
const distinctProjectIds = [];
|
|
1365
|
+
const seenProjectIds = new Set();
|
|
1366
|
+
for (const previousDevice of previousDevices) {
|
|
1367
|
+
if (!previousDevice.projectId ||
|
|
1368
|
+
seenProjectIds.has(previousDevice.projectId.toString())) {
|
|
1369
|
+
continue;
|
|
1370
|
+
}
|
|
1371
|
+
seenProjectIds.add(previousDevice.projectId.toString());
|
|
1372
|
+
distinctProjectIds.push(previousDevice.projectId);
|
|
1373
|
+
}
|
|
1374
|
+
for (const projectId of distinctProjectIds) {
|
|
1375
|
+
if (newProbeId) {
|
|
1376
|
+
await this.assertProbeIsAttachableToProject({
|
|
1377
|
+
probeId: newProbeId,
|
|
1378
|
+
projectId: projectId,
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1381
|
+
if (newSnmpCredentialProfileId) {
|
|
1382
|
+
await this.assertSnmpCredentialProfileBelongsToProject({
|
|
1383
|
+
snmpCredentialProfileId: newSnmpCredentialProfileId,
|
|
1384
|
+
projectId: projectId,
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
await this.applySiteDefaultProbeOnMove({
|
|
1389
|
+
updateBy: updateBy,
|
|
1390
|
+
previousDevices: previousDevices,
|
|
1391
|
+
distinctProjectIds: distinctProjectIds,
|
|
1392
|
+
newSiteId: newSiteId,
|
|
1393
|
+
isProbeChange: isProbeChange,
|
|
1394
|
+
isMethodWrite: isMethodWrite,
|
|
1395
|
+
becomesMonitorBacked: becomesMonitorBacked,
|
|
1396
|
+
});
|
|
949
1397
|
/*
|
|
950
1398
|
* How many OIDs a device may carry of its own.
|
|
951
1399
|
*
|
|
@@ -989,16 +1437,74 @@ export class Service extends DatabaseService {
|
|
|
989
1437
|
label: "Device-Specific Health OIDs",
|
|
990
1438
|
});
|
|
991
1439
|
}
|
|
1440
|
+
const carryForward = {
|
|
1441
|
+
previousDevices: previousDevices,
|
|
1442
|
+
};
|
|
1443
|
+
if (wasMonitorBackedByDeviceId) {
|
|
1444
|
+
carryForward.wasMonitorBackedByDeviceId = wasMonitorBackedByDeviceId;
|
|
1445
|
+
}
|
|
992
1446
|
return {
|
|
993
1447
|
updateBy,
|
|
994
|
-
carryForward:
|
|
995
|
-
previousDevices: previousDevices,
|
|
996
|
-
},
|
|
1448
|
+
carryForward: carryForward,
|
|
997
1449
|
};
|
|
998
1450
|
}
|
|
999
1451
|
/*
|
|
1000
|
-
*
|
|
1001
|
-
*
|
|
1452
|
+
* Site default probe on a MOVE: a device with no probe of its own that is
|
|
1453
|
+
* moved into a site inherits that site's default (or the nearest
|
|
1454
|
+
* ancestor's), copied onto this same write.
|
|
1455
|
+
*
|
|
1456
|
+
* The create path's twin, and the same copy-at-write rule: this runs only
|
|
1457
|
+
* because the payload moves the device, never because a site's default
|
|
1458
|
+
* changed. Editing a site's probe re-points nothing — the device-list bulk
|
|
1459
|
+
* "Set probe" action is the deliberate way to move a fleet.
|
|
1460
|
+
*
|
|
1461
|
+
* Three things stop it: the caller writing a probe of its own (their
|
|
1462
|
+
* choice wins, including an explicit clear), the device already having one
|
|
1463
|
+
* (a probe an operator chose must survive being filed under a site), and
|
|
1464
|
+
* the device being monitor-backed after this write (nothing polls it, so a
|
|
1465
|
+
* probe would be a lie on the row).
|
|
1466
|
+
*
|
|
1467
|
+
* "Already having one" is judged across the WHOLE matched set, because a
|
|
1468
|
+
* single payload writes one probeId to every row it matches: if any
|
|
1469
|
+
* matched device has a probe, inheriting would re-point it, so the
|
|
1470
|
+
* inheritance is skipped for the batch rather than applied to some of it.
|
|
1471
|
+
* The bulk path a user actually takes — "move these devices to this site"
|
|
1472
|
+
* — is overwhelmingly devices in the same state.
|
|
1473
|
+
*/
|
|
1474
|
+
async applySiteDefaultProbeOnMove(data) {
|
|
1475
|
+
if (!data.newSiteId ||
|
|
1476
|
+
data.isProbeChange ||
|
|
1477
|
+
data.previousDevices.length === 0) {
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
for (const previousDevice of data.previousDevices) {
|
|
1481
|
+
if (previousDevice.probeId) {
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
/*
|
|
1485
|
+
* The method AFTER this write: what the payload sets when it sets one,
|
|
1486
|
+
* otherwise what the row already says. A device that stays (or
|
|
1487
|
+
* becomes) monitor-backed is not polled by a probe at all.
|
|
1488
|
+
*/
|
|
1489
|
+
const isMonitorBackedAfterWrite = data.isMethodWrite
|
|
1490
|
+
? data.becomesMonitorBacked
|
|
1491
|
+
: NetworkDeviceMonitoringMethodUtil.isMonitorBacked(previousDevice.monitoringMethod);
|
|
1492
|
+
if (isMonitorBackedAfterWrite) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
const inheritedProbeId = await this.resolveInheritedSiteProbeId({
|
|
1497
|
+
siteId: data.newSiteId,
|
|
1498
|
+
projectIds: data.distinctProjectIds,
|
|
1499
|
+
});
|
|
1500
|
+
if (inheritedProbeId) {
|
|
1501
|
+
data.updateBy.data.probeId = inheritedProbeId;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
/*
|
|
1505
|
+
* Re-derives one device's stamped `currentMonitorStatusId` — and, for a
|
|
1506
|
+
* monitor-backed device, its `isReachable` — from its binding, and
|
|
1507
|
+
* refreshes its site chain if either moved.
|
|
1002
1508
|
*
|
|
1003
1509
|
* The stamp is what every monitor-backed surface reads — the device list
|
|
1004
1510
|
* pill, the site rollup, the topology node — and until this existed the
|
|
@@ -1010,17 +1516,36 @@ export class Service extends DatabaseService {
|
|
|
1010
1516
|
* OneUptime/oneuptime#3392. Binding is itself an event that decides the
|
|
1011
1517
|
* device's status, so it stamps here.
|
|
1012
1518
|
*
|
|
1519
|
+
* `isReachable` rides along because the device list's summary tiles and
|
|
1520
|
+
* its Status facet count and filter in SQL, over that column alone — they
|
|
1521
|
+
* cannot evaluate the stamp's ladder per row — so a monitor-backed device
|
|
1522
|
+
* whose stamp said Operational still counted as "Pending" there. The
|
|
1523
|
+
* value written is `!MonitorStatus.isOfflineState`: the OFFLINE end of the
|
|
1524
|
+
* ladder, not the operational one, because that is exactly what
|
|
1525
|
+
* DeviceReachabilityUtil reads for the pill (a "Degraded" row is neither
|
|
1526
|
+
* operational nor offline, and reads as reachable on both). NULL when
|
|
1527
|
+
* nothing is bound or the monitor has no status, which is the honest
|
|
1528
|
+
* "Pending" the util renders for `undefined`. For a Probe device the poll
|
|
1529
|
+
* owns `isReachable`, and this method never touches it.
|
|
1530
|
+
*
|
|
1013
1531
|
* `clearWhenNotMonitorBacked` is for the write that moves a device OFF
|
|
1014
1532
|
* monitor-backed: the ping monitor's verdict must not outlive the binding
|
|
1015
1533
|
* (DeviceHealthStateUtil lets a stamped status beat reachability, so a
|
|
1016
1534
|
* stale one would poison the site rollup of a device that is now walked).
|
|
1017
1535
|
* It is deliberately NOT set when a write only touches the monitor
|
|
1018
|
-
* binding of
|
|
1019
|
-
*
|
|
1020
|
-
*
|
|
1536
|
+
* binding of a Probe device, nor when a form re-sends "Probe" on a device
|
|
1537
|
+
* that already is one, because a Probe device's stamp comes from the
|
|
1538
|
+
* Network Device monitor that watches it, and that binding lives in the
|
|
1539
|
+
* monitor's step data rather than in this column. onBeforeUpdate records
|
|
1540
|
+
* the old method so onUpdateSuccess can tell the two apart.
|
|
1541
|
+
*
|
|
1542
|
+
* Idempotent: everything is re-derived from the binding, nothing from what
|
|
1543
|
+
* a previous call wrote, and nothing is written when the row already
|
|
1544
|
+
* agrees — which is what makes it safe from every save, from monitor
|
|
1545
|
+
* deletion, and from a backfill running twice concurrently.
|
|
1021
1546
|
*/
|
|
1022
1547
|
async refreshStampedMonitorStatus(data) {
|
|
1023
|
-
var _a;
|
|
1548
|
+
var _a, _b;
|
|
1024
1549
|
const device = await this.findOneById({
|
|
1025
1550
|
id: data.deviceId,
|
|
1026
1551
|
select: {
|
|
@@ -1030,6 +1555,10 @@ export class Service extends DatabaseService {
|
|
|
1030
1555
|
monitoringMethod: true,
|
|
1031
1556
|
monitorId: true,
|
|
1032
1557
|
currentMonitorStatusId: true,
|
|
1558
|
+
isReachable: true,
|
|
1559
|
+
// Read only to decide whether the clear below has anything to clear.
|
|
1560
|
+
isSnmpReachable: true,
|
|
1561
|
+
lastSnmpSeenAt: true,
|
|
1033
1562
|
},
|
|
1034
1563
|
props: {
|
|
1035
1564
|
isRoot: true,
|
|
@@ -1039,11 +1568,53 @@ export class Service extends DatabaseService {
|
|
|
1039
1568
|
return;
|
|
1040
1569
|
}
|
|
1041
1570
|
const isMonitorBacked = NetworkDeviceMonitoringMethodUtil.isMonitorBacked(device.monitoringMethod);
|
|
1042
|
-
if (!isMonitorBacked
|
|
1571
|
+
if (!isMonitorBacked) {
|
|
1572
|
+
if (!data.clearWhenNotMonitorBacked) {
|
|
1573
|
+
return;
|
|
1574
|
+
}
|
|
1575
|
+
/*
|
|
1576
|
+
* The device has just left monitor-backed. While it was monitor-backed
|
|
1577
|
+
* its `isReachable` could only ever be the bound monitor's mirror: the
|
|
1578
|
+
* poll's value was NULLed on the way in (pollResidueReset), and
|
|
1579
|
+
* NetworkInventoryUtil never writes it for a monitor-backed row. So the
|
|
1580
|
+
* mirror goes with the stamp — otherwise a device switched back to
|
|
1581
|
+
* Probe would read "Down — the last poll could not reach it" (or Up)
|
|
1582
|
+
* on every surface, from the verdict of a monitor that no longer
|
|
1583
|
+
* governs it, until a poll happens to land. NULL is the honest answer:
|
|
1584
|
+
* Pending until the first poll decides.
|
|
1585
|
+
*
|
|
1586
|
+
* The SNMP pair is cleared with them for the same reason: nothing
|
|
1587
|
+
* walked the device while it was monitor-backed, so anything on those
|
|
1588
|
+
* two columns predates the binding, and a device switched back to
|
|
1589
|
+
* Probe starts clean — its first poll decides whether SNMP answers.
|
|
1590
|
+
*
|
|
1591
|
+
* Nothing to clear means nothing to write — a null-over-null write
|
|
1592
|
+
* would still recompute the site chain for nothing.
|
|
1593
|
+
*/
|
|
1594
|
+
const hasStamp = Boolean(device.currentMonitorStatusId);
|
|
1595
|
+
const hasMirroredReachability = typeof device.isReachable === "boolean";
|
|
1596
|
+
const hasSnmpResidue = typeof device.isSnmpReachable === "boolean" ||
|
|
1597
|
+
(device.lastSnmpSeenAt !== null && device.lastSnmpSeenAt !== undefined);
|
|
1598
|
+
if (!hasStamp && !hasMirroredReachability && !hasSnmpResidue) {
|
|
1599
|
+
return;
|
|
1600
|
+
}
|
|
1601
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
1602
|
+
id: data.deviceId,
|
|
1603
|
+
data: {
|
|
1604
|
+
currentMonitorStatusId: null,
|
|
1605
|
+
isReachable: null,
|
|
1606
|
+
isSnmpReachable: null,
|
|
1607
|
+
lastSnmpSeenAt: null,
|
|
1608
|
+
},
|
|
1609
|
+
});
|
|
1610
|
+
if (device.siteId) {
|
|
1611
|
+
await NetworkSiteService.recomputeRollupForSiteAndAncestors(device.siteId);
|
|
1612
|
+
}
|
|
1043
1613
|
return;
|
|
1044
1614
|
}
|
|
1045
1615
|
let monitorStatusId = null;
|
|
1046
|
-
|
|
1616
|
+
let nextReachable = null;
|
|
1617
|
+
if (device.monitorId) {
|
|
1047
1618
|
/*
|
|
1048
1619
|
* Scoped to the device's project on the read as well as on the write
|
|
1049
1620
|
* path in onBeforeCreate/onBeforeUpdate: a monitor from another
|
|
@@ -1057,22 +1628,36 @@ export class Service extends DatabaseService {
|
|
|
1057
1628
|
select: {
|
|
1058
1629
|
_id: true,
|
|
1059
1630
|
currentMonitorStatusId: true,
|
|
1631
|
+
currentMonitorStatus: {
|
|
1632
|
+
isOfflineState: true,
|
|
1633
|
+
},
|
|
1060
1634
|
},
|
|
1061
1635
|
props: {
|
|
1062
1636
|
isRoot: true,
|
|
1063
1637
|
},
|
|
1064
1638
|
});
|
|
1065
1639
|
monitorStatusId = (monitor === null || monitor === void 0 ? void 0 : monitor.currentMonitorStatusId) || null;
|
|
1640
|
+
if (monitorStatusId) {
|
|
1641
|
+
nextReachable = ((_a = monitor === null || monitor === void 0 ? void 0 : monitor.currentMonitorStatus) === null || _a === void 0 ? void 0 : _a.isOfflineState) !== true;
|
|
1642
|
+
}
|
|
1066
1643
|
}
|
|
1067
|
-
const currentStampId = ((
|
|
1644
|
+
const currentStampId = ((_b = device.currentMonitorStatusId) === null || _b === void 0 ? void 0 : _b.toString()) || null;
|
|
1068
1645
|
const nextStampId = (monitorStatusId === null || monitorStatusId === void 0 ? void 0 : monitorStatusId.toString()) || null;
|
|
1069
|
-
|
|
1646
|
+
/*
|
|
1647
|
+
* A NULL column reads back as undefined on the model; both mean "no
|
|
1648
|
+
* verdict", and comparing them as one keeps a device that already
|
|
1649
|
+
* agrees from being rewritten on every save.
|
|
1650
|
+
*/
|
|
1651
|
+
const currentReachable = typeof device.isReachable === "boolean" ? device.isReachable : null;
|
|
1652
|
+
if (currentStampId === nextStampId && currentReachable === nextReachable) {
|
|
1070
1653
|
return;
|
|
1071
1654
|
}
|
|
1655
|
+
// One write, so the two columns can never be seen disagreeing.
|
|
1072
1656
|
await this.updateColumnsByIdWithoutHooks({
|
|
1073
1657
|
id: data.deviceId,
|
|
1074
1658
|
data: {
|
|
1075
1659
|
currentMonitorStatusId: monitorStatusId,
|
|
1660
|
+
isReachable: nextReachable,
|
|
1076
1661
|
},
|
|
1077
1662
|
});
|
|
1078
1663
|
if (device.siteId) {
|
|
@@ -1084,7 +1669,7 @@ export class Service extends DatabaseService {
|
|
|
1084
1669
|
* or rule-engine failure must never fail the device update itself.
|
|
1085
1670
|
*/
|
|
1086
1671
|
async onUpdateSuccess(onUpdate, updatedItemIds) {
|
|
1087
|
-
var _a, _b;
|
|
1672
|
+
var _a, _b, _c;
|
|
1088
1673
|
/*
|
|
1089
1674
|
* Re-stamp before the site maintenance below, and in its own try: the
|
|
1090
1675
|
* two are independent, and a rollup failure must not cost the device
|
|
@@ -1095,10 +1680,97 @@ export class Service extends DatabaseService {
|
|
|
1095
1680
|
const isMethodWrite = dataKeys.includes("monitoringMethod");
|
|
1096
1681
|
const isMonitorWrite = RelationIdUtil.isWritten(dataKeys, MONITOR_KEYS);
|
|
1097
1682
|
if (isMethodWrite || isMonitorWrite) {
|
|
1683
|
+
// Same parse as onBeforeUpdate: only a plain string is a method.
|
|
1684
|
+
const writtenMethod = onUpdate.updateBy.data["monitoringMethod"];
|
|
1685
|
+
const becomesMonitorBacked = isMethodWrite &&
|
|
1686
|
+
typeof writtenMethod === "string" &&
|
|
1687
|
+
NetworkDeviceMonitoringMethodUtil.isMonitorBacked(writtenMethod);
|
|
1688
|
+
/*
|
|
1689
|
+
* Recorded by onBeforeUpdate on every method write. Absent on a
|
|
1690
|
+
* binding-only write, where nothing can have transitioned.
|
|
1691
|
+
*/
|
|
1692
|
+
const wasMonitorBackedByDeviceId = ((_a = onUpdate.carryForward) === null || _a === void 0 ? void 0 : _a.wasMonitorBackedByDeviceId) || {};
|
|
1098
1693
|
for (const deviceId of updatedItemIds) {
|
|
1694
|
+
const wasMonitorBacked = wasMonitorBackedByDeviceId[deviceId.toString()];
|
|
1695
|
+
/*
|
|
1696
|
+
* Probe -> Monitor: the probe's last findings are now residue on a
|
|
1697
|
+
* device nothing polls, and they would keep feeding the legacy
|
|
1698
|
+
* staleness rule and the "degraded" query. Cleared as root here
|
|
1699
|
+
* rather than on the caller's payload (see onBeforeUpdate for the
|
|
1700
|
+
* permission reason), and BEFORE the re-stamp, so a device bound
|
|
1701
|
+
* in the same write ends up with its monitor's verdict rather
|
|
1702
|
+
* than the walk's. A device the snapshot did not record is
|
|
1703
|
+
* cleared too: the write is idempotent, and "unknown" must not
|
|
1704
|
+
* mean "keep the residue".
|
|
1705
|
+
*/
|
|
1706
|
+
if (becomesMonitorBacked && wasMonitorBacked !== true) {
|
|
1707
|
+
try {
|
|
1708
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
1709
|
+
id: deviceId,
|
|
1710
|
+
data: pollResidueReset(),
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
catch (error) {
|
|
1714
|
+
/*
|
|
1715
|
+
* Bookkeeping, and separable from the re-stamp: the monitor's
|
|
1716
|
+
* verdict below still lands, and a set isReachable keeps the
|
|
1717
|
+
* legacy freshness branch out of play even with the dates
|
|
1718
|
+
* left behind.
|
|
1719
|
+
*/
|
|
1720
|
+
logger.error(`Error in NetworkDeviceService.onUpdateSuccess poll residue reset for device ${deviceId.toString()}: ${error}`);
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
/*
|
|
1724
|
+
* Monitor -> Probe: the mirror image. Arriving at monitor-backed
|
|
1725
|
+
* turned polling off (onBeforeUpdate), so leaving it turns polling
|
|
1726
|
+
* back on — otherwise the device would sit on "Pending" under a
|
|
1727
|
+
* method whose whole point is that the probe polls it. Decided
|
|
1728
|
+
* per device from the snapshot, never from the payload: one bulk
|
|
1729
|
+
* write of "Probe" also matches devices that already were Probe,
|
|
1730
|
+
* and one of those may have had polling turned off on purpose.
|
|
1731
|
+
* A root write, like the residue reset above, because the two
|
|
1732
|
+
* columns are updatable by fewer roles than the method is.
|
|
1733
|
+
* `nextPollAt = now` makes the device due at once rather than at
|
|
1734
|
+
* whatever moment its last claim — months ago, or never — left
|
|
1735
|
+
* behind. The caller's own word wins when it says the opposite:
|
|
1736
|
+
* a payload writing `isPollingEnabled: false` beside the method
|
|
1737
|
+
* wants a Probe device that is not polled yet. No probe is
|
|
1738
|
+
* required here — the forms require one, the API and Terraform
|
|
1739
|
+
* may assign it in a later write — and a Probe device without one
|
|
1740
|
+
* is simply not claimed until it has one.
|
|
1741
|
+
*/
|
|
1742
|
+
const isMonitorToProbeTransition = wasMonitorBacked === true && !becomesMonitorBacked;
|
|
1743
|
+
const payloadTurnsPollingOff = dataKeys.includes("isPollingEnabled") &&
|
|
1744
|
+
onUpdate.updateBy.data["isPollingEnabled"] === false;
|
|
1745
|
+
if (isMonitorToProbeTransition && !payloadTurnsPollingOff) {
|
|
1746
|
+
try {
|
|
1747
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
1748
|
+
id: deviceId,
|
|
1749
|
+
data: {
|
|
1750
|
+
isPollingEnabled: true,
|
|
1751
|
+
nextPollAt: OneUptimeDate.getCurrentDate(),
|
|
1752
|
+
},
|
|
1753
|
+
});
|
|
1754
|
+
}
|
|
1755
|
+
catch (error) {
|
|
1756
|
+
/*
|
|
1757
|
+
* Bookkeeping, and separable from the re-stamp below: the
|
|
1758
|
+
* stale stamp still goes, and the operator can turn polling
|
|
1759
|
+
* on from Settings if this write was the one that failed.
|
|
1760
|
+
*/
|
|
1761
|
+
logger.error(`Error in NetworkDeviceService.onUpdateSuccess polling restore for device ${deviceId.toString()}: ${error}`);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
/*
|
|
1765
|
+
* Only a device that WAS monitor-backed and now is not may have
|
|
1766
|
+
* its stamp cleared. The Settings form re-sends monitoringMethod
|
|
1767
|
+
* on every save, so "the payload says Probe" is not a transition —
|
|
1768
|
+
* treating it as one wiped the stamp a Network Device monitor had
|
|
1769
|
+
* put on every Probe device that was ever saved.
|
|
1770
|
+
*/
|
|
1099
1771
|
await this.refreshStampedMonitorStatus({
|
|
1100
1772
|
deviceId: deviceId,
|
|
1101
|
-
clearWhenNotMonitorBacked:
|
|
1773
|
+
clearWhenNotMonitorBacked: wasMonitorBacked === true && !becomesMonitorBacked,
|
|
1102
1774
|
});
|
|
1103
1775
|
}
|
|
1104
1776
|
}
|
|
@@ -1111,7 +1783,7 @@ export class Service extends DatabaseService {
|
|
|
1111
1783
|
if (isSiteWrite(dataKeys)) {
|
|
1112
1784
|
// Manual or rule-driven site change: refresh old + new site chains.
|
|
1113
1785
|
const affectedSiteIds = new Map();
|
|
1114
|
-
const previousDevices = ((
|
|
1786
|
+
const previousDevices = ((_b = onUpdate.carryForward) === null || _b === void 0 ? void 0 : _b.previousDevices) || [];
|
|
1115
1787
|
/*
|
|
1116
1788
|
* onUpdateSuccess runs even when the permission-scoped UPDATE matched
|
|
1117
1789
|
* nothing, so only devices the UPDATE actually touched may drive
|
|
@@ -1146,7 +1818,7 @@ export class Service extends DatabaseService {
|
|
|
1146
1818
|
* identity actually moved (or that has no site yet).
|
|
1147
1819
|
*/
|
|
1148
1820
|
const previousDevicesById = new Map();
|
|
1149
|
-
const previousDevices = ((
|
|
1821
|
+
const previousDevices = ((_c = onUpdate.carryForward) === null || _c === void 0 ? void 0 : _c.previousDevices) || [];
|
|
1150
1822
|
for (const previousDevice of previousDevices) {
|
|
1151
1823
|
if (previousDevice.id) {
|
|
1152
1824
|
previousDevicesById.set(previousDevice.id.toString(), previousDevice);
|
|
@@ -1182,8 +1854,75 @@ export class Service extends DatabaseService {
|
|
|
1182
1854
|
catch (error) {
|
|
1183
1855
|
logger.error(`Error in NetworkDeviceService.onUpdateSuccess site maintenance: ${error}`);
|
|
1184
1856
|
}
|
|
1857
|
+
try {
|
|
1858
|
+
await this.reconcileAlertPoliciesAfterUpdate(onUpdate, updatedItemIds);
|
|
1859
|
+
}
|
|
1860
|
+
catch (error) {
|
|
1861
|
+
/*
|
|
1862
|
+
* Isolated from the site maintenance above for the same reason that is
|
|
1863
|
+
* isolated from the status re-stamp: a policy that cannot provision
|
|
1864
|
+
* must not cost the device its site rollup, and the five-minute sweep
|
|
1865
|
+
* recomputes the same difference either way.
|
|
1866
|
+
*/
|
|
1867
|
+
logger.error(`Error in NetworkDeviceService.onUpdateSuccess alert policy reconciliation: ${error}`);
|
|
1868
|
+
}
|
|
1185
1869
|
return onUpdate;
|
|
1186
1870
|
}
|
|
1871
|
+
/*
|
|
1872
|
+
* Keep the device's policy-provisioned monitors in step with what the
|
|
1873
|
+
* update just changed about it.
|
|
1874
|
+
*
|
|
1875
|
+
* INLINE ONLY FOR A HANDFUL OF DEVICES. Reconciling one device is a few
|
|
1876
|
+
* queries and, at most, one monitor create — worth doing inside the write
|
|
1877
|
+
* so the monitor is there by the operator's next page load. A BULK write is
|
|
1878
|
+
* a different animal: "move 1,200 devices into this site" or "archive the
|
|
1879
|
+
* warehouse" matches thousands of rows, and reconciling thousands of
|
|
1880
|
+
* devices inside the request would turn one statement into an hour of
|
|
1881
|
+
* monitor provisioning with the caller still waiting on it. Past
|
|
1882
|
+
* MAX_INLINE_RECONCILE_DEVICES the write returns and the five-minute sweep
|
|
1883
|
+
* converges the fleet — it computes the same difference from the same
|
|
1884
|
+
* columns, so nothing is lost but latency.
|
|
1885
|
+
*
|
|
1886
|
+
* The project comes from the pre-write snapshot rather than from
|
|
1887
|
+
* props.tenantId, because a root caller (a worker, a data migration) has no
|
|
1888
|
+
* tenant and its update can legitimately span projects.
|
|
1889
|
+
*/
|
|
1890
|
+
async reconcileAlertPoliciesAfterUpdate(onUpdate, updatedItemIds) {
|
|
1891
|
+
var _a;
|
|
1892
|
+
const dataKeys = Object.keys(onUpdate.updateBy.data || {});
|
|
1893
|
+
if (!isAlertPolicyRelevantWrite(dataKeys) || updatedItemIds.length === 0) {
|
|
1894
|
+
return;
|
|
1895
|
+
}
|
|
1896
|
+
if (updatedItemIds.length > MAX_INLINE_RECONCILE_DEVICES) {
|
|
1897
|
+
logger.debug(`NetworkDeviceService.onUpdateSuccess: ${updatedItemIds.length} devices changed an alert-policy scope column; leaving reconciliation to the NetworkAlertPolicy sweep.`);
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1900
|
+
const previousDevices = ((_a = onUpdate.carryForward) === null || _a === void 0 ? void 0 : _a.previousDevices) || [];
|
|
1901
|
+
const projectIdByDeviceId = new Map();
|
|
1902
|
+
for (const previousDevice of previousDevices) {
|
|
1903
|
+
if (previousDevice.id && previousDevice.projectId) {
|
|
1904
|
+
projectIdByDeviceId.set(previousDevice.id.toString(), previousDevice.projectId);
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
for (const deviceId of updatedItemIds) {
|
|
1908
|
+
const projectId = projectIdByDeviceId.get(deviceId.toString()) ||
|
|
1909
|
+
onUpdate.updateBy.props.tenantId ||
|
|
1910
|
+
undefined;
|
|
1911
|
+
if (!projectId) {
|
|
1912
|
+
/*
|
|
1913
|
+
* No snapshot row and no tenant: the update matched a device this
|
|
1914
|
+
* hook cannot attribute to a project, so it cannot be reconciled
|
|
1915
|
+
* safely. The sweep, which starts from the policies, will reach it.
|
|
1916
|
+
*/
|
|
1917
|
+
logger.debug(`NetworkDeviceService.onUpdateSuccess: no project known for device ${deviceId.toString()}; leaving its alert-policy monitors to the sweep.`);
|
|
1918
|
+
continue;
|
|
1919
|
+
}
|
|
1920
|
+
await NetworkAlertPolicyEngineService.reconcileDevice({
|
|
1921
|
+
projectId: projectId,
|
|
1922
|
+
deviceId: deviceId,
|
|
1923
|
+
});
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1187
1926
|
/*
|
|
1188
1927
|
* True when an update that touched an identity column is worth re-running
|
|
1189
1928
|
* the assignment rules for.
|
|
@@ -1512,6 +2251,10 @@ export class Service extends DatabaseService {
|
|
|
1512
2251
|
* Suspended projects are skipped for the same reason monitor claiming
|
|
1513
2252
|
* skips them; archived devices keep polling on purpose ("archived devices
|
|
1514
2253
|
* keep collecting telemetry").
|
|
2254
|
+
*
|
|
2255
|
+
* The Probe join is a TENANCY backstop rather than a lookup — nothing from
|
|
2256
|
+
* the probe row is selected. See the predicate for why the write-time
|
|
2257
|
+
* guard is not enough on its own.
|
|
1515
2258
|
*/
|
|
1516
2259
|
async claimDevicesForPolling(data) {
|
|
1517
2260
|
const currentDate = OneUptimeDate.getCurrentDate();
|
|
@@ -1520,12 +2263,22 @@ export class Service extends DatabaseService {
|
|
|
1520
2263
|
SELECT nd."_id", nd."pollingIntervalInMinutes"
|
|
1521
2264
|
FROM "NetworkDevice" nd
|
|
1522
2265
|
INNER JOIN "Project" p ON nd."projectId" = p."_id"
|
|
2266
|
+
INNER JOIN "Probe" pr ON nd."probeId" = pr."_id"
|
|
1523
2267
|
WHERE nd."probeId" = $1
|
|
1524
2268
|
AND nd."isPollingEnabled" = true
|
|
1525
2269
|
AND nd."deletedAt" IS NULL
|
|
1526
2270
|
AND nd."hostname" IS NOT NULL
|
|
1527
|
-
--
|
|
1528
|
-
--
|
|
2271
|
+
-- The tenancy backstop. onBeforeCreate/onBeforeUpdate refuse a
|
|
2272
|
+
-- probe that is not attachable to the device's project, but rows
|
|
2273
|
+
-- written before those guards existed are still on disk, and a
|
|
2274
|
+
-- probe that can CLAIM a device reads its hostname and its SNMP
|
|
2275
|
+
-- credentials. A global probe has no project and may poll anyone;
|
|
2276
|
+
-- anything else must match the device's own project or the row is
|
|
2277
|
+
-- simply never handed out. isGlobalProbe is NOT NULL DEFAULT false,
|
|
2278
|
+
-- so there is no third state here to reason about.
|
|
2279
|
+
AND (pr."isGlobalProbe" = true OR pr."projectId" = nd."projectId")
|
|
2280
|
+
-- Nothing polls a monitor-backed device. NULL is every device
|
|
2281
|
+
-- created before the column existed: those are probe-polled.
|
|
1529
2282
|
AND (nd."monitoringMethod" IS NULL OR nd."monitoringMethod" <> 'Monitor')
|
|
1530
2283
|
AND nd."nextPollAt" <= $2
|
|
1531
2284
|
AND p."deletedAt" IS NULL
|
|
@@ -1643,6 +2396,24 @@ __decorate([
|
|
|
1643
2396
|
__metadata("design:paramtypes", [Object]),
|
|
1644
2397
|
__metadata("design:returntype", Promise)
|
|
1645
2398
|
], Service.prototype, "onBeforeDelete", null);
|
|
2399
|
+
__decorate([
|
|
2400
|
+
CaptureSpan(),
|
|
2401
|
+
__metadata("design:type", Function),
|
|
2402
|
+
__metadata("design:paramtypes", [Object]),
|
|
2403
|
+
__metadata("design:returntype", Promise)
|
|
2404
|
+
], Service.prototype, "assertProbeIsAttachableToProject", null);
|
|
2405
|
+
__decorate([
|
|
2406
|
+
CaptureSpan(),
|
|
2407
|
+
__metadata("design:type", Function),
|
|
2408
|
+
__metadata("design:paramtypes", [Object]),
|
|
2409
|
+
__metadata("design:returntype", Promise)
|
|
2410
|
+
], Service.prototype, "assertSnmpCredentialProfileBelongsToProject", null);
|
|
2411
|
+
__decorate([
|
|
2412
|
+
CaptureSpan(),
|
|
2413
|
+
__metadata("design:type", Function),
|
|
2414
|
+
__metadata("design:paramtypes", [Object]),
|
|
2415
|
+
__metadata("design:returntype", Promise)
|
|
2416
|
+
], Service.prototype, "resolveInheritedSiteProbeId", null);
|
|
1646
2417
|
__decorate([
|
|
1647
2418
|
CaptureSpan(),
|
|
1648
2419
|
__metadata("design:type", Function),
|