@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
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import SnmpVersion, {
|
|
3
|
+
SnmpVersionUtil,
|
|
4
|
+
} from "../../../Types/Monitor/SnmpMonitor/SnmpVersion";
|
|
5
|
+
|
|
6
|
+
/*
|
|
7
|
+
* snmpVersion is a free-text column with two live spellings: the enum VALUES
|
|
8
|
+
* ("1"/"2c"/"3") that the probe contract uses, and the enum KEYS ("V1"/"V2c"/
|
|
9
|
+
* "V3") that every form writes and the column default holds. SnmpVersionUtil is
|
|
10
|
+
* the seam that reconciles them. Reading the column any other way silently takes
|
|
11
|
+
* the wrong branch — a stored "V3" is not === SnmpVersion.V3 ("3"), so a v3
|
|
12
|
+
* device would read as v2c and be polled in cleartext.
|
|
13
|
+
*
|
|
14
|
+
* Unlike the SnmpV3 protocol parsers, parse() cannot return undefined: the probe
|
|
15
|
+
* must pick exactly one session type, so an unreadable value falls back to v2c
|
|
16
|
+
* rather than refusing. These tests pin both the recognized spellings and that
|
|
17
|
+
* deliberate default so a future edit cannot widen or narrow it unnoticed.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
describe("SnmpVersionUtil.parse", () => {
|
|
21
|
+
test.each([
|
|
22
|
+
["1", SnmpVersion.V1],
|
|
23
|
+
["2c", SnmpVersion.V2c],
|
|
24
|
+
["3", SnmpVersion.V3],
|
|
25
|
+
])(
|
|
26
|
+
"reads the probe-contract value spelling %j",
|
|
27
|
+
(stored: string, expected: SnmpVersion) => {
|
|
28
|
+
expect(SnmpVersionUtil.parse(stored)).toBe(expected);
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* The stored spelling — what forms write and the column default holds. This
|
|
34
|
+
* is the spelling the bare-cast bug got wrong, so it is the one that most
|
|
35
|
+
* needs a test.
|
|
36
|
+
*/
|
|
37
|
+
test.each([
|
|
38
|
+
["V1", SnmpVersion.V1],
|
|
39
|
+
["V2c", SnmpVersion.V2c],
|
|
40
|
+
["V3", SnmpVersion.V3],
|
|
41
|
+
])(
|
|
42
|
+
"reads the stored enum-key spelling %j",
|
|
43
|
+
(stored: string, expected: SnmpVersion) => {
|
|
44
|
+
expect(SnmpVersionUtil.parse(stored)).toBe(expected);
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
test.each([
|
|
49
|
+
["V1", SnmpVersion.V1],
|
|
50
|
+
["v1", SnmpVersion.V1],
|
|
51
|
+
[" 1 ", SnmpVersion.V1],
|
|
52
|
+
["\tv3\n", SnmpVersion.V3],
|
|
53
|
+
["V3", SnmpVersion.V3],
|
|
54
|
+
["v3", SnmpVersion.V3],
|
|
55
|
+
])(
|
|
56
|
+
"tolerates case and surrounding whitespace in %j",
|
|
57
|
+
(stored: string, expected: SnmpVersion) => {
|
|
58
|
+
expect(SnmpVersionUtil.parse(stored)).toBe(expected);
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* v2c is the fallback branch, so every v2c spelling AND every value the parser
|
|
64
|
+
* does not recognize must land here. The two are indistinguishable by design:
|
|
65
|
+
* there is no "undefined version", the probe always needs a session type, and
|
|
66
|
+
* v2c is the safe historic default. Anything that stops mapping to v2c here is
|
|
67
|
+
* a behavior change, not a bug fix.
|
|
68
|
+
*/
|
|
69
|
+
test.each([
|
|
70
|
+
["2c", "an exact value"],
|
|
71
|
+
["V2c", "the stored key"],
|
|
72
|
+
["v2c", "lowercased key"],
|
|
73
|
+
["2", "the version number without the c"],
|
|
74
|
+
["V2", "the key without the c"],
|
|
75
|
+
[undefined, "an undefined column"],
|
|
76
|
+
[null, "a null column"],
|
|
77
|
+
["", "an empty string"],
|
|
78
|
+
[" ", "whitespace only"],
|
|
79
|
+
["nonsense", "garbage"],
|
|
80
|
+
["v4", "a version that does not exist"],
|
|
81
|
+
["0", "a zero"],
|
|
82
|
+
])(
|
|
83
|
+
"falls back to v2c for %j (%s)",
|
|
84
|
+
(stored: string | undefined | null, _description: string) => {
|
|
85
|
+
expect(SnmpVersionUtil.parse(stored)).toBe(SnmpVersion.V2c);
|
|
86
|
+
},
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("SnmpVersionUtil.isV3", () => {
|
|
91
|
+
test.each([["3"], ["v3"], ["V3"], [" V3 "], ["\tv3\n"]])(
|
|
92
|
+
"is true for the v3 spelling %j",
|
|
93
|
+
(stored: string) => {
|
|
94
|
+
expect(SnmpVersionUtil.isV3(stored)).toBe(true);
|
|
95
|
+
},
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
* The consequential direction: everything that is not v3 must read as not-v3,
|
|
100
|
+
* because isV3 gates whether auth/priv credentials are applied. A false
|
|
101
|
+
* positive would be harmless; a false negative strands a v3 device in a v2c
|
|
102
|
+
* branch and polls it without credentials.
|
|
103
|
+
*/
|
|
104
|
+
test.each([
|
|
105
|
+
["1"],
|
|
106
|
+
["V1"],
|
|
107
|
+
["2c"],
|
|
108
|
+
["V2c"],
|
|
109
|
+
["v2c"],
|
|
110
|
+
["2"],
|
|
111
|
+
[undefined],
|
|
112
|
+
[null],
|
|
113
|
+
[""],
|
|
114
|
+
[" "],
|
|
115
|
+
["nonsense"],
|
|
116
|
+
])(
|
|
117
|
+
"is false for the non-v3 value %j",
|
|
118
|
+
(stored: string | undefined | null) => {
|
|
119
|
+
expect(SnmpVersionUtil.isV3(stored)).toBe(false);
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
test("agrees with parse() for every recognized spelling", () => {
|
|
124
|
+
for (const spelling of ["1", "v1", "V1", "2c", "V2c", "3", "v3", "V3"]) {
|
|
125
|
+
expect(SnmpVersionUtil.isV3(spelling)).toBe(
|
|
126
|
+
SnmpVersionUtil.parse(spelling) === SnmpVersion.V3,
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
describe("every enum member survives a round trip", () => {
|
|
133
|
+
/*
|
|
134
|
+
* Exhaustive over the enum rather than a fixed list, so adding a version
|
|
135
|
+
* without teaching parse() its value AND key spelling fails here instead of
|
|
136
|
+
* silently collapsing to v2c in production.
|
|
137
|
+
*/
|
|
138
|
+
test("each value spelling parses back to itself", () => {
|
|
139
|
+
for (const member of Object.values(SnmpVersion)) {
|
|
140
|
+
expect(SnmpVersionUtil.parse(member)).toBe(member);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("each key spelling parses to its member", () => {
|
|
145
|
+
for (const key of Object.keys(SnmpVersion)) {
|
|
146
|
+
// Keys are "V1"/"V2c"/"V3"; the member is looked up by that key.
|
|
147
|
+
const expected: SnmpVersion =
|
|
148
|
+
SnmpVersion[key as keyof typeof SnmpVersion];
|
|
149
|
+
expect(SnmpVersionUtil.parse(key)).toBe(expected);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
package/Tests/Types/Port.test.ts
CHANGED
|
@@ -36,4 +36,42 @@ describe("Testing class port", () => {
|
|
|
36
36
|
const value: Port = new Port("6000");
|
|
37
37
|
expect(typeof value.port.positiveNumber).toBe("number");
|
|
38
38
|
});
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* A port column is declared `TableColumnType.Number`, so whatever reaches
|
|
42
|
+
* the transformer may be a Port, a string, or a plain number depending on
|
|
43
|
+
* how far the request body got through deserialization. A raw number used
|
|
44
|
+
* to fall off the end of `toDatabase` and return null, which wrote NULL
|
|
45
|
+
* over an SMTP port the user had just typed — silently, since null is a
|
|
46
|
+
* legal value for the column.
|
|
47
|
+
*/
|
|
48
|
+
describe("getDatabaseTransformer().to", () => {
|
|
49
|
+
const transformer: ReturnType<typeof Port.getDatabaseTransformer> =
|
|
50
|
+
Port.getDatabaseTransformer();
|
|
51
|
+
|
|
52
|
+
test("stores a Port instance as its number", () => {
|
|
53
|
+
expect(transformer.to(new Port(587))).toBe(587);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("stores a raw string port as a number", () => {
|
|
57
|
+
expect(transformer.to("587")).toBe(587);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("stores a raw number port rather than dropping it", () => {
|
|
61
|
+
expect(transformer.to(587)).toBe(587);
|
|
62
|
+
expect(transformer.to(0)).toBe(0);
|
|
63
|
+
expect(transformer.to(65535)).toBe(65535);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("keeps undefined distinct from null so a column DEFAULT applies", () => {
|
|
67
|
+
expect(transformer.to(undefined)).toBeUndefined();
|
|
68
|
+
expect(transformer.to(null)).toBeNull();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("rejects a port outside the valid range instead of storing null", () => {
|
|
72
|
+
expect(() => {
|
|
73
|
+
return transformer.to(70000);
|
|
74
|
+
}).toThrow(BadDataException);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
39
77
|
});
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/** @timezone UTC */
|
|
2
|
+
|
|
3
|
+
import LogsHistogram from "../../../UI/Components/LogsViewer/components/LogsHistogram";
|
|
4
|
+
import { HistogramBucket } from "../../../UI/Components/LogsViewer/types";
|
|
5
|
+
import LogSeverity from "../../../Types/Log/LogSeverity";
|
|
6
|
+
import { render, screen } from "@testing-library/react";
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { describe, expect, test } from "@jest/globals";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* ResponsiveContainer measures its parent, which is always 0x0 in jsdom, so the
|
|
12
|
+
* chart renders nothing without a fixed size.
|
|
13
|
+
*/
|
|
14
|
+
jest.mock("recharts", () => {
|
|
15
|
+
const actual: Record<string, any> = jest.requireActual("recharts");
|
|
16
|
+
return {
|
|
17
|
+
...actual,
|
|
18
|
+
ResponsiveContainer: ({ children }: { children: React.ReactElement }) => {
|
|
19
|
+
return React.cloneElement(children, { width: 600, height: 300 });
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
function bucket(
|
|
25
|
+
time: string,
|
|
26
|
+
severity: string,
|
|
27
|
+
count: number,
|
|
28
|
+
): HistogramBucket {
|
|
29
|
+
return { time, severity, count };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** One bar rectangle is drawn per severity per bucket that has a count. */
|
|
33
|
+
function barCount(container: HTMLElement): number {
|
|
34
|
+
return container.querySelectorAll(".recharts-bar-rectangle").length;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** One <g> per stacked series, i.e. per severity present in the data. */
|
|
38
|
+
function seriesCount(container: HTMLElement): number {
|
|
39
|
+
return container.querySelectorAll(".recharts-bar").length;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const CLOCK_LABEL: RegExp = /^\d{2}:\d{2}$/;
|
|
43
|
+
|
|
44
|
+
/*
|
|
45
|
+
* Recharts portals tick labels out of their axis group, so the two axes are
|
|
46
|
+
* told apart by what they render: the time axis is formatted as a clock, the
|
|
47
|
+
* count axis as a number.
|
|
48
|
+
*/
|
|
49
|
+
function axisLabels(
|
|
50
|
+
container: HTMLElement,
|
|
51
|
+
axis: "time" | "count",
|
|
52
|
+
): Array<string> {
|
|
53
|
+
const labels: Array<string> = Array.from(
|
|
54
|
+
container.querySelectorAll(".recharts-cartesian-axis-tick-value"),
|
|
55
|
+
).map((tick: Element): string => {
|
|
56
|
+
return tick.textContent || "";
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return labels.filter((label: string): boolean => {
|
|
60
|
+
return CLOCK_LABEL.test(label) === (axis === "time");
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const ONE_SEVERITY: Array<HistogramBucket> = [
|
|
65
|
+
bucket("2026-08-05T11:58:00Z", LogSeverity.Error, 3),
|
|
66
|
+
bucket("2026-08-05T11:59:00Z", LogSeverity.Error, 5),
|
|
67
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Error, 7),
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
describe("LogsHistogram", () => {
|
|
71
|
+
describe("empty and loading states", () => {
|
|
72
|
+
test("renders nothing when the window holds no logs", () => {
|
|
73
|
+
const { container } = render(
|
|
74
|
+
<LogsHistogram buckets={[]} isLoading={false} />,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
expect(container.innerHTML).toBe("");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("shows the loader on the very first load", () => {
|
|
81
|
+
render(<LogsHistogram buckets={[]} isLoading={true} />);
|
|
82
|
+
|
|
83
|
+
expect(screen.queryByTestId("component-loader")).not.toBeNull();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* Live mode refreshes the histogram every few seconds. Swapping the chart
|
|
88
|
+
* for a loader on each poll would make it flash; the chart already on
|
|
89
|
+
* screen stays until the new buckets land.
|
|
90
|
+
*/
|
|
91
|
+
test("keeps the chart on screen while a refresh is in flight", () => {
|
|
92
|
+
const { container } = render(
|
|
93
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={true} />,
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(screen.queryByTestId("component-loader")).toBeNull();
|
|
97
|
+
expect(screen.queryByText("Log Volume")).not.toBeNull();
|
|
98
|
+
expect(barCount(container)).toBe(3);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe("drawing the buckets", () => {
|
|
103
|
+
test("draws one bar per bucket", () => {
|
|
104
|
+
const { container } = render(
|
|
105
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
expect(barCount(container)).toBe(3);
|
|
109
|
+
expect(seriesCount(container)).toBe(1);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("stacks a bar per severity inside a bucket", () => {
|
|
113
|
+
const { container } = render(
|
|
114
|
+
<LogsHistogram
|
|
115
|
+
buckets={[
|
|
116
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Error, 4),
|
|
117
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Warning, 6),
|
|
118
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Information, 9),
|
|
119
|
+
]}
|
|
120
|
+
isLoading={false}
|
|
121
|
+
/>,
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(seriesCount(container)).toBe(3);
|
|
125
|
+
expect(barCount(container)).toBe(3);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test("labels the time axis in the reader's clock", () => {
|
|
129
|
+
const { container } = render(
|
|
130
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />,
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(axisLabels(container, "time")).toContain("12:00");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("lists only the severities present in the window", () => {
|
|
137
|
+
render(
|
|
138
|
+
<LogsHistogram
|
|
139
|
+
buckets={[
|
|
140
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Error, 4),
|
|
141
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Debug, 1),
|
|
142
|
+
]}
|
|
143
|
+
isLoading={false}
|
|
144
|
+
/>,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
expect(screen.queryByText("Error")).not.toBeNull();
|
|
148
|
+
expect(screen.queryByText("Debug")).not.toBeNull();
|
|
149
|
+
expect(screen.queryByText("Fatal")).toBeNull();
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
/*
|
|
154
|
+
* What live mode looks like from the chart's side: the same component is
|
|
155
|
+
* handed a fresh set of buckets every poll and has to redraw.
|
|
156
|
+
*/
|
|
157
|
+
describe("when a live refresh brings new data", () => {
|
|
158
|
+
test("adds a bar as a new bucket opens", () => {
|
|
159
|
+
const view: ReturnType<typeof render> = render(
|
|
160
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />,
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
expect(barCount(view.container)).toBe(3);
|
|
164
|
+
|
|
165
|
+
view.rerender(
|
|
166
|
+
<LogsHistogram
|
|
167
|
+
buckets={[
|
|
168
|
+
...ONE_SEVERITY,
|
|
169
|
+
bucket("2026-08-05T12:01:00Z", LogSeverity.Error, 2),
|
|
170
|
+
]}
|
|
171
|
+
isLoading={false}
|
|
172
|
+
/>,
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
expect(barCount(view.container)).toBe(4);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("follows the window as it slides off the oldest bucket", () => {
|
|
179
|
+
const view: ReturnType<typeof render> = render(
|
|
180
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />,
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
expect(axisLabels(view.container, "time")).toContain("11:58");
|
|
184
|
+
|
|
185
|
+
view.rerender(
|
|
186
|
+
<LogsHistogram
|
|
187
|
+
buckets={[
|
|
188
|
+
...ONE_SEVERITY.slice(1),
|
|
189
|
+
bucket("2026-08-05T12:01:00Z", LogSeverity.Error, 2),
|
|
190
|
+
]}
|
|
191
|
+
isLoading={false}
|
|
192
|
+
/>,
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const labels: Array<string> = axisLabels(view.container, "time");
|
|
196
|
+
expect(labels).not.toContain("11:58");
|
|
197
|
+
expect(labels).toContain("12:01");
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("rescales the count axis as the newest bucket fills up", () => {
|
|
201
|
+
const view: ReturnType<typeof render> = render(
|
|
202
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />,
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const before: Array<string> = axisLabels(view.container, "count");
|
|
206
|
+
|
|
207
|
+
view.rerender(
|
|
208
|
+
<LogsHistogram
|
|
209
|
+
buckets={[
|
|
210
|
+
...ONE_SEVERITY.slice(0, 2),
|
|
211
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Error, 400),
|
|
212
|
+
]}
|
|
213
|
+
isLoading={false}
|
|
214
|
+
/>,
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
const after: Array<string> = axisLabels(view.container, "count");
|
|
218
|
+
|
|
219
|
+
expect(after).not.toEqual(before);
|
|
220
|
+
expect(Number(after[after.length - 1])).toBeGreaterThan(
|
|
221
|
+
Number(before[before.length - 1]),
|
|
222
|
+
);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("adds a series and a legend entry when a new severity shows up", () => {
|
|
226
|
+
const view: ReturnType<typeof render> = render(
|
|
227
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />,
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
expect(screen.queryByText("Fatal")).toBeNull();
|
|
231
|
+
|
|
232
|
+
view.rerender(
|
|
233
|
+
<LogsHistogram
|
|
234
|
+
buckets={[
|
|
235
|
+
...ONE_SEVERITY,
|
|
236
|
+
bucket("2026-08-05T12:00:00Z", LogSeverity.Fatal, 1),
|
|
237
|
+
]}
|
|
238
|
+
isLoading={false}
|
|
239
|
+
/>,
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
expect(screen.queryByText("Fatal")).not.toBeNull();
|
|
243
|
+
expect(seriesCount(view.container)).toBe(2);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("empties the chart when the refreshed window has no logs", () => {
|
|
247
|
+
const view: ReturnType<typeof render> = render(
|
|
248
|
+
<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
view.rerender(<LogsHistogram buckets={[]} isLoading={false} />);
|
|
252
|
+
|
|
253
|
+
expect(view.container.innerHTML).toBe("");
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
describe("drag to zoom", () => {
|
|
258
|
+
test("offers the affordance when the parent can act on a selection", () => {
|
|
259
|
+
render(
|
|
260
|
+
<LogsHistogram
|
|
261
|
+
buckets={ONE_SEVERITY}
|
|
262
|
+
isLoading={false}
|
|
263
|
+
onTimeRangeSelect={() => {}}
|
|
264
|
+
/>,
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
expect(screen.queryByText("Drag to zoom")).not.toBeNull();
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test("hides the affordance when there is nothing to zoom into", () => {
|
|
271
|
+
render(<LogsHistogram buckets={ONE_SEVERITY} isLoading={false} />);
|
|
272
|
+
|
|
273
|
+
expect(screen.queryByText("Drag to zoom")).toBeNull();
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
});
|