@oneuptime/common 12.0.13 → 12.0.14
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/OnCallDutyPolicySchedule.ts +14 -0
- 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/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/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/Index.ts +6 -0
- package/Server/Middleware/VerificationCodeRateLimit.ts +586 -0
- package/Server/Services/AnalyticsDatabaseService.ts +169 -0
- package/Server/Services/DatabaseService.ts +101 -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/Monitor/Criteria/IncomingRequestCriteria.ts +13 -16
- package/Server/Utils/Monitor/MonitorAlert.ts +24 -21
- package/Server/Utils/Monitor/MonitorIncident.ts +21 -18
- 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/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/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 +315 -0
- package/Tests/Server/Middleware/VerificationCodeRateLimit.test.ts +775 -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/LogAggregationScanMemory.test.ts +421 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +2 -2
- 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/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/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/Express.test.ts +371 -0
- 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/IncomingEmailBodyCriteria.test.ts +243 -0
- package/Tests/Server/Utils/Monitor/Criteria/IncomingRequestBodyCriteria.test.ts +278 -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/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/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/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/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/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/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/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/Rum/UrlScrubberSegments.test.ts +362 -0
- package/Types/Email/EmailTemplateType.ts +1 -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/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/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/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/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +14 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.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/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/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/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.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/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/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/Monitor/Criteria/IncomingRequestCriteria.js +13 -12
- package/build/dist/Server/Utils/Monitor/Criteria/IncomingRequestCriteria.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/MonitorIncident.js +17 -14
- package/build/dist/Server/Utils/Monitor/MonitorIncident.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/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/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/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/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/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/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
|
@@ -37,10 +37,10 @@ import MonitorSummarySnapshot from "../../../Types/Monitor/MonitorSummarySnapsho
|
|
|
37
37
|
import MonitorSummarySnapshotUtil from "../../../Utils/Monitor/MonitorSummarySnapshotUtil";
|
|
38
38
|
import { IncidentMemberRoleAssignment } from "../../../Types/Monitor/CriteriaIncident";
|
|
39
39
|
import { PerSeriesCriteriaMatch } from "../../../Types/Probe/ProbeApiIngestResponse";
|
|
40
|
-
import
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
import MonitorResourceContextUtil from "./MonitorResourceContext";
|
|
41
|
+
import SeriesResourceLinker, {
|
|
42
|
+
SeriesResolvedResourceIds,
|
|
43
|
+
} from "./SeriesResourceLinker";
|
|
44
44
|
|
|
45
45
|
export default class MonitorIncident {
|
|
46
46
|
@CaptureSpan()
|
|
@@ -364,15 +364,17 @@ export default class MonitorIncident {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
/*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
*
|
|
367
|
+
* Resolve the resources this monitor's own config names — its host,
|
|
368
|
+
* cluster, fleet, telemetry services, or the resource its metric
|
|
369
|
+
* filters scope it to — once per evaluation, so every incident
|
|
370
|
+
* created below is attached to them. Series labels cannot supply
|
|
371
|
+
* this: they only exist for grouped criteria, and most monitors
|
|
372
|
+
* (every shipped Host/Docker/Podman template, all Logs/Traces/
|
|
373
|
+
* Exceptions monitors) are ungrouped. No-op, and no round-trip, for
|
|
374
|
+
* monitor types whose config names no resource.
|
|
373
375
|
*/
|
|
374
|
-
const
|
|
375
|
-
await
|
|
376
|
+
const resourceContext: SeriesResolvedResourceIds =
|
|
377
|
+
await MonitorResourceContextUtil.resolveResourceContextForMonitor({
|
|
376
378
|
monitor: input.monitor,
|
|
377
379
|
});
|
|
378
380
|
|
|
@@ -656,19 +658,20 @@ export default class MonitorIncident {
|
|
|
656
658
|
model: incident,
|
|
657
659
|
seriesLabels,
|
|
658
660
|
projectId: input.monitor.projectId!,
|
|
661
|
+
monitorType: input.monitor.monitorType,
|
|
659
662
|
});
|
|
660
663
|
}
|
|
661
664
|
|
|
662
665
|
/*
|
|
663
|
-
* Deterministic
|
|
664
|
-
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
666
|
+
* Deterministic resource link from the monitor's step config
|
|
667
|
+
* (resolved once above). Runs for both grouped and ungrouped
|
|
668
|
+
* incidents and merges with anything the series-label path
|
|
669
|
+
* resolved, so the per-resource Activity tabs always see
|
|
667
670
|
* monitor-created incidents.
|
|
668
671
|
*/
|
|
669
|
-
SeriesResourceLinker.
|
|
672
|
+
SeriesResourceLinker.attachResolvedResources({
|
|
670
673
|
model: incident,
|
|
671
|
-
|
|
674
|
+
resolved: resourceContext,
|
|
672
675
|
});
|
|
673
676
|
|
|
674
677
|
incident.onCallDutyPolicies =
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
2
|
+
import logger from "../Logger";
|
|
3
|
+
import MonitorStepResourceIdentity from "./MonitorStepResourceIdentity";
|
|
4
|
+
import { SeriesResourceRefs } from "./SeriesResourceLabels";
|
|
5
|
+
import SeriesResourceLinker, {
|
|
6
|
+
SeriesResolvedResourceIds,
|
|
7
|
+
} from "./SeriesResourceLinker";
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* Incidents and alerts created by a monitor must be attached to the
|
|
11
|
+
* resources that monitor watches — the per-resource Activity pages, the
|
|
12
|
+
* SideMenu badge counts, the "Affected Resources" card, the affected-
|
|
13
|
+
* resources filter, and resource owner/label inheritance all query those
|
|
14
|
+
* relations on Incident/Alert.
|
|
15
|
+
*
|
|
16
|
+
* Series labels cannot supply that identity on their own. They exist
|
|
17
|
+
* only when the criteria is GROUPED, and most monitors are not: every
|
|
18
|
+
* shipped Host / Docker / Podman / RUM template is ungrouped, the
|
|
19
|
+
* Kubernetes templates group by node/pod (never by cluster), and
|
|
20
|
+
* Logs / Traces / Exceptions monitors have no series concept at all. An
|
|
21
|
+
* ungrouped monitor therefore linked nothing, which is why a metric
|
|
22
|
+
* monitor scoped to one service with
|
|
23
|
+
* `oneuptime.service.name = checkout-api` opened alerts that showed "No
|
|
24
|
+
* resources affected".
|
|
25
|
+
*
|
|
26
|
+
* The deterministic source is the monitor's own step config, which
|
|
27
|
+
* always carries whatever the user picked when they built the monitor:
|
|
28
|
+
* a hostIdentifier, a clusterIdentifier, a fleetIdentifier, a set of
|
|
29
|
+
* telemetryServiceIds, or a metric attribute filter. This module reads
|
|
30
|
+
* it once per evaluation and resolves it to real rows.
|
|
31
|
+
*
|
|
32
|
+
* This supersedes the old MonitorClusterContext, which did the same
|
|
33
|
+
* thing for exactly four cluster types (Proxmox / Ceph / Docker Swarm /
|
|
34
|
+
* IoT) with a hand-rolled findOneBy per identifier.
|
|
35
|
+
*/
|
|
36
|
+
export default class MonitorResourceContextUtil {
|
|
37
|
+
/*
|
|
38
|
+
* Resolve the resource rows the monitor's configuration names.
|
|
39
|
+
*
|
|
40
|
+
* Lookup-only — row creation belongs to ingest discovery
|
|
41
|
+
* (findOrCreateByName); a monitor pointing at a host that never sent
|
|
42
|
+
* data simply links nothing. Lookups are ALWAYS project-scoped:
|
|
43
|
+
* `isRoot` bypasses row-level access control, so a stale or hostile
|
|
44
|
+
* identifier must never be able to pull a row in from another tenant.
|
|
45
|
+
*
|
|
46
|
+
* Returns empty for every monitor type whose config names no resource
|
|
47
|
+
* (Website, API, Ping, Synthetic, ...) without touching the database.
|
|
48
|
+
*/
|
|
49
|
+
public static async resolveResourceContextForMonitor(input: {
|
|
50
|
+
monitor: Monitor;
|
|
51
|
+
}): Promise<SeriesResolvedResourceIds> {
|
|
52
|
+
const empty: SeriesResolvedResourceIds = this.emptyContext();
|
|
53
|
+
|
|
54
|
+
if (!input.monitor.projectId) {
|
|
55
|
+
return empty;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/*
|
|
59
|
+
* Resource linking is best-effort context — a failure must never
|
|
60
|
+
* block incident/alert creation, which runs inside the probe and
|
|
61
|
+
* telemetry queue workers where a throw retries the whole job
|
|
62
|
+
* forever. The EXTRACTION is inside the try as well as the lookup:
|
|
63
|
+
* it reads free-form, unvalidated step JSON, so a monitor saved
|
|
64
|
+
* through the API or an import can hand it a shape it cannot parse.
|
|
65
|
+
*/
|
|
66
|
+
try {
|
|
67
|
+
const refs: SeriesResourceRefs =
|
|
68
|
+
MonitorStepResourceIdentity.extractResourceRefsFromMonitor({
|
|
69
|
+
monitor: input.monitor,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (MonitorStepResourceIdentity.isEmpty(refs)) {
|
|
73
|
+
return empty;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return await SeriesResourceLinker.resolveResourceRefs({
|
|
77
|
+
refs: refs,
|
|
78
|
+
projectId: input.monitor.projectId,
|
|
79
|
+
/*
|
|
80
|
+
* The identifiers here were typed by a user into the monitor
|
|
81
|
+
* form, while the rows' names were stamped by an agent at
|
|
82
|
+
* ingest; the two legitimately differ by case.
|
|
83
|
+
*/
|
|
84
|
+
nameMatch: "caseInsensitive",
|
|
85
|
+
});
|
|
86
|
+
} catch (err) {
|
|
87
|
+
logger.error(
|
|
88
|
+
`Failed to resolve affected resources for monitor ${input.monitor.id?.toString()}: ${err}`,
|
|
89
|
+
);
|
|
90
|
+
return empty;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public static emptyContext(): SeriesResolvedResourceIds {
|
|
95
|
+
return {
|
|
96
|
+
hostIds: [],
|
|
97
|
+
dockerHostIds: [],
|
|
98
|
+
podmanHostIds: [],
|
|
99
|
+
kubernetesClusterIds: [],
|
|
100
|
+
serviceIds: [],
|
|
101
|
+
proxmoxClusterIds: [],
|
|
102
|
+
cephClusterIds: [],
|
|
103
|
+
dockerSwarmClusterIds: [],
|
|
104
|
+
iotFleetIds: [],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
2
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
3
|
+
import MetricQueryConfigData from "../../../Types/Metrics/MetricQueryConfigData";
|
|
4
|
+
import MetricsViewConfig from "../../../Types/Metrics/MetricsViewConfig";
|
|
5
|
+
import MonitorStep from "../../../Types/Monitor/MonitorStep";
|
|
6
|
+
import MonitorType from "../../../Types/Monitor/MonitorType";
|
|
7
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
8
|
+
import SeriesResourceLabels, {
|
|
9
|
+
SeriesResourceRefs,
|
|
10
|
+
} from "./SeriesResourceLabels";
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* The step-config twin of SeriesResourceLabels.
|
|
14
|
+
*
|
|
15
|
+
* SeriesResourceLabels answers "which resources does this BREACHING
|
|
16
|
+
* SERIES point at" by reading the labels of one grouped series. That
|
|
17
|
+
* only works when the criteria is grouped — an ungrouped monitor emits
|
|
18
|
+
* no series labels at all, so it linked nothing, and the vast majority
|
|
19
|
+
* of monitors (every shipped Host / Docker / Podman / RUM template, and
|
|
20
|
+
* every Logs / Traces / Exceptions monitor, which cannot be grouped in
|
|
21
|
+
* the first place) are ungrouped.
|
|
22
|
+
*
|
|
23
|
+
* This module answers the same question from the other, always-present
|
|
24
|
+
* side: "which resources does this MONITOR'S OWN CONFIGURATION point
|
|
25
|
+
* at". A host monitor names its host, a Kubernetes monitor names its
|
|
26
|
+
* cluster, a log monitor names its telemetry services, and any monitor
|
|
27
|
+
* with a metric query can carry resource identity in its attribute
|
|
28
|
+
* filters (e.g. `oneuptime.service.name = checkout-api`). None of that
|
|
29
|
+
* depends on the criteria being grouped.
|
|
30
|
+
*
|
|
31
|
+
* Both modules emit the SAME `SeriesResourceRefs` shape, so the single
|
|
32
|
+
* nine-way resolver in SeriesResourceLinker serves both, and the two can
|
|
33
|
+
* never drift into disagreeing about what identifies a resource.
|
|
34
|
+
*
|
|
35
|
+
* Pure: no database access, no I/O.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* Which relation a monitor type's own step config speaks for. Held as an
|
|
40
|
+
* exhaustive-by-construction map so a new infra monitor type is a
|
|
41
|
+
* one-line addition next to its siblings rather than a new `if` branch
|
|
42
|
+
* buried in the extractor.
|
|
43
|
+
*/
|
|
44
|
+
type NameRefKey = keyof Pick<
|
|
45
|
+
SeriesResourceRefs,
|
|
46
|
+
| "hostNames"
|
|
47
|
+
| "dockerHostNames"
|
|
48
|
+
| "podmanHostNames"
|
|
49
|
+
| "kubernetesClusterNames"
|
|
50
|
+
| "proxmoxClusterNames"
|
|
51
|
+
| "cephClusterNames"
|
|
52
|
+
| "dockerSwarmClusterNames"
|
|
53
|
+
| "iotFleetNames"
|
|
54
|
+
>;
|
|
55
|
+
|
|
56
|
+
export default class MonitorStepResourceIdentity {
|
|
57
|
+
/*
|
|
58
|
+
* Every resource the monitor's configuration names, unioned across its
|
|
59
|
+
* steps and deduped. A monitor with three host steps names three
|
|
60
|
+
* hosts: the creation path does not know which step fired, and the
|
|
61
|
+
* alternative — attributing nothing — is what this module exists to
|
|
62
|
+
* fix.
|
|
63
|
+
*/
|
|
64
|
+
public static extractResourceRefsFromMonitor(input: {
|
|
65
|
+
monitor: Monitor;
|
|
66
|
+
}): SeriesResourceRefs {
|
|
67
|
+
const refs: SeriesResourceRefs = this.emptyRefs();
|
|
68
|
+
|
|
69
|
+
const monitorType: MonitorType | undefined = input.monitor.monitorType;
|
|
70
|
+
|
|
71
|
+
if (!monitorType) {
|
|
72
|
+
return refs;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const monitorSteps: Array<MonitorStep> =
|
|
76
|
+
input.monitor.monitorSteps?.data?.monitorStepsInstanceArray || [];
|
|
77
|
+
|
|
78
|
+
for (const monitorStep of monitorSteps) {
|
|
79
|
+
this.collectFromStep({
|
|
80
|
+
monitorStep: monitorStep,
|
|
81
|
+
monitorType: monitorType,
|
|
82
|
+
refs: refs,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return this.dedupeRefs(refs);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private static collectFromStep(input: {
|
|
90
|
+
monitorStep: MonitorStep;
|
|
91
|
+
monitorType: MonitorType;
|
|
92
|
+
refs: SeriesResourceRefs;
|
|
93
|
+
}): void {
|
|
94
|
+
const stepData: MonitorStep["data"] = input.monitorStep.data;
|
|
95
|
+
|
|
96
|
+
if (!stepData) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/*
|
|
101
|
+
* 1. The declared resource identifier — the field the user picked in
|
|
102
|
+
* the monitor form. Validation makes it required for each of
|
|
103
|
+
* these types (see MonitorStep's validation), so this is the
|
|
104
|
+
* strongest signal available.
|
|
105
|
+
*/
|
|
106
|
+
const declared: { key: NameRefKey; value: string | undefined } | null =
|
|
107
|
+
this.getDeclaredIdentifier({
|
|
108
|
+
stepData: stepData,
|
|
109
|
+
monitorType: input.monitorType,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/*
|
|
113
|
+
* `typeof` rather than a truthiness check: step JSON is not
|
|
114
|
+
* schema-checked, so an identifier written by the API, a seed or an
|
|
115
|
+
* import can be a number or an object, and `.trim()` on those throws
|
|
116
|
+
* out of the incident/alert creation path.
|
|
117
|
+
*/
|
|
118
|
+
if (declared && typeof declared.value === "string") {
|
|
119
|
+
const identifier: string = declared.value.trim();
|
|
120
|
+
|
|
121
|
+
if (identifier.length > 0) {
|
|
122
|
+
input.refs[declared.key].push(identifier);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/*
|
|
127
|
+
* 2. Telemetry services. Real `Service._id` values written by the
|
|
128
|
+
* monitor form's service picker — a primary key, not a name, so
|
|
129
|
+
* this is the most precise identity in the whole module. Metric
|
|
130
|
+
* monitors carry the field too (RUM recommendation monitors set
|
|
131
|
+
* it), where it is optional.
|
|
132
|
+
*/
|
|
133
|
+
for (const serviceId of this.getTelemetryServiceIds({
|
|
134
|
+
stepData: stepData,
|
|
135
|
+
})) {
|
|
136
|
+
input.refs.serviceIds.push(serviceId);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/*
|
|
140
|
+
* 3. Metric attribute filters. A generic metric monitor names its
|
|
141
|
+
* resource nowhere else: it scopes itself with filters like
|
|
142
|
+
* `oneuptime.service.name = checkout-api`, which is exactly the
|
|
143
|
+
* key map SeriesResourceLabels already owns. Reusing that map
|
|
144
|
+
* means a filter and a group-by on the same attribute resolve to
|
|
145
|
+
* the same row.
|
|
146
|
+
*/
|
|
147
|
+
this.collectFromMetricFilters({
|
|
148
|
+
stepData: stepData,
|
|
149
|
+
monitorType: input.monitorType,
|
|
150
|
+
refs: input.refs,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private static getDeclaredIdentifier(input: {
|
|
155
|
+
stepData: NonNullable<MonitorStep["data"]>;
|
|
156
|
+
monitorType: MonitorType;
|
|
157
|
+
}): { key: NameRefKey; value: string | undefined } | null {
|
|
158
|
+
const stepData: NonNullable<MonitorStep["data"]> = input.stepData;
|
|
159
|
+
|
|
160
|
+
switch (input.monitorType) {
|
|
161
|
+
case MonitorType.Host:
|
|
162
|
+
return {
|
|
163
|
+
key: "hostNames",
|
|
164
|
+
value: stepData.hostMonitor?.hostIdentifier,
|
|
165
|
+
};
|
|
166
|
+
case MonitorType.Docker:
|
|
167
|
+
return {
|
|
168
|
+
key: "dockerHostNames",
|
|
169
|
+
value: stepData.dockerMonitor?.hostIdentifier,
|
|
170
|
+
};
|
|
171
|
+
case MonitorType.Podman:
|
|
172
|
+
return {
|
|
173
|
+
key: "podmanHostNames",
|
|
174
|
+
value: stepData.podmanMonitor?.hostIdentifier,
|
|
175
|
+
};
|
|
176
|
+
case MonitorType.Kubernetes:
|
|
177
|
+
return {
|
|
178
|
+
key: "kubernetesClusterNames",
|
|
179
|
+
value: stepData.kubernetesMonitor?.clusterIdentifier,
|
|
180
|
+
};
|
|
181
|
+
case MonitorType.Proxmox:
|
|
182
|
+
return {
|
|
183
|
+
key: "proxmoxClusterNames",
|
|
184
|
+
value: stepData.proxmoxMonitor?.clusterIdentifier,
|
|
185
|
+
};
|
|
186
|
+
case MonitorType.Ceph:
|
|
187
|
+
return {
|
|
188
|
+
key: "cephClusterNames",
|
|
189
|
+
value: stepData.cephMonitor?.clusterIdentifier,
|
|
190
|
+
};
|
|
191
|
+
case MonitorType.DockerSwarm:
|
|
192
|
+
return {
|
|
193
|
+
key: "dockerSwarmClusterNames",
|
|
194
|
+
value: stepData.dockerSwarmMonitor?.clusterIdentifier,
|
|
195
|
+
};
|
|
196
|
+
case MonitorType.IoTDevice:
|
|
197
|
+
return {
|
|
198
|
+
key: "iotFleetNames",
|
|
199
|
+
value: stepData.iotMonitor?.fleetIdentifier,
|
|
200
|
+
};
|
|
201
|
+
default:
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
private static getTelemetryServiceIds(input: {
|
|
207
|
+
stepData: NonNullable<MonitorStep["data"]>;
|
|
208
|
+
}): Array<string> {
|
|
209
|
+
const stepData: NonNullable<MonitorStep["data"]> = input.stepData;
|
|
210
|
+
|
|
211
|
+
/*
|
|
212
|
+
* Read from every telemetry sub-config present rather than switching
|
|
213
|
+
* on monitorType: only one of them is ever populated for a given
|
|
214
|
+
* monitor, and this way a step written by an older build (or by the
|
|
215
|
+
* API, a seed, or an import) with a mismatched type still resolves.
|
|
216
|
+
*/
|
|
217
|
+
const idLists: Array<Array<ObjectID> | undefined> = [
|
|
218
|
+
stepData.logMonitor?.telemetryServiceIds,
|
|
219
|
+
stepData.traceMonitor?.telemetryServiceIds,
|
|
220
|
+
stepData.exceptionMonitor?.telemetryServiceIds,
|
|
221
|
+
stepData.profileMonitor?.telemetryServiceIds,
|
|
222
|
+
stepData.metricMonitor?.telemetryServiceIds,
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
const serviceIds: Array<string> = [];
|
|
226
|
+
|
|
227
|
+
for (const idList of idLists) {
|
|
228
|
+
/*
|
|
229
|
+
* `Array.isArray` rather than a truthiness check: an unchecked
|
|
230
|
+
* step written by the API or an import can hold an object or a
|
|
231
|
+
* number here, and `for...of` on those throws out of the
|
|
232
|
+
* incident/alert creation path.
|
|
233
|
+
*/
|
|
234
|
+
if (!Array.isArray(idList) || idList.length === 0) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
for (const id of idList) {
|
|
239
|
+
/*
|
|
240
|
+
* An entry can be a bare string rather than a rehydrated
|
|
241
|
+
* ObjectID, for the same reason. `String()` covers both; empty
|
|
242
|
+
* values are dropped so they can't widen the lookup, and a
|
|
243
|
+
* non-scalar is dropped rather than stringified into a garbage
|
|
244
|
+
* "[object Object]" lookup key.
|
|
245
|
+
*/
|
|
246
|
+
if (
|
|
247
|
+
id !== null &&
|
|
248
|
+
typeof id === "object" &&
|
|
249
|
+
!(id instanceof ObjectID)
|
|
250
|
+
) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const idString: string = String(id ?? "").trim();
|
|
255
|
+
|
|
256
|
+
if (idString.length > 0) {
|
|
257
|
+
serviceIds.push(idString);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return serviceIds;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
private static collectFromMetricFilters(input: {
|
|
266
|
+
stepData: NonNullable<MonitorStep["data"]>;
|
|
267
|
+
monitorType: MonitorType;
|
|
268
|
+
refs: SeriesResourceRefs;
|
|
269
|
+
}): void {
|
|
270
|
+
const filterAttributes: JSONObject = this.collectMetricFilterAttributes({
|
|
271
|
+
stepData: input.stepData,
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
if (Object.keys(filterAttributes).length === 0) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const filterRefs: SeriesResourceRefs =
|
|
279
|
+
SeriesResourceLabels.extractResourceRefs(filterAttributes);
|
|
280
|
+
|
|
281
|
+
/*
|
|
282
|
+
* `resource.host.name` belongs to Host in the label key map, but on
|
|
283
|
+
* a Docker or Podman monitor the worker writes that same attribute
|
|
284
|
+
* from the step's `hostIdentifier` — which names a DockerHost /
|
|
285
|
+
* PodmanHost row, not a Host row. Honouring the map here would
|
|
286
|
+
* attach the wrong model and surface the event on an unrelated
|
|
287
|
+
* Host's Activity tab, so the declared identifier (collected above,
|
|
288
|
+
* into the right bucket) is the only host identity these two types
|
|
289
|
+
* get.
|
|
290
|
+
*/
|
|
291
|
+
const suppressHostRefs: boolean =
|
|
292
|
+
input.monitorType === MonitorType.Docker ||
|
|
293
|
+
input.monitorType === MonitorType.Podman;
|
|
294
|
+
|
|
295
|
+
if (suppressHostRefs) {
|
|
296
|
+
filterRefs.hostIds = [];
|
|
297
|
+
filterRefs.hostNames = [];
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
this.mergeRefs({ target: input.refs, source: filterRefs });
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/*
|
|
304
|
+
* The attribute filters of every metric query on the step, merged.
|
|
305
|
+
* Each infra monitor type keeps its metric view config under its own
|
|
306
|
+
* key, so read them all — exactly the set MonitorStep's own
|
|
307
|
+
* metric-view-config resolver knows about.
|
|
308
|
+
*
|
|
309
|
+
* Values accumulate into an ARRAY per key rather than overwriting: a
|
|
310
|
+
* step can hold several queries, and two of them filtering
|
|
311
|
+
* `oneuptime.service.name` on different services both name a real
|
|
312
|
+
* resource. Last-write-wins would silently drop one of them.
|
|
313
|
+
* SeriesResourceLabels.collectLabelValues already flattens
|
|
314
|
+
* array-valued labels, so the multi-value shape needs nothing extra
|
|
315
|
+
* downstream.
|
|
316
|
+
*/
|
|
317
|
+
private static collectMetricFilterAttributes(input: {
|
|
318
|
+
stepData: NonNullable<MonitorStep["data"]>;
|
|
319
|
+
}): JSONObject {
|
|
320
|
+
const stepData: NonNullable<MonitorStep["data"]> = input.stepData;
|
|
321
|
+
|
|
322
|
+
const viewConfigs: Array<MetricsViewConfig | undefined> = [
|
|
323
|
+
stepData.metricMonitor?.metricViewConfig,
|
|
324
|
+
stepData.hostMonitor?.metricViewConfig,
|
|
325
|
+
stepData.kubernetesMonitor?.metricViewConfig,
|
|
326
|
+
stepData.dockerMonitor?.metricViewConfig,
|
|
327
|
+
stepData.podmanMonitor?.metricViewConfig,
|
|
328
|
+
stepData.proxmoxMonitor?.metricViewConfig,
|
|
329
|
+
stepData.cephMonitor?.metricViewConfig,
|
|
330
|
+
stepData.dockerSwarmMonitor?.metricViewConfig,
|
|
331
|
+
stepData.iotMonitor?.metricViewConfig,
|
|
332
|
+
];
|
|
333
|
+
|
|
334
|
+
const valuesByKey: Map<string, Array<string>> = new Map<
|
|
335
|
+
string,
|
|
336
|
+
Array<string>
|
|
337
|
+
>();
|
|
338
|
+
|
|
339
|
+
for (const viewConfig of viewConfigs) {
|
|
340
|
+
const queryConfigs: Array<MetricQueryConfigData> = Array.isArray(
|
|
341
|
+
viewConfig?.queryConfigs,
|
|
342
|
+
)
|
|
343
|
+
? viewConfig.queryConfigs
|
|
344
|
+
: [];
|
|
345
|
+
|
|
346
|
+
for (const queryConfig of queryConfigs) {
|
|
347
|
+
const queryAttributes: unknown =
|
|
348
|
+
queryConfig?.metricQueryData?.filterData?.attributes;
|
|
349
|
+
|
|
350
|
+
if (!queryAttributes || typeof queryAttributes !== "object") {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
for (const [key, value] of Object.entries(
|
|
355
|
+
queryAttributes as Record<string, unknown>,
|
|
356
|
+
)) {
|
|
357
|
+
/*
|
|
358
|
+
* Only plain string filters identify a resource. A filter can
|
|
359
|
+
* also hold a Search or Includes instance (substring / set
|
|
360
|
+
* matching), and neither is an identity we can resolve to one
|
|
361
|
+
* row — a `Search("prod")` filter names no specific service.
|
|
362
|
+
*/
|
|
363
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const existing: Array<string> = valuesByKey.get(key) || [];
|
|
368
|
+
|
|
369
|
+
if (!existing.includes(value)) {
|
|
370
|
+
existing.push(value);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
valuesByKey.set(key, existing);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const attributes: JSONObject = {};
|
|
379
|
+
|
|
380
|
+
for (const [key, values] of valuesByKey) {
|
|
381
|
+
/*
|
|
382
|
+
* A single value stays a bare string so the common case reads
|
|
383
|
+
* exactly like a series label; only a genuinely multi-valued
|
|
384
|
+
* filter becomes an array.
|
|
385
|
+
*/
|
|
386
|
+
attributes[key] = values.length === 1 ? values[0]! : values;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return attributes;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
private static mergeRefs(input: {
|
|
393
|
+
target: SeriesResourceRefs;
|
|
394
|
+
source: SeriesResourceRefs;
|
|
395
|
+
}): void {
|
|
396
|
+
for (const key of Object.keys(input.target) as Array<
|
|
397
|
+
keyof SeriesResourceRefs
|
|
398
|
+
>) {
|
|
399
|
+
input.target[key].push(...input.source[key]);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private static dedupeRefs(refs: SeriesResourceRefs): SeriesResourceRefs {
|
|
404
|
+
for (const key of Object.keys(refs) as Array<keyof SeriesResourceRefs>) {
|
|
405
|
+
refs[key] = Array.from(new Set<string>(refs[key]));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return refs;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
public static emptyRefs(): SeriesResourceRefs {
|
|
412
|
+
return {
|
|
413
|
+
hostIds: [],
|
|
414
|
+
hostNames: [],
|
|
415
|
+
dockerHostIds: [],
|
|
416
|
+
dockerHostNames: [],
|
|
417
|
+
podmanHostIds: [],
|
|
418
|
+
podmanHostNames: [],
|
|
419
|
+
kubernetesClusterIds: [],
|
|
420
|
+
kubernetesClusterNames: [],
|
|
421
|
+
dockerSwarmClusterNames: [],
|
|
422
|
+
proxmoxClusterNames: [],
|
|
423
|
+
cephClusterNames: [],
|
|
424
|
+
iotFleetNames: [],
|
|
425
|
+
serviceIds: [],
|
|
426
|
+
serviceNames: [],
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/*
|
|
431
|
+
* True when the monitor's configuration names nothing at all — the
|
|
432
|
+
* common case for the ~17 monitor types that have no resource
|
|
433
|
+
* identity (Website, API, Ping, Synthetic, ...). Callers use it to
|
|
434
|
+
* skip the lookup entirely so those monitors keep costing zero
|
|
435
|
+
* database round-trips per evaluation.
|
|
436
|
+
*/
|
|
437
|
+
public static isEmpty(refs: SeriesResourceRefs): boolean {
|
|
438
|
+
return Object.values(refs).every((values: Array<string>): boolean => {
|
|
439
|
+
return values.length === 0;
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
@@ -74,7 +74,7 @@ export const PodmanHostNameLabelKeys: ReadonlyArray<string> = [
|
|
|
74
74
|
* Like Proxmox/Ceph, the shipped Swarm alert templates group by
|
|
75
75
|
* datapoint labels (`container.name`), so their series labels do NOT
|
|
76
76
|
* carry this key; the deterministic cluster link for those monitors
|
|
77
|
-
* comes from the monitor step config instead (see
|
|
77
|
+
* comes from the monitor step config instead (see MonitorResourceContext).
|
|
78
78
|
* These keys cover user-built monitors that group by the cluster
|
|
79
79
|
* attribute.
|
|
80
80
|
*/
|
|
@@ -105,7 +105,7 @@ export const KubernetesClusterNameLabelKeys: ReadonlyArray<string> = [
|
|
|
105
105
|
* datapoint labels (`id`, `ceph_daemon`, `pool_id`), so their series
|
|
106
106
|
* labels do NOT carry these keys; the deterministic cluster link for
|
|
107
107
|
* those monitors comes from the monitor step config instead (see
|
|
108
|
-
*
|
|
108
|
+
* MonitorResourceContext). These keys cover user-built monitors that
|
|
109
109
|
* group by the cluster attribute, exactly like the K8s keys above.
|
|
110
110
|
*/
|
|
111
111
|
export const ProxmoxClusterNameLabelKeys: ReadonlyArray<string> = [
|
|
@@ -127,7 +127,7 @@ export const CephClusterNameLabelKeys: ReadonlyArray<string> = [
|
|
|
127
127
|
* alert templates group by the datapoint label `device.id`, so their
|
|
128
128
|
* series labels do NOT carry these keys; the deterministic fleet link
|
|
129
129
|
* for those monitors comes from the monitor step config instead (see
|
|
130
|
-
*
|
|
130
|
+
* MonitorResourceContext). These keys cover user-built monitors that
|
|
131
131
|
* group by the fleet attribute.
|
|
132
132
|
*/
|
|
133
133
|
export const IoTFleetNameLabelKeys: ReadonlyArray<string> = [
|