@oneuptime/common 12.0.1 → 12.0.3
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/DatabaseBaseModel/DatabaseBaseModel.ts +14 -0
- package/Models/DatabaseModels/Host.ts +12 -4
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/KubernetesContainer.ts +5 -4
- package/Models/DatabaseModels/KubernetesResource.ts +8 -7
- package/Models/DatabaseModels/LogDropFilter.ts +9 -20
- package/Models/DatabaseModels/PodmanResource.ts +6 -6
- package/Models/DatabaseModels/ServiceLevelObjective.ts +91 -0
- package/Models/DatabaseModels/StatusPage.ts +95 -0
- package/Models/DatabaseModels/StatusPageMonitorRule.ts +911 -0
- package/Models/DatabaseModels/StatusPageResource.ts +73 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +9 -20
- package/Server/API/BaseAPI.ts +13 -2
- package/Server/API/DashboardAPI.ts +39 -0
- package/Server/API/TeamMemberAPI.ts +85 -0
- package/Server/EnvironmentConfig.ts +31 -1
- package/Server/Infrastructure/GlobalCache.ts +115 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +16 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.ts +84 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.ts +131 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.ts +123 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Middleware/ProjectAuthorization.ts +66 -4
- package/Server/Services/AlertStateTimelineService.ts +20 -0
- package/Server/Services/BillingService.ts +600 -51
- package/Server/Services/CephClusterService.ts +27 -45
- package/Server/Services/CephResourceService.ts +43 -4
- package/Server/Services/CloudResourceService.ts +24 -42
- package/Server/Services/DatabaseService.ts +198 -6
- package/Server/Services/DockerHostService.ts +20 -38
- package/Server/Services/DockerResourceService.ts +62 -8
- package/Server/Services/DockerSwarmClusterService.ts +28 -46
- package/Server/Services/DockerSwarmResourceService.ts +53 -4
- package/Server/Services/HostService.ts +47 -57
- package/Server/Services/IncidentStateTimelineService.ts +20 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/IoTDeviceService.ts +1 -17
- package/Server/Services/IoTFleetService.ts +20 -38
- package/Server/Services/KubernetesClusterService.ts +18 -36
- package/Server/Services/KubernetesContainerService.ts +50 -9
- package/Server/Services/KubernetesResourceService.ts +53 -7
- package/Server/Services/LabelService.ts +153 -1
- package/Server/Services/MetricTypeService.ts +84 -0
- package/Server/Services/MonitorService.ts +146 -14
- package/Server/Services/MonitorStatusTimelineService.ts +29 -0
- package/Server/Services/MonitorTemplateService.ts +65 -0
- package/Server/Services/PodmanHostService.ts +20 -38
- package/Server/Services/PodmanResourceService.ts +62 -8
- package/Server/Services/ProjectService.ts +165 -35
- package/Server/Services/ProxmoxClusterService.ts +24 -42
- package/Server/Services/ProxmoxResourceService.ts +43 -4
- package/Server/Services/RumApplicationService.ts +20 -38
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +21 -0
- package/Server/Services/ServerlessFunctionService.ts +25 -43
- package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +426 -0
- package/Server/Services/ServiceLevelObjectiveService.ts +39 -0
- package/Server/Services/ServiceService.ts +299 -73
- package/Server/Services/StatusPageMonitorRuleEngineService.ts +752 -0
- package/Server/Services/StatusPageMonitorRuleService.ts +471 -0
- package/Server/Services/StatusPageService.ts +95 -36
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +18 -1
- package/Server/Services/StatusPageSubscriberService.ts +3 -0
- package/Server/Services/TelemetryEntityRelationshipService.ts +1 -0
- package/Server/Services/TelemetryEntityService.ts +1 -0
- package/Server/Types/Database/JSONColumnQuery.ts +621 -0
- package/Server/Types/Database/Permissions/PublicPermission.ts +9 -2
- package/Server/Types/Database/QueryHelper.ts +17 -32
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +170 -39
- package/Server/Utils/Database/TruncateColumnValue.ts +84 -0
- package/Server/Utils/Monitor/MonitorResource.ts +63 -36
- package/Server/Utils/Monitor/MonitorStatusTimeline.ts +36 -0
- package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +148 -127
- package/Server/Utils/Monitor/MonitorStepsReferenceExtractor.ts +434 -0
- package/Server/Utils/SingleFlight.ts +83 -0
- package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +46 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +107 -26
- package/Server/Utils/Telemetry/ResourceHeartbeat.ts +314 -0
- package/Server/Utils/Telemetry/Telemetry.ts +351 -122
- package/Tests/App/Dashboard/UsersTableGroupsByPerson.test.tsx +448 -0
- package/Tests/App/Dashboard/WidgetCatalog.test.ts +2 -0
- package/Tests/Models/DatabaseModels/ColumnTransformerInvariants.test.ts +306 -0
- package/Tests/Models/DatabaseModels/NumberColumnDeserialization.test.ts +333 -0
- package/Tests/Models/DatabaseModels/StatusPageMonitorRuleModel.test.ts +190 -0
- package/Tests/Server/API/BaseAPIApiKeyAuth.test.ts +704 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +26 -0
- package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +303 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +226 -0
- package/Tests/Server/Infrastructure/PostgresLockTimeoutOptions.test.ts +181 -0
- package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +350 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyHeader.test.ts +362 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +687 -0
- package/Tests/Server/Services/BillingService.test.ts +78 -3
- package/Tests/Server/Services/BillingServiceChangePlanCancel.test.ts +645 -0
- package/Tests/Server/Services/BillingServiceTrialPlanChange.test.ts +1005 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlocked.test.ts +342 -0
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +245 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +503 -0
- package/Tests/Server/Services/HostIpAddressesColumnWidth.test.ts +198 -0
- package/Tests/Server/Services/HostServiceUpdateLastSeen.test.ts +658 -0
- package/Tests/Server/Services/InventoryResourceNameColumnWidth.test.ts +500 -0
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +586 -0
- package/Tests/Server/Services/InventoryUpsertTruncationGuard.test.ts +1242 -0
- package/Tests/Server/Services/MetricTypeAttachServices.test.ts +222 -0
- package/Tests/Server/Services/MissingReferenceWriteGuard.test.ts +614 -0
- package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +23 -0
- package/Tests/Server/Services/ProjectServiceChangePlan.test.ts +650 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +1 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +636 -0
- package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +770 -0
- package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +130 -0
- package/Tests/Server/Services/ServiceUpdateLastSeenSplitGates.test.ts +705 -0
- package/Tests/Server/Services/SloMonitorLabelRuleHooks.test.ts +352 -0
- package/Tests/Server/Services/StatusPageMonitorRuleEngineService.test.ts +1719 -0
- package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +1212 -0
- package/Tests/Server/Services/StatusPageMonitorRuleMonitorCreateHook.test.ts +228 -0
- package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +29 -13
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +69 -8
- package/Tests/Server/Types/Database/JSONColumnQuery.test.ts +593 -0
- package/Tests/Server/Types/Database/Permissions/PublicPermission.test.ts +495 -0
- package/Tests/Server/Types/Database/QueryUtil.test.ts +113 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +267 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +260 -13
- package/Tests/Server/Utils/Database/TruncateColumnValue.test.ts +179 -0
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +302 -0
- package/Tests/Server/Utils/MetricTypeIndexConvergence.test.ts +598 -0
- package/Tests/Server/Utils/Monitor/MonitorStatusTimelineUnusableStatus.test.ts +154 -0
- package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +638 -92
- package/Tests/Server/Utils/Monitor/MonitorStepsReferenceExtractor.test.ts +724 -0
- package/Tests/Server/Utils/SingleFlight.test.ts +221 -0
- package/Tests/Types/Dashboard/NetworkDashboardTemplate.test.ts +793 -0
- package/Tests/Types/Database/BigIntColumnTransformer.test.ts +147 -0
- package/Tests/Types/Database/DatabasePropertyTransformer.test.ts +140 -0
- package/Tests/Types/Database/NumericColumnValue.test.ts +127 -0
- package/Tests/Types/Decimal.test.ts +37 -0
- package/Tests/Types/Events/Recurring.test.ts +157 -0
- package/Tests/Types/Monitor/SnmpVersionParsing.test.ts +152 -0
- package/Tests/Types/Port.test.ts +38 -0
- package/Tests/UI/Components/LogsHistogram.test.tsx +276 -0
- package/Tests/UI/Components/ModelTable/ModelTableGroupsProjectUsers.test.tsx +375 -0
- package/Tests/UI/Components/ModelTable/useCustomFieldColumns.test.tsx +196 -0
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +489 -0
- package/Tests/UI/Components/UseLogsHistogram.test.tsx +500 -0
- package/Tests/UI/Utils/ProjectUsersModelAPI.test.ts +739 -0
- package/Tests/UI/Utils/TeamMembersByUser.test.ts +633 -0
- package/Tests/Utils/Dashboard/Components/DashboardComponentsUtil.test.ts +120 -0
- package/Tests/Utils/Dashboard/DashboardNetworkMapComponent.test.ts +327 -0
- package/Tests/Utils/StatusPage/ReportPeriod.test.ts +218 -0
- package/Tests/Utils/Telemetry/HostIpAddresses.test.ts +291 -0
- package/Types/CustomField/CustomFieldDefinition.ts +24 -0
- package/Types/Dashboard/DashboardComponentType.ts +1 -0
- package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +1 -0
- package/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.ts +40 -0
- package/Types/Dashboard/DashboardTemplates.ts +397 -0
- package/Types/Database/BigIntColumnTransformer.ts +74 -0
- package/Types/Database/DatabaseProperty.ts +26 -0
- package/Types/Database/NumericColumnValue.ts +128 -0
- package/Types/Date.ts +112 -0
- package/Types/Decimal.ts +16 -4
- package/Types/Events/Recurring.ts +99 -1
- package/Types/Permission.ts +48 -0
- package/Types/Port.ts +16 -4
- package/Types/StatusPage/StatusPageReport.ts +11 -0
- package/Types/StatusPage/StatusPageReportPeriodType.ts +21 -0
- package/UI/Components/LogsViewer/useLiveLogsRefresh.ts +86 -0
- package/UI/Components/LogsViewer/useLogsHistogram.ts +113 -0
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +2 -6
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +21 -2
- package/UI/Utils/ModelAPI/ProjectUsersModelAPI.ts +305 -0
- package/UI/Utils/TeamMembersByUser.ts +302 -0
- package/Utils/Dashboard/Components/DashboardNetworkMapComponent.ts +136 -0
- package/Utils/Dashboard/Components/Index.ts +7 -0
- package/Utils/StatusPage/ReportPeriod.ts +236 -0
- package/Utils/Telemetry/HostIpAddresses.ts +98 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +12 -0
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +12 -4
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesContainer.js +4 -4
- package/build/dist/Models/DatabaseModels/KubernetesContainer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesResource.js +7 -7
- package/build/dist/Models/DatabaseModels/KubernetesResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/PodmanResource.js +6 -6
- package/build/dist/Models/DatabaseModels/PodmanResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +87 -0
- package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +98 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js +925 -0
- package/build/dist/Models/DatabaseModels/StatusPageMonitorRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageResource.js +72 -0
- package/build/dist/Models/DatabaseModels/StatusPageResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +9 -20
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +11 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +39 -0
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/TeamMemberAPI.js +57 -2
- package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +27 -1
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +91 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +5 -3
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.js +45 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785900000000-AddSloMonitorLabelRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785915638551-IncreaseHostIpAddressesLength.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.js +90 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930000000-WidenInventoryResourceNameColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785930709405-AddStatusPageReportPeriod.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786005052769-AddStatusPageMonitorRule.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/ProjectAuthorization.js +59 -4
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AlertStateTimelineService.js +19 -0
- package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +466 -36
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +26 -39
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CephResourceService.js +28 -3
- package/build/dist/Server/Services/CephResourceService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +23 -36
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +155 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +19 -32
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerResourceService.js +34 -4
- package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +27 -40
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmResourceService.js +28 -3
- package/build/dist/Server/Services/DockerSwarmResourceService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +58 -64
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +19 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceService.js +1 -8
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetService.js +19 -32
- package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +17 -30
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesContainerService.js +29 -3
- package/build/dist/Server/Services/KubernetesContainerService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesResourceService.js +32 -4
- package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +127 -0
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/MetricTypeService.js +74 -0
- package/build/dist/Server/Services/MetricTypeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +128 -9
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorStatusTimelineService.js +28 -0
- package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +60 -0
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +19 -32
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/PodmanResourceService.js +34 -4
- package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +135 -21
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +23 -36
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxResourceService.js +28 -3
- package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationService.js +19 -32
- package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +20 -0
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionService.js +24 -37
- package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +347 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js +33 -1
- package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +236 -61
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +603 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js +401 -0
- package/build/dist/Server/Services/StatusPageMonitorRuleService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageService.js +69 -46
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +17 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +3 -0
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +1 -0
- package/build/dist/Server/Services/TelemetryEntityService.js.map +1 -1
- package/build/dist/Server/Types/Database/JSONColumnQuery.js +402 -0
- package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -0
- package/build/dist/Server/Types/Database/Permissions/PublicPermission.js +9 -2
- package/build/dist/Server/Types/Database/Permissions/PublicPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +17 -27
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +105 -29
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/Database/TruncateColumnValue.js +32 -0
- package/build/dist/Server/Utils/Database/TruncateColumnValue.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +56 -32
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +30 -3
- package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +110 -98
- package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js +312 -0
- package/build/dist/Server/Utils/Monitor/MonitorStepsReferenceExtractor.js.map +1 -0
- package/build/dist/Server/Utils/SingleFlight.js +76 -0
- package/build/dist/Server/Utils/SingleFlight.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +29 -0
- package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +78 -19
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js +160 -0
- package/build/dist/Server/Utils/Telemetry/ResourceHeartbeat.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +279 -104
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldDefinition.js +2 -0
- package/build/dist/Types/CustomField/CustomFieldDefinition.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +1 -0
- package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js +2 -0
- package/build/dist/Types/Dashboard/DashboardComponents/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +368 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Database/BigIntColumnTransformer.js +66 -0
- package/build/dist/Types/Database/BigIntColumnTransformer.js.map +1 -0
- package/build/dist/Types/Database/DatabaseProperty.js +25 -0
- package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
- package/build/dist/Types/Database/NumericColumnValue.js +97 -0
- package/build/dist/Types/Database/NumericColumnValue.js.map +1 -0
- package/build/dist/Types/Date.js +68 -0
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Decimal.js +14 -3
- package/build/dist/Types/Decimal.js.map +1 -1
- package/build/dist/Types/Events/Recurring.js +63 -0
- package/build/dist/Types/Events/Recurring.js.map +1 -1
- package/build/dist/Types/Permission.js +42 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Port.js +15 -5
- package/build/dist/Types/Port.js.map +1 -1
- package/build/dist/Types/StatusPage/StatusPageReportPeriodType.js +22 -0
- package/build/dist/Types/StatusPage/StatusPageReportPeriodType.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js +44 -0
- package/build/dist/UI/Components/LogsViewer/useLiveLogsRefresh.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js +75 -0
- package/build/dist/UI/Components/LogsViewer/useLogsHistogram.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +18 -2
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js +213 -0
- package/build/dist/UI/Utils/ModelAPI/ProjectUsersModelAPI.js.map +1 -0
- package/build/dist/UI/Utils/TeamMembersByUser.js +195 -0
- package/build/dist/UI/Utils/TeamMembersByUser.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js +114 -0
- package/build/dist/Utils/Dashboard/Components/DashboardNetworkMapComponent.js.map +1 -0
- package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
- package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
- package/build/dist/Utils/StatusPage/ReportPeriod.js +131 -0
- package/build/dist/Utils/StatusPage/ReportPeriod.js.map +1 -0
- package/build/dist/Utils/Telemetry/HostIpAddresses.js +82 -0
- package/build/dist/Utils/Telemetry/HostIpAddresses.js.map +1 -0
- package/jest.config.json +2 -0
- package/package.json +1 -1
- package/tsconfig.json +12 -1
|
@@ -11,6 +11,7 @@ import MetricsAggregationType from "../Metrics/MetricsAggregationType";
|
|
|
11
11
|
import IncidentMetricType from "../Incident/IncidentMetricType";
|
|
12
12
|
import AlertMetricType from "../Alerts/AlertMetricType";
|
|
13
13
|
import MonitorMetricType from "../Monitor/MonitorMetricType";
|
|
14
|
+
import MonitorType from "../Monitor/MonitorType";
|
|
14
15
|
import MetricDashboardMetricType from "../Metrics/MetricDashboardMetricType";
|
|
15
16
|
import { DashboardValueTrendDirection } from "./DashboardComponents/DashboardValueComponent";
|
|
16
17
|
|
|
@@ -39,6 +40,7 @@ export enum DashboardTemplateType {
|
|
|
39
40
|
DockerSwarm = "DockerSwarm",
|
|
40
41
|
Metrics = "Metrics",
|
|
41
42
|
Rum = "Rum",
|
|
43
|
+
Network = "Network",
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
/*
|
|
@@ -165,6 +167,14 @@ export const DashboardTemplates: Array<DashboardTemplate> = [
|
|
|
165
167
|
icon: IconProp.Cube,
|
|
166
168
|
category: DashboardTemplateCategory.Infrastructure,
|
|
167
169
|
},
|
|
170
|
+
{
|
|
171
|
+
type: DashboardTemplateType.Network,
|
|
172
|
+
name: "Network Dashboard",
|
|
173
|
+
description:
|
|
174
|
+
"Your sites on the world map, SNMP interface throughput, utilization and errors, device reachability and round-trip latency, and the monitors watching them.",
|
|
175
|
+
icon: IconProp.Map,
|
|
176
|
+
category: DashboardTemplateCategory.Infrastructure,
|
|
177
|
+
},
|
|
168
178
|
];
|
|
169
179
|
|
|
170
180
|
/*
|
|
@@ -796,6 +806,71 @@ function createCephPoolListComponent(data: {
|
|
|
796
806
|
};
|
|
797
807
|
}
|
|
798
808
|
|
|
809
|
+
function createNetworkMapComponent(data: {
|
|
810
|
+
title: string;
|
|
811
|
+
top: number;
|
|
812
|
+
left: number;
|
|
813
|
+
width: number;
|
|
814
|
+
height: number;
|
|
815
|
+
maxSites?: number;
|
|
816
|
+
statusFilter?: string;
|
|
817
|
+
showLabels?: boolean;
|
|
818
|
+
}): DashboardBaseComponent {
|
|
819
|
+
return {
|
|
820
|
+
_type: ObjectType.DashboardComponent,
|
|
821
|
+
componentType: DashboardComponentType.NetworkMap,
|
|
822
|
+
componentId: ObjectID.generate(),
|
|
823
|
+
topInDashboardUnits: data.top,
|
|
824
|
+
leftInDashboardUnits: data.left,
|
|
825
|
+
widthInDashboardUnits: data.width,
|
|
826
|
+
heightInDashboardUnits: data.height,
|
|
827
|
+
/*
|
|
828
|
+
* A map needs room in BOTH axes — the world is roughly 2:1, so a short
|
|
829
|
+
* tile letterboxes it into a strip. Same floor the widget's own default
|
|
830
|
+
* declares (Common/Utils/Dashboard/Components/DashboardNetworkMapComponent).
|
|
831
|
+
*/
|
|
832
|
+
minHeightInDashboardUnits: 4,
|
|
833
|
+
minWidthInDashboardUnits: 4,
|
|
834
|
+
arguments: {
|
|
835
|
+
title: data.title,
|
|
836
|
+
maxSites: data.maxSites ?? 250,
|
|
837
|
+
viewMode: "map",
|
|
838
|
+
showLabels: data.showLabels ?? true,
|
|
839
|
+
statusFilter: data.statusFilter,
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
function createMonitorListComponent(data: {
|
|
845
|
+
title: string;
|
|
846
|
+
top: number;
|
|
847
|
+
left: number;
|
|
848
|
+
width: number;
|
|
849
|
+
height: number;
|
|
850
|
+
maxRows?: number;
|
|
851
|
+
monitorTypes?: Array<string>;
|
|
852
|
+
statusFilter?: string;
|
|
853
|
+
}): DashboardBaseComponent {
|
|
854
|
+
return {
|
|
855
|
+
_type: ObjectType.DashboardComponent,
|
|
856
|
+
componentType: DashboardComponentType.MonitorList,
|
|
857
|
+
componentId: ObjectID.generate(),
|
|
858
|
+
topInDashboardUnits: data.top,
|
|
859
|
+
leftInDashboardUnits: data.left,
|
|
860
|
+
widthInDashboardUnits: data.width,
|
|
861
|
+
heightInDashboardUnits: data.height,
|
|
862
|
+
minHeightInDashboardUnits: 3,
|
|
863
|
+
minWidthInDashboardUnits: 6,
|
|
864
|
+
arguments: {
|
|
865
|
+
title: data.title,
|
|
866
|
+
maxRows: data.maxRows ?? 25,
|
|
867
|
+
viewMode: "list",
|
|
868
|
+
monitorTypes: data.monitorTypes,
|
|
869
|
+
statusFilter: data.statusFilter,
|
|
870
|
+
},
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
|
|
799
874
|
// -- Dashboard configs --
|
|
800
875
|
|
|
801
876
|
function createMonitorDashboardConfig(): DashboardViewConfig {
|
|
@@ -3411,6 +3486,326 @@ function createCephDashboardConfig(): DashboardViewConfig {
|
|
|
3411
3486
|
};
|
|
3412
3487
|
}
|
|
3413
3488
|
|
|
3489
|
+
function createNetworkDashboardConfig(): DashboardViewConfig {
|
|
3490
|
+
/*
|
|
3491
|
+
* Layout and metric notes:
|
|
3492
|
+
*
|
|
3493
|
+
* - The map reads the Postgres NetworkSite inventory rather than a metric
|
|
3494
|
+
* series, so its markers are true right now — the same reasoning the
|
|
3495
|
+
* Kubernetes / Ceph templates use for their inventory widgets.
|
|
3496
|
+
*
|
|
3497
|
+
* - EVERY metric widget here queries an `oneuptime.monitor.snmp.*` series,
|
|
3498
|
+
* and those are emitted by exactly one code path:
|
|
3499
|
+
* NetworkDeviceMetricUtil.saveWalkMetrics, off a network device walk.
|
|
3500
|
+
* That is deliberate and it is the constraint the rest of this template
|
|
3501
|
+
* is built around.
|
|
3502
|
+
*
|
|
3503
|
+
* The obvious tiles to reach for — uptime, round-trip time, packet loss,
|
|
3504
|
+
* jitter — do NOT belong here, however much a network dashboard wants
|
|
3505
|
+
* them. `oneuptime.monitor.online` and `oneuptime.monitor.response.time`
|
|
3506
|
+
* are emitted by MonitorMetricUtil for EVERY probeable monitor in the
|
|
3507
|
+
* project, and packet loss and jitter come from Ping/IP monitors. A tile
|
|
3508
|
+
* titled "Round-trip Time" on a network dashboard that silently averages
|
|
3509
|
+
* every website check in the project is worse than no tile: it is a
|
|
3510
|
+
* number a reader will act on. Device reachability is on this dashboard
|
|
3511
|
+
* as the Network Device monitor list, which IS correctly scoped.
|
|
3512
|
+
*
|
|
3513
|
+
* - Because every series here comes from the device walk, every series
|
|
3514
|
+
* carries `deviceName`, and the per-interface ones also carry
|
|
3515
|
+
* `interfaceName` — so both template variables bind to something real on
|
|
3516
|
+
* every widget. Those keys are BARE, not `resource.`-prefixed; see
|
|
3517
|
+
* NetworkDeviceMetricUtil.buildDeviceMetricRow.
|
|
3518
|
+
*
|
|
3519
|
+
* - No widget aggregates with Sum. The interface series are already
|
|
3520
|
+
* per-second RATES, and the Value tile reduces across time buckets — so
|
|
3521
|
+
* a summed rate grows with the dashboard's time range rather than
|
|
3522
|
+
* describing the network. Max answers "how bad did it get", Avg answers
|
|
3523
|
+
* "what is normal"; both are range-independent.
|
|
3524
|
+
*
|
|
3525
|
+
* - For the same reason the in/out bit-rate charts are NOT
|
|
3526
|
+
* transformAsRate'd the way the Ceph template's cumulative
|
|
3527
|
+
* ceph_pool_*_bytes counters are. They are already rates; rate-of-a-rate
|
|
3528
|
+
* plots noise around zero.
|
|
3529
|
+
*/
|
|
3530
|
+
const components: Array<DashboardBaseComponent> = [
|
|
3531
|
+
// Row 0: Title
|
|
3532
|
+
createTextComponent({
|
|
3533
|
+
text: "Network Dashboard",
|
|
3534
|
+
top: 0,
|
|
3535
|
+
left: 0,
|
|
3536
|
+
width: 12,
|
|
3537
|
+
height: 1,
|
|
3538
|
+
isBold: true,
|
|
3539
|
+
}),
|
|
3540
|
+
|
|
3541
|
+
/*
|
|
3542
|
+
* Rows 1-5: where the network IS, next to how it is doing. The map is
|
|
3543
|
+
* the subject and takes two thirds of the width; the column beside it
|
|
3544
|
+
* is the numbers a reader checks without leaving the picture.
|
|
3545
|
+
*/
|
|
3546
|
+
createNetworkMapComponent({
|
|
3547
|
+
title: "Sites",
|
|
3548
|
+
top: 1,
|
|
3549
|
+
left: 0,
|
|
3550
|
+
width: 8,
|
|
3551
|
+
height: 5,
|
|
3552
|
+
maxSites: 250,
|
|
3553
|
+
}),
|
|
3554
|
+
/*
|
|
3555
|
+
* SnmpInterfaceOperStatus is emitted as 0/1 per interface, so Avg is the
|
|
3556
|
+
* FRACTION of interfaces currently up — in [0, 1], not a percent.
|
|
3557
|
+
* Labelled "(avg)" for the same reason the Monitor template labels its
|
|
3558
|
+
* uptime tile that way rather than printing a misleading "%".
|
|
3559
|
+
*/
|
|
3560
|
+
createValueComponent({
|
|
3561
|
+
title: "Interfaces Up (avg)",
|
|
3562
|
+
top: 1,
|
|
3563
|
+
left: 8,
|
|
3564
|
+
width: 4,
|
|
3565
|
+
metricConfig: {
|
|
3566
|
+
metricName: MonitorMetricType.SnmpInterfaceOperStatus,
|
|
3567
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
3568
|
+
},
|
|
3569
|
+
trendDirection: DashboardValueTrendDirection.HigherIsBetter,
|
|
3570
|
+
}),
|
|
3571
|
+
createValueComponent({
|
|
3572
|
+
title: "Avg Interface Utilization",
|
|
3573
|
+
top: 2,
|
|
3574
|
+
left: 8,
|
|
3575
|
+
width: 4,
|
|
3576
|
+
metricConfig: {
|
|
3577
|
+
metricName: MonitorMetricType.SnmpInterfaceUtilizationPercent,
|
|
3578
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
3579
|
+
},
|
|
3580
|
+
trendDirection: DashboardValueTrendDirection.HigherIsWorse,
|
|
3581
|
+
}),
|
|
3582
|
+
/*
|
|
3583
|
+
* Max, not Sum: this is "how bad did the worst port get", which is what
|
|
3584
|
+
* an operator acts on. Summing a per-second error rate across every
|
|
3585
|
+
* interface and every time bucket produces a number that doubles when
|
|
3586
|
+
* you widen the time picker.
|
|
3587
|
+
*/
|
|
3588
|
+
createValueComponent({
|
|
3589
|
+
title: "Worst Interface Errors/sec",
|
|
3590
|
+
top: 3,
|
|
3591
|
+
left: 8,
|
|
3592
|
+
width: 4,
|
|
3593
|
+
metricConfig: {
|
|
3594
|
+
metricName: MonitorMetricType.SnmpInterfaceErrorsPerSecond,
|
|
3595
|
+
aggregationType: MetricsAggregationType.Max,
|
|
3596
|
+
},
|
|
3597
|
+
trendDirection: DashboardValueTrendDirection.HigherIsWorse,
|
|
3598
|
+
}),
|
|
3599
|
+
createValueComponent({
|
|
3600
|
+
title: "Peak Inbound",
|
|
3601
|
+
top: 4,
|
|
3602
|
+
left: 8,
|
|
3603
|
+
width: 4,
|
|
3604
|
+
metricConfig: {
|
|
3605
|
+
metricName: MonitorMetricType.SnmpInterfaceInBitsPerSecond,
|
|
3606
|
+
aggregationType: MetricsAggregationType.Max,
|
|
3607
|
+
},
|
|
3608
|
+
}),
|
|
3609
|
+
createValueComponent({
|
|
3610
|
+
title: "Peak Outbound",
|
|
3611
|
+
top: 5,
|
|
3612
|
+
left: 8,
|
|
3613
|
+
width: 4,
|
|
3614
|
+
metricConfig: {
|
|
3615
|
+
metricName: MonitorMetricType.SnmpInterfaceOutBitsPerSecond,
|
|
3616
|
+
aggregationType: MetricsAggregationType.Max,
|
|
3617
|
+
},
|
|
3618
|
+
}),
|
|
3619
|
+
|
|
3620
|
+
// Row 6: Section header
|
|
3621
|
+
createTextComponent({
|
|
3622
|
+
text: "Interface Throughput",
|
|
3623
|
+
top: 6,
|
|
3624
|
+
left: 0,
|
|
3625
|
+
width: 12,
|
|
3626
|
+
height: 1,
|
|
3627
|
+
isBold: true,
|
|
3628
|
+
}),
|
|
3629
|
+
|
|
3630
|
+
/*
|
|
3631
|
+
* Rows 7-9: throughput, split per interface. Grouping by
|
|
3632
|
+
* `interfaceName` is what turns one flat line into one line per uplink,
|
|
3633
|
+
* which is the only form in which "is a link saturated" is answerable —
|
|
3634
|
+
* an ungrouped chart averages a saturated uplink with nine idle access
|
|
3635
|
+
* ports and reports that everything is fine.
|
|
3636
|
+
*/
|
|
3637
|
+
createChartComponent({
|
|
3638
|
+
title: "Inbound by Interface",
|
|
3639
|
+
chartType: DashboardChartType.Area,
|
|
3640
|
+
top: 7,
|
|
3641
|
+
left: 0,
|
|
3642
|
+
width: 6,
|
|
3643
|
+
height: 3,
|
|
3644
|
+
metricConfig: {
|
|
3645
|
+
metricName: MonitorMetricType.SnmpInterfaceInBitsPerSecond,
|
|
3646
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
3647
|
+
legend: "Inbound",
|
|
3648
|
+
legendUnit: "bps",
|
|
3649
|
+
groupByAttributeKeys: ["interfaceName"],
|
|
3650
|
+
},
|
|
3651
|
+
}),
|
|
3652
|
+
createChartComponent({
|
|
3653
|
+
title: "Outbound by Interface",
|
|
3654
|
+
chartType: DashboardChartType.Area,
|
|
3655
|
+
top: 7,
|
|
3656
|
+
left: 6,
|
|
3657
|
+
width: 6,
|
|
3658
|
+
height: 3,
|
|
3659
|
+
metricConfig: {
|
|
3660
|
+
metricName: MonitorMetricType.SnmpInterfaceOutBitsPerSecond,
|
|
3661
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
3662
|
+
legend: "Outbound",
|
|
3663
|
+
legendUnit: "bps",
|
|
3664
|
+
groupByAttributeKeys: ["interfaceName"],
|
|
3665
|
+
},
|
|
3666
|
+
}),
|
|
3667
|
+
|
|
3668
|
+
// Row 10: Section header
|
|
3669
|
+
createTextComponent({
|
|
3670
|
+
text: "Utilization & Errors",
|
|
3671
|
+
top: 10,
|
|
3672
|
+
left: 0,
|
|
3673
|
+
width: 12,
|
|
3674
|
+
height: 1,
|
|
3675
|
+
isBold: true,
|
|
3676
|
+
}),
|
|
3677
|
+
|
|
3678
|
+
/*
|
|
3679
|
+
* Rows 11-13: the gauge an operator watches during an incident, the
|
|
3680
|
+
* error-rate gauge that leads it, and the per-interface error breakdown
|
|
3681
|
+
* that says WHICH port to look at.
|
|
3682
|
+
*/
|
|
3683
|
+
createGaugeComponent({
|
|
3684
|
+
title: "Peak Interface Utilization",
|
|
3685
|
+
top: 11,
|
|
3686
|
+
left: 0,
|
|
3687
|
+
width: 3,
|
|
3688
|
+
height: 3,
|
|
3689
|
+
minValue: 0,
|
|
3690
|
+
maxValue: 100,
|
|
3691
|
+
warningThreshold: 70,
|
|
3692
|
+
criticalThreshold: 90,
|
|
3693
|
+
metricConfig: {
|
|
3694
|
+
metricName: MonitorMetricType.SnmpInterfaceUtilizationPercent,
|
|
3695
|
+
aggregationType: MetricsAggregationType.Max,
|
|
3696
|
+
},
|
|
3697
|
+
}),
|
|
3698
|
+
createGaugeComponent({
|
|
3699
|
+
title: "Interface Error Rate",
|
|
3700
|
+
top: 11,
|
|
3701
|
+
left: 3,
|
|
3702
|
+
width: 3,
|
|
3703
|
+
height: 3,
|
|
3704
|
+
/*
|
|
3705
|
+
* A healthy Ethernet port errors essentially never, so the scale is
|
|
3706
|
+
* deliberately tight: a sustained one error per second is already a
|
|
3707
|
+
* cable, duplex or optic problem worth a ticket, and five is a link
|
|
3708
|
+
* on its way out. A 0-100 scale like the utilization gauge next to it
|
|
3709
|
+
* would render every real fault as a flat line on the floor.
|
|
3710
|
+
*/
|
|
3711
|
+
minValue: 0,
|
|
3712
|
+
maxValue: 10,
|
|
3713
|
+
warningThreshold: 1,
|
|
3714
|
+
criticalThreshold: 5,
|
|
3715
|
+
metricConfig: {
|
|
3716
|
+
metricName: MonitorMetricType.SnmpInterfaceErrorsPerSecond,
|
|
3717
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
3718
|
+
},
|
|
3719
|
+
}),
|
|
3720
|
+
createChartComponent({
|
|
3721
|
+
title: "Interface Errors by Interface",
|
|
3722
|
+
chartType: DashboardChartType.Bar,
|
|
3723
|
+
top: 11,
|
|
3724
|
+
left: 6,
|
|
3725
|
+
width: 6,
|
|
3726
|
+
height: 3,
|
|
3727
|
+
metricConfig: {
|
|
3728
|
+
metricName: MonitorMetricType.SnmpInterfaceErrorsPerSecond,
|
|
3729
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
3730
|
+
legend: "Errors/sec",
|
|
3731
|
+
groupByAttributeKeys: ["interfaceName"],
|
|
3732
|
+
},
|
|
3733
|
+
}),
|
|
3734
|
+
|
|
3735
|
+
// Row 14: Section header
|
|
3736
|
+
createTextComponent({
|
|
3737
|
+
text: "Devices & Monitors",
|
|
3738
|
+
top: 14,
|
|
3739
|
+
left: 0,
|
|
3740
|
+
width: 12,
|
|
3741
|
+
height: 1,
|
|
3742
|
+
isBold: true,
|
|
3743
|
+
}),
|
|
3744
|
+
|
|
3745
|
+
/*
|
|
3746
|
+
* Rows 15-18: utilization per interface, beside the monitors that page
|
|
3747
|
+
* somebody when a device stops answering. The list is pinned to Network
|
|
3748
|
+
* Device monitors — an unfiltered monitor list on a network dashboard is
|
|
3749
|
+
* just the Monitors page with fewer columns — and it is also this
|
|
3750
|
+
* dashboard's reachability view, correctly scoped in a way a shared
|
|
3751
|
+
* uptime metric could never be.
|
|
3752
|
+
*/
|
|
3753
|
+
createChartComponent({
|
|
3754
|
+
title: "Utilization by Interface",
|
|
3755
|
+
chartType: DashboardChartType.Line,
|
|
3756
|
+
top: 15,
|
|
3757
|
+
left: 0,
|
|
3758
|
+
width: 6,
|
|
3759
|
+
height: 4,
|
|
3760
|
+
metricConfig: {
|
|
3761
|
+
metricName: MonitorMetricType.SnmpInterfaceUtilizationPercent,
|
|
3762
|
+
aggregationType: MetricsAggregationType.Avg,
|
|
3763
|
+
legend: "Utilization",
|
|
3764
|
+
legendUnit: "%",
|
|
3765
|
+
groupByAttributeKeys: ["interfaceName"],
|
|
3766
|
+
},
|
|
3767
|
+
}),
|
|
3768
|
+
createMonitorListComponent({
|
|
3769
|
+
title: "Network Device Monitors",
|
|
3770
|
+
top: 15,
|
|
3771
|
+
left: 6,
|
|
3772
|
+
width: 6,
|
|
3773
|
+
height: 4,
|
|
3774
|
+
maxRows: 25,
|
|
3775
|
+
monitorTypes: [MonitorType.NetworkDevice],
|
|
3776
|
+
}),
|
|
3777
|
+
];
|
|
3778
|
+
|
|
3779
|
+
/*
|
|
3780
|
+
* Network device metrics are stored with BARE attribute keys
|
|
3781
|
+
* (`deviceName`, `interfaceName`) rather than the OTel `resource.` prefix
|
|
3782
|
+
* — see NetworkDeviceMetricUtil.buildDeviceMetricRow — so the variables
|
|
3783
|
+
* bind to the bare keys. Both are multi-select: comparing two uplinks, or
|
|
3784
|
+
* two branch routers, is the normal use rather than the exception.
|
|
3785
|
+
*/
|
|
3786
|
+
const variables: Array<DashboardVariable> = [
|
|
3787
|
+
createTelemetryAttributeVariable({
|
|
3788
|
+
name: "device",
|
|
3789
|
+
label: "Device",
|
|
3790
|
+
attributeKey: "deviceName",
|
|
3791
|
+
isMultiSelect: true,
|
|
3792
|
+
}),
|
|
3793
|
+
createTelemetryAttributeVariable({
|
|
3794
|
+
name: "interface",
|
|
3795
|
+
label: "Interface",
|
|
3796
|
+
attributeKey: "interfaceName",
|
|
3797
|
+
isMultiSelect: true,
|
|
3798
|
+
}),
|
|
3799
|
+
];
|
|
3800
|
+
|
|
3801
|
+
return {
|
|
3802
|
+
_type: ObjectType.DashboardViewConfig,
|
|
3803
|
+
components,
|
|
3804
|
+
variables,
|
|
3805
|
+
heightInDashboardUnits: Math.max(DashboardSize.heightInDashboardUnits, 19),
|
|
3806
|
+
};
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3414
3809
|
export function getTemplateConfig(
|
|
3415
3810
|
type: DashboardTemplateType,
|
|
3416
3811
|
): DashboardViewConfig | null {
|
|
@@ -3437,6 +3832,8 @@ export function getTemplateConfig(
|
|
|
3437
3832
|
return createMetricsDashboardConfig();
|
|
3438
3833
|
case DashboardTemplateType.Rum:
|
|
3439
3834
|
return createRumDashboardConfig();
|
|
3835
|
+
case DashboardTemplateType.Network:
|
|
3836
|
+
return createNetworkDashboardConfig();
|
|
3440
3837
|
case DashboardTemplateType.Blank:
|
|
3441
3838
|
return null;
|
|
3442
3839
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { ValueTransformer } from "typeorm/decorator/options/ValueTransformer";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Round-trip for columns declared `ColumnType.BigPositiveNumber` (Postgres
|
|
5
|
+
* bigint) that the rest of the codebase wants to read as a plain number.
|
|
6
|
+
*
|
|
7
|
+
* `to` MUST pass `undefined` through untouched. TypeORM runs the column
|
|
8
|
+
* transformer *before* it decides whether the column was supplied at all:
|
|
9
|
+
*
|
|
10
|
+
* InsertQueryBuilder.createColumnValueExpression
|
|
11
|
+
* -> driver.preparePersistentValue (applies transformer.to)
|
|
12
|
+
* -> if (value === undefined) expression += "DEFAULT"
|
|
13
|
+
*
|
|
14
|
+
* so a transformer that folds `undefined` into `null` rewrites "the caller
|
|
15
|
+
* did not set this column" into "the caller explicitly set it to NULL". The
|
|
16
|
+
* column's DEFAULT is then never reached. On a `NOT NULL DEFAULT 0` counter
|
|
17
|
+
* that is a 500 on *every* insert:
|
|
18
|
+
*
|
|
19
|
+
* null value in column "droppedCount" of relation "LogDropFilter"
|
|
20
|
+
* violates not-null constraint
|
|
21
|
+
*
|
|
22
|
+
* which is exactly what shipped for the drop-filter drop counters. Nothing
|
|
23
|
+
* in the product sets those counters on create — they are ingest-owned — so
|
|
24
|
+
* every drop filter created through the dashboard failed.
|
|
25
|
+
*
|
|
26
|
+
* `from` exists because node-postgres hands bigint back as a string (it does
|
|
27
|
+
* not fit a JS number in the general case). Every value we store here is a
|
|
28
|
+
* record counter well inside Number.MAX_SAFE_INTEGER, and the UI renders it
|
|
29
|
+
* as a number, so normalize once here rather than making each reader
|
|
30
|
+
* remember.
|
|
31
|
+
*/
|
|
32
|
+
export function getBigIntDatabaseTransformer(): ValueTransformer {
|
|
33
|
+
return {
|
|
34
|
+
to: (value: number | null | undefined): string | null | undefined => {
|
|
35
|
+
/*
|
|
36
|
+
* Not a mistake and not the same as `null`: see the note above. This
|
|
37
|
+
* is the branch that lets the column DEFAULT apply.
|
|
38
|
+
*/
|
|
39
|
+
if (value === undefined) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (value === null) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
48
|
+
/*
|
|
49
|
+
* `Math.trunc(NaN).toString()` is the string "NaN", which Postgres
|
|
50
|
+
* rejects with a syntax error that names neither the column nor the
|
|
51
|
+
* caller. Null at least fails as a constraint violation on the
|
|
52
|
+
* column it belongs to.
|
|
53
|
+
*/
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return Math.trunc(value).toString();
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
from: (value: string | number | null | undefined): number | null => {
|
|
61
|
+
if (value === null || value === undefined) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (typeof value === "number") {
|
|
66
|
+
return Number.isFinite(value) ? value : null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const parsed: number = parseInt(value, 10);
|
|
70
|
+
|
|
71
|
+
return isNaN(parsed) ? null : parsed;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
@@ -45,6 +45,32 @@ export default class DatabaseProperty extends SerializableObject {
|
|
|
45
45
|
public static getDatabaseTransformer(): ValueTransformer {
|
|
46
46
|
return {
|
|
47
47
|
to: (value: any) => {
|
|
48
|
+
/*
|
|
49
|
+
* `undefined` means "the caller did not set this column", and it has
|
|
50
|
+
* to stay distinguishable from `null` all the way into TypeORM.
|
|
51
|
+
*
|
|
52
|
+
* TypeORM runs the transformer BEFORE deciding whether the column
|
|
53
|
+
* was supplied:
|
|
54
|
+
*
|
|
55
|
+
* InsertQueryBuilder.createColumnValueExpression
|
|
56
|
+
* -> driver.preparePersistentValue (runs this function)
|
|
57
|
+
* -> if (value === undefined) expression += "DEFAULT"
|
|
58
|
+
*
|
|
59
|
+
* so answering `null` here (which every `toDatabase` does for a
|
|
60
|
+
* falsy value) rewrites an omitted column into an explicit NULL and
|
|
61
|
+
* makes the column's DEFAULT unreachable. On a NOT NULL column with
|
|
62
|
+
* a default — an on-call layer's `rotation`, a drop filter's
|
|
63
|
+
* `droppedCount` — that is a not-null constraint violation, i.e. an
|
|
64
|
+
* HTTP 500, on every create that leaves the column alone.
|
|
65
|
+
*
|
|
66
|
+
* UPDATE is unaffected either way: UpdateQueryBuilder strips
|
|
67
|
+
* undefined properties before the transformer ever sees them
|
|
68
|
+
* ("it doesn't make sense to update undefined properties").
|
|
69
|
+
*/
|
|
70
|
+
if (value === undefined) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
48
74
|
return this._toDatabase(value);
|
|
49
75
|
},
|
|
50
76
|
from: (value: any) => {
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { JSONObject, JSONValue } from "../JSON";
|
|
2
|
+
import { TableColumnMetadata } from "./TableColumn";
|
|
3
|
+
import TableColumnType from "./TableColumnType";
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Column types whose in-memory representation is a plain JavaScript number.
|
|
7
|
+
*
|
|
8
|
+
* Deliberately excludes the types that merely *look* numeric — `Port`,
|
|
9
|
+
* `Version`, `Date` — because coercing those would destroy them.
|
|
10
|
+
*
|
|
11
|
+
* The declared type is not a perfect proxy for the in-memory one: an SMTP
|
|
12
|
+
* port is declared `Number` but typed `Port`, and a usage figure is declared
|
|
13
|
+
* `Number` but typed `Decimal`. Coercing a string to a number is safe for
|
|
14
|
+
* those only because each of their transformers accepts a raw number —
|
|
15
|
+
* which is a property their tests pin, not an accident.
|
|
16
|
+
*/
|
|
17
|
+
const NUMERIC_TABLE_COLUMN_TYPES: Set<TableColumnType> =
|
|
18
|
+
new Set<TableColumnType>([
|
|
19
|
+
TableColumnType.Number,
|
|
20
|
+
TableColumnType.SmallNumber,
|
|
21
|
+
TableColumnType.BigNumber,
|
|
22
|
+
TableColumnType.PositiveNumber,
|
|
23
|
+
TableColumnType.SmallPositiveNumber,
|
|
24
|
+
TableColumnType.BigPositiveNumber,
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
export function isNumericTableColumnType(
|
|
28
|
+
type: TableColumnType | undefined | null,
|
|
29
|
+
): boolean {
|
|
30
|
+
if (!type) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return NUMERIC_TABLE_COLUMN_TYPES.has(type);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*
|
|
38
|
+
* Normalize a JSON value destined for a number column.
|
|
39
|
+
*
|
|
40
|
+
* The dashboard's number form field is an `<input type="number">`, and a DOM
|
|
41
|
+
* input's value is a *string* — there is no numeric input event in HTML. So
|
|
42
|
+
* "10" typed into "Sample Percentage" reached the API as the JSON string
|
|
43
|
+
* "10", and any server-side check spelled `typeof value === "number"`
|
|
44
|
+
* rejected a perfectly valid form submission:
|
|
45
|
+
*
|
|
46
|
+
* BadDataException: Sample percentage is required when the action is
|
|
47
|
+
* "Sample" ... between 1 and 99.
|
|
48
|
+
*
|
|
49
|
+
* Postgres silently coerces '10' to 10 on the way in, which is why this had
|
|
50
|
+
* gone unnoticed on every other number field in the product: the string only
|
|
51
|
+
* becomes visible when something reads the value before it is stored.
|
|
52
|
+
*
|
|
53
|
+
* Normalizing here — where the column's declared type is known, on both the
|
|
54
|
+
* browser side (ModelForm -> BaseModel.fromJSON) and the server side
|
|
55
|
+
* (BaseAPI -> BaseModel.fromJSON) — means a number column holds a number by
|
|
56
|
+
* the time any hook, validator or query sees it.
|
|
57
|
+
*
|
|
58
|
+
* Only strings that parse cleanly to a finite number are converted. A blank
|
|
59
|
+
* string is left alone rather than turned into `0` (`Number("")` is 0, which
|
|
60
|
+
* would silently write a real value for a field the user cleared) or into
|
|
61
|
+
* `null` (which would defeat a column DEFAULT the same way the bigint
|
|
62
|
+
* transformer used to). Garbage like "abc" is left alone too, so validation
|
|
63
|
+
* rejects it with a message about the field instead of this function
|
|
64
|
+
* inventing a value.
|
|
65
|
+
*/
|
|
66
|
+
export function coerceNumericColumnValue(value: unknown): unknown {
|
|
67
|
+
if (typeof value !== "string") {
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const trimmed: string = value.trim();
|
|
72
|
+
|
|
73
|
+
if (trimmed.length === 0) {
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const parsed: number = Number(trimmed);
|
|
78
|
+
|
|
79
|
+
if (!Number.isFinite(parsed)) {
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return parsed;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* The minimum a model has to offer for its number columns to be found.
|
|
88
|
+
* Every DatabaseBaseModel satisfies it; asking for only this keeps the
|
|
89
|
+
* coercion usable from the API layer without dragging the model class in.
|
|
90
|
+
*/
|
|
91
|
+
export interface ColumnMetadataSource {
|
|
92
|
+
getTableColumnMetadata: (columnName: string) => TableColumnMetadata;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* Coerce the number columns of a loose JSON patch, in place.
|
|
97
|
+
*
|
|
98
|
+
* `BaseModel.fromJSON` does this on its way to building a model, but an
|
|
99
|
+
* update never builds one — `BaseAPI.updateItem` goes from the request body
|
|
100
|
+
* straight to a partial entity — so without this a PATCH and a POST
|
|
101
|
+
* disagree about whether "10" is a number. That matters because the
|
|
102
|
+
* save-time hooks read these values before the database gets a chance to
|
|
103
|
+
* coerce them.
|
|
104
|
+
*
|
|
105
|
+
* Values that are not strings are left exactly as they are, including the
|
|
106
|
+
* `() => string` raw SQL expressions a PartialEntity may carry.
|
|
107
|
+
*/
|
|
108
|
+
export function coerceNumericColumnsInJSON(
|
|
109
|
+
json: JSONObject,
|
|
110
|
+
model: ColumnMetadataSource,
|
|
111
|
+
): JSONObject {
|
|
112
|
+
for (const key of Object.keys(json)) {
|
|
113
|
+
const tableColumnMetadata: TableColumnMetadata =
|
|
114
|
+
model.getTableColumnMetadata(key);
|
|
115
|
+
|
|
116
|
+
if (!tableColumnMetadata) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!isNumericTableColumnType(tableColumnMetadata.type)) {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
json[key] = coerceNumericColumnValue(json[key]) as JSONValue;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return json;
|
|
128
|
+
}
|