@oneuptime/common 12.0.13 → 12.0.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/GlobalOidc.ts +20 -0
- package/Models/DatabaseModels/GlobalSso.ts +20 -0
- package/Models/DatabaseModels/MarketingConversion.ts +19 -9
- package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +46 -0
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +14 -0
- package/Models/DatabaseModels/StatusPage.ts +7 -4
- package/Models/DatabaseModels/UserCall.ts +94 -3
- package/Models/DatabaseModels/UserEmail.ts +94 -3
- package/Models/DatabaseModels/UserIncomingCallNumber.ts +94 -3
- package/Models/DatabaseModels/UserPush.ts +37 -0
- package/Models/DatabaseModels/UserSMS.ts +94 -3
- package/Models/DatabaseModels/UserWhatsApp.ts +93 -2
- package/Server/API/BaseAPI.ts +79 -14
- package/Server/API/StatusPageAPI.ts +29 -4
- package/Server/API/UserCallAPI.ts +53 -45
- package/Server/API/UserEmailAPI.ts +53 -44
- package/Server/API/UserIncomingCallNumberAPI.ts +48 -38
- package/Server/API/UserNotificationMethodAdminAPI.ts +481 -0
- package/Server/API/UserPushAPI.ts +126 -2
- package/Server/API/UserSmsAPI.ts +53 -44
- package/Server/API/UserWhatsAppAPI.ts +53 -50
- package/Server/EnvironmentConfig.ts +7 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.ts +154 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.ts +45 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.ts +19 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Middleware/SlackAuthorization.ts +43 -6
- package/Server/Middleware/UserAuthorization.ts +236 -26
- package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
- package/Server/Middleware/WhatsAppAuthorization.ts +43 -3
- package/Server/Services/AnalyticsDatabaseService.ts +169 -0
- package/Server/Services/DatabaseService.ts +101 -0
- package/Server/Services/GlobalOidcProjectService.ts +126 -1
- package/Server/Services/GlobalOidcService.ts +132 -0
- package/Server/Services/GlobalSsoProjectService.ts +126 -1
- package/Server/Services/GlobalSsoService.ts +132 -0
- package/Server/Services/LogAggregationService.ts +5 -0
- package/Server/Services/PushNotificationService.ts +127 -12
- package/Server/Services/TeamMemberService.ts +53 -13
- package/Server/Services/UserCallService.ts +55 -24
- package/Server/Services/UserEmailService.ts +83 -17
- package/Server/Services/UserIncomingCallNumberService.ts +49 -85
- package/Server/Services/UserNotificationMethodAdminService.ts +1527 -0
- package/Server/Services/UserNotificationRuleService.ts +26 -0
- package/Server/Services/UserPushService.ts +89 -0
- package/Server/Services/UserSmsService.ts +50 -17
- package/Server/Services/UserWhatsAppService.ts +48 -15
- package/Server/Types/Database/QueryHelper.ts +30 -0
- package/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.ts +59 -0
- package/Server/Utils/ChannelVerification.ts +510 -0
- package/Server/Utils/CronTab.ts +73 -0
- package/Server/Utils/GlobalSsoAuthorization.ts +175 -0
- package/Server/Utils/Marketing/ConversionUploadProvider.ts +35 -5
- package/Server/Utils/Marketing/Providers/GoogleAds.ts +1 -1
- package/Server/Utils/Marketing/Providers/LinkedIn.ts +1 -1
- package/Server/Utils/Marketing/Providers/Meta.ts +1 -1
- package/Server/Utils/Marketing/Providers/MicrosoftAds.ts +1 -1
- package/Server/Utils/Marketing/Providers/Reddit.ts +1 -1
- package/Server/Utils/Monitor/Criteria/APIRequestCriteria.ts +48 -33
- package/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.ts +35 -30
- package/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.ts +33 -28
- package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +475 -47
- package/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.ts +35 -30
- package/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.ts +47 -44
- package/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.ts +33 -28
- package/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.ts +69 -40
- package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +35 -29
- package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +8 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
- package/Server/Utils/Monitor/MonitorResource.ts +161 -21
- package/Server/Utils/Monitor/MonitorResourceContext.ts +107 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +442 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +3 -3
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +96 -28
- package/Server/Utils/StatusPageContentSecurityPolicy.ts +56 -0
- package/Server/Utils/StatusPageCustomizationAccess.ts +117 -0
- package/Server/Utils/TotpAuth.ts +137 -9
- package/Server/Utils/UserRegistrationToken.ts +182 -0
- package/Server/Utils/VerificationCode.ts +134 -0
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +173 -94
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +1151 -0
- package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +905 -0
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +338 -0
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1 -1
- package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +28 -0
- package/Tests/Models/UserPushCriticalAlertColumn.test.ts +172 -0
- package/Tests/Server/API/BaseAPIGetListParallel.test.ts +519 -0
- package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +543 -0
- package/Tests/Server/API/StatusPageCustomizationOrigin.test.ts +348 -0
- package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +108 -18
- package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +963 -0
- package/Tests/Server/API/UserPushCriticalAlertsApi.test.ts +114 -0
- package/Tests/Server/API/UserSmsApi.test.ts +107 -14
- package/Tests/Server/API/UserTotpAuthAPI.test.ts +427 -0
- package/Tests/Server/Infrastructure/Postgres/FixTotpOtpUrlAlgorithmMigration.test.ts +265 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +227 -0
- package/Tests/Server/Middleware/SlackAuthorization.test.ts +149 -0
- package/Tests/Server/Middleware/UserAuthorization.test.ts +27 -13
- package/Tests/Server/Middleware/UserAuthorizationGlobalSsoGovernance.test.ts +1455 -0
- package/Tests/Server/Middleware/UserAuthorizationSSOProvider.test.ts +91 -2
- package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -0
- package/Tests/Server/Middleware/WhatsAppAuthorization.test.ts +233 -0
- package/Tests/Server/Services/AddNetworkDeviceReachabilityColumnsMigration.test.ts +10 -62
- package/Tests/Server/Services/AnalyticsDatabasePaginationStability.test.ts +33 -13
- package/Tests/Server/Services/AnalyticsDatabaseSortKeyBoundary.test.ts +658 -0
- package/Tests/Server/Services/CriticalOnCallAlertDelivery.test.ts +458 -0
- package/Tests/Server/Services/CriticalPushAlertPayload.test.ts +301 -0
- package/Tests/Server/Services/DatabaseServiceAtomicIncrement.test.ts +143 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +21 -8
- package/Tests/Server/Services/GlobalSsoProviderAuthorization.test.ts +1242 -0
- package/Tests/Server/Services/LogAggregationScanMemory.test.ts +421 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
- package/Tests/Server/Services/MonitorResourceProbeAgreementHydration.test.ts +459 -0
- package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +10 -0
- package/Tests/Server/Services/NotificationChannelCodeIssuance.test.ts +401 -0
- package/Tests/Server/Services/PushNotificationDeliveryOptions.test.ts +204 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +21 -1
- package/Tests/Server/Services/TeamMemberInviteRegistrationToken.test.ts +290 -0
- package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +948 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1 -0
- package/Tests/Server/Services/UserPushCriticalAlertToggle.test.ts +255 -0
- package/Tests/Server/Services/UserTotpAuthEnrolment.test.ts +218 -0
- package/Tests/Server/TestingUtils/AuthenticatorApp.ts +248 -0
- package/Tests/Server/Types/AnalyticsDatabase/AggregateUtilBucketTimestamp.test.ts +416 -0
- package/Tests/Server/Types/Database/Permissions/NotificationChannelVerificationColumns.test.ts +135 -0
- package/Tests/Server/Types/Database/Permissions/OnCallScheduleRelationSelect.test.ts +504 -0
- package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAnyOf.test.ts +91 -0
- package/Tests/Server/Types/Database/QueryHelperManyToManyAndEmptyValues.test.ts +551 -0
- package/Tests/Server/Types/Database/SelectUtil.test.ts +348 -0
- package/Tests/Server/Types/Workflow/Components/JsonToText.test.ts +384 -0
- package/Tests/Server/Types/Workflow/Components/MergeJson.test.ts +403 -0
- package/Tests/Server/Utils/Browser.test.ts +162 -0
- package/Tests/Server/Utils/ChannelVerification.test.ts +689 -0
- package/Tests/Server/Utils/CronTab.test.ts +116 -0
- package/Tests/Server/Utils/Express.test.ts +371 -0
- package/Tests/Server/Utils/GlobalSSOToken.test.ts +581 -0
- package/Tests/Server/Utils/GlobalSsoAuthorization.test.ts +1401 -0
- package/Tests/Server/Utils/Marketing/AdUploadableConversionTypes.test.ts +254 -0
- package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +1 -1
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaEvaluateOverTime.test.ts +508 -0
- package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaPortTimings.test.ts +30 -9
- package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +707 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +698 -0
- package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +987 -0
- package/Tests/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.test.ts +916 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingEmailBodyCriteria.test.ts +243 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -0
- package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +382 -0
- package/Tests/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.test.ts +1219 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +160 -20
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +13 -8
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +162 -18
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +349 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceIngestedStepSelection.test.ts +86 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +690 -0
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +7 -2
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +92 -18
- package/Tests/Server/Utils/PushNotificationUtilCreators.test.ts +267 -0
- package/Tests/Server/Utils/StatusPageContentSecurityPolicy.test.ts +136 -0
- package/Tests/Server/Utils/StatusPageCustomizationAccess.test.ts +223 -0
- package/Tests/Server/Utils/Telemetry/OneuptimeLabel.test.ts +439 -0
- package/Tests/Server/Utils/TotpAuth.test.ts +719 -0
- package/Tests/Server/Utils/UserRegistrationToken.test.ts +322 -0
- package/Tests/Server/Utils/VerificationCode.test.ts +296 -0
- package/Tests/Types/AutoRemediation/AutoRemediationSuggestionStatus.test.ts +192 -0
- package/Tests/Types/Call/CallRequest.test.ts +189 -0
- package/Tests/Types/Dashboard/DashboardSize.test.ts +226 -0
- package/Tests/Types/Incident/IncidentSlaStatus.test.ts +191 -0
- package/Tests/Types/Metrics/MetricDashboardMetricType.test.ts +278 -0
- package/Tests/Types/Metrics/MetricPipelineRuleType.test.ts +517 -0
- package/Tests/Types/Monitor/IncomingMonitorDefaultCriteria.test.ts +470 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +6 -4
- package/Tests/Types/Monitor/MonitorStepConfigHelpers.test.ts +165 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +262 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +1 -1
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +1 -1
- package/Tests/Types/Monitor/ServiceAlertTemplates.test.ts +905 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceLinkRuleScope.test.ts +215 -0
- package/Tests/Types/Service/ServiceLanguage.test.ts +255 -0
- package/Tests/Types/TextRandomGeneration.test.ts +211 -0
- package/Tests/UI/Components/Button.test.tsx +175 -1
- package/Tests/UI/Components/CodeBlockLanguages.test.tsx +236 -0
- package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +568 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteKeyboard.test.tsx +239 -0
- package/Tests/UI/Components/CommandPalette/CommandPaletteProviders.test.tsx +400 -0
- package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +234 -0
- package/Tests/UI/Components/CommandPalette/RecentCommands.test.ts +97 -0
- package/Tests/UI/Components/CountModelSideMenuItemGuard.test.tsx +198 -0
- package/Tests/UI/Components/FeedItemSafeMode.test.tsx +1 -1
- package/Tests/UI/Components/Forms/FormSubmitAnalytics.test.tsx +206 -0
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +267 -0
- package/Tests/UI/Components/List.test.tsx +9 -2
- package/Tests/UI/Components/ListLoadingStates.test.tsx +173 -0
- package/Tests/UI/Components/MarkdownLazy.test.tsx +113 -0
- package/Tests/UI/Components/MarkdownMermaidRetry.test.tsx +110 -0
- package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +8 -0
- package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +692 -0
- package/Tests/UI/Components/MoreMenuMotion.test.tsx +118 -0
- package/Tests/UI/Components/NavBarCommandKGating.test.tsx +178 -0
- package/Tests/UI/Components/OrderedStatesList.test.tsx +19 -2
- package/Tests/UI/Components/SideOverMotion.test.tsx +109 -0
- package/Tests/UI/Components/Skeleton.test.tsx +71 -0
- package/Tests/UI/Components/TableLoadingStates.test.tsx +279 -0
- package/Tests/UI/Components/Tabs.test.tsx +24 -0
- package/Tests/UI/Components/Toast.test.tsx +130 -7
- package/Tests/UI/Components/ToastStacking.test.tsx +198 -0
- package/Tests/UI/Utils/AIChatExport/ConversationMarkdown.test.ts +774 -0
- package/Tests/UI/Utils/AIChatExport/MarkdownBlocks.test.ts +791 -0
- package/Tests/UI/Utils/AIChatExport/MarkdownSafety.test.ts +544 -0
- package/Tests/UI/Utils/Dropdown.test.ts +423 -0
- package/Tests/UI/Utils/ModelAPITenantHeader.test.ts +122 -0
- package/Tests/UI/Utils/ModelListCache.test.ts +338 -0
- package/Tests/UI/Utils/ProjectListCacheInvalidation.test.ts +225 -0
- package/Tests/Utils/API.test.ts +16 -2
- package/Tests/Utils/Analytics.test.ts +187 -0
- package/Tests/Utils/Dashboard/Components/DashboardKubernetesResourceListShared.test.ts +347 -0
- package/Tests/Utils/Dashboard/Components/DashboardListSharedArgs.test.ts +259 -0
- package/Tests/Utils/Dashboard/Components/DashboardMonitorListComponent.test.ts +466 -0
- package/Tests/Utils/Monitor/MonitorMetricType.test.ts +80 -0
- package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +1291 -0
- package/Tests/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.test.ts +214 -0
- package/Tests/Utils/Rum/UrlScrubberSegments.test.ts +362 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Marketing/MarketingConversion.ts +12 -0
- package/Types/Monitor/CriteriaFilter.ts +9 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +41 -20
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +131 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +48 -8
- package/Types/Monitor/ServiceAlertTemplates.ts +1352 -0
- package/Types/NetworkDevice/NetworkDeviceLinkRuleScope.ts +51 -0
- package/Types/Permission.ts +35 -0
- package/Types/PushNotification/AndroidNotificationChannel.ts +26 -0
- package/Types/PushNotification/PushNotificationMessage.ts +15 -0
- package/Types/PushNotification/PushNotificationRequest.ts +8 -16
- package/Types/Service/ServiceLanguage.ts +144 -0
- package/Types/Text.ts +111 -19
- package/UI/Components/Button/Button.tsx +27 -14
- package/UI/Components/CodeBlock/CodeBlock.tsx +54 -7
- package/UI/Components/CodeBlock/LanguageRegistry.ts +103 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +790 -0
- package/UI/Components/CommandPalette/PaletteFilter.ts +196 -0
- package/UI/Components/CommandPalette/PaletteRow.tsx +173 -0
- package/UI/Components/CommandPalette/RecentCommands.ts +57 -0
- package/UI/Components/CommandPalette/Types.ts +49 -0
- package/UI/Components/CommandPalette/UseProviderSearch.ts +129 -0
- package/UI/Components/Dropdown/Dropdown.tsx +6 -1
- package/UI/Components/Feed/FeedItem.tsx +1 -1
- package/UI/Components/FormModal/BasicFormModal.tsx +12 -0
- package/UI/Components/Forms/BasicForm.tsx +13 -1
- package/UI/Components/Forms/BasicModelForm.tsx +2 -1
- package/UI/Components/Forms/ModelForm.tsx +10 -1
- package/UI/Components/Forms/Utils/FormAnalyticsName.ts +39 -0
- package/UI/Components/List/List.tsx +37 -5
- package/UI/Components/List/ListSkeleton.tsx +54 -0
- package/UI/Components/Markdown.tsx/LazyMarkdownViewer.tsx +6 -1
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +71 -26
- package/UI/Components/Modal/Modal.tsx +2 -2
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +6 -1
- package/UI/Components/ModelTable/BaseModelTable.tsx +1 -1
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +11 -5
- package/UI/Components/MoreMenu/MoreMenu.tsx +39 -1
- package/UI/Components/Navbar/NavBar.tsx +14 -1
- package/UI/Components/OrderedStatesList/OrderedStatesList.tsx +50 -5
- package/UI/Components/SideMenu/CountModelSideMenuItem.tsx +40 -1
- package/UI/Components/SideOver/SideOver.tsx +37 -2
- package/UI/Components/Skeleton/Skeleton.tsx +53 -0
- package/UI/Components/Table/Table.tsx +74 -44
- package/UI/Components/Table/TableSkeletonRows.tsx +141 -0
- package/UI/Components/Tabs/Tab.tsx +1 -1
- package/UI/Components/Toast/Toast.tsx +118 -53
- package/UI/Components/Toast/ToastInit.tsx +82 -32
- package/UI/Styles/Theme.css +40 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +20 -10
- package/UI/Utils/ModelListCache.ts +188 -0
- package/UI/Utils/Project.ts +29 -0
- package/Utils/API.ts +6 -1
- package/Utils/Analytics.ts +55 -2
- package/Utils/Monitor/MonitorMetricType.ts +40 -0
- package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +587 -37
- package/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.ts +115 -0
- package/build/dist/Models/DatabaseModels/GlobalOidc.js +21 -0
- package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSso.js +21 -0
- package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MarketingConversion.js +20 -10
- package/build/dist/Models/DatabaseModels/MarketingConversion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +47 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +4 -4
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +101 -3
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +101 -3
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js +101 -3
- package/build/dist/Models/DatabaseModels/UserIncomingCallNumber.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +38 -0
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +101 -3
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +100 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +69 -13
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +25 -4
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/UserCallAPI.js +42 -38
- package/build/dist/Server/API/UserCallAPI.js.map +1 -1
- package/build/dist/Server/API/UserEmailAPI.js +42 -38
- package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js +37 -32
- package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js +341 -0
- package/build/dist/Server/API/UserNotificationMethodAdminAPI.js.map +1 -0
- package/build/dist/Server/API/UserPushAPI.js +95 -2
- package/build/dist/Server/API/UserPushAPI.js.map +1 -1
- package/build/dist/Server/API/UserSmsAPI.js +42 -38
- package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
- package/build/dist/Server/API/UserWhatsAppAPI.js +42 -40
- package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +6 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787142779538-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787156982416-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787700000000-FixTotpOtpUrlAlgorithm.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787800000000-AddScopeToNetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js +29 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787900000000-AddRestrictToAttachedProjectsToGlobalSso.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/SlackAuthorization.js +28 -4
- package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +197 -22
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js +393 -0
- package/build/dist/Server/Middleware/VerificationCodeRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/WhatsAppAuthorization.js +32 -2
- package/build/dist/Server/Middleware/WhatsAppAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +136 -0
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +74 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/GlobalOidcProjectService.js +105 -0
- package/build/dist/Server/Services/GlobalOidcProjectService.js.map +1 -1
- package/build/dist/Server/Services/GlobalOidcService.js +127 -0
- package/build/dist/Server/Services/GlobalOidcService.js.map +1 -1
- package/build/dist/Server/Services/GlobalSsoProjectService.js +105 -0
- package/build/dist/Server/Services/GlobalSsoProjectService.js.map +1 -1
- package/build/dist/Server/Services/GlobalSsoService.js +127 -0
- package/build/dist/Server/Services/GlobalSsoService.js.map +1 -1
- package/build/dist/Server/Services/LogAggregationService.js +5 -0
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +69 -30
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +43 -7
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +54 -22
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +78 -17
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +45 -74
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js +1117 -0
- package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +20 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +77 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +50 -17
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +48 -15
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +27 -0
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js +46 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.js.map +1 -1
- package/build/dist/Server/Utils/ChannelVerification.js +348 -0
- package/build/dist/Server/Utils/ChannelVerification.js.map +1 -0
- package/build/dist/Server/Utils/CronTab.js +66 -0
- package/build/dist/Server/Utils/CronTab.js.map +1 -1
- package/build/dist/Server/Utils/GlobalSsoAuthorization.js +112 -0
- package/build/dist/Server/Utils/GlobalSsoAuthorization.js.map +1 -0
- package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js +17 -1
- package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Meta.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Meta.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Reddit.js +1 -1
- package/build/dist/Server/Utils/Marketing/Providers/Reddit.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js +37 -35
- package/build/dist/Server/Utils/Monitor/Criteria/APIRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js +20 -22
- package/build/dist/Server/Utils/Monitor/Criteria/DomainMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +370 -42
- package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js +34 -37
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js +21 -25
- package/build/dist/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js +64 -52
- package/build/dist/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +25 -29
- package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +20 -17
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +8 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +17 -14
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +123 -23
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +95 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +313 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +3 -3
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +67 -26
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js +39 -0
- package/build/dist/Server/Utils/StatusPageContentSecurityPolicy.js.map +1 -0
- package/build/dist/Server/Utils/StatusPageCustomizationAccess.js +85 -0
- package/build/dist/Server/Utils/StatusPageCustomizationAccess.js.map +1 -0
- package/build/dist/Server/Utils/TotpAuth.js +127 -8
- package/build/dist/Server/Utils/TotpAuth.js.map +1 -1
- package/build/dist/Server/Utils/UserRegistrationToken.js +170 -0
- package/build/dist/Server/Utils/UserRegistrationToken.js.map +1 -0
- package/build/dist/Server/Utils/VerificationCode.js +120 -0
- package/build/dist/Server/Utils/VerificationCode.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/Marketing/MarketingConversion.js +10 -0
- package/build/dist/Types/Marketing/MarketingConversion.js.map +1 -1
- package/build/dist/Types/Monitor/CriteriaFilter.js +1 -0
- package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +42 -21
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +77 -5
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +18 -6
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js +1028 -0
- package/build/dist/Types/Monitor/ServiceAlertTemplates.js.map +1 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js +46 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceLinkRuleScope.js.map +1 -0
- package/build/dist/Types/Permission.js +33 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js +27 -0
- package/build/dist/Types/PushNotification/AndroidNotificationChannel.js.map +1 -0
- package/build/dist/Types/Service/ServiceLanguage.js +96 -0
- package/build/dist/Types/Service/ServiceLanguage.js.map +1 -0
- package/build/dist/Types/Text.js +82 -17
- package/build/dist/Types/Text.js.map +1 -1
- package/build/dist/UI/Components/Button/Button.js +22 -14
- package/build/dist/UI/Components/Button/Button.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js +35 -3
- package/build/dist/UI/Components/CodeBlock/CodeBlock.js.map +1 -1
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js +57 -0
- package/build/dist/UI/Components/CodeBlock/LanguageRegistry.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +439 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +135 -0
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js +83 -0
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js +47 -0
- package/build/dist/UI/Components/CommandPalette/RecentCommands.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/Types.js +2 -0
- package/build/dist/UI/Components/CommandPalette/Types.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js +88 -0
- package/build/dist/UI/Components/CommandPalette/UseProviderSearch.js.map +1 -0
- package/build/dist/UI/Components/Dropdown/Dropdown.js +6 -1
- package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js +1 -1
- package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js +2 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +10 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js +2 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +4 -1
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js +33 -0
- package/build/dist/UI/Components/Forms/Utils/FormAnalyticsName.js.map +1 -0
- package/build/dist/UI/Components/List/List.js +19 -5
- package/build/dist/UI/Components/List/List.js.map +1 -1
- package/build/dist/UI/Components/List/ListSkeleton.js +21 -0
- package/build/dist/UI/Components/List/ListSkeleton.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/LazyMarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +52 -25
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +2 -2
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js +2 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +9 -2
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +32 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +5 -1
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js +29 -5
- package/build/dist/UI/Components/OrderedStatesList/OrderedStatesList.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js +23 -1
- package/build/dist/UI/Components/SideMenu/CountModelSideMenuItem.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +23 -2
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Components/Skeleton/Skeleton.js +23 -0
- package/build/dist/UI/Components/Skeleton/Skeleton.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +35 -24
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableSkeletonRows.js +52 -0
- package/build/dist/UI/Components/Table/TableSkeletonRows.js.map +1 -0
- package/build/dist/UI/Components/Tabs/Tab.js +1 -1
- package/build/dist/UI/Components/Tabs/Tab.js.map +1 -1
- package/build/dist/UI/Components/Toast/Toast.js +77 -23
- package/build/dist/UI/Components/Toast/Toast.js.map +1 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +37 -15
- package/build/dist/UI/Components/Toast/ToastInit.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +18 -9
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/ModelListCache.js +126 -0
- package/build/dist/UI/Utils/ModelListCache.js.map +1 -0
- package/build/dist/UI/Utils/Project.js +24 -1
- package/build/dist/UI/Utils/Project.js.map +1 -1
- package/build/dist/Utils/API.js +6 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Analytics.js +50 -2
- package/build/dist/Utils/Analytics.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorMetricType.js +37 -0
- package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +318 -37
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js +87 -0
- package/build/dist/Utils/NetworkDiscovery/UnclaimedScanDiagnosis.js.map +1 -0
- package/jest.config.json +1 -1
- package/package.json +2 -3
- package/Server/Utils/Monitor/MonitorClusterContext.ts +0 -182
- package/Tests/__mocks__/otpauth.js +0 -30
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +0 -141
- package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +0 -1
|
@@ -0,0 +1,1219 @@
|
|
|
1
|
+
import ServerMonitorCriteria from "../../../../../Server/Utils/Monitor/Criteria/ServerMonitorCriteria";
|
|
2
|
+
import EvaluateOverTime, {
|
|
3
|
+
OverTimeCriteriaValue,
|
|
4
|
+
} from "../../../../../Server/Utils/Monitor/Criteria/EvaluateOverTime";
|
|
5
|
+
import BasicInfrastructureMetrics, {
|
|
6
|
+
BasicDiskMetrics,
|
|
7
|
+
LoadMetrics,
|
|
8
|
+
} from "../../../../../Types/Infrastructure/BasicMetrics";
|
|
9
|
+
import {
|
|
10
|
+
CheckOn,
|
|
11
|
+
CriteriaFilter,
|
|
12
|
+
EvaluateOverTimeType,
|
|
13
|
+
FilterType,
|
|
14
|
+
} from "../../../../../Types/Monitor/CriteriaFilter";
|
|
15
|
+
import ServerMonitorResponse, {
|
|
16
|
+
ServerProcess,
|
|
17
|
+
} from "../../../../../Types/Monitor/ServerMonitor/ServerMonitorResponse";
|
|
18
|
+
import ObjectID from "../../../../../Types/ObjectID";
|
|
19
|
+
import { afterEach, describe, expect, jest, test } from "@jest/globals";
|
|
20
|
+
|
|
21
|
+
/*
|
|
22
|
+
* Fixed reference "now" so that the difference-in-minutes computation the
|
|
23
|
+
* evaluator performs (requestReceivedAt vs timeNow) is fully deterministic
|
|
24
|
+
* and never touches the wall clock.
|
|
25
|
+
*/
|
|
26
|
+
const BASE_TIME: Date = new Date("2026-08-20T12:00:00.000Z");
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
* Build a BasicInfrastructureMetrics payload. Every sub-metric has a benign
|
|
30
|
+
* default so an individual test only supplies the field it exercises.
|
|
31
|
+
*/
|
|
32
|
+
function buildMetrics(input: {
|
|
33
|
+
cpuPercentUsed?: number | undefined;
|
|
34
|
+
cpuIoWaitPercent?: number | undefined;
|
|
35
|
+
memoryPercentUsed?: number | undefined;
|
|
36
|
+
swapPercentUsed?: number | undefined;
|
|
37
|
+
diskMetrics?: Array<BasicDiskMetrics> | undefined;
|
|
38
|
+
loadMetrics?: LoadMetrics | undefined;
|
|
39
|
+
}): BasicInfrastructureMetrics {
|
|
40
|
+
return {
|
|
41
|
+
cpuMetrics: {
|
|
42
|
+
percentUsed: input.cpuPercentUsed ?? 0,
|
|
43
|
+
cores: 4,
|
|
44
|
+
timeIoWaitPercent: input.cpuIoWaitPercent,
|
|
45
|
+
},
|
|
46
|
+
memoryMetrics: {
|
|
47
|
+
total: 100,
|
|
48
|
+
free: 50,
|
|
49
|
+
used: 50,
|
|
50
|
+
percentUsed: input.memoryPercentUsed ?? 0,
|
|
51
|
+
percentFree: 100 - (input.memoryPercentUsed ?? 0),
|
|
52
|
+
swapPercentUsed: input.swapPercentUsed,
|
|
53
|
+
},
|
|
54
|
+
diskMetrics: input.diskMetrics ?? [],
|
|
55
|
+
loadMetrics: input.loadMetrics,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/*
|
|
60
|
+
* Build a single disk metric entry. percentUsed / percentFree are optional so
|
|
61
|
+
* the evaluator's `percentUsed ?? percentFree ?? 0` fallback chain can be
|
|
62
|
+
* exercised; the cast tolerates the deliberately-absent required field.
|
|
63
|
+
*/
|
|
64
|
+
function buildDiskMetric(input: {
|
|
65
|
+
diskPath: string;
|
|
66
|
+
percentUsed?: number | undefined;
|
|
67
|
+
percentFree?: number | undefined;
|
|
68
|
+
}): BasicDiskMetrics {
|
|
69
|
+
return {
|
|
70
|
+
total: 100,
|
|
71
|
+
free: 40,
|
|
72
|
+
used: 60,
|
|
73
|
+
diskPath: input.diskPath,
|
|
74
|
+
percentUsed: input.percentUsed as number,
|
|
75
|
+
percentFree: input.percentFree as number,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function buildProcess(input: {
|
|
80
|
+
pid?: number | undefined;
|
|
81
|
+
name?: string | undefined;
|
|
82
|
+
command?: string | undefined;
|
|
83
|
+
}): ServerProcess {
|
|
84
|
+
return {
|
|
85
|
+
pid: input.pid ?? 1,
|
|
86
|
+
name: input.name ?? "proc",
|
|
87
|
+
command: input.command ?? "/bin/proc",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
* Build a ServerMonitorResponse. `minutesSinceLastCheck` positions
|
|
93
|
+
* requestReceivedAt that many minutes before the fixed timeNow, which drives
|
|
94
|
+
* the online/offline decision for IsOnline checks.
|
|
95
|
+
*/
|
|
96
|
+
function buildServerResponse(input: {
|
|
97
|
+
metrics?: BasicInfrastructureMetrics | undefined;
|
|
98
|
+
processes?: Array<ServerProcess> | undefined;
|
|
99
|
+
onlyCheckRequestReceivedAt?: boolean | undefined;
|
|
100
|
+
minutesSinceLastCheck?: number | undefined;
|
|
101
|
+
}): ServerMonitorResponse {
|
|
102
|
+
const minutesAgo: number = input.minutesSinceLastCheck ?? 0;
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
projectId: ObjectID.generate(),
|
|
106
|
+
monitorId: ObjectID.generate(),
|
|
107
|
+
hostname: "test-host",
|
|
108
|
+
requestReceivedAt: new Date(BASE_TIME.getTime() - minutesAgo * 60000),
|
|
109
|
+
timeNow: BASE_TIME,
|
|
110
|
+
onlyCheckRequestReceivedAt: input.onlyCheckRequestReceivedAt ?? false,
|
|
111
|
+
basicInfrastructureMetrics: input.metrics,
|
|
112
|
+
processes: input.processes,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function evaluate(
|
|
117
|
+
dataToProcess: ServerMonitorResponse,
|
|
118
|
+
criteriaFilter: CriteriaFilter,
|
|
119
|
+
): Promise<string | null> {
|
|
120
|
+
return ServerMonitorCriteria.isMonitorInstanceCriteriaFilterMet({
|
|
121
|
+
dataToProcess,
|
|
122
|
+
criteriaFilter,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
describe("ServerMonitorCriteria.isMonitorInstanceCriteriaFilterMet", () => {
|
|
127
|
+
afterEach(() => {
|
|
128
|
+
jest.restoreAllMocks();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("an unrelated CheckOn is not claimed by this evaluator", async () => {
|
|
132
|
+
const result: string | null = await evaluate(buildServerResponse({}), {
|
|
133
|
+
checkOn: CheckOn.ResponseTime,
|
|
134
|
+
filterType: FilterType.LessThan,
|
|
135
|
+
value: 1000,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
expect(result).toBeNull();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe("IsOnline", () => {
|
|
142
|
+
/*
|
|
143
|
+
* A recent check (difference < 3 minute default) is treated as online.
|
|
144
|
+
*/
|
|
145
|
+
test("recent check + True → met", async () => {
|
|
146
|
+
const result: string | null = await evaluate(
|
|
147
|
+
buildServerResponse({ minutesSinceLastCheck: 1 }),
|
|
148
|
+
{
|
|
149
|
+
checkOn: CheckOn.IsOnline,
|
|
150
|
+
filterType: FilterType.True,
|
|
151
|
+
value: undefined,
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
expect(result).toContain(CheckOn.IsOnline);
|
|
156
|
+
expect(result).toContain("true");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
test("recent check + False → not met", async () => {
|
|
160
|
+
const result: string | null = await evaluate(
|
|
161
|
+
buildServerResponse({ minutesSinceLastCheck: 1 }),
|
|
162
|
+
{
|
|
163
|
+
checkOn: CheckOn.IsOnline,
|
|
164
|
+
filterType: FilterType.False,
|
|
165
|
+
value: undefined,
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
expect(result).toBeNull();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
/*
|
|
173
|
+
* A stale check (difference >= 3 minute default) is treated as offline.
|
|
174
|
+
*/
|
|
175
|
+
test("stale check + False → met", async () => {
|
|
176
|
+
const result: string | null = await evaluate(
|
|
177
|
+
buildServerResponse({ minutesSinceLastCheck: 5 }),
|
|
178
|
+
{
|
|
179
|
+
checkOn: CheckOn.IsOnline,
|
|
180
|
+
filterType: FilterType.False,
|
|
181
|
+
value: undefined,
|
|
182
|
+
},
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
expect(result).toContain(CheckOn.IsOnline);
|
|
186
|
+
expect(result).toContain("false");
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("stale check + True → not met", async () => {
|
|
190
|
+
const result: string | null = await evaluate(
|
|
191
|
+
buildServerResponse({ minutesSinceLastCheck: 5 }),
|
|
192
|
+
{
|
|
193
|
+
checkOn: CheckOn.IsOnline,
|
|
194
|
+
filterType: FilterType.True,
|
|
195
|
+
value: undefined,
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
expect(result).toBeNull();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
/*
|
|
203
|
+
* The offline boundary is inclusive: a difference of exactly the 3 minute
|
|
204
|
+
* threshold takes the offline branch.
|
|
205
|
+
*/
|
|
206
|
+
test("difference exactly at the 3 minute threshold → offline branch", async () => {
|
|
207
|
+
const result: string | null = await evaluate(
|
|
208
|
+
buildServerResponse({ minutesSinceLastCheck: 3 }),
|
|
209
|
+
{
|
|
210
|
+
checkOn: CheckOn.IsOnline,
|
|
211
|
+
filterType: FilterType.False,
|
|
212
|
+
value: undefined,
|
|
213
|
+
},
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
expect(result).toContain("false");
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test("difference just below the 3 minute threshold → online branch", async () => {
|
|
220
|
+
const result: string | null = await evaluate(
|
|
221
|
+
buildServerResponse({ minutesSinceLastCheck: 2 }),
|
|
222
|
+
{
|
|
223
|
+
checkOn: CheckOn.IsOnline,
|
|
224
|
+
filterType: FilterType.True,
|
|
225
|
+
value: undefined,
|
|
226
|
+
},
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
expect(result).toContain("true");
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
/*
|
|
233
|
+
* The IsOnline branches deliberately ignore onlyCheckRequestReceivedAt —
|
|
234
|
+
* liveness must still be evaluated on a heartbeat-only payload.
|
|
235
|
+
*/
|
|
236
|
+
test("evaluates even when onlyCheckRequestReceivedAt is set", async () => {
|
|
237
|
+
const result: string | null = await evaluate(
|
|
238
|
+
buildServerResponse({
|
|
239
|
+
minutesSinceLastCheck: 1,
|
|
240
|
+
onlyCheckRequestReceivedAt: true,
|
|
241
|
+
}),
|
|
242
|
+
{
|
|
243
|
+
checkOn: CheckOn.IsOnline,
|
|
244
|
+
filterType: FilterType.True,
|
|
245
|
+
value: undefined,
|
|
246
|
+
},
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
expect(result).toContain(CheckOn.IsOnline);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
/*
|
|
253
|
+
* A filter type the boolean comparator does not handle (a numeric
|
|
254
|
+
* operator) is undecidable for IsOnline.
|
|
255
|
+
*/
|
|
256
|
+
test("unhandled filter type → undecidable", async () => {
|
|
257
|
+
const result: string | null = await evaluate(
|
|
258
|
+
buildServerResponse({ minutesSinceLastCheck: 1 }),
|
|
259
|
+
{
|
|
260
|
+
checkOn: CheckOn.IsOnline,
|
|
261
|
+
filterType: FilterType.GreaterThan,
|
|
262
|
+
value: 1,
|
|
263
|
+
},
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
expect(result).toBeNull();
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe("CPUUsagePercent", () => {
|
|
271
|
+
test("usage above threshold + GreaterThan → met", async () => {
|
|
272
|
+
const result: string | null = await evaluate(
|
|
273
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 80 }) }),
|
|
274
|
+
{
|
|
275
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
276
|
+
filterType: FilterType.GreaterThan,
|
|
277
|
+
value: 50,
|
|
278
|
+
},
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
expect(result).toContain(CheckOn.CPUUsagePercent);
|
|
282
|
+
expect(result).toContain("greater than");
|
|
283
|
+
expect(result).toContain("80");
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("usage below threshold + GreaterThan → not met", async () => {
|
|
287
|
+
const result: string | null = await evaluate(
|
|
288
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 30 }) }),
|
|
289
|
+
{
|
|
290
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
291
|
+
filterType: FilterType.GreaterThan,
|
|
292
|
+
value: 50,
|
|
293
|
+
},
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
expect(result).toBeNull();
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test("numeric string threshold is accepted", async () => {
|
|
300
|
+
const result: string | null = await evaluate(
|
|
301
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 80 }) }),
|
|
302
|
+
{
|
|
303
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
304
|
+
filterType: FilterType.GreaterThan,
|
|
305
|
+
value: "50",
|
|
306
|
+
},
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
expect(result).toContain(CheckOn.CPUUsagePercent);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test("non-numeric threshold → undecidable", async () => {
|
|
313
|
+
const result: string | null = await evaluate(
|
|
314
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 80 }) }),
|
|
315
|
+
{
|
|
316
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
317
|
+
filterType: FilterType.GreaterThan,
|
|
318
|
+
value: "not-a-number",
|
|
319
|
+
},
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
expect(result).toBeNull();
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
/*
|
|
326
|
+
* With no infrastructure metrics present the CPU value falls back to 0,
|
|
327
|
+
* so a LessThan-1 check is met while a GreaterThan-1 check is not.
|
|
328
|
+
*/
|
|
329
|
+
test("missing metrics fall back to zero usage", async () => {
|
|
330
|
+
const result: string | null = await evaluate(buildServerResponse({}), {
|
|
331
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
332
|
+
filterType: FilterType.LessThan,
|
|
333
|
+
value: 1,
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
expect(result).toContain(CheckOn.CPUUsagePercent);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
/*
|
|
340
|
+
* onlyCheckRequestReceivedAt short-circuits every infrastructure metric
|
|
341
|
+
* branch — a heartbeat payload carries no fresh metric to evaluate.
|
|
342
|
+
*/
|
|
343
|
+
test("onlyCheckRequestReceivedAt short-circuits the CPU branch", async () => {
|
|
344
|
+
const result: string | null = await evaluate(
|
|
345
|
+
buildServerResponse({
|
|
346
|
+
metrics: buildMetrics({ cpuPercentUsed: 90 }),
|
|
347
|
+
onlyCheckRequestReceivedAt: true,
|
|
348
|
+
}),
|
|
349
|
+
{
|
|
350
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
351
|
+
filterType: FilterType.GreaterThan,
|
|
352
|
+
value: 50,
|
|
353
|
+
},
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
expect(result).toBeNull();
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
describe("MemoryUsagePercent", () => {
|
|
361
|
+
test("usage below threshold + LessThan → met", async () => {
|
|
362
|
+
const result: string | null = await evaluate(
|
|
363
|
+
buildServerResponse({
|
|
364
|
+
metrics: buildMetrics({ memoryPercentUsed: 40 }),
|
|
365
|
+
}),
|
|
366
|
+
{
|
|
367
|
+
checkOn: CheckOn.MemoryUsagePercent,
|
|
368
|
+
filterType: FilterType.LessThan,
|
|
369
|
+
value: 95,
|
|
370
|
+
},
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
expect(result).toContain(CheckOn.MemoryUsagePercent);
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
test("usage above threshold + LessThan → not met", async () => {
|
|
377
|
+
const result: string | null = await evaluate(
|
|
378
|
+
buildServerResponse({
|
|
379
|
+
metrics: buildMetrics({ memoryPercentUsed: 96 }),
|
|
380
|
+
}),
|
|
381
|
+
{
|
|
382
|
+
checkOn: CheckOn.MemoryUsagePercent,
|
|
383
|
+
filterType: FilterType.LessThan,
|
|
384
|
+
value: 95,
|
|
385
|
+
},
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
expect(result).toBeNull();
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
test("usage equal to threshold + GreaterThanOrEqualTo → met (boundary)", async () => {
|
|
392
|
+
const result: string | null = await evaluate(
|
|
393
|
+
buildServerResponse({
|
|
394
|
+
metrics: buildMetrics({ memoryPercentUsed: 90 }),
|
|
395
|
+
}),
|
|
396
|
+
{
|
|
397
|
+
checkOn: CheckOn.MemoryUsagePercent,
|
|
398
|
+
filterType: FilterType.GreaterThanOrEqualTo,
|
|
399
|
+
value: 90,
|
|
400
|
+
},
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
expect(result).toContain(CheckOn.MemoryUsagePercent);
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
describe("SwapUsagePercent", () => {
|
|
408
|
+
test("swap usage above threshold + GreaterThan → met", async () => {
|
|
409
|
+
const result: string | null = await evaluate(
|
|
410
|
+
buildServerResponse({ metrics: buildMetrics({ swapPercentUsed: 30 }) }),
|
|
411
|
+
{
|
|
412
|
+
checkOn: CheckOn.SwapUsagePercent,
|
|
413
|
+
filterType: FilterType.GreaterThan,
|
|
414
|
+
value: 20,
|
|
415
|
+
},
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
expect(result).toContain(CheckOn.SwapUsagePercent);
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
test("absent swap metric falls back to zero", async () => {
|
|
422
|
+
const result: string | null = await evaluate(
|
|
423
|
+
buildServerResponse({ metrics: buildMetrics({}) }),
|
|
424
|
+
{
|
|
425
|
+
checkOn: CheckOn.SwapUsagePercent,
|
|
426
|
+
filterType: FilterType.GreaterThan,
|
|
427
|
+
value: 20,
|
|
428
|
+
},
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
expect(result).toBeNull();
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
describe("CPUIoWaitPercent", () => {
|
|
436
|
+
test("io wait above threshold + GreaterThan → met", async () => {
|
|
437
|
+
const result: string | null = await evaluate(
|
|
438
|
+
buildServerResponse({
|
|
439
|
+
metrics: buildMetrics({ cpuIoWaitPercent: 15 }),
|
|
440
|
+
}),
|
|
441
|
+
{
|
|
442
|
+
checkOn: CheckOn.CPUIoWaitPercent,
|
|
443
|
+
filterType: FilterType.GreaterThan,
|
|
444
|
+
value: 10,
|
|
445
|
+
},
|
|
446
|
+
);
|
|
447
|
+
|
|
448
|
+
expect(result).toContain(CheckOn.CPUIoWaitPercent);
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
test("absent io wait metric falls back to zero", async () => {
|
|
452
|
+
const result: string | null = await evaluate(
|
|
453
|
+
buildServerResponse({ metrics: buildMetrics({}) }),
|
|
454
|
+
{
|
|
455
|
+
checkOn: CheckOn.CPUIoWaitPercent,
|
|
456
|
+
filterType: FilterType.GreaterThan,
|
|
457
|
+
value: 10,
|
|
458
|
+
},
|
|
459
|
+
);
|
|
460
|
+
|
|
461
|
+
expect(result).toBeNull();
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
describe("LoadAverage", () => {
|
|
466
|
+
const load: LoadMetrics = { load1: 2, load5: 1.5, load15: 0.5 };
|
|
467
|
+
|
|
468
|
+
test("LoadAverage1Min reads the 1 minute figure", async () => {
|
|
469
|
+
const result: string | null = await evaluate(
|
|
470
|
+
buildServerResponse({ metrics: buildMetrics({ loadMetrics: load }) }),
|
|
471
|
+
{
|
|
472
|
+
checkOn: CheckOn.LoadAverage1Min,
|
|
473
|
+
filterType: FilterType.GreaterThan,
|
|
474
|
+
value: 1,
|
|
475
|
+
},
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
expect(result).toContain(CheckOn.LoadAverage1Min);
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
test("LoadAverage5Min reads the 5 minute figure", async () => {
|
|
482
|
+
const result: string | null = await evaluate(
|
|
483
|
+
buildServerResponse({ metrics: buildMetrics({ loadMetrics: load }) }),
|
|
484
|
+
{
|
|
485
|
+
checkOn: CheckOn.LoadAverage5Min,
|
|
486
|
+
filterType: FilterType.GreaterThan,
|
|
487
|
+
value: 1,
|
|
488
|
+
},
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
expect(result).toContain(CheckOn.LoadAverage5Min);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
/*
|
|
495
|
+
* The 15 minute figure (0.5) is below the threshold, so the same filter
|
|
496
|
+
* that matched the 1 and 5 minute figures does not fire here — proving
|
|
497
|
+
* the correct load slot is selected per CheckOn.
|
|
498
|
+
*/
|
|
499
|
+
test("LoadAverage15Min reads the 15 minute figure → not met", async () => {
|
|
500
|
+
const result: string | null = await evaluate(
|
|
501
|
+
buildServerResponse({ metrics: buildMetrics({ loadMetrics: load }) }),
|
|
502
|
+
{
|
|
503
|
+
checkOn: CheckOn.LoadAverage15Min,
|
|
504
|
+
filterType: FilterType.GreaterThan,
|
|
505
|
+
value: 1,
|
|
506
|
+
},
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
expect(result).toBeNull();
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
test("absent load metrics fall back to zero", async () => {
|
|
513
|
+
const result: string | null = await evaluate(
|
|
514
|
+
buildServerResponse({ metrics: buildMetrics({}) }),
|
|
515
|
+
{
|
|
516
|
+
checkOn: CheckOn.LoadAverage1Min,
|
|
517
|
+
filterType: FilterType.LessThan,
|
|
518
|
+
value: 1,
|
|
519
|
+
},
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
expect(result).toContain(CheckOn.LoadAverage1Min);
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
describe("DiskUsagePercent", () => {
|
|
527
|
+
/*
|
|
528
|
+
* A trailing slash on the requested path and none on the reported path
|
|
529
|
+
* still resolve to the same disk after normalization.
|
|
530
|
+
*/
|
|
531
|
+
test("matches disk after path normalization and uses percentUsed", async () => {
|
|
532
|
+
const result: string | null = await evaluate(
|
|
533
|
+
buildServerResponse({
|
|
534
|
+
metrics: buildMetrics({
|
|
535
|
+
diskMetrics: [
|
|
536
|
+
buildDiskMetric({ diskPath: "/var/log", percentUsed: 75 }),
|
|
537
|
+
],
|
|
538
|
+
}),
|
|
539
|
+
}),
|
|
540
|
+
{
|
|
541
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
542
|
+
filterType: FilterType.GreaterThan,
|
|
543
|
+
value: 50,
|
|
544
|
+
serverMonitorOptions: { diskPath: "/var/log/" },
|
|
545
|
+
},
|
|
546
|
+
);
|
|
547
|
+
|
|
548
|
+
expect(result).toContain(CheckOn.DiskUsagePercent);
|
|
549
|
+
expect(result).toContain("/var/log/");
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
/*
|
|
553
|
+
* Backslash separators and mixed case both normalize away before the
|
|
554
|
+
* lookup, so a Windows-style reported path matches a forward-slash
|
|
555
|
+
* lower-case request.
|
|
556
|
+
*/
|
|
557
|
+
test("normalizes backslashes and case when matching the disk", async () => {
|
|
558
|
+
const result: string | null = await evaluate(
|
|
559
|
+
buildServerResponse({
|
|
560
|
+
metrics: buildMetrics({
|
|
561
|
+
diskMetrics: [
|
|
562
|
+
buildDiskMetric({ diskPath: "C:\\Data", percentUsed: 88 }),
|
|
563
|
+
],
|
|
564
|
+
}),
|
|
565
|
+
}),
|
|
566
|
+
{
|
|
567
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
568
|
+
filterType: FilterType.GreaterThan,
|
|
569
|
+
value: 50,
|
|
570
|
+
serverMonitorOptions: { diskPath: "c:/data" },
|
|
571
|
+
},
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
expect(result).toContain(CheckOn.DiskUsagePercent);
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
/*
|
|
578
|
+
* With no serverMonitorOptions the requested path defaults to "/".
|
|
579
|
+
*/
|
|
580
|
+
test("defaults to the root disk when no path option is given", async () => {
|
|
581
|
+
const result: string | null = await evaluate(
|
|
582
|
+
buildServerResponse({
|
|
583
|
+
metrics: buildMetrics({
|
|
584
|
+
diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 40 })],
|
|
585
|
+
}),
|
|
586
|
+
}),
|
|
587
|
+
{
|
|
588
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
589
|
+
filterType: FilterType.GreaterThanOrEqualTo,
|
|
590
|
+
value: 40,
|
|
591
|
+
},
|
|
592
|
+
);
|
|
593
|
+
|
|
594
|
+
expect(result).toContain(CheckOn.DiskUsagePercent);
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
/*
|
|
598
|
+
* When percentUsed is absent the evaluator falls back to percentFree.
|
|
599
|
+
*/
|
|
600
|
+
test("falls back to percentFree when percentUsed is absent", async () => {
|
|
601
|
+
const result: string | null = await evaluate(
|
|
602
|
+
buildServerResponse({
|
|
603
|
+
metrics: buildMetrics({
|
|
604
|
+
diskMetrics: [
|
|
605
|
+
buildDiskMetric({
|
|
606
|
+
diskPath: "/data",
|
|
607
|
+
percentUsed: undefined,
|
|
608
|
+
percentFree: 65,
|
|
609
|
+
}),
|
|
610
|
+
],
|
|
611
|
+
}),
|
|
612
|
+
}),
|
|
613
|
+
{
|
|
614
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
615
|
+
filterType: FilterType.GreaterThan,
|
|
616
|
+
value: 50,
|
|
617
|
+
serverMonitorOptions: { diskPath: "/data" },
|
|
618
|
+
},
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
expect(result).toContain(CheckOn.DiskUsagePercent);
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
/*
|
|
625
|
+
* A requested path that matches no reported disk yields a usage of 0.
|
|
626
|
+
*/
|
|
627
|
+
test("unmatched disk path yields zero usage", async () => {
|
|
628
|
+
const result: string | null = await evaluate(
|
|
629
|
+
buildServerResponse({
|
|
630
|
+
metrics: buildMetrics({
|
|
631
|
+
diskMetrics: [
|
|
632
|
+
buildDiskMetric({ diskPath: "/other", percentUsed: 99 }),
|
|
633
|
+
],
|
|
634
|
+
}),
|
|
635
|
+
}),
|
|
636
|
+
{
|
|
637
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
638
|
+
filterType: FilterType.LessThan,
|
|
639
|
+
value: 10,
|
|
640
|
+
serverMonitorOptions: { diskPath: "/data" },
|
|
641
|
+
},
|
|
642
|
+
);
|
|
643
|
+
|
|
644
|
+
expect(result).toContain(CheckOn.DiskUsagePercent);
|
|
645
|
+
});
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
describe("ServerProcessName", () => {
|
|
649
|
+
test("IsExecuting + process present → met", async () => {
|
|
650
|
+
const result: string | null = await evaluate(
|
|
651
|
+
buildServerResponse({
|
|
652
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
653
|
+
}),
|
|
654
|
+
{
|
|
655
|
+
checkOn: CheckOn.ServerProcessName,
|
|
656
|
+
filterType: FilterType.IsExecuting,
|
|
657
|
+
value: "nginx",
|
|
658
|
+
},
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
expect(result).toBe("Process nginx is executing.");
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
/*
|
|
665
|
+
* Matching is case-insensitive and trimmed, but the original threshold
|
|
666
|
+
* text is echoed back in the message.
|
|
667
|
+
*/
|
|
668
|
+
test("IsExecuting matches case-insensitively", async () => {
|
|
669
|
+
const result: string | null = await evaluate(
|
|
670
|
+
buildServerResponse({
|
|
671
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
672
|
+
}),
|
|
673
|
+
{
|
|
674
|
+
checkOn: CheckOn.ServerProcessName,
|
|
675
|
+
filterType: FilterType.IsExecuting,
|
|
676
|
+
value: "NGINX",
|
|
677
|
+
},
|
|
678
|
+
);
|
|
679
|
+
|
|
680
|
+
expect(result).toBe("Process NGINX is executing.");
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
test("IsExecuting + process absent → not met", async () => {
|
|
684
|
+
const result: string | null = await evaluate(
|
|
685
|
+
buildServerResponse({
|
|
686
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
687
|
+
}),
|
|
688
|
+
{
|
|
689
|
+
checkOn: CheckOn.ServerProcessName,
|
|
690
|
+
filterType: FilterType.IsExecuting,
|
|
691
|
+
value: "redis",
|
|
692
|
+
},
|
|
693
|
+
);
|
|
694
|
+
|
|
695
|
+
expect(result).toBeNull();
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
test("IsNotExecuting + process absent → met", async () => {
|
|
699
|
+
const result: string | null = await evaluate(
|
|
700
|
+
buildServerResponse({
|
|
701
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
702
|
+
}),
|
|
703
|
+
{
|
|
704
|
+
checkOn: CheckOn.ServerProcessName,
|
|
705
|
+
filterType: FilterType.IsNotExecuting,
|
|
706
|
+
value: "redis",
|
|
707
|
+
},
|
|
708
|
+
);
|
|
709
|
+
|
|
710
|
+
expect(result).toBe("Process redis is not executing.");
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
test("IsNotExecuting + process present → not met", async () => {
|
|
714
|
+
const result: string | null = await evaluate(
|
|
715
|
+
buildServerResponse({
|
|
716
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
717
|
+
}),
|
|
718
|
+
{
|
|
719
|
+
checkOn: CheckOn.ServerProcessName,
|
|
720
|
+
filterType: FilterType.IsNotExecuting,
|
|
721
|
+
value: "nginx",
|
|
722
|
+
},
|
|
723
|
+
);
|
|
724
|
+
|
|
725
|
+
expect(result).toBeNull();
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
/*
|
|
729
|
+
* An absent processes array is treated as an empty list, so nothing is
|
|
730
|
+
* executing and IsNotExecuting is satisfied.
|
|
731
|
+
*/
|
|
732
|
+
test("absent processes list satisfies IsNotExecuting", async () => {
|
|
733
|
+
const result: string | null = await evaluate(buildServerResponse({}), {
|
|
734
|
+
checkOn: CheckOn.ServerProcessName,
|
|
735
|
+
filterType: FilterType.IsNotExecuting,
|
|
736
|
+
value: "nginx",
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
expect(result).toBe("Process nginx is not executing.");
|
|
740
|
+
});
|
|
741
|
+
|
|
742
|
+
/*
|
|
743
|
+
* A falsy threshold (undefined value) skips the whole process block via
|
|
744
|
+
* the `threshold &&` guard, leaving the check undecidable.
|
|
745
|
+
*/
|
|
746
|
+
test("undefined threshold skips the process block", async () => {
|
|
747
|
+
const result: string | null = await evaluate(
|
|
748
|
+
buildServerResponse({
|
|
749
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
750
|
+
}),
|
|
751
|
+
{
|
|
752
|
+
checkOn: CheckOn.ServerProcessName,
|
|
753
|
+
filterType: FilterType.IsExecuting,
|
|
754
|
+
value: undefined,
|
|
755
|
+
},
|
|
756
|
+
);
|
|
757
|
+
|
|
758
|
+
expect(result).toBeNull();
|
|
759
|
+
});
|
|
760
|
+
|
|
761
|
+
/*
|
|
762
|
+
* A filter type that is neither executing nor not-executing falls through
|
|
763
|
+
* the process block without a decision.
|
|
764
|
+
*/
|
|
765
|
+
test("unhandled filter type → undecidable", async () => {
|
|
766
|
+
const result: string | null = await evaluate(
|
|
767
|
+
buildServerResponse({
|
|
768
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
769
|
+
}),
|
|
770
|
+
{
|
|
771
|
+
checkOn: CheckOn.ServerProcessName,
|
|
772
|
+
filterType: FilterType.EqualTo,
|
|
773
|
+
value: "nginx",
|
|
774
|
+
},
|
|
775
|
+
);
|
|
776
|
+
|
|
777
|
+
expect(result).toBeNull();
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
test("onlyCheckRequestReceivedAt short-circuits the process block", async () => {
|
|
781
|
+
const result: string | null = await evaluate(
|
|
782
|
+
buildServerResponse({
|
|
783
|
+
processes: [buildProcess({ name: "nginx" })],
|
|
784
|
+
onlyCheckRequestReceivedAt: true,
|
|
785
|
+
}),
|
|
786
|
+
{
|
|
787
|
+
checkOn: CheckOn.ServerProcessName,
|
|
788
|
+
filterType: FilterType.IsExecuting,
|
|
789
|
+
value: "nginx",
|
|
790
|
+
},
|
|
791
|
+
);
|
|
792
|
+
|
|
793
|
+
expect(result).toBeNull();
|
|
794
|
+
});
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
describe("ServerProcessPID", () => {
|
|
798
|
+
test("IsExecuting matches a numeric PID threshold", async () => {
|
|
799
|
+
const result: string | null = await evaluate(
|
|
800
|
+
buildServerResponse({
|
|
801
|
+
processes: [buildProcess({ pid: 4321 })],
|
|
802
|
+
}),
|
|
803
|
+
{
|
|
804
|
+
checkOn: CheckOn.ServerProcessPID,
|
|
805
|
+
filterType: FilterType.IsExecuting,
|
|
806
|
+
value: 4321,
|
|
807
|
+
},
|
|
808
|
+
);
|
|
809
|
+
|
|
810
|
+
expect(result).toBe("Process with PID 4321 is executing.");
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
test("IsNotExecuting + PID absent → met", async () => {
|
|
814
|
+
const result: string | null = await evaluate(
|
|
815
|
+
buildServerResponse({
|
|
816
|
+
processes: [buildProcess({ pid: 4321 })],
|
|
817
|
+
}),
|
|
818
|
+
{
|
|
819
|
+
checkOn: CheckOn.ServerProcessPID,
|
|
820
|
+
filterType: FilterType.IsNotExecuting,
|
|
821
|
+
value: "9999",
|
|
822
|
+
},
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
expect(result).toBe("Process with PID 9999 is not executing.");
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
/*
|
|
829
|
+
* The PID block has an explicit trailing null return, so an unhandled
|
|
830
|
+
* filter type resolves to null without falling through to later blocks.
|
|
831
|
+
*/
|
|
832
|
+
test("unhandled filter type → undecidable", async () => {
|
|
833
|
+
const result: string | null = await evaluate(
|
|
834
|
+
buildServerResponse({
|
|
835
|
+
processes: [buildProcess({ pid: 4321 })],
|
|
836
|
+
}),
|
|
837
|
+
{
|
|
838
|
+
checkOn: CheckOn.ServerProcessPID,
|
|
839
|
+
filterType: FilterType.EqualTo,
|
|
840
|
+
value: 4321,
|
|
841
|
+
},
|
|
842
|
+
);
|
|
843
|
+
|
|
844
|
+
expect(result).toBeNull();
|
|
845
|
+
});
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
describe("ServerProcessCommand", () => {
|
|
849
|
+
test("IsExecuting matches an exact command", async () => {
|
|
850
|
+
const result: string | null = await evaluate(
|
|
851
|
+
buildServerResponse({
|
|
852
|
+
processes: [buildProcess({ command: "/usr/bin/node server.js" })],
|
|
853
|
+
}),
|
|
854
|
+
{
|
|
855
|
+
checkOn: CheckOn.ServerProcessCommand,
|
|
856
|
+
filterType: FilterType.IsExecuting,
|
|
857
|
+
value: "/usr/bin/node server.js",
|
|
858
|
+
},
|
|
859
|
+
);
|
|
860
|
+
|
|
861
|
+
expect(result).toBe(
|
|
862
|
+
"Process with command /usr/bin/node server.js is executing.",
|
|
863
|
+
);
|
|
864
|
+
});
|
|
865
|
+
|
|
866
|
+
test("IsExecuting matches after trimming and lower-casing", async () => {
|
|
867
|
+
const result: string | null = await evaluate(
|
|
868
|
+
buildServerResponse({
|
|
869
|
+
processes: [buildProcess({ command: "/usr/bin/node server.js" })],
|
|
870
|
+
}),
|
|
871
|
+
{
|
|
872
|
+
checkOn: CheckOn.ServerProcessCommand,
|
|
873
|
+
filterType: FilterType.IsExecuting,
|
|
874
|
+
value: " /USR/bin/Node server.js ",
|
|
875
|
+
},
|
|
876
|
+
);
|
|
877
|
+
|
|
878
|
+
expect(result).toContain("is executing.");
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
test("IsNotExecuting + command absent → met", async () => {
|
|
882
|
+
const result: string | null = await evaluate(
|
|
883
|
+
buildServerResponse({
|
|
884
|
+
processes: [buildProcess({ command: "/usr/bin/node server.js" })],
|
|
885
|
+
}),
|
|
886
|
+
{
|
|
887
|
+
checkOn: CheckOn.ServerProcessCommand,
|
|
888
|
+
filterType: FilterType.IsNotExecuting,
|
|
889
|
+
value: "/bin/bash",
|
|
890
|
+
},
|
|
891
|
+
);
|
|
892
|
+
|
|
893
|
+
expect(result).toBe("Process with command /bin/bash is not executing.");
|
|
894
|
+
});
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
/*
|
|
898
|
+
* The evaluate-over-time path replaces the current metric value with the
|
|
899
|
+
* window recorded for the monitor. The DB-backed lookup is spied so these
|
|
900
|
+
* tests stay deterministic.
|
|
901
|
+
*/
|
|
902
|
+
describe("evaluate over time", () => {
|
|
903
|
+
/** The window produced a usable value. */
|
|
904
|
+
function usable(
|
|
905
|
+
value: Array<number | boolean> | number | boolean,
|
|
906
|
+
): OverTimeCriteriaValue {
|
|
907
|
+
return { earlyReturn: null, value: value };
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/** The window could not back the filter, so nothing is compared. */
|
|
911
|
+
function noUsableWindow(): OverTimeCriteriaValue {
|
|
912
|
+
return { earlyReturn: { result: null }, value: undefined };
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
function mockOverTime(
|
|
916
|
+
result: OverTimeCriteriaValue,
|
|
917
|
+
): ReturnType<typeof jest.spyOn> {
|
|
918
|
+
return jest
|
|
919
|
+
.spyOn(EvaluateOverTime, "getOverTimeValueForCriteriaFilter")
|
|
920
|
+
.mockResolvedValue(result) as ReturnType<typeof jest.spyOn>;
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
test("uses the over-time boolean series for IsOnline while online", async () => {
|
|
924
|
+
const spy: ReturnType<typeof jest.spyOn> = mockOverTime(
|
|
925
|
+
usable([true, false]),
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
const response: ServerMonitorResponse = buildServerResponse({
|
|
929
|
+
minutesSinceLastCheck: 5,
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
const result: string | null = await evaluate(response, {
|
|
933
|
+
checkOn: CheckOn.IsOnline,
|
|
934
|
+
filterType: FilterType.True,
|
|
935
|
+
value: undefined,
|
|
936
|
+
evaluateOverTime: true,
|
|
937
|
+
evaluateOverTimeOptions: {
|
|
938
|
+
timeValueInMinutes: 10,
|
|
939
|
+
evaluateOverTimeType: EvaluateOverTimeType.AnyValue,
|
|
940
|
+
},
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
expect(result).toContain(CheckOn.IsOnline);
|
|
944
|
+
expect(spy).toHaveBeenCalledWith(
|
|
945
|
+
expect.objectContaining({
|
|
946
|
+
projectId: response.projectId,
|
|
947
|
+
monitorId: response.monitorId,
|
|
948
|
+
criteriaFilter: expect.objectContaining({
|
|
949
|
+
checkOn: CheckOn.IsOnline,
|
|
950
|
+
}),
|
|
951
|
+
}),
|
|
952
|
+
);
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
/*
|
|
956
|
+
* timeValueInMinutes overrides the default offline threshold: a 5 minute
|
|
957
|
+
* gap is still "online" when the window is 10 minutes, which would have
|
|
958
|
+
* been offline under the default of 3.
|
|
959
|
+
*/
|
|
960
|
+
test("timeValueInMinutes overrides the offline threshold", async () => {
|
|
961
|
+
mockOverTime(usable([false, false]));
|
|
962
|
+
|
|
963
|
+
const result: string | null = await evaluate(
|
|
964
|
+
buildServerResponse({ minutesSinceLastCheck: 5 }),
|
|
965
|
+
{
|
|
966
|
+
checkOn: CheckOn.IsOnline,
|
|
967
|
+
filterType: FilterType.False,
|
|
968
|
+
value: undefined,
|
|
969
|
+
evaluateOverTime: true,
|
|
970
|
+
evaluateOverTimeOptions: {
|
|
971
|
+
timeValueInMinutes: 3,
|
|
972
|
+
evaluateOverTimeType: EvaluateOverTimeType.AllValues,
|
|
973
|
+
},
|
|
974
|
+
},
|
|
975
|
+
);
|
|
976
|
+
|
|
977
|
+
expect(result).toContain("false");
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
/*
|
|
981
|
+
* "Is Online" is the one filter that keeps its fallback: for a server
|
|
982
|
+
* monitor the absence of data IS the signal, and the last-check-in
|
|
983
|
+
* arithmetic above already implements the "wait this long" behaviour. So
|
|
984
|
+
* an unusable window still falls back to the "recent check -> online"
|
|
985
|
+
* default rather than declining to evaluate.
|
|
986
|
+
*/
|
|
987
|
+
test("empty over-time series falls back to the liveness default", async () => {
|
|
988
|
+
mockOverTime(noUsableWindow());
|
|
989
|
+
|
|
990
|
+
const result: string | null = await evaluate(
|
|
991
|
+
buildServerResponse({ minutesSinceLastCheck: 1 }),
|
|
992
|
+
{
|
|
993
|
+
checkOn: CheckOn.IsOnline,
|
|
994
|
+
filterType: FilterType.True,
|
|
995
|
+
value: undefined,
|
|
996
|
+
evaluateOverTime: true,
|
|
997
|
+
evaluateOverTimeOptions: {
|
|
998
|
+
timeValueInMinutes: 3,
|
|
999
|
+
evaluateOverTimeType: EvaluateOverTimeType.AllValues,
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
);
|
|
1003
|
+
|
|
1004
|
+
expect(result).toContain("true");
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
/*
|
|
1008
|
+
* A numeric over-time series takes precedence over the point-in-time CPU
|
|
1009
|
+
* metric. The array (70, 80) breaches while the live value (10) would not.
|
|
1010
|
+
*/
|
|
1011
|
+
test("over-time numeric series takes precedence over the live CPU metric", async () => {
|
|
1012
|
+
mockOverTime(usable([70, 80]));
|
|
1013
|
+
|
|
1014
|
+
const result: string | null = await evaluate(
|
|
1015
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 10 }) }),
|
|
1016
|
+
{
|
|
1017
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
1018
|
+
filterType: FilterType.GreaterThan,
|
|
1019
|
+
value: 50,
|
|
1020
|
+
evaluateOverTime: true,
|
|
1021
|
+
evaluateOverTimeOptions: {
|
|
1022
|
+
timeValueInMinutes: 5,
|
|
1023
|
+
evaluateOverTimeType: EvaluateOverTimeType.AllValues,
|
|
1024
|
+
},
|
|
1025
|
+
},
|
|
1026
|
+
);
|
|
1027
|
+
|
|
1028
|
+
expect(result).toContain(CheckOn.CPUUsagePercent);
|
|
1029
|
+
expect(result).toContain("70");
|
|
1030
|
+
});
|
|
1031
|
+
|
|
1032
|
+
/*
|
|
1033
|
+
* Only the disk-usage series carries a diskPath attribute. Scoping any
|
|
1034
|
+
* other series by it would filter against an attribute no row has, and
|
|
1035
|
+
* an unusable window now means the filter waits rather than comparing
|
|
1036
|
+
* the live value - so the stray option would silence it outright.
|
|
1037
|
+
*/
|
|
1038
|
+
test("scopes the window by disk path only for disk usage", async () => {
|
|
1039
|
+
const spy: ReturnType<typeof jest.spyOn> = mockOverTime(usable([95]));
|
|
1040
|
+
|
|
1041
|
+
await evaluate(
|
|
1042
|
+
buildServerResponse({
|
|
1043
|
+
metrics: buildMetrics({
|
|
1044
|
+
diskMetrics: [
|
|
1045
|
+
buildDiskMetric({ diskPath: "/data", percentUsed: 95 }),
|
|
1046
|
+
],
|
|
1047
|
+
}),
|
|
1048
|
+
}),
|
|
1049
|
+
{
|
|
1050
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
1051
|
+
filterType: FilterType.GreaterThan,
|
|
1052
|
+
value: 90,
|
|
1053
|
+
evaluateOverTime: true,
|
|
1054
|
+
evaluateOverTimeOptions: {
|
|
1055
|
+
timeValueInMinutes: 5,
|
|
1056
|
+
evaluateOverTimeType: EvaluateOverTimeType.AllValues,
|
|
1057
|
+
},
|
|
1058
|
+
serverMonitorOptions: { diskPath: "/data" },
|
|
1059
|
+
},
|
|
1060
|
+
);
|
|
1061
|
+
|
|
1062
|
+
expect(spy).toHaveBeenCalledWith(
|
|
1063
|
+
expect.objectContaining({ miscData: { diskPath: "/data" } }),
|
|
1064
|
+
);
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
test("does not scope a CPU window by a stray disk path", async () => {
|
|
1068
|
+
const spy: ReturnType<typeof jest.spyOn> = mockOverTime(usable([70, 80]));
|
|
1069
|
+
|
|
1070
|
+
await evaluate(
|
|
1071
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 75 }) }),
|
|
1072
|
+
{
|
|
1073
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
1074
|
+
filterType: FilterType.GreaterThan,
|
|
1075
|
+
value: 50,
|
|
1076
|
+
evaluateOverTime: true,
|
|
1077
|
+
evaluateOverTimeOptions: {
|
|
1078
|
+
timeValueInMinutes: 5,
|
|
1079
|
+
evaluateOverTimeType: EvaluateOverTimeType.AllValues,
|
|
1080
|
+
},
|
|
1081
|
+
serverMonitorOptions: { diskPath: "/" },
|
|
1082
|
+
},
|
|
1083
|
+
);
|
|
1084
|
+
|
|
1085
|
+
expect(spy).toHaveBeenCalledWith(
|
|
1086
|
+
expect.objectContaining({ miscData: undefined }),
|
|
1087
|
+
);
|
|
1088
|
+
});
|
|
1089
|
+
|
|
1090
|
+
/*
|
|
1091
|
+
* Disk usage read its over-time window and then threw the result away,
|
|
1092
|
+
* comparing the reading from this check instead - so "evaluate over
|
|
1093
|
+
* time" on a disk filter did nothing at all.
|
|
1094
|
+
*/
|
|
1095
|
+
test("disk usage compares the over-time window, not just this check", async () => {
|
|
1096
|
+
mockOverTime(usable([95, 96, 97]));
|
|
1097
|
+
|
|
1098
|
+
const result: string | null = await evaluate(
|
|
1099
|
+
buildServerResponse({
|
|
1100
|
+
metrics: buildMetrics({
|
|
1101
|
+
diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 10 })],
|
|
1102
|
+
}),
|
|
1103
|
+
}),
|
|
1104
|
+
{
|
|
1105
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
1106
|
+
filterType: FilterType.GreaterThan,
|
|
1107
|
+
value: 90,
|
|
1108
|
+
evaluateOverTime: true,
|
|
1109
|
+
evaluateOverTimeOptions: {
|
|
1110
|
+
timeValueInMinutes: 5,
|
|
1111
|
+
evaluateOverTimeType: EvaluateOverTimeType.AllValues,
|
|
1112
|
+
},
|
|
1113
|
+
serverMonitorOptions: { diskPath: "/" },
|
|
1114
|
+
},
|
|
1115
|
+
);
|
|
1116
|
+
|
|
1117
|
+
expect(result).toContain("All values of");
|
|
1118
|
+
expect(result).toContain("95");
|
|
1119
|
+
});
|
|
1120
|
+
|
|
1121
|
+
test("disk usage does not fire while its window is unusable", async () => {
|
|
1122
|
+
mockOverTime(noUsableWindow());
|
|
1123
|
+
|
|
1124
|
+
const result: string | null = await evaluate(
|
|
1125
|
+
buildServerResponse({
|
|
1126
|
+
metrics: buildMetrics({
|
|
1127
|
+
diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 99 })],
|
|
1128
|
+
}),
|
|
1129
|
+
}),
|
|
1130
|
+
{
|
|
1131
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
1132
|
+
filterType: FilterType.GreaterThan,
|
|
1133
|
+
value: 90,
|
|
1134
|
+
evaluateOverTime: true,
|
|
1135
|
+
evaluateOverTimeOptions: {
|
|
1136
|
+
timeValueInMinutes: 5,
|
|
1137
|
+
evaluateOverTimeType: EvaluateOverTimeType.AllValues,
|
|
1138
|
+
},
|
|
1139
|
+
serverMonitorOptions: { diskPath: "/" },
|
|
1140
|
+
},
|
|
1141
|
+
);
|
|
1142
|
+
|
|
1143
|
+
expect(result).toBeNull();
|
|
1144
|
+
});
|
|
1145
|
+
|
|
1146
|
+
/*
|
|
1147
|
+
* A disk filter that does NOT evaluate over time keeps comparing the
|
|
1148
|
+
* reading from this check.
|
|
1149
|
+
*/
|
|
1150
|
+
test("disk usage without over-time still compares this check", async () => {
|
|
1151
|
+
const result: string | null = await evaluate(
|
|
1152
|
+
buildServerResponse({
|
|
1153
|
+
metrics: buildMetrics({
|
|
1154
|
+
diskMetrics: [buildDiskMetric({ diskPath: "/", percentUsed: 99 })],
|
|
1155
|
+
}),
|
|
1156
|
+
}),
|
|
1157
|
+
{
|
|
1158
|
+
checkOn: CheckOn.DiskUsagePercent,
|
|
1159
|
+
filterType: FilterType.GreaterThan,
|
|
1160
|
+
value: 90,
|
|
1161
|
+
serverMonitorOptions: { diskPath: "/" },
|
|
1162
|
+
},
|
|
1163
|
+
);
|
|
1164
|
+
|
|
1165
|
+
expect(result).toContain("99");
|
|
1166
|
+
});
|
|
1167
|
+
|
|
1168
|
+
/*
|
|
1169
|
+
* An average of exactly zero is a real measurement, not a missing one.
|
|
1170
|
+
* It used to be swallowed by a truthiness check and replaced with the
|
|
1171
|
+
* live CPU reading, so "average CPU over 5 minutes above 50%" could fire
|
|
1172
|
+
* on a single busy sample while the average itself was 0.
|
|
1173
|
+
*/
|
|
1174
|
+
test("a zero aggregate is compared as zero, not replaced by the live metric", async () => {
|
|
1175
|
+
mockOverTime(usable(0));
|
|
1176
|
+
|
|
1177
|
+
const result: string | null = await evaluate(
|
|
1178
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 90 }) }),
|
|
1179
|
+
{
|
|
1180
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
1181
|
+
filterType: FilterType.GreaterThan,
|
|
1182
|
+
value: 50,
|
|
1183
|
+
evaluateOverTime: true,
|
|
1184
|
+
evaluateOverTimeOptions: {
|
|
1185
|
+
timeValueInMinutes: 5,
|
|
1186
|
+
evaluateOverTimeType: EvaluateOverTimeType.Average,
|
|
1187
|
+
},
|
|
1188
|
+
},
|
|
1189
|
+
);
|
|
1190
|
+
|
|
1191
|
+
expect(result).toBeNull();
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
/*
|
|
1195
|
+
* A window that could not be read says nothing about the last five
|
|
1196
|
+
* minutes, so the filter waits rather than firing off the single live
|
|
1197
|
+
* reading that happens to have arrived with this check.
|
|
1198
|
+
*/
|
|
1199
|
+
test("an unreadable window does not fire off the live CPU metric", async () => {
|
|
1200
|
+
mockOverTime(noUsableWindow());
|
|
1201
|
+
|
|
1202
|
+
const result: string | null = await evaluate(
|
|
1203
|
+
buildServerResponse({ metrics: buildMetrics({ cpuPercentUsed: 90 }) }),
|
|
1204
|
+
{
|
|
1205
|
+
checkOn: CheckOn.CPUUsagePercent,
|
|
1206
|
+
filterType: FilterType.GreaterThan,
|
|
1207
|
+
value: 50,
|
|
1208
|
+
evaluateOverTime: true,
|
|
1209
|
+
evaluateOverTimeOptions: {
|
|
1210
|
+
timeValueInMinutes: 5,
|
|
1211
|
+
evaluateOverTimeType: EvaluateOverTimeType.Average,
|
|
1212
|
+
},
|
|
1213
|
+
},
|
|
1214
|
+
);
|
|
1215
|
+
|
|
1216
|
+
expect(result).toBeNull();
|
|
1217
|
+
});
|
|
1218
|
+
});
|
|
1219
|
+
});
|