@oneuptime/common 12.0.32 → 12.0.34
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/RumSession.ts +117 -1
- package/Models/AnalyticsModels/RumSessionChunk.ts +13 -0
- package/Models/AnalyticsModels/Span.ts +14 -0
- package/Models/DatabaseModels/AlertCustomField.ts +77 -3
- package/Models/DatabaseModels/ApiKeyPermission.ts +3 -27
- package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
- package/Models/DatabaseModels/IncidentCustomField.ts +77 -3
- package/Models/DatabaseModels/Index.ts +10 -0
- package/Models/DatabaseModels/InventoryItemCustomField.ts +77 -3
- package/Models/DatabaseModels/Monitor.ts +76 -0
- package/Models/DatabaseModels/MonitorCustomField.ts +77 -3
- package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
- package/Models/DatabaseModels/NetworkDevice.ts +176 -1
- package/Models/DatabaseModels/NetworkSite.ts +201 -2
- package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
- package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
- package/Models/DatabaseModels/OnCallDutyPolicyCustomField.ts +77 -3
- package/Models/DatabaseModels/RumApplication.ts +6 -6
- package/Models/DatabaseModels/ScheduledMaintenanceCustomField.ts +77 -3
- package/Models/DatabaseModels/StatusPageCustomField.ts +77 -3
- package/Models/DatabaseModels/TeamCustomField.ts +77 -3
- package/Models/DatabaseModels/TeamMember.ts +0 -9
- package/Models/DatabaseModels/TeamMemberCustomField.ts +77 -3
- package/Models/DatabaseModels/TeamPermission.ts +3 -24
- package/Models/DatabaseModels/TelemetryException.ts +119 -0
- package/Models/DatabaseModels/TelemetryIngestionKey.ts +260 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
- package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
- package/Models/DatabaseModels/UserTelegram.ts +0 -4
- package/Scripts/benchmark-fanin-capacity.js +181 -0
- package/Server/API/EnterpriseLicenseAPI.ts +391 -64
- package/Server/API/LlmProviderAPI.ts +137 -22
- package/Server/API/TelemetryAPI.ts +1284 -164
- package/Server/API/UserNotificationSettingAPI.ts +55 -0
- package/Server/API/UserTelegramAPI.ts +48 -4
- package/Server/EnvironmentConfig.ts +49 -2
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.ts +91 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.ts +139 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.ts +121 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
- package/Server/Infrastructure/QueueWorker.ts +59 -23
- package/Server/Infrastructure/Semaphore.ts +2 -0
- 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 +464 -7
- package/Server/Services/AIBillingService.ts +101 -27
- package/Server/Services/AccessTokenService.ts +1 -0
- package/Server/Services/AlertCustomFieldService.ts +98 -0
- package/Server/Services/AlertService.ts +37 -0
- package/Server/Services/ApiKeyPermissionService.ts +461 -29
- package/Server/Services/CustomFieldMappingService.ts +879 -0
- package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
- package/Server/Services/EnterpriseLicenseService.ts +55 -0
- package/Server/Services/GlobalConfigService.ts +194 -0
- package/Server/Services/IncidentCustomFieldService.ts +98 -0
- package/Server/Services/IncidentService.ts +35 -0
- package/Server/Services/Index.ts +10 -0
- package/Server/Services/MetricService.ts +194 -0
- package/Server/Services/MonitorService.ts +175 -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 +87 -35
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
- package/Server/Services/NetworkDeviceService.ts +1032 -73
- package/Server/Services/NetworkSiteService.ts +1502 -129
- package/Server/Services/NetworkSiteTypeService.ts +1216 -0
- package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
- package/Server/Services/NotificationService.ts +118 -28
- package/Server/Services/ProjectService.ts +127 -48
- package/Server/Services/RoutineEmailSettingsService.ts +73 -0
- package/Server/Services/RumSessionReplayViewService.ts +104 -24
- package/Server/Services/ScheduledMaintenanceCustomFieldService.ts +98 -0
- package/Server/Services/ScheduledMaintenanceService.ts +32 -0
- package/Server/Services/StatusPagePrivateUserService.ts +103 -3
- package/Server/Services/TeamMemberService.ts +78 -0
- package/Server/Services/TeamPermissionService.ts +235 -3
- package/Server/Services/TelemetryIngestionKeyService.ts +722 -19
- 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 +90 -25
- package/Server/Services/UserService.ts +95 -0
- package/Server/Services/UserTelegramService.ts +326 -5
- package/Server/Types/Database/QueryHelper.ts +4 -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/APIKey/AccessPermission.ts +5 -2
- package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
- package/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.ts +54 -0
- package/Server/Utils/CustomField/CustomFieldMappingRegistry.ts +415 -0
- package/Server/Utils/CustomField/CustomFieldMappingValidator.ts +335 -0
- package/Server/Utils/DataSource/EgressGuard.ts +177 -8
- package/Server/Utils/DataSource/HttpFetch.ts +9 -2
- package/Server/Utils/EmailRollup/EmailRollupConstants.ts +131 -0
- package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +925 -0
- package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
- package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
- package/Server/Utils/FrontendEnvironment.ts +40 -0
- package/Server/Utils/LLM/LLMService.ts +78 -0
- package/Server/Utils/LogRedaction.ts +28 -0
- package/Server/Utils/Logger.ts +90 -1
- package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +338 -77
- package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +30 -4
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
- package/Server/Utils/Monitor/MonitorAlert.ts +29 -6
- package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +159 -15
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
- package/Server/Utils/Monitor/MonitorIncident.ts +22 -6
- package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
- package/Server/Utils/Monitor/MonitorTemplateUtil.ts +72 -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/Monitor/SeriesContextEnricher.ts +304 -0
- 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/SSRFProtection.ts +217 -10
- package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +239 -138
- package/Server/Utils/SessionReplay/SessionReplayHealthCounters.ts +305 -0
- package/Server/Utils/SessionReplay/SessionReplayReadService.ts +1430 -289
- package/Server/Utils/StartServer.ts +53 -36
- package/Server/Utils/TelegramVerificationToken.ts +185 -0
- package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
- package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
- package/Server/Utils/Telemetry/PinServiceName.ts +197 -0
- package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
- package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +38 -16
- package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +92 -0
- package/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.ts +217 -0
- package/Server/Utils/Telemetry.ts +198 -51
- package/Server/Utils/VM/VMAPI.ts +1 -0
- package/Server/Utils/VM/VMRunner.ts +975 -95
- package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
- package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +202 -0
- package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
- package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
- package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +404 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
- package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +486 -9
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
- package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
- package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
- package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
- package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
- package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
- package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
- package/Tests/App/Dashboard/NotificationEmailPreferences.test.tsx +399 -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/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/StatusPageLastUpdated.test.tsx +263 -0
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
- package/Tests/App/StatusPage/StatusPageOverviewLiveAndSearch.test.tsx +753 -0
- package/Tests/App/StatusPage/StatusPageResourceSearchBox.test.tsx +224 -0
- package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +262 -0
- package/Tests/Models/CustomFieldMappingColumns.test.ts +166 -0
- package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +20 -6
- package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
- package/Tests/ResponsiveVisibility.test.ts +115 -0
- package/Tests/ResponsiveVisibility.ts +183 -0
- package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
- package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
- package/Tests/Server/API/SessionReplayAPI.test.ts +1940 -216
- package/Tests/Server/API/UserNotificationSettingAPI.test.ts +186 -0
- package/Tests/Server/API/UserTelegramAPISecurity.test.ts +231 -0
- package/Tests/Server/EnvironmentConfigFrontendSecurity.test.ts +234 -0
- package/Tests/Server/Infrastructure/Postgres/CustomFieldValueMappingMigration.test.ts +202 -0
- package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +41 -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/SessionReplayRecordEverySessionByDefaultMigration.test.ts +169 -0
- package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
- package/Tests/Server/Infrastructure/QueueWorkerTimeout.test.ts +210 -0
- package/Tests/Server/Infrastructure/TelemetryExporterDeploymentConfig.test.ts +130 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -1
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +1163 -0
- package/Tests/Server/Middleware/TelemetryIngestTokenLog.test.ts +5 -3
- package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
- package/Tests/Server/Services/AddTelemetryIngestionKeyTypeMigration.test.ts +555 -0
- package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +678 -0
- package/Tests/Server/Services/ApiKeyPermissionService.test.ts +276 -28
- package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
- package/Tests/Server/Services/CustomFieldDropdownOptionsColumnWidth.test.ts +431 -0
- package/Tests/Server/Services/CustomFieldMappingService.test.ts +850 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +32 -0
- package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
- package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
- package/Tests/Server/Services/GlobalConfigService.test.ts +414 -1
- package/Tests/Server/Services/MetricRawEntityKeyPrune.test.ts +592 -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 +273 -5
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
- package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
- package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
- package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
- package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
- package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
- package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
- package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
- package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
- package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
- package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
- package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
- package/Tests/Server/Services/RoutineEmailSettingsPostgres.test.ts +329 -0
- package/Tests/Server/Services/RumSessionReplayViewService.test.ts +267 -0
- package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +9 -0
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +9 -0
- package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +834 -0
- package/Tests/Server/Services/TelemetryIngestionKeyPolicyResolution.test.ts +814 -0
- package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +998 -0
- package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
- package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
- package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
- package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +997 -0
- package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +110 -1
- package/Tests/Server/Services/UserTelegramVerificationSecurity.test.ts +688 -0
- 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/AI/SRE/Insights/FixRouting.test.ts +497 -0
- package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +383 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +7 -3
- package/Tests/Server/Utils/AnalyticsDatabase/ClusterConfig.test.ts +315 -0
- package/Tests/Server/Utils/Captcha.test.ts +422 -0
- package/Tests/Server/Utils/CustomField/CustomFieldMappingValidator.test.ts +437 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +300 -11
- 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/EmailRollupBurstWindow.test.ts +83 -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/EmailRollupFlushRunnerPreferences.test.ts +362 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +828 -0
- package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
- package/Tests/Server/Utils/FrontendEnvironment.test.ts +190 -0
- package/Tests/Server/Utils/LogRedaction.test.ts +26 -0
- package/Tests/Server/Utils/LoggerCredentialLeak.test.ts +23 -9
- package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
- package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +584 -0
- package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestHeaderCriteria.test.ts +236 -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/MonitorCriteriaEvaluator.test.ts +437 -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/MonitorTemplateUtilSeriesContext.test.ts +176 -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/Monitor/SeriesContextEnricher.test.ts +356 -0
- 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/SSRFProtectionCloudServiceAddresses.test.ts +595 -0
- package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +198 -1
- package/Tests/Server/Utils/SessionReplay/SessionReplayHealthCounters.test.ts +453 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1378 -0
- package/Tests/Server/Utils/SessionReplayOriginAllowListRefactor.test.ts +420 -0
- package/Tests/Server/Utils/TelegramVerificationToken.test.ts +253 -0
- package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
- package/Tests/Server/Utils/Telemetry/PinServiceName.test.ts +666 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriterCapacity.test.ts +458 -0
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +424 -0
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.test.ts +528 -0
- package/Tests/Server/Utils/Telemetry.test.ts +456 -66
- package/Tests/Server/Utils/TelemetryExporterEnvironment.test.ts +56 -0
- package/Tests/Server/Utils/VM/VMRunnerHostBridgeLatency.test.ts +74 -0
- package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +100 -7
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +1176 -6
- package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +220 -0
- package/Tests/Types/CustomField/CustomFieldValueMapping.test.ts +348 -0
- package/Tests/Types/JSONFunctions.test.ts +260 -0
- package/Tests/Types/Monitor/CephAlertTemplates.test.ts +422 -53
- package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
- package/Tests/Types/Monitor/DockerAlertTemplates.test.ts +495 -15
- package/Tests/Types/Monitor/DockerSwarmAlertTemplates.test.ts +191 -45
- package/Tests/Types/Monitor/HostAlertTemplates.test.ts +370 -42
- package/Tests/Types/Monitor/IotAlertTemplates.test.ts +375 -20
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +636 -42
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +189 -0
- package/Tests/Types/Monitor/KubernetesTemplateGroupByKeys.test.ts +95 -14
- 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/Monitor/PodmanAlertTemplates.test.ts +190 -21
- package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +352 -22
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationAlertDebuggability.test.ts +363 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +93 -18
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +259 -0
- package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +476 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +136 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesDebugHints.test.ts +661 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +507 -0
- package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +270 -0
- package/Tests/Types/Monitor/TemplateGroupByKeys.test.ts +38 -10
- package/Tests/Types/Monitor/Utils/RecommendationCriteriaAssertions.ts +102 -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/NotificationSetting/RoutineEmailEvents.test.ts +47 -0
- package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +608 -0
- package/Tests/Types/Rum/SessionReplayCustomEvents.test.ts +434 -0
- package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
- package/Tests/Types/WebsiteRequest.test.ts +285 -3
- package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
- package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +16 -3
- package/Tests/UI/Components/Charts/ChartTrailingBucketGap.test.ts +691 -0
- package/Tests/UI/Components/ComponentsModal.test.tsx +12 -4
- package/Tests/UI/Components/ComponentsModalUsability.test.tsx +518 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetailMapping.test.tsx +324 -0
- package/Tests/UI/Components/CustomFields/MapFromCustomFieldInput.test.tsx +176 -0
- package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +484 -0
- package/Tests/UI/Components/HeaderRightRail.test.tsx +157 -0
- package/Tests/UI/Components/IconDropdownItem.test.tsx +102 -0
- package/Tests/UI/Components/JSONTablePrototypePollution.test.tsx +117 -0
- package/Tests/UI/Components/KeyboardShortcutsModal.test.tsx +214 -0
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +561 -0
- package/Tests/UI/Components/MonitorGraphs/UptimeBarDayModal.test.tsx +302 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +43 -12
- package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
- package/Tests/UI/Components/ShortcutDialogGuard.test.tsx +74 -0
- package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
- package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
- package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSectionAutoExpand.test.tsx +248 -0
- package/Tests/UI/Components/TableCellWrapping.test.tsx +625 -0
- package/Tests/UI/Components/TableLoadingStates.test.tsx +205 -0
- package/Tests/UI/Components/Workflow/NodePlacement.test.ts +148 -0
- package/Tests/UI/Components/Workflow/Workflow.test.tsx +981 -0
- package/Tests/UI/ConfigBrowserTelemetry.test.ts +70 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +1036 -2
- package/Tests/UI/Rum/FidelityNotices.test.ts +187 -0
- package/Tests/UI/Rum/InactivityMap.test.ts +341 -0
- package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +259 -0
- package/Tests/UI/Rum/RecordingHealthCard.test.tsx +855 -0
- package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +594 -0
- package/Tests/UI/Rum/ReplayCard.test.tsx +451 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +536 -0
- package/Tests/UI/Rum/ReplayEngine.test.ts +2503 -0
- package/Tests/UI/Rum/ReplayEngineTypes.test.ts +171 -0
- package/Tests/UI/Rum/ReplayHeader.test.tsx +711 -0
- package/Tests/UI/Rum/ReplayLink.test.tsx +119 -0
- package/Tests/UI/Rum/ReplayPinControl.test.tsx +408 -0
- package/Tests/UI/Rum/ReplayPlaybackIntent.test.ts +152 -0
- package/Tests/UI/Rum/ReplayRail.test.tsx +1296 -0
- package/Tests/UI/Rum/ReplayRailDetail.test.tsx +900 -0
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +763 -147
- package/Tests/UI/Rum/ReplaySignalTypes.test.ts +189 -0
- package/Tests/UI/Rum/ReplaySignals.test.ts +1579 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +396 -473
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +918 -0
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +696 -0
- package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +499 -0
- package/Tests/UI/Rum/SessionReplaySearchBar.test.tsx +346 -0
- package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +545 -0
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +991 -0
- package/Tests/UI/Rum/TargetedCapturePanel.test.tsx +254 -0
- package/Tests/UI/Telemetry/BrowserExporterIsolation.test.ts +71 -0
- package/Tests/UI/Utils/GlobalKeyboardShortcut.test.ts +344 -0
- package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
- package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
- package/Tests/Utils/API.test.ts +308 -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/HTTPResponseBodyReader.test.ts +323 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
- package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
- package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
- package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
- package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
- package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
- package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
- package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
- package/Tests/Utils/NetworkDiscovery/DiscoveryScanStatus.test.ts +117 -0
- 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/Rum/ChunkMath.test.ts +83 -0
- package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +993 -0
- package/Tests/Utils/Rum/SessionReplayStringMap.test.ts +245 -0
- package/Tests/Utils/StatusPage/ResourceSearch.test.ts +631 -0
- package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
- package/Tests/Utils/Telemetry/OriginAllowList.test.ts +633 -0
- package/Tests/Utils/Uptime/DayUptimeGraphUtil.test.ts +461 -0
- package/Tests/Utils/ValueFormatter.test.ts +148 -0
- package/Types/AI/ExceptionAIClassification.ts +10 -24
- package/Types/CustomField/CustomFieldMappingCatalog.ts +161 -0
- package/Types/CustomField/CustomFieldMappingSourceResource.ts +19 -0
- package/Types/CustomField/CustomFieldValueMapping.ts +288 -0
- 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/Icon/IconProp.ts +1 -0
- package/Types/JSONFunctions.ts +189 -43
- package/Types/Monitor/CephAlertTemplates.ts +157 -195
- 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/DockerAlertTemplates.ts +338 -128
- package/Types/Monitor/DockerSwarmAlertTemplates.ts +95 -112
- package/Types/Monitor/HostAlertTemplates.ts +302 -130
- package/Types/Monitor/IotAlertTemplates.ts +112 -104
- package/Types/Monitor/KubernetesAlertTemplates.ts +415 -224
- package/Types/Monitor/KubernetesMetricCatalog.ts +23 -19
- 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/PodmanAlertTemplates.ts +116 -163
- package/Types/Monitor/ProxmoxAlertTemplates.ts +217 -99
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +98 -6
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +44 -7
- package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +383 -0
- package/Types/Monitor/RumAlertTemplates.ts +46 -7
- package/Types/Monitor/SeriesContext/SeriesDebugHints.ts +596 -0
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +554 -0
- package/Types/Monitor/ServiceAlertTemplates.ts +98 -11
- package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
- package/Types/Monitor/SqlConnectionConfig.ts +31 -0
- package/Types/Monitor/UptimeHistoryLabels.ts +56 -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/NotificationSetting/RoutineEmailEvents.ts +30 -0
- package/Types/Permission.ts +90 -0
- package/Types/Probe/ProbeMonitorResponse.ts +16 -0
- package/Types/Rum/SessionReplay.ts +209 -0
- package/Types/Rum/SessionReplayApi.ts +722 -0
- package/Types/Rum/SessionReplayCaptureTrigger.ts +21 -12
- package/Types/Rum/SessionReplayConsentMode.ts +11 -7
- package/Types/Rum/SessionReplayCustomEvents.ts +549 -0
- package/Types/Rum/SessionReplayHealth.ts +238 -0
- package/Types/Telemetry/ErrorClass.ts +274 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +95 -0
- package/Types/Telemetry/TelemetryIngestionKeyPolicy.ts +75 -0
- package/Types/Telemetry/TelemetryIngestionKeyType.ts +29 -0
- package/Types/Telemetry/UnitOfWork.ts +59 -0
- package/Types/WebsiteRequest.ts +85 -3
- package/UI/Components/Charts/Area/AreaChart.tsx +13 -2
- package/UI/Components/Charts/Bar/BarChart.tsx +6 -2
- package/UI/Components/Charts/Line/LineChart.tsx +13 -2
- package/UI/Components/Charts/Types/XAxis/XAxis.ts +29 -0
- package/UI/Components/Charts/Utils/DataPoint.ts +22 -3
- package/UI/Components/Charts/Utils/TimeAnnotation.ts +76 -9
- package/UI/Components/Charts/Utils/XAxis.ts +217 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +143 -25
- package/UI/Components/CustomFields/MapFromCustomFieldInput.tsx +216 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
- package/UI/Components/Graphs/DayUptimeGraph.tsx +173 -8
- package/UI/Components/Graphs/UptimeBarTooltip.tsx +22 -278
- package/UI/Components/Graphs/UptimeDaySummary.tsx +327 -0
- package/UI/Components/Header/Header.tsx +25 -9
- package/UI/Components/Header/IconDropdown/IconDropdownItem.tsx +10 -1
- package/UI/Components/Header/IconDropdown/IconDropdownMenu.tsx +6 -1
- package/UI/Components/Header/ProjectPicker/ProjectPicker.tsx +6 -1
- package/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.tsx +6 -1
- package/UI/Components/Icon/Icon.tsx +11 -0
- package/UI/Components/JSONTable/JSONTable.tsx +2 -2
- package/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.tsx +125 -0
- package/UI/Components/KeyboardShortcut/Screenshots/README.md +19 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-command-palette.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog-dark.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-dialog.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-help-menu.png +0 -0
- package/UI/Components/KeyboardShortcut/Screenshots/keyboard-shortcuts-narrow.png +0 -0
- package/UI/Components/Modal/Modal.tsx +2 -8
- package/UI/Components/ModelTable/Column.ts +15 -0
- package/UI/Components/Monitor/SeriesDebugCommandsViewer.tsx +64 -0
- package/UI/Components/Monitor/SeriesLabelsViewer.tsx +93 -0
- package/UI/Components/MonitorGraphs/Uptime.tsx +14 -2
- package/UI/Components/MonitorGraphs/UptimeBarDayModal.tsx +63 -10
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +88 -0
- package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
- package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
- package/UI/Components/SideMenu/SideMenu.tsx +123 -5
- package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
- package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
- package/UI/Components/SideOver/SideOver.tsx +21 -20
- package/UI/Components/StatusPage/ResourceGroupSection.tsx +40 -0
- package/UI/Components/Table/CellClassName.ts +81 -0
- package/UI/Components/Table/TableRow.tsx +20 -14
- package/UI/Components/Table/TableSkeletonRows.tsx +9 -9
- package/UI/Components/Table/Types/Column.ts +36 -0
- package/UI/Components/Tooltip/Tooltip.tsx +11 -1
- package/UI/Components/Workflow/ComponentsModal.tsx +60 -39
- package/UI/Components/Workflow/NodePlacement.ts +57 -0
- package/UI/Components/Workflow/Workflow.tsx +47 -18
- package/UI/Config.ts +15 -33
- package/UI/Utils/GlobalKeyboardShortcut.ts +208 -0
- package/UI/Utils/PageScrollLock.ts +79 -3
- package/UI/Utils/PermissionGate.ts +61 -0
- package/UI/Utils/SensitiveUrlToken.ts +112 -0
- package/UI/Utils/Telemetry/BrowserTelemetryConfig.ts +28 -0
- package/UI/Utils/Telemetry/Telemetry.ts +10 -8
- package/UI/Utils/TestLLMProvider.ts +11 -0
- package/Utils/API.ts +129 -3
- package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
- package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
- package/Utils/HTTPResponseBodyReader.ts +221 -0
- package/Utils/Monitor/MonitorMetricType.ts +153 -1
- package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
- package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
- package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
- package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
- package/Utils/NetworkDiscovery/DiscoveryScanStatus.ts +77 -0
- package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
- package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
- package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
- package/Utils/Rum/ChunkMath.ts +106 -0
- package/Utils/Rum/SessionReplayHealth.ts +732 -0
- package/Utils/Rum/SessionReplayStringMap.ts +226 -0
- package/Utils/Schema/ModelSchema.ts +1 -0
- package/Utils/StatusPage/ResourceSearch.ts +290 -0
- package/Utils/Telemetry/OriginAllowList.ts +355 -0
- package/Utils/Uptime/DayUptimeGraphUtil.ts +205 -0
- package/Utils/ValueFormatter.ts +35 -1
- package/build/dist/Models/AnalyticsModels/RumSession.js +102 -19
- package/build/dist/Models/AnalyticsModels/RumSession.js.map +1 -1
- package/build/dist/Models/AnalyticsModels/RumSessionChunk.js +11 -9
- package/build/dist/Models/AnalyticsModels/RumSessionChunk.js.map +1 -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/AlertCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/AlertCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ApiKeyPermission.js +3 -27
- package/build/dist/Models/DatabaseModels/ApiKeyPermission.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/IncidentCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +10 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.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/MonitorCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/MonitorCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
- package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
- package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
- package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
- package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +6 -6
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/StatusPageCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/TeamCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamMember.js +0 -9
- package/build/dist/Models/DatabaseModels/TeamMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js +79 -3
- package/build/dist/Models/DatabaseModels/TeamMemberCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamPermission.js +3 -24
- package/build/dist/Models/DatabaseModels/TeamPermission.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/TelemetryIngestionKey.js +267 -0
- package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.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/Models/DatabaseModels/UserTelegram.js +0 -4
- package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
- 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/API/TelemetryAPI.js +769 -109
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/API/UserNotificationSettingAPI.js +35 -0
- package/build/dist/Server/API/UserNotificationSettingAPI.js.map +1 -0
- package/build/dist/Server/API/UserTelegramAPI.js +28 -6
- package/build/dist/Server/API/UserTelegramAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +41 -2
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js +60 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791300000000-AddTelemetryIngestionKeyType.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js +53 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791400000000-SessionReplayRecordEverySessionByDefault.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js +82 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791500000000-WidenCustomFieldDropdownOptions.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js +46 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791600000000-AddCustomFieldValueMapping.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/QueueWorker.js +52 -12
- package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +1 -0
- package/build/dist/Server/Infrastructure/Semaphore.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 +326 -8
- 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/AccessTokenService.js +1 -0
- package/build/dist/Server/Services/AccessTokenService.js.map +1 -1
- package/build/dist/Server/Services/AlertCustomFieldService.js +93 -0
- package/build/dist/Server/Services/AlertCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +34 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/ApiKeyPermissionService.js +331 -28
- package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
- package/build/dist/Server/Services/CustomFieldMappingService.js +614 -0
- package/build/dist/Server/Services/CustomFieldMappingService.js.map +1 -0
- 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/GlobalConfigService.js +133 -0
- package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +93 -0
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +32 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +10 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +163 -0
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +148 -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 +89 -36
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
- package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
- package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
- package/build/dist/Server/Services/NotificationService.js +80 -17
- package/build/dist/Server/Services/NotificationService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +88 -30
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RoutineEmailSettingsService.js +69 -0
- package/build/dist/Server/Services/RoutineEmailSettingsService.js.map +1 -0
- package/build/dist/Server/Services/RumSessionReplayViewService.js +86 -24
- package/build/dist/Server/Services/RumSessionReplayViewService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js +93 -0
- package/build/dist/Server/Services/ScheduledMaintenanceCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +29 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.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/TeamMemberService.js +62 -2
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TeamPermissionService.js +166 -3
- package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +562 -18
- package/build/dist/Server/Services/TelemetryIngestionKeyService.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 +66 -20
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +90 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/UserTelegramService.js +257 -4
- package/build/dist/Server/Services/UserTelegramService.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/APIKey/AccessPermission.js +2 -2
- package/build/dist/Server/Utils/APIKey/AccessPermission.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/CustomField/CustomFieldDefinitionMappingHooks.js +27 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldDefinitionMappingHooks.js.map +1 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js +226 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingRegistry.js.map +1 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js +189 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldMappingValidator.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +121 -7
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- 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 +124 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
- package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +733 -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/FrontendEnvironment.js +33 -0
- package/build/dist/Server/Utils/FrontendEnvironment.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 +28 -0
- package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
- package/build/dist/Server/Utils/Logger.js +73 -1
- package/build/dist/Server/Utils/Logger.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +287 -68
- package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.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/IncomingRequestCriteria.js +20 -4
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.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/MonitorAlert.js +29 -6
- package/build/dist/Server/Utils/Monitor/MonitorAlert.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 +125 -13
- 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/MonitorIncident.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorIncident.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 +54 -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/Monitor/SeriesContextEnricher.js +237 -0
- package/build/dist/Server/Utils/Monitor/SeriesContextEnricher.js.map +1 -0
- 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/SSRFProtection.js +136 -9
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +174 -89
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js +223 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayHealthCounters.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +945 -164
- package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +41 -28
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/TelegramVerificationToken.js +129 -0
- package/build/dist/Server/Utils/TelegramVerificationToken.js.map +1 -0
- 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/PinServiceName.js +163 -0
- package/build/dist/Server/Utils/Telemetry/PinServiceName.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/TelemetryFanInWriter.js +28 -15
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +64 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js +171 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyRateLimiter.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry.js +162 -46
- package/build/dist/Server/Utils/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +780 -69
- package/build/dist/Server/Utils/VM/VMRunner.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/CustomField/CustomFieldMappingCatalog.js +60 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js +20 -0
- package/build/dist/Types/CustomField/CustomFieldMappingSourceResource.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldValueMapping.js +141 -0
- package/build/dist/Types/CustomField/CustomFieldValueMapping.js.map +1 -0
- 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/Icon/IconProp.js +1 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +118 -37
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Monitor/CephAlertTemplates.js +130 -171
- package/build/dist/Types/Monitor/CephAlertTemplates.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/DockerAlertTemplates.js +286 -121
- package/build/dist/Types/Monitor/DockerAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js +84 -105
- package/build/dist/Types/Monitor/DockerSwarmAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/HostAlertTemplates.js +250 -122
- package/build/dist/Types/Monitor/HostAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/IotAlertTemplates.js +81 -81
- package/build/dist/Types/Monitor/IotAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +375 -215
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +19 -19
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
- 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/PodmanAlertTemplates.js +104 -153
- package/build/dist/Types/Monitor/PodmanAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +156 -91
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +67 -6
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +38 -7
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +261 -0
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -0
- package/build/dist/Types/Monitor/RumAlertTemplates.js +46 -7
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js +422 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesDebugHints.js.map +1 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +441 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -0
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js +79 -15
- package/build/dist/Types/Monitor/ServiceAlertTemplates.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/Monitor/UptimeHistoryLabels.js +17 -0
- package/build/dist/Types/Monitor/UptimeHistoryLabels.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/NotificationSetting/RoutineEmailEvents.js +29 -0
- package/build/dist/Types/NotificationSetting/RoutineEmailEvents.js.map +1 -0
- package/build/dist/Types/Permission.js +80 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplay.js +117 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayApi.js +181 -0
- package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js +21 -12
- package/build/dist/Types/Rum/SessionReplayCaptureTrigger.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayConsentMode.js +11 -7
- package/build/dist/Types/Rum/SessionReplayConsentMode.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayCustomEvents.js +172 -0
- package/build/dist/Types/Rum/SessionReplayCustomEvents.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplayHealth.js +37 -0
- package/build/dist/Types/Rum/SessionReplayHealth.js.map +1 -0
- package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
- package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +85 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js +15 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyPolicy.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.js +30 -0
- package/build/dist/Types/Telemetry/TelemetryIngestionKeyType.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/Types/WebsiteRequest.js +55 -3
- package/build/dist/Types/WebsiteRequest.js.map +1 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +13 -2
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +6 -2
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +13 -2
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Types/XAxis/XAxis.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -3
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +40 -9
- package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/XAxis.js +186 -0
- package/build/dist/UI/Components/Charts/Utils/XAxis.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/CustomFields/CustomFieldsDetail.js +80 -6
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js +118 -0
- package/build/dist/UI/Components/CustomFields/MapFromCustomFieldInput.js.map +1 -0
- 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/Graphs/DayUptimeGraph.js +112 -7
- package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js +5 -162
- package/build/dist/UI/Components/Graphs/UptimeBarTooltip.js.map +1 -1
- package/build/dist/UI/Components/Graphs/UptimeDaySummary.js +181 -0
- package/build/dist/UI/Components/Graphs/UptimeDaySummary.js.map +1 -0
- package/build/dist/UI/Components/Header/Header.js +2 -3
- package/build/dist/UI/Components/Header/Header.js.map +1 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js +2 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownItem.js.map +1 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js +7 -1
- package/build/dist/UI/Components/Header/IconDropdown/IconDropdownMenu.js.map +1 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js +7 -1
- package/build/dist/UI/Components/Header/ProjectPicker/ProjectPicker.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js +7 -1
- package/build/dist/UI/Components/HeaderAlert/NotificationBell/NotificationBellDropdown.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +5 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/JSONTable/JSONTable.js +2 -2
- package/build/dist/UI/Components/JSONTable/JSONTable.js.map +1 -1
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js +35 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcutsModal.js.map +1 -0
- 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/Monitor/SeriesDebugCommandsViewer.js +34 -0
- package/build/dist/UI/Components/Monitor/SeriesDebugCommandsViewer.js.map +1 -0
- package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js +49 -0
- package/build/dist/UI/Components/Monitor/SeriesLabelsViewer.js.map +1 -0
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js +1 -1
- package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js +32 -6
- package/build/dist/UI/Components/MonitorGraphs/UptimeBarDayModal.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +77 -0
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
- package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
- package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
- package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
- package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +22 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -1
- package/build/dist/UI/Components/Table/CellClassName.js +55 -0
- package/build/dist/UI/Components/Table/CellClassName.js.map +1 -0
- package/build/dist/UI/Components/Table/TableRow.js +16 -13
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/Table/TableSkeletonRows.js +9 -8
- package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +25 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +47 -30
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/NodePlacement.js +37 -0
- package/build/dist/UI/Components/Workflow/NodePlacement.js.map +1 -0
- package/build/dist/UI/Components/Workflow/Workflow.js +35 -18
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Config.js +10 -20
- package/build/dist/UI/Config.js.map +1 -1
- package/build/dist/UI/Utils/GlobalKeyboardShortcut.js +138 -0
- package/build/dist/UI/Utils/GlobalKeyboardShortcut.js.map +1 -0
- 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/Telemetry/BrowserTelemetryConfig.js +14 -0
- package/build/dist/UI/Utils/Telemetry/BrowserTelemetryConfig.js.map +1 -0
- package/build/dist/UI/Utils/Telemetry/Telemetry.js +7 -5
- package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
- package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
- package/build/dist/Utils/API.js +67 -5
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
- package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
- package/build/dist/Utils/HTTPResponseBodyReader.js +157 -0
- package/build/dist/Utils/HTTPResponseBodyReader.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
- package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
- package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
- package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js +69 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryScanStatus.js.map +1 -0
- 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/Rum/ChunkMath.js +76 -0
- package/build/dist/Utils/Rum/ChunkMath.js.map +1 -1
- package/build/dist/Utils/Rum/SessionReplayHealth.js +534 -0
- package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -0
- package/build/dist/Utils/Rum/SessionReplayStringMap.js +165 -0
- package/build/dist/Utils/Rum/SessionReplayStringMap.js.map +1 -0
- package/build/dist/Utils/Schema/ModelSchema.js +1 -0
- package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
- package/build/dist/Utils/StatusPage/ResourceSearch.js +200 -0
- package/build/dist/Utils/StatusPage/ResourceSearch.js.map +1 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js +299 -0
- package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -0
- package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js +147 -0
- package/build/dist/Utils/Uptime/DayUptimeGraphUtil.js.map +1 -0
- package/build/dist/Utils/ValueFormatter.js +32 -1
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +2 -2
|
@@ -6,6 +6,9 @@ import MonitorService from "./MonitorService";
|
|
|
6
6
|
import MonitorStatusService from "./MonitorStatusService";
|
|
7
7
|
import NetworkDeviceService from "./NetworkDeviceService";
|
|
8
8
|
import NetworkSiteStatusTimelineService from "./NetworkSiteStatusTimelineService";
|
|
9
|
+
import NetworkSiteTypeService from "./NetworkSiteTypeService";
|
|
10
|
+
import NetworkSnmpCredentialProfileService from "./NetworkSnmpCredentialProfileService";
|
|
11
|
+
import ProbeService from "./ProbeService";
|
|
9
12
|
import Model from "../../Models/DatabaseModels/NetworkSite";
|
|
10
13
|
import Alert from "../../Models/DatabaseModels/Alert";
|
|
11
14
|
import AlertSeverity from "../../Models/DatabaseModels/AlertSeverity";
|
|
@@ -14,17 +17,23 @@ import Monitor from "../../Models/DatabaseModels/Monitor";
|
|
|
14
17
|
import MonitorStatus from "../../Models/DatabaseModels/MonitorStatus";
|
|
15
18
|
import NetworkDevice from "../../Models/DatabaseModels/NetworkDevice";
|
|
16
19
|
import NetworkSiteStatusTimeline from "../../Models/DatabaseModels/NetworkSiteStatusTimeline";
|
|
20
|
+
import NetworkSiteType from "../../Models/DatabaseModels/NetworkSiteType";
|
|
21
|
+
import NetworkSnmpCredentialProfile from "../../Models/DatabaseModels/NetworkSnmpCredentialProfile";
|
|
17
22
|
import { DisableAutomaticAlertCreation } from "../EnvironmentConfig";
|
|
18
23
|
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
19
24
|
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
20
25
|
import CreateBy from "../Types/Database/CreateBy";
|
|
21
26
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
27
|
+
import DeleteOneBy from "../Types/Database/DeleteOneBy";
|
|
22
28
|
import UpdateBy from "../Types/Database/UpdateBy";
|
|
29
|
+
import UpdateOneBy from "../Types/Database/UpdateOneBy";
|
|
23
30
|
import Query from "../Types/Database/Query";
|
|
24
31
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
25
32
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
26
33
|
import NetworkDeviceHydrationUtil from "../Utils/Monitor/NetworkDeviceHydrationUtil";
|
|
27
34
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
35
|
+
import PartialEntity from "../../Types/Database/PartialEntity";
|
|
36
|
+
import { NetworkDeviceMonitoringMethodUtil } from "../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
|
|
28
37
|
import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
29
38
|
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
30
39
|
import { FindWhereProperty } from "../../Types/BaseDatabase/Query";
|
|
@@ -32,6 +41,7 @@ import BadDataException from "../../Types/Exception/BadDataException";
|
|
|
32
41
|
import MonitorType from "../../Types/Monitor/MonitorType";
|
|
33
42
|
import ObjectID from "../../Types/ObjectID";
|
|
34
43
|
import OneUptimeDate from "../../Types/Date";
|
|
44
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
35
45
|
import Text from "../../Types/Text";
|
|
36
46
|
import { Raw } from "typeorm";
|
|
37
47
|
import RelationIdUtil from "../Utils/Database/RelationIdUtil";
|
|
@@ -42,6 +52,7 @@ import SiteStatusRollupUtil, {
|
|
|
42
52
|
} from "../../Utils/NetworkSite/SiteStatusRollupUtil";
|
|
43
53
|
import { parseSiteHealthRollupPolicy } from "../../Types/NetworkSite/SiteHealthRollupPolicy";
|
|
44
54
|
import NetworkSiteMaintenanceSuppression from "../Utils/NetworkSite/NetworkSiteMaintenanceSuppression";
|
|
55
|
+
import NetworkSiteHierarchyLock from "../Utils/NetworkSite/NetworkSiteHierarchyLock";
|
|
45
56
|
import { AggregateRow } from "../Types/Database/AggregateBy";
|
|
46
57
|
import AggregateResultUtil from "../Types/Database/AggregateResultUtil";
|
|
47
58
|
import {
|
|
@@ -67,6 +78,118 @@ export interface SiteStatusCount {
|
|
|
67
78
|
*/
|
|
68
79
|
const PARENT_SITE_KEYS: Array<string> = ["parentSiteId", "parentSite"];
|
|
69
80
|
|
|
81
|
+
/*
|
|
82
|
+
* Like parentSite, the site's type can be written either as its FK or as the
|
|
83
|
+
* serialised relation produced by dashboard forms. Hierarchy validation must
|
|
84
|
+
* inspect both spellings because TypeORM has not resolved the relation when
|
|
85
|
+
* the before hooks run.
|
|
86
|
+
*/
|
|
87
|
+
const NETWORK_SITE_TYPE_KEYS: Array<string> = [
|
|
88
|
+
"networkSiteTypeId",
|
|
89
|
+
"networkSiteType",
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
const PROJECT_KEYS: Array<string> = ["projectId", "project"];
|
|
93
|
+
|
|
94
|
+
/*
|
|
95
|
+
* Both spellings of the site's two monitoring defaults: the probe that polls
|
|
96
|
+
* devices here, and the SNMP credentials they are walked with.
|
|
97
|
+
*
|
|
98
|
+
* Both are references that a device INHERITS - the probe copied onto the
|
|
99
|
+
* device at write (see NetworkDeviceService), the credentials read live at
|
|
100
|
+
* poll time (see NetworkDeviceHydrationUtil.resolveSnmpCredentials). So a
|
|
101
|
+
* cross-project value here is not a cosmetic error on one row: it reaches
|
|
102
|
+
* every device in the subtree. Watching only the FK spelling would leave the
|
|
103
|
+
* dashboard's site form - which posts the relation - unguarded, which is the
|
|
104
|
+
* bug RelationIdUtil exists to document.
|
|
105
|
+
*/
|
|
106
|
+
const PROBE_KEYS: Array<string> = ["probeId", "probe"];
|
|
107
|
+
const SNMP_CREDENTIAL_PROFILE_KEYS: Array<string> = [
|
|
108
|
+
"snmpCredentialProfileId",
|
|
109
|
+
"snmpCredentialProfile",
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
const MATERIALIZED_HIERARCHY_KEYS: Array<string> = [
|
|
113
|
+
"materializedPath",
|
|
114
|
+
"depth",
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
* Type edits have to inspect every direct child. Keep each read bounded and
|
|
119
|
+
* page until exhaustion so a very wide site cannot hide invalid edges beyond
|
|
120
|
+
* DatabaseService's single-query limit.
|
|
121
|
+
*/
|
|
122
|
+
const DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE: number = 1000;
|
|
123
|
+
|
|
124
|
+
/*
|
|
125
|
+
* Rebase large subtrees in bounded pages. Each successful rewrite removes the
|
|
126
|
+
* row from the old path prefix, so every page must start at offset zero.
|
|
127
|
+
*/
|
|
128
|
+
const SUBTREE_REBASE_PAGE_SIZE: number = 1000;
|
|
129
|
+
|
|
130
|
+
/*
|
|
131
|
+
* Model instances initialise optional fields to undefined. Those properties
|
|
132
|
+
* are omissions, not requests to clear a relation; null is the explicit
|
|
133
|
+
* clear value and must still run validation.
|
|
134
|
+
*/
|
|
135
|
+
function isRelationWritten(
|
|
136
|
+
data: Record<string, unknown>,
|
|
137
|
+
keys: Array<string>,
|
|
138
|
+
): boolean {
|
|
139
|
+
return keys.some((key: string) => {
|
|
140
|
+
return key in data && data[key] !== undefined;
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function normalizeId(id: ObjectID | string): string {
|
|
145
|
+
return id.toString().toLowerCase();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function sameId(left: ObjectID | string, right: ObjectID | string): boolean {
|
|
149
|
+
return normalizeId(left) === normalizeId(right);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/*
|
|
153
|
+
* RelationIdUtil intentionally returns null for anything it cannot resolve.
|
|
154
|
+
* In a hierarchy hook, however, an unresolvable NON-null value cannot mean
|
|
155
|
+
* "clear": TypeORM may still interpret a raw expression or relation-shaped
|
|
156
|
+
* object during the eventual write. Require each supplied spelling to be an
|
|
157
|
+
* explicit clear or a concrete ID before checking cross-spelling agreement.
|
|
158
|
+
*/
|
|
159
|
+
function readStrictRelationId(data: {
|
|
160
|
+
payload: Record<string, unknown>;
|
|
161
|
+
keys: Array<string>;
|
|
162
|
+
relationTitle: string;
|
|
163
|
+
}): ObjectID | null {
|
|
164
|
+
for (const key of data.keys) {
|
|
165
|
+
const value: unknown = data.payload[key];
|
|
166
|
+
|
|
167
|
+
if (typeof value === "function") {
|
|
168
|
+
throw new BadDataException(
|
|
169
|
+
`${key} cannot be set to a raw SQL expression because the network site hierarchy must be validated against an actual ID.`,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const isExplicitClear: boolean = value === null || value === "";
|
|
174
|
+
|
|
175
|
+
if (
|
|
176
|
+
value !== undefined &&
|
|
177
|
+
!isExplicitClear &&
|
|
178
|
+
!RelationIdUtil.read(data.payload, [key])
|
|
179
|
+
) {
|
|
180
|
+
throw new BadDataException(
|
|
181
|
+
`${key} must contain a valid ${data.relationTitle} ID.`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return RelationIdUtil.readConsistent(
|
|
187
|
+
data.payload,
|
|
188
|
+
data.keys,
|
|
189
|
+
data.relationTitle,
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
70
193
|
/*
|
|
71
194
|
* Carried from onBeforeUpdate to onUpdateSuccess when an update touches
|
|
72
195
|
* parentSiteId, so the subtree rebase knows each site's previous state.
|
|
@@ -78,9 +201,10 @@ interface ParentChangeCarryForward {
|
|
|
78
201
|
}
|
|
79
202
|
|
|
80
203
|
/*
|
|
81
|
-
* Carried from onBeforeDelete to onDeleteSuccess
|
|
82
|
-
*
|
|
83
|
-
*
|
|
204
|
+
* Carried from onBeforeDelete to onDeleteSuccess. The normal path rejects a
|
|
205
|
+
* delete with surviving children, but retaining the pre-delete hierarchy
|
|
206
|
+
* state lets the success hook repair rows created under older SET NULL
|
|
207
|
+
* schemas or by an in-flight legacy write.
|
|
84
208
|
*/
|
|
85
209
|
interface DeleteCarryForward {
|
|
86
210
|
sitesToDelete: Array<Model>;
|
|
@@ -91,6 +215,393 @@ export class Service extends DatabaseService<Model> {
|
|
|
91
215
|
super(Model);
|
|
92
216
|
}
|
|
93
217
|
|
|
218
|
+
/*
|
|
219
|
+
* Parent/type validation and the eventual write must observe one serialized
|
|
220
|
+
* project hierarchy. The same distributed lock is used by
|
|
221
|
+
* NetworkSiteTypeService, because changing either table can invalidate the
|
|
222
|
+
* other. It surrounds the whole DatabaseService mutation so success-hook
|
|
223
|
+
* subtree maintenance is protected too and finally always releases it.
|
|
224
|
+
*/
|
|
225
|
+
@CaptureSpan()
|
|
226
|
+
public override async create(createBy: CreateBy<Model>): Promise<Model> {
|
|
227
|
+
if (createBy.props.ignoreHooks) {
|
|
228
|
+
return await super.create(createBy);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const rawData: Record<string, unknown> = createBy.data as unknown as Record<
|
|
232
|
+
string,
|
|
233
|
+
unknown
|
|
234
|
+
>;
|
|
235
|
+
const projectId: ObjectID | null =
|
|
236
|
+
createBy.props.tenantId ||
|
|
237
|
+
RelationIdUtil.readConsistent(
|
|
238
|
+
rawData,
|
|
239
|
+
["projectId", "project"],
|
|
240
|
+
"Project",
|
|
241
|
+
) ||
|
|
242
|
+
null;
|
|
243
|
+
|
|
244
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
245
|
+
projectIds: projectId ? [projectId] : [],
|
|
246
|
+
operation: async (): Promise<Model> => {
|
|
247
|
+
return await super.create(createBy);
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
@CaptureSpan()
|
|
253
|
+
public override async updateOneBy(
|
|
254
|
+
updateOneBy: UpdateOneBy<Model>,
|
|
255
|
+
): Promise<number> {
|
|
256
|
+
if (
|
|
257
|
+
updateOneBy.props.ignoreHooks ||
|
|
258
|
+
!this.updateTouchesHierarchy(updateOneBy.data)
|
|
259
|
+
) {
|
|
260
|
+
return await super.updateOneBy(updateOneBy);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const projectIds: Array<ObjectID | string> =
|
|
264
|
+
await this.findMutationProjectIds({
|
|
265
|
+
query: updateOneBy.query,
|
|
266
|
+
props: updateOneBy.props,
|
|
267
|
+
limit: 1,
|
|
268
|
+
skip: 0,
|
|
269
|
+
isDelete: false,
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
273
|
+
projectIds,
|
|
274
|
+
operation: async (): Promise<number> => {
|
|
275
|
+
return await super.updateOneBy(updateOneBy);
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
@CaptureSpan()
|
|
281
|
+
public override async updateBy(updateBy: UpdateBy<Model>): Promise<number> {
|
|
282
|
+
if (
|
|
283
|
+
updateBy.props.ignoreHooks ||
|
|
284
|
+
!this.updateTouchesHierarchy(updateBy.data)
|
|
285
|
+
) {
|
|
286
|
+
return await super.updateBy(updateBy);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const projectIds: Array<ObjectID | string> =
|
|
290
|
+
await this.findMutationProjectIds({
|
|
291
|
+
query: updateBy.query,
|
|
292
|
+
props: updateBy.props,
|
|
293
|
+
limit: this.positiveNumberValue(updateBy.limit, LIMIT_MAX),
|
|
294
|
+
skip: this.positiveNumberValue(updateBy.skip, 0),
|
|
295
|
+
isDelete: false,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
299
|
+
projectIds,
|
|
300
|
+
operation: async (): Promise<number> => {
|
|
301
|
+
return await super.updateBy(updateBy);
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
@CaptureSpan()
|
|
307
|
+
public override async deleteOneBy(
|
|
308
|
+
deleteOneBy: DeleteOneBy<Model>,
|
|
309
|
+
): Promise<number> {
|
|
310
|
+
if (deleteOneBy.props.ignoreHooks) {
|
|
311
|
+
return await super.deleteOneBy(deleteOneBy);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const projectIds: Array<ObjectID | string> =
|
|
315
|
+
await this.findMutationProjectIds({
|
|
316
|
+
query: deleteOneBy.query,
|
|
317
|
+
props: deleteOneBy.props,
|
|
318
|
+
limit: 1,
|
|
319
|
+
skip: 0,
|
|
320
|
+
isDelete: true,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
324
|
+
projectIds,
|
|
325
|
+
operation: async (): Promise<number> => {
|
|
326
|
+
return await super.deleteOneBy(deleteOneBy);
|
|
327
|
+
},
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
@CaptureSpan()
|
|
332
|
+
public override async deleteBy(deleteBy: DeleteBy<Model>): Promise<number> {
|
|
333
|
+
if (deleteBy.props.ignoreHooks) {
|
|
334
|
+
return await super.deleteBy(deleteBy);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const projectIds: Array<ObjectID | string> =
|
|
338
|
+
await this.findMutationProjectIds({
|
|
339
|
+
query: deleteBy.query,
|
|
340
|
+
props: deleteBy.props,
|
|
341
|
+
limit: this.positiveNumberValue(deleteBy.limit, LIMIT_MAX),
|
|
342
|
+
skip: this.positiveNumberValue(deleteBy.skip, 0),
|
|
343
|
+
isDelete: true,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
347
|
+
projectIds,
|
|
348
|
+
operation: async (): Promise<number> => {
|
|
349
|
+
return await super.deleteBy(deleteBy);
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
@CaptureSpan()
|
|
355
|
+
public override async hardDeleteBy(
|
|
356
|
+
deleteBy: DeleteBy<Model>,
|
|
357
|
+
): Promise<number> {
|
|
358
|
+
if (deleteBy.props.ignoreHooks) {
|
|
359
|
+
return await super.hardDeleteBy(deleteBy);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/*
|
|
363
|
+
* The generic retention cron intentionally queries every tenant at once
|
|
364
|
+
* by deletedAt. Resolve that open-ended query to a closed set of leaf IDs
|
|
365
|
+
* before locking and deleting. Deleting leaves only means a limit can
|
|
366
|
+
* never split a parent from a surviving child; the cron's next iteration
|
|
367
|
+
* naturally works upward through the tree.
|
|
368
|
+
*/
|
|
369
|
+
if (
|
|
370
|
+
!NetworkSiteHierarchyLock.isSafeRootMutationScope({
|
|
371
|
+
query: deleteBy.query as unknown as Record<string, unknown>,
|
|
372
|
+
props: deleteBy.props,
|
|
373
|
+
tenantScopeIsClosed: true,
|
|
374
|
+
})
|
|
375
|
+
) {
|
|
376
|
+
return await this.hardDeleteClosedLeafBatch(deleteBy);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const projectIds: Array<ObjectID | string> =
|
|
380
|
+
await this.findMutationProjectIds({
|
|
381
|
+
query: deleteBy.query,
|
|
382
|
+
props: deleteBy.props,
|
|
383
|
+
limit: this.positiveNumberValue(deleteBy.limit, LIMIT_MAX),
|
|
384
|
+
skip: this.positiveNumberValue(deleteBy.skip, 0),
|
|
385
|
+
isDelete: true,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
389
|
+
projectIds,
|
|
390
|
+
operation: async (): Promise<number> => {
|
|
391
|
+
return await super.hardDeleteBy(deleteBy);
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private updateTouchesHierarchy(data: UpdateOneBy<Model>["data"]): boolean {
|
|
397
|
+
const record: Record<string, unknown> = data as unknown as Record<
|
|
398
|
+
string,
|
|
399
|
+
unknown
|
|
400
|
+
>;
|
|
401
|
+
|
|
402
|
+
return (
|
|
403
|
+
isRelationWritten(record, PARENT_SITE_KEYS) ||
|
|
404
|
+
isRelationWritten(record, NETWORK_SITE_TYPE_KEYS) ||
|
|
405
|
+
isRelationWritten(record, PROJECT_KEYS) ||
|
|
406
|
+
isRelationWritten(record, MATERIALIZED_HIERARCHY_KEYS)
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
private positiveNumberValue(
|
|
411
|
+
value: PositiveNumber | number | undefined,
|
|
412
|
+
fallback: number,
|
|
413
|
+
): number {
|
|
414
|
+
if (value instanceof PositiveNumber) {
|
|
415
|
+
return value.toNumber();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
return value ?? fallback;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private async hardDeleteClosedLeafBatch(
|
|
422
|
+
deleteBy: DeleteBy<Model>,
|
|
423
|
+
): Promise<number> {
|
|
424
|
+
const requestedLimit: number = this.positiveNumberValue(
|
|
425
|
+
deleteBy.limit,
|
|
426
|
+
LIMIT_MAX,
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
if (requestedLimit <= 0) {
|
|
430
|
+
return 0;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const scanPageSize: number = Math.min(
|
|
434
|
+
DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
435
|
+
requestedLimit,
|
|
436
|
+
);
|
|
437
|
+
const leafSites: Array<Model> = [];
|
|
438
|
+
let scanSkip: number = this.positiveNumberValue(deleteBy.skip, 0);
|
|
439
|
+
|
|
440
|
+
while (leafSites.length < requestedLimit) {
|
|
441
|
+
const candidates: Array<Model> = await this.findBy({
|
|
442
|
+
query: deleteBy.query,
|
|
443
|
+
select: {
|
|
444
|
+
_id: true,
|
|
445
|
+
projectId: true,
|
|
446
|
+
},
|
|
447
|
+
sort: { _id: SortOrder.Ascending },
|
|
448
|
+
limit: scanPageSize,
|
|
449
|
+
skip: scanSkip,
|
|
450
|
+
props: { isRoot: true },
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
if (candidates.length === 0) {
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const candidateIds: Array<ObjectID> = candidates
|
|
458
|
+
.map((candidate: Model): ObjectID | null => {
|
|
459
|
+
return candidate.id || null;
|
|
460
|
+
})
|
|
461
|
+
.filter((id: ObjectID | null): id is ObjectID => {
|
|
462
|
+
return Boolean(id);
|
|
463
|
+
});
|
|
464
|
+
const parentIdsWithChildren: Set<string> = new Set<string>();
|
|
465
|
+
|
|
466
|
+
for (
|
|
467
|
+
let parentOffset: number = 0;
|
|
468
|
+
parentOffset < candidateIds.length;
|
|
469
|
+
parentOffset += DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE
|
|
470
|
+
) {
|
|
471
|
+
const parentIdBatch: Array<ObjectID> = candidateIds.slice(
|
|
472
|
+
parentOffset,
|
|
473
|
+
parentOffset + DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
474
|
+
);
|
|
475
|
+
let childSkip: number = 0;
|
|
476
|
+
|
|
477
|
+
while (parentIdBatch.length > 0) {
|
|
478
|
+
const children: Array<Model> = await this.findBy({
|
|
479
|
+
query: {
|
|
480
|
+
parentSiteId: QueryHelper.any(parentIdBatch),
|
|
481
|
+
},
|
|
482
|
+
select: { parentSiteId: true },
|
|
483
|
+
sort: { _id: SortOrder.Ascending },
|
|
484
|
+
limit: DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
485
|
+
skip: childSkip,
|
|
486
|
+
props: { isRoot: true },
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
for (const child of children) {
|
|
490
|
+
if (child.parentSiteId) {
|
|
491
|
+
parentIdsWithChildren.add(normalizeId(child.parentSiteId));
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (children.length < DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
496
|
+
break;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
childSkip += children.length;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
for (const candidate of candidates) {
|
|
504
|
+
if (
|
|
505
|
+
candidate.id &&
|
|
506
|
+
candidate.projectId &&
|
|
507
|
+
!parentIdsWithChildren.has(normalizeId(candidate.id))
|
|
508
|
+
) {
|
|
509
|
+
leafSites.push(candidate);
|
|
510
|
+
|
|
511
|
+
if (leafSites.length === requestedLimit) {
|
|
512
|
+
break;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
scanSkip += candidates.length;
|
|
518
|
+
|
|
519
|
+
if (candidates.length < scanPageSize) {
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (leafSites.length === 0) {
|
|
525
|
+
return 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
const leafIds: Array<ObjectID> = leafSites.map((site: Model): ObjectID => {
|
|
529
|
+
return site.id!;
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
return await NetworkSiteHierarchyLock.runExclusive({
|
|
533
|
+
projectIds: leafSites.map((site: Model): ObjectID => {
|
|
534
|
+
return site.projectId!;
|
|
535
|
+
}),
|
|
536
|
+
operation: async (): Promise<number> => {
|
|
537
|
+
return await super.hardDeleteBy({
|
|
538
|
+
...deleteBy,
|
|
539
|
+
query: {
|
|
540
|
+
...deleteBy.query,
|
|
541
|
+
_id: QueryHelper.any(leafIds),
|
|
542
|
+
},
|
|
543
|
+
limit: leafIds.length,
|
|
544
|
+
skip: 0,
|
|
545
|
+
});
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
private async findMutationProjectIds(data: {
|
|
551
|
+
query: Query<Model>;
|
|
552
|
+
props: DatabaseCommonInteractionProps;
|
|
553
|
+
limit: number;
|
|
554
|
+
skip: number;
|
|
555
|
+
isDelete: boolean;
|
|
556
|
+
}): Promise<Array<ObjectID | string>> {
|
|
557
|
+
NetworkSiteHierarchyLock.assertSafeRootMutationScope({
|
|
558
|
+
query: data.query as unknown as Record<string, unknown>,
|
|
559
|
+
props: data.props,
|
|
560
|
+
tenantScopeIsClosed: data.isDelete,
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
const sites: Array<Model> = await this.findBy({
|
|
564
|
+
query: data.isDelete
|
|
565
|
+
? this.scopeDeleteQueryToCallerTenant(data.query, data.props)
|
|
566
|
+
: this.scopeQueryToCallerTenant(data.query, data.props),
|
|
567
|
+
select: { projectId: true },
|
|
568
|
+
limit: data.limit,
|
|
569
|
+
skip: data.skip,
|
|
570
|
+
props: { isRoot: true },
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
const projectIds: Array<ObjectID | string> = sites
|
|
574
|
+
.map((site: Model): ObjectID | undefined => {
|
|
575
|
+
return site.projectId;
|
|
576
|
+
})
|
|
577
|
+
.filter((projectId: ObjectID | undefined): projectId is ObjectID => {
|
|
578
|
+
return Boolean(projectId);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
projectIds.push(
|
|
582
|
+
...NetworkSiteHierarchyLock.getExplicitProjectIds(
|
|
583
|
+
data.query as unknown as Record<string, unknown>,
|
|
584
|
+
),
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
if (projectIds.length === 0 && data.props.tenantId) {
|
|
588
|
+
projectIds.push(data.props.tenantId);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const seenProjectIds: Set<string> = new Set<string>();
|
|
592
|
+
|
|
593
|
+
return projectIds.filter((projectId: ObjectID | string): boolean => {
|
|
594
|
+
const normalizedProjectId: string = normalizeId(projectId);
|
|
595
|
+
|
|
596
|
+
if (seenProjectIds.has(normalizedProjectId)) {
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
seenProjectIds.add(normalizedProjectId);
|
|
601
|
+
return true;
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
|
|
94
605
|
/**
|
|
95
606
|
* How many sites sit under each rolled-up MonitorStatus, counted in the
|
|
96
607
|
* database.
|
|
@@ -155,7 +666,26 @@ export class Service extends DatabaseService<Model> {
|
|
|
155
666
|
query: Query<Model>,
|
|
156
667
|
props: DatabaseCommonInteractionProps,
|
|
157
668
|
): Query<Model> {
|
|
158
|
-
if (props.isRoot || !props.tenantId) {
|
|
669
|
+
if (props.isRoot || props.isMasterAdmin || !props.tenantId) {
|
|
670
|
+
return query;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
return {
|
|
674
|
+
...query,
|
|
675
|
+
projectId: props.tenantId,
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/*
|
|
680
|
+
* Root deletes are also tenant-scoped by DeletePermission when tenantId is
|
|
681
|
+
* present. Mirror that exact rule in the preflight read so limit/skip guard
|
|
682
|
+
* the same rows the eventual delete can select.
|
|
683
|
+
*/
|
|
684
|
+
private scopeDeleteQueryToCallerTenant(
|
|
685
|
+
query: Query<Model>,
|
|
686
|
+
props: DatabaseCommonInteractionProps,
|
|
687
|
+
): Query<Model> {
|
|
688
|
+
if (!props.tenantId || props.isMultiTenantRequest) {
|
|
159
689
|
return query;
|
|
160
690
|
}
|
|
161
691
|
|
|
@@ -214,10 +744,10 @@ export class Service extends DatabaseService<Model> {
|
|
|
214
744
|
/*
|
|
215
745
|
* A stored path is trustworthy only when it agrees with parentSiteId: it
|
|
216
746
|
* must end with the site's own id, and the segment before it must be the
|
|
217
|
-
* parent (nothing before it for a root). A delete that
|
|
218
|
-
* or a half-applied move, leaves the two disagreeing - and a
|
|
219
|
-
* silently corrupts every prefix query built from it, so treat
|
|
220
|
-
* missing and let the caller rebuild.
|
|
747
|
+
* parent (nothing before it for a root). A legacy delete that nullified
|
|
748
|
+
* parentSiteId, or a half-applied move, leaves the two disagreeing - and a
|
|
749
|
+
* stale path silently corrupts every prefix query built from it, so treat
|
|
750
|
+
* it as missing and let the caller rebuild.
|
|
221
751
|
*/
|
|
222
752
|
private isPathConsistent(site: Model): boolean {
|
|
223
753
|
if (!site.id) {
|
|
@@ -245,47 +775,446 @@ export class Service extends DatabaseService<Model> {
|
|
|
245
775
|
return parentSegment === parentId;
|
|
246
776
|
}
|
|
247
777
|
|
|
778
|
+
/*
|
|
779
|
+
* Resolve a site type with tenant information and its configured direct
|
|
780
|
+
* parent type. The lookup deliberately runs as root: hook validation occurs
|
|
781
|
+
* before DatabaseService applies the caller's permission-scoped query, so
|
|
782
|
+
* the service must see the referenced row and perform the project check
|
|
783
|
+
* explicitly rather than confuse "foreign" with "missing".
|
|
784
|
+
*/
|
|
785
|
+
private async getNetworkSiteTypeForHierarchy(
|
|
786
|
+
networkSiteTypeId: ObjectID,
|
|
787
|
+
cache: Map<string, NetworkSiteType>,
|
|
788
|
+
): Promise<NetworkSiteType> {
|
|
789
|
+
const key: string = normalizeId(networkSiteTypeId);
|
|
790
|
+
const cached: NetworkSiteType | undefined = cache.get(key);
|
|
791
|
+
|
|
792
|
+
if (cached) {
|
|
793
|
+
return cached;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
const networkSiteType: NetworkSiteType | null =
|
|
797
|
+
await NetworkSiteTypeService.findOneById({
|
|
798
|
+
id: networkSiteTypeId,
|
|
799
|
+
select: {
|
|
800
|
+
_id: true,
|
|
801
|
+
projectId: true,
|
|
802
|
+
parentNetworkSiteTypeId: true,
|
|
803
|
+
},
|
|
804
|
+
props: {
|
|
805
|
+
isRoot: true,
|
|
806
|
+
},
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
if (!networkSiteType) {
|
|
810
|
+
throw new BadDataException("Network site type not found.");
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
cache.set(key, networkSiteType);
|
|
814
|
+
return networkSiteType;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/*
|
|
818
|
+
* Assert one proposed site edge against the type hierarchy. Untyped legacy
|
|
819
|
+
* root rows remain readable/editable, but as soon as a site has a type its
|
|
820
|
+
* placement is exact: a root type has no parent, and a non-root type has a
|
|
821
|
+
* parent site whose type is precisely the configured direct parent type.
|
|
822
|
+
*/
|
|
823
|
+
private async validateSiteTypeEdge(data: {
|
|
824
|
+
networkSiteTypeId: ObjectID | null;
|
|
825
|
+
parentSite: Model | null;
|
|
826
|
+
projectId: ObjectID | undefined;
|
|
827
|
+
typeCache: Map<string, NetworkSiteType>;
|
|
828
|
+
}): Promise<void> {
|
|
829
|
+
if (!data.networkSiteTypeId) {
|
|
830
|
+
if (data.parentSite) {
|
|
831
|
+
throw new BadDataException(
|
|
832
|
+
"A network site with a parent must have a network site type.",
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
const networkSiteType: NetworkSiteType =
|
|
840
|
+
await this.getNetworkSiteTypeForHierarchy(
|
|
841
|
+
data.networkSiteTypeId,
|
|
842
|
+
data.typeCache,
|
|
843
|
+
);
|
|
844
|
+
|
|
845
|
+
if (
|
|
846
|
+
data.projectId &&
|
|
847
|
+
networkSiteType.projectId &&
|
|
848
|
+
!sameId(networkSiteType.projectId, data.projectId)
|
|
849
|
+
) {
|
|
850
|
+
throw new BadDataException(
|
|
851
|
+
"Network site type must belong to the same project.",
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const requiredParentTypeId: ObjectID | null =
|
|
856
|
+
networkSiteType.parentNetworkSiteTypeId || null;
|
|
857
|
+
|
|
858
|
+
if (!requiredParentTypeId) {
|
|
859
|
+
if (data.parentSite) {
|
|
860
|
+
throw new BadDataException(
|
|
861
|
+
"A site with a root network site type cannot have a parent site.",
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
return;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
if (!data.parentSite) {
|
|
869
|
+
throw new BadDataException(
|
|
870
|
+
"This network site type requires a parent site.",
|
|
871
|
+
);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if (
|
|
875
|
+
!data.parentSite.networkSiteTypeId ||
|
|
876
|
+
!sameId(data.parentSite.networkSiteTypeId, requiredParentTypeId)
|
|
877
|
+
) {
|
|
878
|
+
throw new BadDataException(
|
|
879
|
+
"Parent site must use the configured parent network site type.",
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
/*
|
|
885
|
+
* Changing a site's type also changes what every direct child's type must
|
|
886
|
+
* point at. Validate those reverse edges before the update so one edit
|
|
887
|
+
* cannot strand a previously valid subtree.
|
|
888
|
+
*/
|
|
889
|
+
private async validateDirectChildrenForTypeChange(data: {
|
|
890
|
+
site: Model;
|
|
891
|
+
proposedNetworkSiteTypeId: ObjectID | null;
|
|
892
|
+
typeCache: Map<string, NetworkSiteType>;
|
|
893
|
+
}): Promise<void> {
|
|
894
|
+
if (!data.site.id || !data.site.projectId) {
|
|
895
|
+
return;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
const proposedParent: Model = {
|
|
899
|
+
id: data.site.id,
|
|
900
|
+
projectId: data.site.projectId,
|
|
901
|
+
networkSiteTypeId: data.proposedNetworkSiteTypeId || undefined,
|
|
902
|
+
} as Model;
|
|
903
|
+
|
|
904
|
+
let skip: number = 0;
|
|
905
|
+
|
|
906
|
+
while (true) {
|
|
907
|
+
const children: Array<Model> = await this.findBy({
|
|
908
|
+
query: {
|
|
909
|
+
projectId: data.site.projectId,
|
|
910
|
+
parentSiteId: data.site.id,
|
|
911
|
+
},
|
|
912
|
+
select: {
|
|
913
|
+
_id: true,
|
|
914
|
+
projectId: true,
|
|
915
|
+
networkSiteTypeId: true,
|
|
916
|
+
},
|
|
917
|
+
sort: {
|
|
918
|
+
_id: SortOrder.Ascending,
|
|
919
|
+
},
|
|
920
|
+
limit: DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
921
|
+
skip: skip,
|
|
922
|
+
props: {
|
|
923
|
+
isRoot: true,
|
|
924
|
+
},
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
for (const child of children) {
|
|
928
|
+
await this.validateSiteTypeEdge({
|
|
929
|
+
networkSiteTypeId: child.networkSiteTypeId || null,
|
|
930
|
+
parentSite: proposedParent,
|
|
931
|
+
projectId: child.projectId || data.site.projectId,
|
|
932
|
+
typeCache: data.typeCache,
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
if (children.length < DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
skip += children.length;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
/*
|
|
945
|
+
* The FK behind `probeId` only requires the Probe row to exist. It does
|
|
946
|
+
* NOT require it to belong to this project, and probe ids reach the server
|
|
947
|
+
* from the browser (the site form's dropdown posts one), so without this
|
|
948
|
+
* check an operator could name another project's probe as this site's
|
|
949
|
+
* default - and NetworkDeviceService would then copy it onto every device
|
|
950
|
+
* created into the site, handing that project's probe a target list inside
|
|
951
|
+
* this one.
|
|
952
|
+
*
|
|
953
|
+
* A GLOBAL probe has no project and is attachable anywhere, which is why
|
|
954
|
+
* this delegates to ProbeService rather than comparing projectIds: the
|
|
955
|
+
* same predicate that decides which probes a monitor may use decides which
|
|
956
|
+
* probe a site may default to.
|
|
957
|
+
*/
|
|
958
|
+
private async assertProbeIsAttachableToProject(data: {
|
|
959
|
+
probeId: ObjectID;
|
|
960
|
+
projectId: ObjectID | undefined;
|
|
961
|
+
}): Promise<void> {
|
|
962
|
+
if (!data.projectId) {
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
const isAttachable: boolean = await ProbeService.isProbeAttachableToProject(
|
|
967
|
+
{
|
|
968
|
+
probeId: data.probeId,
|
|
969
|
+
projectId: data.projectId,
|
|
970
|
+
},
|
|
971
|
+
);
|
|
972
|
+
|
|
973
|
+
if (!isAttachable) {
|
|
974
|
+
throw new BadDataException(
|
|
975
|
+
"Probe not found or it does not belong to this project.",
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
/*
|
|
981
|
+
* Same hole as the probe above, and the consequence is worse: a site's
|
|
982
|
+
* credential profile is read LIVE at poll time for every device in the
|
|
983
|
+
* site that has no credentials of its own
|
|
984
|
+
* (NetworkDeviceHydrationUtil.resolveSnmpCredentials), so a cross-project
|
|
985
|
+
* reference here would put another project's community string on this
|
|
986
|
+
* project's probe's wire. The resolver drops such a reference as a
|
|
987
|
+
* backstop; this is the half that stops it being written at all.
|
|
988
|
+
*/
|
|
989
|
+
private async assertSnmpCredentialProfileBelongsToProject(data: {
|
|
990
|
+
snmpCredentialProfileId: ObjectID;
|
|
991
|
+
projectId: ObjectID | undefined;
|
|
992
|
+
}): Promise<void> {
|
|
993
|
+
if (!data.projectId) {
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
const profile: NetworkSnmpCredentialProfile | null =
|
|
998
|
+
await NetworkSnmpCredentialProfileService.findOneById({
|
|
999
|
+
id: data.snmpCredentialProfileId,
|
|
1000
|
+
select: {
|
|
1001
|
+
_id: true,
|
|
1002
|
+
projectId: true,
|
|
1003
|
+
},
|
|
1004
|
+
props: {
|
|
1005
|
+
isRoot: true,
|
|
1006
|
+
},
|
|
1007
|
+
});
|
|
1008
|
+
|
|
1009
|
+
if (!profile) {
|
|
1010
|
+
throw new BadDataException("SNMP Credential Profile not found.");
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
if (profile.projectId && !sameId(profile.projectId, data.projectId)) {
|
|
1014
|
+
throw new BadDataException(
|
|
1015
|
+
"SNMP Credential Profile must belong to the same project.",
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
/*
|
|
1021
|
+
* The site's default probe, inherited: this site's own `probeId`, or the
|
|
1022
|
+
* nearest ancestor that has one.
|
|
1023
|
+
*
|
|
1024
|
+
* Copy-at-write, not read-through — NetworkDeviceService calls this once,
|
|
1025
|
+
* when a device is created into or moved to a site with no probe of its
|
|
1026
|
+
* own, and stamps the answer on the device. That is what makes editing a
|
|
1027
|
+
* site's default a decision about FUTURE devices only: nothing re-reads
|
|
1028
|
+
* this, so no site edit can silently re-point a fleet that is already
|
|
1029
|
+
* polling.
|
|
1030
|
+
*
|
|
1031
|
+
* Nearest ancestor wins, so a Region's probe covers every Market under it
|
|
1032
|
+
* while a Market that names its own overrides it for its own subtree.
|
|
1033
|
+
* `getAncestorIds` returns root-first, hence the reverse walk.
|
|
1034
|
+
*/
|
|
1035
|
+
@CaptureSpan()
|
|
1036
|
+
public async resolveDefaultProbeIdForSite(
|
|
1037
|
+
siteId: ObjectID,
|
|
1038
|
+
): Promise<ObjectID | null> {
|
|
1039
|
+
const site: Model | null = await this.findOneById({
|
|
1040
|
+
id: siteId,
|
|
1041
|
+
select: {
|
|
1042
|
+
_id: true,
|
|
1043
|
+
probeId: true,
|
|
1044
|
+
parentSiteId: true,
|
|
1045
|
+
},
|
|
1046
|
+
props: {
|
|
1047
|
+
isRoot: true,
|
|
1048
|
+
},
|
|
1049
|
+
});
|
|
1050
|
+
|
|
1051
|
+
if (!site) {
|
|
1052
|
+
return null;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
if (site.probeId) {
|
|
1056
|
+
return site.probeId;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/*
|
|
1060
|
+
* A root site has no ancestors, so there is nothing above it to inherit
|
|
1061
|
+
* from. Short-circuited here rather than left to getAncestorIds because
|
|
1062
|
+
* that call is not free: it resolves — and, for a row whose path is
|
|
1063
|
+
* missing or stale, REBUILDS AND PERSISTS — the materialized path. This
|
|
1064
|
+
* runs on the device create path, where most sites are roots and no
|
|
1065
|
+
* device write should be paying for hierarchy maintenance it cannot use.
|
|
1066
|
+
*/
|
|
1067
|
+
if (!site.parentSiteId) {
|
|
1068
|
+
return null;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
const ancestorIds: Array<ObjectID> = await this.getAncestorIds(siteId);
|
|
1072
|
+
|
|
1073
|
+
if (ancestorIds.length === 0) {
|
|
1074
|
+
return null;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
const ancestors: Array<Model> = await this.findBy({
|
|
1078
|
+
query: {
|
|
1079
|
+
_id: QueryHelper.any(
|
|
1080
|
+
ancestorIds.map((ancestorId: ObjectID) => {
|
|
1081
|
+
return ancestorId.toString();
|
|
1082
|
+
}),
|
|
1083
|
+
),
|
|
1084
|
+
},
|
|
1085
|
+
select: {
|
|
1086
|
+
_id: true,
|
|
1087
|
+
probeId: true,
|
|
1088
|
+
},
|
|
1089
|
+
limit: LIMIT_MAX,
|
|
1090
|
+
skip: 0,
|
|
1091
|
+
props: {
|
|
1092
|
+
isRoot: true,
|
|
1093
|
+
},
|
|
1094
|
+
});
|
|
1095
|
+
|
|
1096
|
+
const probeIdBySiteId: Map<string, ObjectID> = new Map();
|
|
1097
|
+
|
|
1098
|
+
for (const ancestor of ancestors) {
|
|
1099
|
+
if (ancestor.id && ancestor.probeId) {
|
|
1100
|
+
probeIdBySiteId.set(ancestor.id.toString(), ancestor.probeId);
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
for (let index: number = ancestorIds.length - 1; index >= 0; index--) {
|
|
1105
|
+
const probeId: ObjectID | undefined = probeIdBySiteId.get(
|
|
1106
|
+
ancestorIds[index]!.toString(),
|
|
1107
|
+
);
|
|
1108
|
+
|
|
1109
|
+
if (probeId) {
|
|
1110
|
+
return probeId;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
return null;
|
|
1115
|
+
}
|
|
1116
|
+
|
|
248
1117
|
@CaptureSpan()
|
|
249
1118
|
protected override async onBeforeCreate(
|
|
250
1119
|
createBy: CreateBy<Model>,
|
|
251
1120
|
): Promise<OnCreate<Model>> {
|
|
252
1121
|
let parentPath: string | null = null;
|
|
1122
|
+
let parentSite: Model | null = null;
|
|
1123
|
+
const rawData: Record<string, unknown> = createBy.data as unknown as Record<
|
|
1124
|
+
string,
|
|
1125
|
+
unknown
|
|
1126
|
+
>;
|
|
1127
|
+
const projectId: ObjectID | undefined =
|
|
1128
|
+
createBy.props.tenantId ||
|
|
1129
|
+
RelationIdUtil.readConsistent(
|
|
1130
|
+
rawData,
|
|
1131
|
+
["projectId", "project"],
|
|
1132
|
+
"Project",
|
|
1133
|
+
) ||
|
|
1134
|
+
undefined;
|
|
253
1135
|
|
|
254
1136
|
/*
|
|
255
1137
|
* Both spellings: the dashboard's site form posts the `parentSite`
|
|
256
1138
|
* relation, not the `parentSiteId` column. See RelationIdUtil.
|
|
257
1139
|
*/
|
|
258
|
-
const parentSiteId: ObjectID | null =
|
|
259
|
-
|
|
260
|
-
PARENT_SITE_KEYS,
|
|
261
|
-
|
|
1140
|
+
const parentSiteId: ObjectID | null = readStrictRelationId({
|
|
1141
|
+
payload: rawData,
|
|
1142
|
+
keys: PARENT_SITE_KEYS,
|
|
1143
|
+
relationTitle: "Parent Site",
|
|
1144
|
+
});
|
|
1145
|
+
const networkSiteTypeId: ObjectID | null = readStrictRelationId({
|
|
1146
|
+
payload: rawData,
|
|
1147
|
+
keys: NETWORK_SITE_TYPE_KEYS,
|
|
1148
|
+
relationTitle: "Network Site Type",
|
|
1149
|
+
});
|
|
262
1150
|
|
|
263
1151
|
if (parentSiteId) {
|
|
264
|
-
|
|
1152
|
+
parentSite = await this.findOneById({
|
|
265
1153
|
id: parentSiteId,
|
|
266
1154
|
select: {
|
|
267
1155
|
_id: true,
|
|
268
1156
|
projectId: true,
|
|
1157
|
+
networkSiteTypeId: true,
|
|
269
1158
|
},
|
|
270
1159
|
props: {
|
|
271
1160
|
isRoot: true,
|
|
272
1161
|
},
|
|
273
1162
|
});
|
|
274
1163
|
|
|
275
|
-
if (!
|
|
1164
|
+
if (!parentSite) {
|
|
276
1165
|
throw new BadDataException("Parent site not found.");
|
|
277
1166
|
}
|
|
278
1167
|
|
|
279
1168
|
if (
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
1169
|
+
projectId &&
|
|
1170
|
+
parentSite.projectId &&
|
|
1171
|
+
!sameId(parentSite.projectId, projectId)
|
|
283
1172
|
) {
|
|
284
1173
|
throw new BadDataException(
|
|
285
1174
|
"Parent site must belong to the same project.",
|
|
286
1175
|
);
|
|
287
1176
|
}
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
await this.validateSiteTypeEdge({
|
|
1180
|
+
networkSiteTypeId: networkSiteTypeId,
|
|
1181
|
+
parentSite: parentSite,
|
|
1182
|
+
projectId: projectId,
|
|
1183
|
+
typeCache: new Map<string, NetworkSiteType>(),
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
/*
|
|
1187
|
+
* The monitoring defaults are tenant-checked on the way in, in both
|
|
1188
|
+
* spellings. See the constants for why a bad value here is not confined
|
|
1189
|
+
* to this row.
|
|
1190
|
+
*/
|
|
1191
|
+
const probeId: ObjectID | null = readStrictRelationId({
|
|
1192
|
+
payload: rawData,
|
|
1193
|
+
keys: PROBE_KEYS,
|
|
1194
|
+
relationTitle: "Probe",
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
if (probeId) {
|
|
1198
|
+
await this.assertProbeIsAttachableToProject({
|
|
1199
|
+
probeId: probeId,
|
|
1200
|
+
projectId: projectId,
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
const snmpCredentialProfileId: ObjectID | null = readStrictRelationId({
|
|
1205
|
+
payload: rawData,
|
|
1206
|
+
keys: SNMP_CREDENTIAL_PROFILE_KEYS,
|
|
1207
|
+
relationTitle: "SNMP Credential Profile",
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
if (snmpCredentialProfileId) {
|
|
1211
|
+
await this.assertSnmpCredentialProfileBelongsToProject({
|
|
1212
|
+
snmpCredentialProfileId: snmpCredentialProfileId,
|
|
1213
|
+
projectId: projectId,
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
288
1216
|
|
|
1217
|
+
if (parentSiteId) {
|
|
289
1218
|
parentPath = await this.getMaterializedPathForSite(parentSiteId);
|
|
290
1219
|
}
|
|
291
1220
|
|
|
@@ -332,16 +1261,86 @@ export class Service extends DatabaseService<Model> {
|
|
|
332
1261
|
protected override async onBeforeUpdate(
|
|
333
1262
|
updateBy: UpdateBy<Model>,
|
|
334
1263
|
): Promise<OnUpdate<Model>> {
|
|
335
|
-
const
|
|
1264
|
+
const rawData: Record<string, unknown> = updateBy.data as unknown as Record<
|
|
1265
|
+
string,
|
|
1266
|
+
unknown
|
|
1267
|
+
>;
|
|
1268
|
+
const touchesParent: boolean = isRelationWritten(rawData, PARENT_SITE_KEYS);
|
|
1269
|
+
const touchesNetworkSiteType: boolean = isRelationWritten(
|
|
1270
|
+
rawData,
|
|
1271
|
+
NETWORK_SITE_TYPE_KEYS,
|
|
1272
|
+
);
|
|
1273
|
+
const touchesProject: boolean = isRelationWritten(rawData, PROJECT_KEYS);
|
|
1274
|
+
const touchesMaterializedHierarchy: boolean = isRelationWritten(
|
|
1275
|
+
rawData,
|
|
1276
|
+
MATERIALIZED_HIERARCHY_KEYS,
|
|
1277
|
+
);
|
|
1278
|
+
/*
|
|
1279
|
+
* These two have to be named in the early return, and that is the whole
|
|
1280
|
+
* reason they are here. Setting a site's default probe or credential
|
|
1281
|
+
* profile touches neither the parent nor the type, so a tenancy guard
|
|
1282
|
+
* placed below the return would be dead code on exactly the write it
|
|
1283
|
+
* exists for — the shape the site settings form actually posts.
|
|
1284
|
+
*/
|
|
1285
|
+
const touchesProbe: boolean = isRelationWritten(rawData, PROBE_KEYS);
|
|
1286
|
+
const touchesSnmpCredentialProfile: boolean = isRelationWritten(
|
|
1287
|
+
rawData,
|
|
1288
|
+
SNMP_CREDENTIAL_PROFILE_KEYS,
|
|
1289
|
+
);
|
|
336
1290
|
|
|
337
|
-
if (
|
|
1291
|
+
if (
|
|
1292
|
+
!touchesParent &&
|
|
1293
|
+
!touchesNetworkSiteType &&
|
|
1294
|
+
!touchesProject &&
|
|
1295
|
+
!touchesMaterializedHierarchy &&
|
|
1296
|
+
!touchesProbe &&
|
|
1297
|
+
!touchesSnmpCredentialProfile
|
|
1298
|
+
) {
|
|
338
1299
|
return { updateBy, carryForward: null };
|
|
339
1300
|
}
|
|
340
1301
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
1302
|
+
if (touchesMaterializedHierarchy) {
|
|
1303
|
+
throw new BadDataException(
|
|
1304
|
+
"materializedPath and depth are managed by the Network Site hierarchy and cannot be updated directly.",
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
const proposedProjectId: ObjectID | null = touchesProject
|
|
1309
|
+
? readStrictRelationId({
|
|
1310
|
+
payload: rawData,
|
|
1311
|
+
keys: PROJECT_KEYS,
|
|
1312
|
+
relationTitle: "Project",
|
|
1313
|
+
})
|
|
1314
|
+
: null;
|
|
1315
|
+
|
|
1316
|
+
if (touchesProject && !proposedProjectId) {
|
|
1317
|
+
throw new BadDataException(
|
|
1318
|
+
"A Network Site cannot be moved to another project.",
|
|
1319
|
+
);
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
const newParentId: ObjectID | null = touchesParent
|
|
1323
|
+
? readStrictRelationId({
|
|
1324
|
+
payload: rawData,
|
|
1325
|
+
keys: PARENT_SITE_KEYS,
|
|
1326
|
+
relationTitle: "Parent Site",
|
|
1327
|
+
})
|
|
1328
|
+
: null;
|
|
1329
|
+
const newNetworkSiteTypeId: ObjectID | null = touchesNetworkSiteType
|
|
1330
|
+
? readStrictRelationId({
|
|
1331
|
+
payload: rawData,
|
|
1332
|
+
keys: NETWORK_SITE_TYPE_KEYS,
|
|
1333
|
+
relationTitle: "Network Site Type",
|
|
1334
|
+
})
|
|
1335
|
+
: null;
|
|
1336
|
+
const updateLimit: number =
|
|
1337
|
+
updateBy.limit instanceof PositiveNumber
|
|
1338
|
+
? updateBy.limit.toNumber()
|
|
1339
|
+
: updateBy.limit || LIMIT_MAX;
|
|
1340
|
+
const updateSkip: number =
|
|
1341
|
+
updateBy.skip instanceof PositiveNumber
|
|
1342
|
+
? updateBy.skip.toNumber()
|
|
1343
|
+
: updateBy.skip || 0;
|
|
345
1344
|
|
|
346
1345
|
const previousItems: Array<Model> = await this.findBy({
|
|
347
1346
|
query: this.scopeQueryToCallerTenant(updateBy.query, updateBy.props),
|
|
@@ -349,15 +1348,30 @@ export class Service extends DatabaseService<Model> {
|
|
|
349
1348
|
_id: true,
|
|
350
1349
|
projectId: true,
|
|
351
1350
|
parentSiteId: true,
|
|
1351
|
+
networkSiteTypeId: true,
|
|
352
1352
|
materializedPath: true,
|
|
353
1353
|
},
|
|
354
|
-
limit:
|
|
355
|
-
skip:
|
|
1354
|
+
limit: updateLimit,
|
|
1355
|
+
skip: updateSkip,
|
|
356
1356
|
props: {
|
|
357
1357
|
isRoot: true,
|
|
358
1358
|
},
|
|
359
1359
|
});
|
|
360
1360
|
|
|
1361
|
+
if (touchesProject) {
|
|
1362
|
+
for (const item of previousItems) {
|
|
1363
|
+
if (
|
|
1364
|
+
!item.projectId ||
|
|
1365
|
+
!proposedProjectId ||
|
|
1366
|
+
!sameId(item.projectId, proposedProjectId)
|
|
1367
|
+
) {
|
|
1368
|
+
throw new BadDataException(
|
|
1369
|
+
"A Network Site cannot be moved to another project.",
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
|
|
361
1375
|
/*
|
|
362
1376
|
* Same-project assertion for EVERY parentSiteId write, including the
|
|
363
1377
|
* detach case (parentSiteId: null) which has no parent to compare
|
|
@@ -368,7 +1382,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
368
1382
|
for (const item of previousItems) {
|
|
369
1383
|
if (
|
|
370
1384
|
item.projectId &&
|
|
371
|
-
item.projectId
|
|
1385
|
+
!sameId(item.projectId, updateBy.props.tenantId)
|
|
372
1386
|
) {
|
|
373
1387
|
throw new BadDataException(
|
|
374
1388
|
"Network site must belong to the same project.",
|
|
@@ -377,33 +1391,93 @@ export class Service extends DatabaseService<Model> {
|
|
|
377
1391
|
}
|
|
378
1392
|
}
|
|
379
1393
|
|
|
1394
|
+
/*
|
|
1395
|
+
* One check per DISTINCT project in the matched set, because a single
|
|
1396
|
+
* updateBy can span more than one project when a root caller issues it,
|
|
1397
|
+
* and the payload names one probe / one profile for all of them. Reading
|
|
1398
|
+
* the ids here (rather than above the previousItems read) keeps a
|
|
1399
|
+
* conflicting-spelling payload refused on every write shape.
|
|
1400
|
+
*/
|
|
1401
|
+
if (touchesProbe || touchesSnmpCredentialProfile) {
|
|
1402
|
+
const newProbeId: ObjectID | null = touchesProbe
|
|
1403
|
+
? readStrictRelationId({
|
|
1404
|
+
payload: rawData,
|
|
1405
|
+
keys: PROBE_KEYS,
|
|
1406
|
+
relationTitle: "Probe",
|
|
1407
|
+
})
|
|
1408
|
+
: null;
|
|
1409
|
+
const newSnmpCredentialProfileId: ObjectID | null =
|
|
1410
|
+
touchesSnmpCredentialProfile
|
|
1411
|
+
? readStrictRelationId({
|
|
1412
|
+
payload: rawData,
|
|
1413
|
+
keys: SNMP_CREDENTIAL_PROFILE_KEYS,
|
|
1414
|
+
relationTitle: "SNMP Credential Profile",
|
|
1415
|
+
})
|
|
1416
|
+
: null;
|
|
1417
|
+
|
|
1418
|
+
// A clear (null) points at nothing and has nothing to check.
|
|
1419
|
+
if (newProbeId || newSnmpCredentialProfileId) {
|
|
1420
|
+
const checkedProjectIds: Set<string> = new Set();
|
|
1421
|
+
|
|
1422
|
+
for (const item of previousItems) {
|
|
1423
|
+
if (
|
|
1424
|
+
!item.projectId ||
|
|
1425
|
+
checkedProjectIds.has(normalizeId(item.projectId))
|
|
1426
|
+
) {
|
|
1427
|
+
continue;
|
|
1428
|
+
}
|
|
1429
|
+
checkedProjectIds.add(normalizeId(item.projectId));
|
|
1430
|
+
|
|
1431
|
+
if (newProbeId) {
|
|
1432
|
+
await this.assertProbeIsAttachableToProject({
|
|
1433
|
+
probeId: newProbeId,
|
|
1434
|
+
projectId: item.projectId,
|
|
1435
|
+
});
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
if (newSnmpCredentialProfileId) {
|
|
1439
|
+
await this.assertSnmpCredentialProfileBelongsToProject({
|
|
1440
|
+
snmpCredentialProfileId: newSnmpCredentialProfileId,
|
|
1441
|
+
projectId: item.projectId,
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
if (!touchesParent && !touchesNetworkSiteType) {
|
|
1449
|
+
return { updateBy, carryForward: null };
|
|
1450
|
+
}
|
|
1451
|
+
|
|
380
1452
|
let newParentPath: string | null = null;
|
|
1453
|
+
let newParent: Model | null = null;
|
|
381
1454
|
|
|
382
|
-
if (newParentId) {
|
|
383
|
-
|
|
1455
|
+
if (touchesParent && newParentId) {
|
|
1456
|
+
newParent = await this.findOneById({
|
|
384
1457
|
id: newParentId,
|
|
385
1458
|
select: {
|
|
386
1459
|
_id: true,
|
|
387
1460
|
projectId: true,
|
|
1461
|
+
networkSiteTypeId: true,
|
|
388
1462
|
},
|
|
389
1463
|
props: {
|
|
390
1464
|
isRoot: true,
|
|
391
1465
|
},
|
|
392
1466
|
});
|
|
393
1467
|
|
|
394
|
-
if (!
|
|
1468
|
+
if (!newParent) {
|
|
395
1469
|
throw new BadDataException("Parent site not found.");
|
|
396
1470
|
}
|
|
397
1471
|
|
|
398
1472
|
for (const item of previousItems) {
|
|
399
|
-
if (item.id && item.id
|
|
1473
|
+
if (item.id && sameId(item.id, newParentId)) {
|
|
400
1474
|
throw new BadDataException("A site cannot be its own parent.");
|
|
401
1475
|
}
|
|
402
1476
|
|
|
403
1477
|
if (
|
|
404
1478
|
item.projectId &&
|
|
405
|
-
|
|
406
|
-
item.projectId
|
|
1479
|
+
newParent.projectId &&
|
|
1480
|
+
!sameId(item.projectId, newParent.projectId)
|
|
407
1481
|
) {
|
|
408
1482
|
throw new BadDataException(
|
|
409
1483
|
"Parent site must belong to the same project.",
|
|
@@ -428,6 +1502,84 @@ export class Service extends DatabaseService<Model> {
|
|
|
428
1502
|
}
|
|
429
1503
|
}
|
|
430
1504
|
|
|
1505
|
+
const typeCache: Map<string, NetworkSiteType> = new Map();
|
|
1506
|
+
const existingParents: Map<string, Model> = new Map();
|
|
1507
|
+
|
|
1508
|
+
for (const item of previousItems) {
|
|
1509
|
+
let proposedParent: Model | null = null;
|
|
1510
|
+
|
|
1511
|
+
if (touchesParent) {
|
|
1512
|
+
proposedParent = newParent;
|
|
1513
|
+
} else if (item.parentSiteId) {
|
|
1514
|
+
const currentParentId: string = normalizeId(item.parentSiteId);
|
|
1515
|
+
proposedParent = existingParents.get(currentParentId) || null;
|
|
1516
|
+
|
|
1517
|
+
if (!proposedParent) {
|
|
1518
|
+
proposedParent = await this.findOneById({
|
|
1519
|
+
id: item.parentSiteId,
|
|
1520
|
+
select: {
|
|
1521
|
+
_id: true,
|
|
1522
|
+
projectId: true,
|
|
1523
|
+
networkSiteTypeId: true,
|
|
1524
|
+
},
|
|
1525
|
+
props: {
|
|
1526
|
+
isRoot: true,
|
|
1527
|
+
},
|
|
1528
|
+
});
|
|
1529
|
+
|
|
1530
|
+
if (!proposedParent) {
|
|
1531
|
+
throw new BadDataException("Parent site not found.");
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
existingParents.set(currentParentId, proposedParent);
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
if (
|
|
1538
|
+
item.projectId &&
|
|
1539
|
+
proposedParent.projectId &&
|
|
1540
|
+
!sameId(item.projectId, proposedParent.projectId)
|
|
1541
|
+
) {
|
|
1542
|
+
throw new BadDataException(
|
|
1543
|
+
"Parent site must belong to the same project.",
|
|
1544
|
+
);
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
const proposedNetworkSiteTypeId: ObjectID | null = touchesNetworkSiteType
|
|
1549
|
+
? newNetworkSiteTypeId
|
|
1550
|
+
: item.networkSiteTypeId || null;
|
|
1551
|
+
|
|
1552
|
+
await this.validateSiteTypeEdge({
|
|
1553
|
+
networkSiteTypeId: proposedNetworkSiteTypeId,
|
|
1554
|
+
parentSite: proposedParent,
|
|
1555
|
+
projectId: item.projectId,
|
|
1556
|
+
typeCache: typeCache,
|
|
1557
|
+
});
|
|
1558
|
+
|
|
1559
|
+
const previousNetworkSiteTypeId: string | null = item.networkSiteTypeId
|
|
1560
|
+
? normalizeId(item.networkSiteTypeId)
|
|
1561
|
+
: null;
|
|
1562
|
+
const proposedNetworkSiteTypeIdString: string | null =
|
|
1563
|
+
proposedNetworkSiteTypeId
|
|
1564
|
+
? normalizeId(proposedNetworkSiteTypeId)
|
|
1565
|
+
: null;
|
|
1566
|
+
|
|
1567
|
+
if (
|
|
1568
|
+
touchesNetworkSiteType &&
|
|
1569
|
+
previousNetworkSiteTypeId !== proposedNetworkSiteTypeIdString
|
|
1570
|
+
) {
|
|
1571
|
+
await this.validateDirectChildrenForTypeChange({
|
|
1572
|
+
site: item,
|
|
1573
|
+
proposedNetworkSiteTypeId: proposedNetworkSiteTypeId,
|
|
1574
|
+
typeCache: typeCache,
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
if (!touchesParent) {
|
|
1580
|
+
return { updateBy, carryForward: null };
|
|
1581
|
+
}
|
|
1582
|
+
|
|
431
1583
|
const carryForward: ParentChangeCarryForward = {
|
|
432
1584
|
previousItems: previousItems,
|
|
433
1585
|
newParentId: newParentId,
|
|
@@ -494,7 +1646,22 @@ export class Service extends DatabaseService<Model> {
|
|
|
494
1646
|
}),
|
|
495
1647
|
);
|
|
496
1648
|
|
|
497
|
-
|
|
1649
|
+
/*
|
|
1650
|
+
* A bulk update can include both an ancestor and one of its descendants.
|
|
1651
|
+
* Move the deepest roots first; otherwise rebasing the ancestor changes
|
|
1652
|
+
* the descendant branch away from the latter's old prefix before its own
|
|
1653
|
+
* subtree has been processed.
|
|
1654
|
+
*/
|
|
1655
|
+
const previousItemsDeepestFirst: Array<Model> = [
|
|
1656
|
+
...parentChange.previousItems,
|
|
1657
|
+
].sort((left: Model, right: Model): number => {
|
|
1658
|
+
return (
|
|
1659
|
+
MaterializedPathUtil.segmentsOf(right.materializedPath).length -
|
|
1660
|
+
MaterializedPathUtil.segmentsOf(left.materializedPath).length
|
|
1661
|
+
);
|
|
1662
|
+
});
|
|
1663
|
+
|
|
1664
|
+
for (const previousItem of previousItemsDeepestFirst) {
|
|
498
1665
|
if (!previousItem.id || !updatedIds.has(previousItem.id.toString())) {
|
|
499
1666
|
continue;
|
|
500
1667
|
}
|
|
@@ -520,44 +1687,53 @@ export class Service extends DatabaseService<Model> {
|
|
|
520
1687
|
|
|
521
1688
|
// ...then its entire subtree in one prefix query.
|
|
522
1689
|
if (oldPath) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
1690
|
+
while (true) {
|
|
1691
|
+
const descendants: Array<Model> = await this.findBy({
|
|
1692
|
+
query: {
|
|
1693
|
+
projectId: previousItem.projectId!,
|
|
1694
|
+
materializedPath: this.pathStartsWith(oldPath),
|
|
1695
|
+
},
|
|
1696
|
+
select: {
|
|
1697
|
+
_id: true,
|
|
1698
|
+
materializedPath: true,
|
|
1699
|
+
},
|
|
1700
|
+
sort: {
|
|
1701
|
+
_id: SortOrder.Ascending,
|
|
1702
|
+
},
|
|
1703
|
+
limit: SUBTREE_REBASE_PAGE_SIZE,
|
|
1704
|
+
skip: 0,
|
|
1705
|
+
props: {
|
|
1706
|
+
isRoot: true,
|
|
1707
|
+
},
|
|
1708
|
+
});
|
|
538
1709
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
1710
|
+
for (const descendant of descendants) {
|
|
1711
|
+
if (
|
|
1712
|
+
!descendant.id ||
|
|
1713
|
+
!descendant.materializedPath ||
|
|
1714
|
+
descendant.id.toString() === previousItem.id.toString()
|
|
1715
|
+
) {
|
|
1716
|
+
continue;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
const rebasedPath: string = MaterializedPathUtil.rebasePaths(
|
|
1720
|
+
oldPath,
|
|
1721
|
+
newPath,
|
|
1722
|
+
[descendant.materializedPath],
|
|
1723
|
+
)[0]!;
|
|
1724
|
+
|
|
1725
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
1726
|
+
id: descendant.id,
|
|
1727
|
+
data: {
|
|
1728
|
+
materializedPath: rebasedPath,
|
|
1729
|
+
depth: MaterializedPathUtil.depthOf(rebasedPath),
|
|
1730
|
+
},
|
|
1731
|
+
});
|
|
546
1732
|
}
|
|
547
1733
|
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
[descendant.materializedPath],
|
|
552
|
-
)[0]!;
|
|
553
|
-
|
|
554
|
-
await this.updateColumnsByIdWithoutHooks({
|
|
555
|
-
id: descendant.id,
|
|
556
|
-
data: {
|
|
557
|
-
materializedPath: rebasedPath,
|
|
558
|
-
depth: MaterializedPathUtil.depthOf(rebasedPath),
|
|
559
|
-
},
|
|
560
|
-
});
|
|
1734
|
+
if (descendants.length < SUBTREE_REBASE_PAGE_SIZE) {
|
|
1735
|
+
break;
|
|
1736
|
+
}
|
|
561
1737
|
}
|
|
562
1738
|
}
|
|
563
1739
|
|
|
@@ -598,21 +1774,117 @@ export class Service extends DatabaseService<Model> {
|
|
|
598
1774
|
protected override async onBeforeDelete(
|
|
599
1775
|
deleteBy: DeleteBy<Model>,
|
|
600
1776
|
): Promise<OnDelete<Model>> {
|
|
1777
|
+
const deleteLimit: number =
|
|
1778
|
+
deleteBy.limit instanceof PositiveNumber
|
|
1779
|
+
? deleteBy.limit.toNumber()
|
|
1780
|
+
: deleteBy.limit || LIMIT_MAX;
|
|
1781
|
+
const deleteSkip: number =
|
|
1782
|
+
deleteBy.skip instanceof PositiveNumber
|
|
1783
|
+
? deleteBy.skip.toNumber()
|
|
1784
|
+
: deleteBy.skip || 0;
|
|
1785
|
+
|
|
601
1786
|
const sitesToDelete: Array<Model> = await this.findBy({
|
|
602
|
-
query: this.
|
|
1787
|
+
query: this.scopeDeleteQueryToCallerTenant(
|
|
1788
|
+
deleteBy.query,
|
|
1789
|
+
deleteBy.props,
|
|
1790
|
+
),
|
|
603
1791
|
select: {
|
|
604
1792
|
_id: true,
|
|
605
1793
|
projectId: true,
|
|
606
1794
|
parentSiteId: true,
|
|
607
1795
|
materializedPath: true,
|
|
608
1796
|
},
|
|
609
|
-
limit:
|
|
610
|
-
skip:
|
|
1797
|
+
limit: deleteLimit,
|
|
1798
|
+
skip: deleteSkip,
|
|
611
1799
|
props: {
|
|
612
1800
|
isRoot: true,
|
|
613
1801
|
},
|
|
614
1802
|
});
|
|
615
1803
|
|
|
1804
|
+
const deletingSiteIds: Set<string> = new Set(
|
|
1805
|
+
sitesToDelete
|
|
1806
|
+
.map((site: Model): string | null => {
|
|
1807
|
+
return site.id ? normalizeId(site.id) : null;
|
|
1808
|
+
})
|
|
1809
|
+
.filter((siteId: string | null): siteId is string => {
|
|
1810
|
+
return Boolean(siteId);
|
|
1811
|
+
}),
|
|
1812
|
+
);
|
|
1813
|
+
|
|
1814
|
+
const deletingSiteIdList: Array<string> = Array.from(deletingSiteIds);
|
|
1815
|
+
const deletingProjectIdList: Array<string> = Array.from(
|
|
1816
|
+
new Set(
|
|
1817
|
+
sitesToDelete
|
|
1818
|
+
.map((site: Model): string | null => {
|
|
1819
|
+
return site.projectId ? normalizeId(site.projectId) : null;
|
|
1820
|
+
})
|
|
1821
|
+
.filter((projectId: string | null): projectId is string => {
|
|
1822
|
+
return Boolean(projectId);
|
|
1823
|
+
}),
|
|
1824
|
+
),
|
|
1825
|
+
);
|
|
1826
|
+
|
|
1827
|
+
/*
|
|
1828
|
+
* A valid child type explicitly names the deleted site's type as its
|
|
1829
|
+
* required direct parent type. Legacy SET NULL/orphan-repair behaviour
|
|
1830
|
+
* therefore cannot produce a valid edge: promoting the child to root or
|
|
1831
|
+
* attaching it to the grandparent both violate its type. Reject the
|
|
1832
|
+
* delete unless every direct child is part of this same bulk delete.
|
|
1833
|
+
*
|
|
1834
|
+
* Parent ids and result rows are both batched so neither a wide delete nor
|
|
1835
|
+
* a wide site is silently truncated at a service query limit.
|
|
1836
|
+
*/
|
|
1837
|
+
for (
|
|
1838
|
+
let parentIdOffset: number = 0;
|
|
1839
|
+
parentIdOffset < deletingSiteIdList.length;
|
|
1840
|
+
parentIdOffset += DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE
|
|
1841
|
+
) {
|
|
1842
|
+
const parentIdBatch: Array<string> = deletingSiteIdList.slice(
|
|
1843
|
+
parentIdOffset,
|
|
1844
|
+
parentIdOffset + DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
1845
|
+
);
|
|
1846
|
+
let childSkip: number = 0;
|
|
1847
|
+
|
|
1848
|
+
while (true) {
|
|
1849
|
+
const directChildren: Array<Model> = await this.findBy({
|
|
1850
|
+
query: {
|
|
1851
|
+
projectId: QueryHelper.any(deletingProjectIdList),
|
|
1852
|
+
parentSiteId: QueryHelper.any(parentIdBatch),
|
|
1853
|
+
},
|
|
1854
|
+
select: {
|
|
1855
|
+
_id: true,
|
|
1856
|
+
parentSiteId: true,
|
|
1857
|
+
},
|
|
1858
|
+
sort: {
|
|
1859
|
+
_id: SortOrder.Ascending,
|
|
1860
|
+
},
|
|
1861
|
+
limit: DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE,
|
|
1862
|
+
skip: childSkip,
|
|
1863
|
+
props: {
|
|
1864
|
+
isRoot: true,
|
|
1865
|
+
},
|
|
1866
|
+
});
|
|
1867
|
+
|
|
1868
|
+
const hasSurvivingChild: boolean = directChildren.some(
|
|
1869
|
+
(child: Model): boolean => {
|
|
1870
|
+
return !child.id || !deletingSiteIds.has(normalizeId(child.id));
|
|
1871
|
+
},
|
|
1872
|
+
);
|
|
1873
|
+
|
|
1874
|
+
if (hasSurvivingChild) {
|
|
1875
|
+
throw new BadDataException(
|
|
1876
|
+
"A network site with child sites cannot be deleted. Move or delete its child sites first.",
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
if (directChildren.length < DIRECT_CHILD_TYPE_VALIDATION_PAGE_SIZE) {
|
|
1881
|
+
break;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
childSkip += directChildren.length;
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
616
1888
|
const carryForward: DeleteCarryForward = {
|
|
617
1889
|
sitesToDelete: sitesToDelete,
|
|
618
1890
|
};
|
|
@@ -621,15 +1893,12 @@ export class Service extends DatabaseService<Model> {
|
|
|
621
1893
|
}
|
|
622
1894
|
|
|
623
1895
|
/*
|
|
624
|
-
*
|
|
625
|
-
*
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
* materializedPath
|
|
630
|
-
* counting every outage. Re-attach the orphans to the deleted site's own
|
|
631
|
-
* parent - NULL when it was a root, which is exactly what the FK did - and
|
|
632
|
-
* rebase the subtree paths so both readers agree again.
|
|
1896
|
+
* New schemas use a non-nullifying foreign key and onBeforeDelete rejects
|
|
1897
|
+
* surviving children, so this repair is normally a no-op. Keep it as a
|
|
1898
|
+
* defensive bridge for a database that has not applied the FK migration
|
|
1899
|
+
* yet, or for a legacy write already in flight during an upgrade: reattach
|
|
1900
|
+
* any detached children and rebase their subtree paths so parentSiteId and
|
|
1901
|
+
* materializedPath agree.
|
|
633
1902
|
*/
|
|
634
1903
|
@CaptureSpan()
|
|
635
1904
|
protected override async onDeleteSuccess(
|
|
@@ -699,58 +1968,67 @@ export class Service extends DatabaseService<Model> {
|
|
|
699
1968
|
const deletedDepth: number =
|
|
700
1969
|
MaterializedPathUtil.segmentsOf(oldPath).length;
|
|
701
1970
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
1971
|
+
while (true) {
|
|
1972
|
+
const descendants: Array<Model> = await this.findBy({
|
|
1973
|
+
query: {
|
|
1974
|
+
projectId: deletedSite.projectId!,
|
|
1975
|
+
materializedPath: this.pathStartsWith(oldPath),
|
|
1976
|
+
},
|
|
1977
|
+
select: {
|
|
1978
|
+
_id: true,
|
|
1979
|
+
materializedPath: true,
|
|
1980
|
+
},
|
|
1981
|
+
sort: {
|
|
1982
|
+
_id: SortOrder.Ascending,
|
|
1983
|
+
},
|
|
1984
|
+
limit: SUBTREE_REBASE_PAGE_SIZE,
|
|
1985
|
+
skip: 0,
|
|
1986
|
+
props: {
|
|
1987
|
+
isRoot: true,
|
|
1988
|
+
},
|
|
1989
|
+
});
|
|
717
1990
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
1991
|
+
for (const descendant of descendants) {
|
|
1992
|
+
if (
|
|
1993
|
+
!descendant.id ||
|
|
1994
|
+
!descendant.materializedPath ||
|
|
1995
|
+
descendant.id.toString() === deletedSite.id.toString()
|
|
1996
|
+
) {
|
|
1997
|
+
continue;
|
|
1998
|
+
}
|
|
726
1999
|
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
2000
|
+
const tailSegments: Array<string> = MaterializedPathUtil.segmentsOf(
|
|
2001
|
+
descendant.materializedPath,
|
|
2002
|
+
).slice(deletedDepth);
|
|
730
2003
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
2004
|
+
if (tailSegments.length === 0) {
|
|
2005
|
+
continue;
|
|
2006
|
+
}
|
|
734
2007
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
2008
|
+
let rebasedPath: string | null = parentPath;
|
|
2009
|
+
for (const segment of tailSegments) {
|
|
2010
|
+
rebasedPath = MaterializedPathUtil.buildPath(rebasedPath, segment);
|
|
2011
|
+
}
|
|
739
2012
|
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
2013
|
+
const updateData: Record<string, unknown> = {
|
|
2014
|
+
materializedPath: rebasedPath!,
|
|
2015
|
+
depth: MaterializedPathUtil.depthOf(rebasedPath!),
|
|
2016
|
+
};
|
|
744
2017
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
2018
|
+
// A direct child is the one the FK just detached - give it a parent back.
|
|
2019
|
+
if (tailSegments.length === 1) {
|
|
2020
|
+
updateData["parentSiteId"] = deletedSite.parentSiteId || null;
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
await this.updateColumnsByIdWithoutHooks({
|
|
2024
|
+
id: descendant.id,
|
|
2025
|
+
data: updateData as any,
|
|
2026
|
+
});
|
|
748
2027
|
}
|
|
749
2028
|
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
});
|
|
2029
|
+
if (descendants.length < SUBTREE_REBASE_PAGE_SIZE) {
|
|
2030
|
+
break;
|
|
2031
|
+
}
|
|
754
2032
|
}
|
|
755
2033
|
|
|
756
2034
|
/*
|
|
@@ -1617,8 +2895,11 @@ export class Service extends DatabaseService<Model> {
|
|
|
1617
2895
|
*/
|
|
1618
2896
|
|
|
1619
2897
|
/*
|
|
1620
|
-
* Called
|
|
1621
|
-
*
|
|
2898
|
+
* Called after a monitor's current status persists - from
|
|
2899
|
+
* MonitorStatusTimelineService.onCreateSuccess / onDeleteSuccess (the one
|
|
2900
|
+
* path every status change, probe-driven or manual, passes through) and
|
|
2901
|
+
* from MonitorService.refreshMonitorCurrentStatus when a repair moves the
|
|
2902
|
+
* id. Resolves which NetworkDevices these monitors report on, stamps those
|
|
1622
2903
|
* devices' currentMonitorStatusId, then recomputes the rollup for every
|
|
1623
2904
|
* affected site chain. Never throws - a rollup failure must never break a
|
|
1624
2905
|
* monitor status change.
|
|
@@ -1632,6 +2913,26 @@ export class Service extends DatabaseService<Model> {
|
|
|
1632
2913
|
* monitor-backed path (monitoringMethod "Monitor") for gear that does
|
|
1633
2914
|
* not speak SNMP, so ANY monitor type qualifies — a Ping monitor on an
|
|
1634
2915
|
* access point is the whole point of it.
|
|
2916
|
+
*
|
|
2917
|
+
* What gets stamped depends on how the device is monitored:
|
|
2918
|
+
*
|
|
2919
|
+
* - every device gets currentMonitorStatusId, which the pill, the site
|
|
2920
|
+
* rollup and the topology node read.
|
|
2921
|
+
* - a MONITOR-BACKED device also gets isReachable, derived from the
|
|
2922
|
+
* status row (`!isOfflineState`, the same offline-end reading
|
|
2923
|
+
* DeviceReachabilityUtil uses). Nothing polls such a device, so the
|
|
2924
|
+
* column is NULL forever otherwise - and the device list's summary
|
|
2925
|
+
* tiles and its Status filter count and filter on isReachable in SQL,
|
|
2926
|
+
* which is why a bound ping-only device sat under "Pending" there while
|
|
2927
|
+
* its own pill said Up. The server keeps the two in sync so the list
|
|
2928
|
+
* agrees with itself.
|
|
2929
|
+
* - an SNMP device's isReachable is left alone: the walk owns it
|
|
2930
|
+
* (NetworkInventoryUtil.updateFromWalk), and a Network Device monitor
|
|
2931
|
+
* going Degraded must not overwrite what the probe actually found.
|
|
2932
|
+
*
|
|
2933
|
+
* The status row is read at most once per call, and only when at least one
|
|
2934
|
+
* collected device is monitor-backed, so an all-SNMP estate costs no extra
|
|
2935
|
+
* query.
|
|
1635
2936
|
*/
|
|
1636
2937
|
@CaptureSpan()
|
|
1637
2938
|
public async onMonitorStatusChanged(data: {
|
|
@@ -1697,6 +2998,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
1697
2998
|
select: {
|
|
1698
2999
|
_id: true,
|
|
1699
3000
|
siteId: true,
|
|
3001
|
+
// Decides whether isReachable is stamped alongside the status.
|
|
3002
|
+
monitoringMethod: true,
|
|
1700
3003
|
},
|
|
1701
3004
|
limit: LIMIT_MAX,
|
|
1702
3005
|
skip: 0,
|
|
@@ -1716,6 +3019,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
1716
3019
|
select: {
|
|
1717
3020
|
_id: true,
|
|
1718
3021
|
siteId: true,
|
|
3022
|
+
// Decides whether isReachable is stamped alongside the status.
|
|
3023
|
+
monitoringMethod: true,
|
|
1719
3024
|
},
|
|
1720
3025
|
limit: LIMIT_MAX,
|
|
1721
3026
|
skip: 0,
|
|
@@ -1731,15 +3036,83 @@ export class Service extends DatabaseService<Model> {
|
|
|
1731
3036
|
return;
|
|
1732
3037
|
}
|
|
1733
3038
|
|
|
3039
|
+
/*
|
|
3040
|
+
* Resolve the status row lazily - once, and only if a monitor-backed
|
|
3041
|
+
* device is in the set - because it is only needed to derive
|
|
3042
|
+
* isReachable, and the SNMP-only case must stay one query cheaper.
|
|
3043
|
+
*
|
|
3044
|
+
* `undefined` afterwards means "do not touch isReachable": either no
|
|
3045
|
+
* device needs it, or the row could not be found in this project (a
|
|
3046
|
+
* status deleted between the timeline write and this call, or one
|
|
3047
|
+
* from another tenant). The id is still stamped in that case so the
|
|
3048
|
+
* pill keeps moving; a stale reachability is the lesser harm next to
|
|
3049
|
+
* a device that stops reporting altogether.
|
|
3050
|
+
*/
|
|
3051
|
+
const hasMonitorBackedDevice: boolean = devices.some(
|
|
3052
|
+
(device: NetworkDevice) => {
|
|
3053
|
+
return NetworkDeviceMonitoringMethodUtil.isMonitorBacked(
|
|
3054
|
+
device.monitoringMethod,
|
|
3055
|
+
);
|
|
3056
|
+
},
|
|
3057
|
+
);
|
|
3058
|
+
|
|
3059
|
+
let monitorBackedIsReachable: boolean | undefined = undefined;
|
|
3060
|
+
|
|
3061
|
+
if (hasMonitorBackedDevice) {
|
|
3062
|
+
const status: MonitorStatus | null =
|
|
3063
|
+
await MonitorStatusService.findOneBy({
|
|
3064
|
+
query: {
|
|
3065
|
+
_id: data.monitorStatusId,
|
|
3066
|
+
projectId: data.projectId,
|
|
3067
|
+
},
|
|
3068
|
+
select: {
|
|
3069
|
+
_id: true,
|
|
3070
|
+
isOfflineState: true,
|
|
3071
|
+
},
|
|
3072
|
+
props: {
|
|
3073
|
+
isRoot: true,
|
|
3074
|
+
},
|
|
3075
|
+
});
|
|
3076
|
+
|
|
3077
|
+
if (status) {
|
|
3078
|
+
monitorBackedIsReachable = !status.isOfflineState;
|
|
3079
|
+
} else {
|
|
3080
|
+
logger.warn(
|
|
3081
|
+
`NetworkSiteService.onMonitorStatusChanged: monitor status ${data.monitorStatusId.toString()} was not found in project ${data.projectId.toString()}; stamping the status id on the bound network devices but leaving isReachable unchanged.`,
|
|
3082
|
+
{
|
|
3083
|
+
projectId: data.projectId.toString(),
|
|
3084
|
+
monitorStatusId: data.monitorStatusId.toString(),
|
|
3085
|
+
} as LogAttributes,
|
|
3086
|
+
);
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
|
|
1734
3090
|
for (const device of devices) {
|
|
1735
3091
|
if (!device.id) {
|
|
1736
3092
|
continue;
|
|
1737
3093
|
}
|
|
3094
|
+
|
|
3095
|
+
const stamp: PartialEntity<NetworkDevice> = {
|
|
3096
|
+
currentMonitorStatusId: data.monitorStatusId,
|
|
3097
|
+
};
|
|
3098
|
+
|
|
3099
|
+
/*
|
|
3100
|
+
* Only a monitor-backed device gets isReachable from here. The key
|
|
3101
|
+
* is left OUT of the payload for an SNMP device rather than set to
|
|
3102
|
+
* undefined, so the walk's verdict is provably untouched.
|
|
3103
|
+
*/
|
|
3104
|
+
if (
|
|
3105
|
+
monitorBackedIsReachable !== undefined &&
|
|
3106
|
+
NetworkDeviceMonitoringMethodUtil.isMonitorBacked(
|
|
3107
|
+
device.monitoringMethod,
|
|
3108
|
+
)
|
|
3109
|
+
) {
|
|
3110
|
+
stamp.isReachable = monitorBackedIsReachable;
|
|
3111
|
+
}
|
|
3112
|
+
|
|
1738
3113
|
await NetworkDeviceService.updateColumnsByIdWithoutHooks({
|
|
1739
3114
|
id: device.id,
|
|
1740
|
-
data:
|
|
1741
|
-
currentMonitorStatusId: data.monitorStatusId,
|
|
1742
|
-
},
|
|
3115
|
+
data: stamp,
|
|
1743
3116
|
});
|
|
1744
3117
|
}
|
|
1745
3118
|
|