@oneuptime/common 14.0.2 → 14.0.5
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/Alert.ts +55 -0
- package/Models/DatabaseModels/AlertFeed.ts +2 -0
- package/Models/DatabaseModels/DatabaseServer.ts +1650 -0
- package/Models/DatabaseModels/DatabaseServerEndpoint.ts +540 -0
- package/Models/DatabaseModels/DatabaseServerFeed.ts +625 -0
- package/Models/DatabaseModels/DatabaseServerLabelRule.ts +514 -0
- package/Models/DatabaseModels/DatabaseServerOwnerRule.ts +596 -0
- package/Models/DatabaseModels/DatabaseServerOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/DatabaseServerOwnerUser.ts +490 -0
- package/Models/DatabaseModels/Incident.ts +55 -0
- package/Models/DatabaseModels/IncidentAlert.ts +540 -0
- package/Models/DatabaseModels/IncidentFeed.ts +2 -0
- package/Models/DatabaseModels/Index.ts +18 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +26 -0
- package/Models/DatabaseModels/Project.ts +60 -0
- package/Models/DatabaseModels/RumApplication.ts +52 -1
- package/Models/DatabaseModels/ScheduledMaintenance.ts +55 -0
- package/Models/DatabaseModels/TelemetryException.ts +2 -0
- package/Models/DatabaseModels/UserProjectSsoConsent.ts +146 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.ts +28 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.ts +89 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.ts +673 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
- package/Server/Middleware/MultipartFormData.ts +1 -1
- package/Server/Middleware/TelemetryIngest.ts +15 -8
- package/Server/Services/AlertReminderRuleService.ts +100 -24
- package/Server/Services/DatabaseServerEndpointService.ts +895 -0
- package/Server/Services/DatabaseServerFeedService.ts +128 -0
- package/Server/Services/DatabaseServerLabelRuleEngineService.ts +340 -0
- package/Server/Services/DatabaseServerLabelRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerRuleEngineService.ts +425 -0
- package/Server/Services/DatabaseServerOwnerRuleService.ts +14 -0
- package/Server/Services/DatabaseServerOwnerTeamService.ts +180 -0
- package/Server/Services/DatabaseServerOwnerUserService.ts +173 -0
- package/Server/Services/DatabaseServerService.ts +4546 -0
- package/Server/Services/DatabaseService.ts +14 -8
- package/Server/Services/DockerResourceService.ts +43 -2
- package/Server/Services/IncidentAlertService.ts +1811 -0
- package/Server/Services/IncidentReminderRuleService.ts +103 -23
- package/Server/Services/IncidentService.ts +210 -10
- package/Server/Services/IncidentStateTimelineService.ts +24 -0
- package/Server/Services/Index.ts +18 -0
- package/Server/Services/InventoryItemService.ts +113 -5
- package/Server/Services/IoTDeviceService.ts +145 -37
- package/Server/Services/OpenTelemetryIngestService.ts +19 -0
- package/Server/Services/PodmanResourceService.ts +43 -2
- package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +107 -23
- package/Server/Services/ServiceService.ts +1 -1
- package/Server/Services/TelemetryUsageBillingService.ts +29 -2
- package/Server/Services/UserProjectSsoConsentService.ts +74 -0
- package/Server/Services/UserService.ts +14 -1
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +18 -0
- package/Server/Types/Database/QueryHelper.ts +30 -1
- package/Server/Utils/AI/Toolbox/ResourceTools.ts +69 -1
- package/Server/Utils/Database/AffectedResourceRelations.ts +6 -0
- package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +188 -6
- package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +2262 -755
- package/Server/Utils/Monitor/MonitorIncident.ts +28 -1
- package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +268 -6
- package/Server/Utils/Monitor/MonitorResource.ts +47 -11
- package/Server/Utils/Monitor/MonitorResourceContext.ts +1 -0
- package/Server/Utils/Monitor/MonitorStepResourceIdentity.ts +239 -21
- package/Server/Utils/Monitor/PerSeriesResolutionRootCause.ts +43 -0
- package/Server/Utils/Monitor/SeriesResourceLabels.ts +291 -0
- package/Server/Utils/Monitor/SeriesResourceLinker.ts +111 -12
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/SessionReplay/SessionReplayGateCache.ts +24 -2
- package/Server/Utils/StartServer.ts +26 -6
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/DatabaseEndpointDiscovery.ts +688 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +5 -1
- package/Server/Utils/Telemetry/LogExceptionExtractor.ts +18 -1
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +175 -12
- package/Server/Utils/Telemetry/ResourceFacetResolver.ts +12 -0
- package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +606 -36
- package/Server/Utils/Telemetry/Telemetry.ts +16 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +22 -22
- package/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.ts +16 -10
- package/Tests/App/Accounts/SignedInRedirect.test.tsx +241 -0
- package/Tests/App/AdminDashboard/AdminHeaderSmallScreens.test.tsx +221 -4
- package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +42 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +100 -0
- package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +86 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +2 -0
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +19 -0
- package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +14 -0
- package/Tests/App/Dashboard/BulkIncidentLinkActions.test.tsx +869 -0
- package/Tests/App/Dashboard/CephMetricTooltips.test.tsx +1777 -0
- package/Tests/App/Dashboard/CloudFleetSummary.test.ts +8 -0
- package/Tests/App/Dashboard/CloudMetricTooltips.test.tsx +887 -0
- package/Tests/App/Dashboard/ContainerHostMetricTooltips.test.tsx +1309 -0
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +26 -1
- package/Tests/App/Dashboard/DashboardAppSsoError.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +64 -1
- package/Tests/App/Dashboard/DashboardHeaderSmallScreens.test.tsx +178 -18
- package/Tests/App/Dashboard/DashboardMasterPageSsoRedirect.test.tsx +444 -0
- package/Tests/App/Dashboard/DashboardNavBarForeignHiddenRule.test.tsx +573 -0
- package/Tests/App/Dashboard/DatabaseChartAxes.test.tsx +431 -0
- package/Tests/App/Dashboard/DatabaseContainerDetailBadge.test.tsx +249 -0
- package/Tests/App/Dashboard/DatabaseDashboardE2EFixes.test.ts +681 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +1801 -0
- package/Tests/App/Dashboard/DatabaseFleetSummaryRefresh.test.tsx +280 -0
- package/Tests/App/Dashboard/DatabaseFormHelpers.test.tsx +321 -0
- package/Tests/App/Dashboard/DatabaseMetricMonitorLink.test.tsx +795 -0
- package/Tests/App/Dashboard/DatabaseOverviewHeader.test.tsx +580 -0
- package/Tests/App/Dashboard/DatabaseRecommendationsEngineMetrics.test.ts +270 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +1486 -0
- package/Tests/App/Dashboard/DatabaseServerEngineMetricsFilter.test.ts +223 -0
- package/Tests/App/Dashboard/DatabaseServerPresentation.test.ts +435 -0
- package/Tests/App/Dashboard/DatabaseServerSummary.test.ts +186 -0
- package/Tests/App/Dashboard/DatabaseServerTelemetryQueries.test.ts +1553 -0
- package/Tests/App/Dashboard/DatabaseTableTruncation.test.tsx +326 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +512 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +774 -0
- package/Tests/App/Dashboard/DatabaseViewLayout.test.tsx +233 -0
- package/Tests/App/Dashboard/DatabaseWorkloadBadge.test.tsx +972 -0
- package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +5 -0
- package/Tests/App/Dashboard/DiscoveryReviewUnnamedHostHint.test.tsx +1061 -0
- package/Tests/App/Dashboard/DiscoveryScanLivePage.test.tsx +39 -0
- package/Tests/App/Dashboard/DockerSwarmClustersListTooltips.test.tsx +414 -0
- package/Tests/App/Dashboard/DockerSwarmMetricTooltips.test.ts +796 -0
- package/Tests/App/Dashboard/DockerSwarmOverviewTooltips.test.tsx +747 -0
- package/Tests/App/Dashboard/EventOverlayScope.test.ts +147 -0
- package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +1 -0
- package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +38 -18
- package/Tests/App/Dashboard/HostDetailViewTooltips.test.tsx +725 -0
- package/Tests/App/Dashboard/HostListColumnTooltips.test.tsx +472 -0
- package/Tests/App/Dashboard/HostMetricTooltips.test.ts +709 -0
- package/Tests/App/Dashboard/HostOverviewTooltips.test.tsx +698 -0
- package/Tests/App/Dashboard/HostTooltipHarness.ts +124 -0
- package/Tests/App/Dashboard/HostsListTooltips.test.tsx +395 -0
- package/Tests/App/Dashboard/IncidentAlertLinkDialog.test.tsx +691 -0
- package/Tests/App/Dashboard/IncidentAlertLinkHelpers.test.ts +458 -0
- package/Tests/App/Dashboard/IncidentAlertLinkPages.test.tsx +828 -0
- package/Tests/App/Dashboard/IncidentAlertLinkSideMenus.test.tsx +231 -0
- package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +689 -0
- package/Tests/App/Dashboard/IoTMetricTooltips.test.tsx +1123 -0
- package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +837 -0
- package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +699 -0
- package/Tests/App/Dashboard/KubernetesContainersTabTooltips.test.tsx +320 -0
- package/Tests/App/Dashboard/KubernetesCostTooltips.test.tsx +502 -0
- package/Tests/App/Dashboard/KubernetesInsightsTooltips.test.tsx +222 -0
- package/Tests/App/Dashboard/KubernetesResourceMetricTooltips.test.ts +561 -0
- package/Tests/App/Dashboard/KubernetesResourcePagesTooltips.test.tsx +1168 -0
- package/Tests/App/Dashboard/LinkIncidentAlertModal.test.tsx +154 -0
- package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +1 -0
- package/Tests/App/Dashboard/MetricDescriptionRules.ts +170 -0
- package/Tests/App/Dashboard/MetricDescriptionsCatalog.test.ts +206 -0
- package/Tests/App/Dashboard/MetricDescriptionsConsistency.test.ts +275 -0
- package/Tests/App/Dashboard/MetricsViewerDrillDown.test.tsx +310 -0
- package/Tests/App/Dashboard/MetricsViewerEntityScopedRows.test.tsx +495 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +132 -1
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +5 -0
- package/Tests/App/Dashboard/NetworkDeviceTooltips.test.tsx +852 -0
- package/Tests/App/Dashboard/NetworkDiagnosticsTooltips.test.tsx +556 -0
- package/Tests/App/Dashboard/NetworkMetricTooltips.test.ts +1348 -0
- package/Tests/App/Dashboard/NetworkSiteTooltips.test.tsx +679 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +4 -3
- package/Tests/App/Dashboard/ProxmoxMetricTooltips.test.ts +592 -0
- package/Tests/App/Dashboard/ProxmoxOverviewTooltips.test.tsx +1002 -0
- package/Tests/App/Dashboard/ProxmoxResourcePageTooltips.test.tsx +923 -0
- package/Tests/App/Dashboard/RecommendationsLoadedContext.test.tsx +349 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +62 -0
- package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
- package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +14 -0
- package/Tests/App/Dashboard/ResourceOverviewTileTooltips.test.tsx +1066 -0
- package/Tests/App/Dashboard/RumOverviewPage.test.tsx +1195 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +2 -0
- package/Tests/App/Dashboard/ServerlessMetricTooltips.test.tsx +474 -0
- package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +1085 -0
- package/Tests/App/Dashboard/ServiceMetricTooltips.test.tsx +772 -0
- package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +56 -1
- package/Tests/App/Dashboard/TelemetryMetricsSignals.test.ts +1207 -0
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +10 -0
- package/Tests/App/Dashboard/TelemetryResourceTabTooltips.test.tsx +437 -0
- package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +2 -1
- package/Tests/App/Dashboard/VMwareMetricTooltips.test.ts +801 -0
- package/Tests/App/Dashboard/VMwareOverviewTooltips.test.tsx +601 -0
- package/Tests/App/Dashboard/VMwareResourcePagesTooltips.test.tsx +646 -0
- package/Tests/App/Dashboard/VMwareTooltipHarness.ts +145 -0
- package/Tests/App/StatusPage/StatusPageHeaderForeignHiddenRule.test.tsx +284 -0
- package/Tests/ClassStrings.ts +178 -0
- package/Tests/Fixtures/MobilePasskeyUser.json +1 -2
- package/Tests/ForeignHiddenRuleGuard.ts +2152 -0
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +2250 -0
- package/Tests/Models/DatabaseModels/IncidentAlertModel.test.ts +554 -0
- package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +24 -5
- package/Tests/Models/DatabaseModels/SessionReplayModels.test.ts +117 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/RenderedMarkup.ts +518 -0
- package/Tests/ResponsiveVisibility.test.ts +490 -4
- package/Tests/ResponsiveVisibility.ts +505 -52
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +541 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentAlertMigration.test.ts +341 -0
- package/Tests/Server/Infrastructure/Postgres/AddSessionReplaySameOriginTracePropagationMigration.test.ts +247 -0
- package/Tests/Server/Infrastructure/Postgres/AddUserProjectSsoConsentMigration.test.ts +234 -0
- package/Tests/Server/Services/ContainerSnapshotUpsertPostgres.test.ts +319 -0
- package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +13 -0
- package/Tests/Server/Services/DatabaseServerEndpointService.test.ts +2033 -0
- package/Tests/Server/Services/DatabaseServerFeedAndOwnerServices.test.ts +529 -0
- package/Tests/Server/Services/DatabaseServerLifecycle.test.ts +3302 -0
- package/Tests/Server/Services/DatabaseServerRegistries.test.ts +603 -0
- package/Tests/Server/Services/DatabaseServerRuleEngines.test.ts +754 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +3558 -0
- package/Tests/Server/Services/DatabaseServerSqlPostgres.test.ts +2045 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedPostgres.test.ts +362 -0
- package/Tests/Server/Services/DatabaseServiceUpdateColumnsIfUnlockedReply.test.ts +210 -0
- package/Tests/Server/Services/HookFreeWriteLengthClamp.test.ts +18 -0
- package/Tests/Server/Services/IncidentAlertPostgres.test.ts +903 -0
- package/Tests/Server/Services/IncidentAlertRegistration.test.ts +96 -0
- package/Tests/Server/Services/IncidentAlertService.test.ts +2225 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +2 -0
- package/Tests/Server/Services/IncidentAlertStateCascade.test.ts +970 -0
- package/Tests/Server/Services/IncidentCreateFromAlerts.test.ts +1284 -0
- package/Tests/Server/Services/IncomingCallPolicyEscalationRuleTarget.test.ts +225 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +280 -2
- package/Tests/Server/Services/InventoryUpsertSchemaParity.test.ts +8 -2
- package/Tests/Server/Services/IoTDeviceLatestMetricsPostgres.test.ts +689 -0
- package/Tests/Server/Services/IoTDeviceService.test.ts +379 -0
- package/Tests/Server/Services/LatestMetricsValuesShape.test.ts +360 -0
- package/Tests/Server/Services/LlmModelPriceService.test.ts +402 -0
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +7 -1
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +61 -9
- package/Tests/Server/Services/ReminderRuleLookupPostgres.test.ts +2250 -0
- package/Tests/Server/Services/ReminderRuleRefreshOpenSubjectsPaging.test.ts +653 -0
- package/Tests/Server/Services/ResourceUpdateLastSeenLivenessFallback.test.ts +68 -20
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +9 -0
- package/Tests/Server/Services/UserProjectSsoConsentPostgres.test.ts +153 -0
- package/Tests/Server/Services/UserProjectSsoConsentService.test.ts +192 -0
- package/Tests/Server/Services/UserServiceFirstMasterAdminElection.test.ts +71 -0
- package/Tests/Server/Services/UserSignupIdTakeoverPostgres.test.ts +238 -0
- package/Tests/Server/Services/WorkspaceNotificationSummaryHelpers.test.ts +592 -0
- package/Tests/Server/Types/Billing/PayAsYouGoMeteredAuthorization.test.ts +3 -0
- package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +1 -0
- package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +11 -0
- package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +8 -0
- package/Tests/Server/Types/Database/QueryHelperBooleanForCriteriaBackedRule.test.ts +1094 -0
- package/Tests/Server/Utils/AI/ResourceTools.test.ts +134 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +41 -0
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +279 -9
- package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaDisplayContext.test.ts +933 -0
- package/Tests/Server/Utils/Monitor/DatabaseMaintenanceSuppression.test.ts +582 -0
- package/Tests/Server/Utils/Monitor/DatabaseServerMonitorLinking.test.ts +753 -0
- package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +119 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +60 -25
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorAffectedResourceEdgeCases.test.ts +1719 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesAffectedResources.test.ts +1447 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorKubernetesRatioEmail.test.ts +352 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformMetricUnits.test.ts +717 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformRawScan.test.ts +2125 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPlatformSeriesAffectedResources.test.ts +1288 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentCriteriaReferences.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentMemberRoleMembership.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +88 -0
- package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +205 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceContext.test.ts +62 -0
- package/Tests/Server/Utils/Monitor/MonitorResourceDatabaseMaintenance.test.ts +803 -0
- package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +133 -3
- package/Tests/Server/Utils/Monitor/MonitorSummaryPersistence.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/PerSeriesRecoveryResolution.test.ts +472 -1
- package/Tests/Server/Utils/Monitor/PerSeriesSecondEntityAlerting.test.ts +1 -0
- package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +236 -2
- package/Tests/Server/Utils/SeriesResourceLabels.test.ts +70 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayGateCachePolicy.test.ts +103 -0
- package/Tests/Server/Utils/StartServerProtobufContentType.test.ts +54 -0
- package/Tests/Server/Utils/Telemetry/DatabaseEndpointDiscovery.test.ts +1895 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +7 -0
- package/Tests/Server/Utils/Telemetry/LogExceptionExtractorSeverityGate.test.ts +90 -0
- package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +570 -0
- package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +97 -2
- package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +1337 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +295 -0
- package/Tests/Types/AI/AIResourceContext.test.ts +30 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerClassifier.test.ts +3644 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommand.test.ts +340 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandCorpus.ts +826 -0
- package/Tests/Types/DatabaseServer/DatabaseContainerCommandPostgres.test.ts +150 -0
- package/Tests/Types/DatabaseServer/DatabaseEndpoint.test.ts +2657 -0
- package/Tests/Types/DatabaseServer/DatabaseServerDiscoverySource.test.ts +64 -0
- package/Tests/Types/DatabaseServer/DatabaseServerEntityKeys.test.ts +952 -0
- package/Tests/Types/DatabaseServer/DatabaseServerMetricCatalog.test.ts +1161 -0
- package/Tests/Types/DatabaseServer/DatabaseSystem.test.ts +1514 -0
- package/Tests/Types/DatabaseServer/DatabaseTelemetryResolver.test.ts +1558 -0
- package/Tests/Types/Monitor/CephAlertTemplates.test.ts +255 -6
- package/Tests/Types/Monitor/DatabaseAlertTemplates.test.ts +2254 -0
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +298 -0
- package/Tests/Types/Monitor/KubernetesMetricCatalog.test.ts +271 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +253 -9
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +13 -5
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +4 -2
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +111 -2
- package/Tests/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.test.ts +61 -0
- package/Tests/Types/Monitor/SeriesContext/SeriesLabelDisplay.test.ts +114 -0
- package/Tests/Types/Monitor/Utils/KubernetesAgentEmittedMetrics.ts +181 -0
- package/Tests/Types/NetworkDevice/DiscoveredHostNamingStatus.test.ts +401 -0
- package/Tests/Types/Rum/WebVitals.test.ts +173 -0
- package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +4 -1
- package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +24 -2
- package/Tests/UI/Components/Card.test.tsx +93 -2
- package/Tests/UI/Components/FeedOptions.test.ts +6 -0
- package/Tests/UI/Components/FeedOptionsButton.test.tsx +8 -1
- package/Tests/UI/Components/FieldLabelInfoCardTooltip.test.tsx +413 -0
- package/Tests/UI/Components/ForeignHiddenRuleResilience.test.tsx +1147 -0
- package/Tests/UI/Components/HeaderRightRail.test.tsx +41 -1
- package/Tests/UI/Components/InfoTooltip.test.tsx +242 -0
- package/Tests/UI/Components/LogsEntityNames.test.ts +16 -1
- package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +7 -3
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +207 -3
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDeleteVerb.test.tsx +367 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableCreateButtonTitle.test.tsx +275 -0
- package/Tests/UI/Components/ResourceFacetConfigs.test.ts +2 -1
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/SrOnlyForeignRule.test.tsx +994 -0
- package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +34 -1
- package/Tests/UI/Components/TableHeaderTooltip.test.tsx +662 -0
- package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +4 -1
- package/Tests/UI/ForeignHiddenRuleGuard.test.ts +1951 -0
- package/Tests/UI/Rum/PrivacySummaryCard.test.tsx +166 -9
- package/Tests/UI/Rum/RecordingHealthTooltips.test.tsx +447 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +164 -0
- package/Tests/UI/Rum/ReplayFrameCapture.test.ts +6750 -0
- package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +19 -1
- package/Tests/UI/Rum/ReplayRail.test.tsx +723 -12
- package/Tests/UI/Rum/ReplayRailDetail.test.tsx +86 -0
- package/Tests/UI/Rum/ReplayScreenshot.test.ts +2124 -0
- package/Tests/UI/Rum/ReplayScreenshotActions.test.tsx +3288 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +62 -0
- package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +983 -2
- package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +19 -1
- package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +149 -0
- package/Tests/UI/Rum/SessionReplaySetupGuide.test.tsx +107 -6
- package/Tests/UI/Rum/SessionReplayUsersTableTooltips.test.tsx +330 -0
- package/Tests/UI/Rum/UserFlowTooltips.test.tsx +886 -0
- package/Tests/UI/TailwindPlayCdnForeignHiddenRule.test.ts +1005 -0
- package/Tests/UI/ThemeGroupHoverReveal.test.ts +847 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +80 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +23 -0
- package/Tests/UI/Utils/ModelAPISsoRedirect.test.ts +127 -0
- package/Tests/UI/Utils/Navigation.test.ts +102 -0
- package/Tests/UI/Utils/PermissionGate.test.ts +76 -0
- package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +23 -0
- package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +696 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/MetricUnitUtil.test.ts +227 -2
- package/Tests/Utils/Monitor/MetricValueFormatter.test.ts +288 -2
- package/Tests/Utils/Monitor/PlatformResourceIdentityAndUnits.test.ts +1559 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.test.ts +2546 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +315 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +336 -1
- package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +244 -0
- package/Tests/Utils/Rum/SessionTraceState.test.ts +239 -0
- package/Tests/Utils/ValueFormatter.test.ts +50 -0
- package/Tests/tsconfig.json +16 -0
- package/Types/AI/AIResourceContext.ts +7 -0
- package/Types/Dashboard/DashboardTemplates.ts +2 -1
- package/Types/DatabaseServer/DatabaseConnectionSpan.ts +77 -0
- package/Types/DatabaseServer/DatabaseContainerClassifier.ts +2068 -0
- package/Types/DatabaseServer/DatabaseContainerCommand.ts +801 -0
- package/Types/DatabaseServer/DatabaseEndpoint.ts +1943 -0
- package/Types/DatabaseServer/DatabaseServerDiscoverySource.ts +68 -0
- package/Types/DatabaseServer/DatabaseServerMetricCatalog.ts +966 -0
- package/Types/DatabaseServer/DatabaseSystem.ts +2124 -0
- package/Types/DatabaseServer/DatabaseTelemetryResolver.ts +555 -0
- package/Types/Email/EmailTemplateType.ts +1 -0
- package/Types/Incident/IncidentAlertLink.ts +38 -0
- package/Types/Monitor/CephAlertTemplates.ts +18 -0
- package/Types/Monitor/DatabaseAlertTemplates.ts +2020 -0
- package/Types/Monitor/KubernetesAlertTemplates.ts +64 -24
- package/Types/Monitor/KubernetesMetricCatalog.ts +118 -19
- package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +14 -0
- package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +93 -10
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +109 -8
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +36 -7
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +43 -2
- package/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.ts +41 -6
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +26 -0
- package/Types/NetworkDevice/DiscoveredHostNamingStatus.ts +147 -0
- package/Types/Permission.ts +315 -0
- package/Types/Probe/ProbeApiIngestResponse.ts +8 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +10 -0
- package/Types/Rules/RuleRun.ts +12 -0
- package/Types/Rum/SessionReplay.ts +25 -6
- package/Types/Rum/WebVitals.ts +52 -0
- package/Types/Telemetry/EntityType.ts +23 -0
- package/Types/Telemetry/ResourceFacetCatalog.ts +14 -0
- package/Types/Telemetry/ServiceType.ts +8 -0
- package/UI/Components/Banner/Banner.tsx +1 -1
- package/UI/Components/Card/Card.tsx +1 -1
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +2 -2
- package/UI/Components/Charts/Line/LineChart.tsx +7 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +1 -1
- package/UI/Components/Date/StartAndEndDate.tsx +5 -5
- package/UI/Components/Detail/FieldLabel.tsx +8 -0
- package/UI/Components/Diagram/HorizontalStepChain.tsx +1 -1
- package/UI/Components/Feed/FeedOptionsButton.tsx +1 -1
- package/UI/Components/Forms/BasicForm.tsx +1 -1
- package/UI/Components/Header/Header.tsx +1 -1
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -1
- package/UI/Components/HeaderAlert/HeaderAlert.tsx +1 -1
- package/UI/Components/InfoCard/InfoCard.tsx +47 -1
- package/UI/Components/LogsViewer/components/FacetValueRow.tsx +1 -1
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +1 -1
- package/UI/Components/Modal/ModalFooter.tsx +1 -1
- package/UI/Components/ModelDetail/CardModelDetail.tsx +2 -2
- package/UI/Components/ModelTable/BaseModelTable.tsx +99 -21
- package/UI/Components/ModelTable/Column.ts +5 -0
- package/UI/Components/Navbar/NavBar.tsx +9 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +2 -2
- package/UI/Components/Page/Page.tsx +1 -1
- package/UI/Components/Pagination/Pagination.tsx +3 -3
- package/UI/Components/ProgressButtons/ProgressButtonItem.tsx +1 -1
- package/UI/Components/SideMenu/SideMenu.tsx +4 -1
- package/UI/Components/StatusPage/ResourceGroupNavigator.tsx +4 -2
- package/UI/Components/StatusPage/ResourceList.tsx +6 -6
- package/UI/Components/Table/TableHeader.tsx +47 -2
- package/UI/Components/Table/Types/Column.ts +7 -0
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +1 -1
- package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +1 -1
- package/UI/Components/Tooltip/InfoTooltip.tsx +78 -0
- package/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.tsx +1 -1
- package/UI/Components/Workflow/ComponentsModal.tsx +2 -2
- package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
- package/UI/Styles/Theme.css +8 -1
- package/UI/Utils/Navigation.ts +89 -42
- package/UI/Utils/PermissionGate.ts +11 -2
- package/UI/Utils/Telemetry/TelemetryEntityNames.ts +7 -0
- package/UI/Utils/TelemetryService.ts +4 -3
- package/Utils/Incident/IncidentFromAlerts.ts +516 -0
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/MetricUnitUtil.ts +103 -11
- package/Utils/Monitor/MetricValueFormatter.ts +66 -13
- package/Utils/Monitor/PlatformMetricUnitUtil.ts +215 -0
- package/Utils/Monitor/PlatformResourceIdentity.ts +514 -0
- package/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.ts +425 -0
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +32 -0
- package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +73 -0
- package/Utils/Rum/SessionTraceState.ts +212 -0
- package/Utils/Telemetry/DatabaseServerEntityKeys.ts +275 -0
- package/Utils/Telemetry/EntityKey.ts +176 -0
- package/Utils/ValueFormatter.ts +16 -0
- package/build/dist/Models/DatabaseModels/Alert.js +54 -0
- package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +1683 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js +559 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerEndpoint.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js +648 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js +522 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js +603 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/DatabaseServerOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Incident.js +54 -0
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentAlert.js +553 -0
- package/build/dist/Models/DatabaseModels/IncidentAlert.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js +2 -0
- package/build/dist/Models/DatabaseModels/IncidentFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +18 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +62 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js +53 -1
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +54 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryException.js +2 -0
- package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js +162 -0
- package/build/dist/Models/DatabaseModels/UserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794800000000-AddSessionReplaySameOriginTracePropagation.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js +42 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794900000000-AddIncidentAlert.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js +240 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795000000000-AddDatabaseServerTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795100000000-AddUserProjectSsoConsent.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/MultipartFormData.js +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +15 -8
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AlertReminderRuleService.js +72 -23
- package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerEndpointService.js +694 -0
- package/build/dist/Server/Services/DatabaseServerEndpointService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js +110 -0
- package/build/dist/Server/Services/DatabaseServerFeedService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js +272 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js +340 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/DatabaseServerOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js +160 -0
- package/build/dist/Server/Services/DatabaseServerOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js +153 -0
- package/build/dist/Server/Services/DatabaseServerOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseServerService.js +3272 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -0
- package/build/dist/Server/Services/DatabaseService.js +8 -4
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerResourceService.js +30 -3
- package/build/dist/Server/Services/DockerResourceService.js.map +1 -1
- package/build/dist/Server/Services/IncidentAlertService.js +1370 -0
- package/build/dist/Server/Services/IncidentAlertService.js.map +1 -0
- package/build/dist/Server/Services/IncidentReminderRuleService.js +73 -23
- package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +164 -12
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +21 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +18 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +88 -5
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceService.js +111 -24
- package/build/dist/Server/Services/IoTDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +24 -9
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanResourceService.js +30 -3
- package/build/dist/Server/Services/PodmanResourceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +75 -23
- package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +1 -1
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +23 -2
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/UserProjectSsoConsentService.js +79 -0
- package/build/dist/Server/Services/UserProjectSsoConsentService.js.map +1 -0
- package/build/dist/Server/Services/UserService.js +13 -1
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +18 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/QueryHelper.js +26 -1
- package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +46 -0
- package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -1
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js +6 -0
- package/build/dist/Server/Utils/Database/AffectedResourceRelations.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +134 -13
- package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +1489 -524
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +22 -6
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +196 -6
- package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +36 -9
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorResourceContext.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js +175 -17
- package/build/dist/Server/Utils/Monitor/MonitorStepResourceIdentity.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js +29 -0
- package/build/dist/Server/Utils/Monitor/PerSeriesResolutionRootCause.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +211 -0
- package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +82 -10
- package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -1
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js +8 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayGateCache.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +20 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js +442 -0
- package/build/dist/Server/Utils/Telemetry/DatabaseEndpointDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +5 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +15 -1
- package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +121 -5
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +12 -0
- package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +438 -36
- package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/Telemetry.js +12 -0
- package/build/dist/Server/Utils/Telemetry/Telemetry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +17 -18
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js +16 -10
- package/build/dist/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.js.map +1 -1
- package/build/dist/Types/AI/AIResourceContext.js +7 -0
- package/build/dist/Types/AI/AIResourceContext.js.map +1 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js +2 -1
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js +71 -0
- package/build/dist/Types/DatabaseServer/DatabaseConnectionSpan.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js +1462 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerClassifier.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js +691 -0
- package/build/dist/Types/DatabaseServer/DatabaseContainerCommand.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js +1407 -0
- package/build/dist/Types/DatabaseServer/DatabaseEndpoint.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js +60 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerDiscoverySource.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js +804 -0
- package/build/dist/Types/DatabaseServer/DatabaseServerMetricCatalog.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js +1860 -0
- package/build/dist/Types/DatabaseServer/DatabaseSystem.js.map +1 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js +406 -0
- package/build/dist/Types/DatabaseServer/DatabaseTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js +1 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/Incident/IncidentAlertLink.js +34 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -0
- package/build/dist/Types/Monitor/CephAlertTemplates.js +18 -0
- package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js +1518 -0
- package/build/dist/Types/Monitor/DatabaseAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +57 -24
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js +104 -18
- package/build/dist/Types/Monitor/KubernetesMetricCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +80 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +10 -3
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +29 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js +21 -6
- package/build/dist/Types/Monitor/Recommendation/RecommendationCriteriaBuilder.js.map +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +25 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js +136 -0
- package/build/dist/Types/NetworkDevice/DiscoveredHostNamingStatus.js.map +1 -0
- package/build/dist/Types/Permission.js +276 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +10 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Rum/WebVitals.js +25 -0
- package/build/dist/Types/Rum/WebVitals.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +23 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +14 -0
- package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -1
- package/build/dist/Types/Telemetry/ServiceType.js +8 -0
- package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
- package/build/dist/UI/Components/Banner/Banner.js +1 -1
- package/build/dist/UI/Components/Banner/Banner.js.map +1 -1
- package/build/dist/UI/Components/Card/Card.js +1 -1
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +2 -2
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +1 -1
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/Date/StartAndEndDate.js +5 -5
- package/build/dist/UI/Components/Date/StartAndEndDate.js.map +1 -1
- package/build/dist/UI/Components/Detail/FieldLabel.js +2 -0
- package/build/dist/UI/Components/Detail/FieldLabel.js.map +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js +1 -1
- package/build/dist/UI/Components/Diagram/HorizontalStepChain.js.map +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js +1 -1
- package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js +22 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +2 -2
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +70 -18
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +9 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +2 -2
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/Page/Page.js +1 -1
- package/build/dist/UI/Components/Page/Page.js.map +1 -1
- package/build/dist/UI/Components/Pagination/Pagination.js +3 -3
- package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js +1 -1
- package/build/dist/UI/Components/ProgressButtons/ProgressButtonItem.js.map +1 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js +4 -1
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js +3 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupNavigator.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceList.js +6 -6
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
- package/build/dist/UI/Components/Table/TableHeader.js +18 -2
- package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/InfoTooltip.js +28 -0
- package/build/dist/UI/Components/Tooltip/InfoTooltip.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js +1 -1
- package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +2 -2
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +66 -33
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +4 -2
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +7 -0
- package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
- package/build/dist/UI/Utils/TelemetryService.js +3 -2
- package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
- package/build/dist/Utils/Incident/IncidentFromAlerts.js +306 -0
- package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -0
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/MetricUnitUtil.js +77 -13
- package/build/dist/Utils/MetricUnitUtil.js.map +1 -1
- package/build/dist/Utils/Monitor/MetricValueFormatter.js +58 -13
- package/build/dist/Utils/Monitor/MetricValueFormatter.js.map +1 -1
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js +161 -0
- package/build/dist/Utils/Monitor/PlatformMetricUnitUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js +323 -0
- package/build/dist/Utils/Monitor/PlatformResourceIdentity.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js +270 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostNamingDiagnosis.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +23 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +61 -0
- package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -1
- package/build/dist/Utils/Rum/SessionTraceState.js +154 -0
- package/build/dist/Utils/Rum/SessionTraceState.js.map +1 -0
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js +178 -0
- package/build/dist/Utils/Telemetry/DatabaseServerEntityKeys.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +133 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/ValueFormatter.js +15 -0
- package/build/dist/Utils/ValueFormatter.js.map +1 -1
- package/package.json +1 -1
- package/tsconfig.tests.json +7 -5
|
@@ -0,0 +1,837 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import {
|
|
3
|
+
expectReadableDescriptionRecord,
|
|
4
|
+
expectTitleExplained,
|
|
5
|
+
} from "./MetricDescriptionRules";
|
|
6
|
+
import {
|
|
7
|
+
KUBERNETES_CLUSTER_METRIC_DESCRIPTIONS,
|
|
8
|
+
KUBERNETES_COST_METRIC_DESCRIPTIONS,
|
|
9
|
+
KUBERNETES_RIGHT_SIZING_METRIC_DESCRIPTIONS,
|
|
10
|
+
KubernetesClusterMetric,
|
|
11
|
+
KubernetesCostMetric,
|
|
12
|
+
KubernetesRightSizingMetric,
|
|
13
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Components/MetricDescriptions/KubernetesClusterMetricDescriptions";
|
|
14
|
+
import {
|
|
15
|
+
CPU_HEADROOM_RATIO,
|
|
16
|
+
HOURS_IN_MONTH,
|
|
17
|
+
MEMORY_HEADROOM_RATIO,
|
|
18
|
+
MIN_OBSERVED_HOURS,
|
|
19
|
+
RightSizingObservation,
|
|
20
|
+
RightSizingRecommendation,
|
|
21
|
+
RightSizingVerdict,
|
|
22
|
+
SIGNIFICANCE_RATIO,
|
|
23
|
+
buildRightSizingRecommendation,
|
|
24
|
+
} from "../../../Types/Kubernetes/KubernetesRightSizing";
|
|
25
|
+
import {
|
|
26
|
+
ExtractedInventoryRecord,
|
|
27
|
+
extractInventoryResource,
|
|
28
|
+
} from "../../../Types/Kubernetes/KubernetesInventoryExtractor";
|
|
29
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
30
|
+
import AggregationIntervalUtil from "../../../Types/BaseDatabase/AggregationIntervalUtil";
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* The (i) texts on the Kubernetes cluster pages: the overview, the Insights
|
|
34
|
+
* network card, the cluster and project Costs pages and the Right-Sizing
|
|
35
|
+
* card. The catalog test holds every module to the shared text rules; this
|
|
36
|
+
* file adds what is specific to these pages - the title each text sits
|
|
37
|
+
* beside, and accuracy anchors that pin a text to what the page actually
|
|
38
|
+
* computes (the 5-minute tile window, the inventory snapshot, the cost
|
|
39
|
+
* engine's idle / unallocated split, the recommender's constants).
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
const CLUSTER: Record<KubernetesClusterMetric, string> =
|
|
43
|
+
KUBERNETES_CLUSTER_METRIC_DESCRIPTIONS;
|
|
44
|
+
const COST: Record<KubernetesCostMetric, string> =
|
|
45
|
+
KUBERNETES_COST_METRIC_DESCRIPTIONS;
|
|
46
|
+
const RIGHT_SIZING: Record<KubernetesRightSizingMetric, string> =
|
|
47
|
+
KUBERNETES_RIGHT_SIZING_METRIC_DESCRIPTIONS;
|
|
48
|
+
|
|
49
|
+
function percentOf(ratio: number): string {
|
|
50
|
+
return `${Math.round(ratio * 100)}%`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
type PlainValue =
|
|
54
|
+
| string
|
|
55
|
+
| number
|
|
56
|
+
| boolean
|
|
57
|
+
| Array<PlainValue>
|
|
58
|
+
| { [key: string]: PlainValue };
|
|
59
|
+
|
|
60
|
+
/*
|
|
61
|
+
* Encode a plain object as the OTLP AnyValue the Kubernetes agent ships
|
|
62
|
+
* inventory objects in, so the real extractor can be run on it.
|
|
63
|
+
*/
|
|
64
|
+
function toOtlpValue(value: PlainValue): JSONObject {
|
|
65
|
+
if (typeof value === "string") {
|
|
66
|
+
return { stringValue: value };
|
|
67
|
+
}
|
|
68
|
+
if (typeof value === "number") {
|
|
69
|
+
return { intValue: value };
|
|
70
|
+
}
|
|
71
|
+
if (typeof value === "boolean") {
|
|
72
|
+
return { boolValue: value };
|
|
73
|
+
}
|
|
74
|
+
if (Array.isArray(value)) {
|
|
75
|
+
return { arrayValue: { values: value.map(toOtlpValue) } };
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
kvlistValue: {
|
|
79
|
+
values: Object.entries(value).map(
|
|
80
|
+
([key, entry]: [string, PlainValue]): JSONObject => {
|
|
81
|
+
return { key: key, value: toOtlpValue(entry) };
|
|
82
|
+
},
|
|
83
|
+
),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
describe("the Kubernetes cluster description records read well", () => {
|
|
89
|
+
test("cluster overview texts pass the shared rules", () => {
|
|
90
|
+
expectReadableDescriptionRecord(
|
|
91
|
+
CLUSTER,
|
|
92
|
+
"KUBERNETES_CLUSTER_METRIC_DESCRIPTIONS",
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test("cost texts pass the shared rules", () => {
|
|
97
|
+
expectReadableDescriptionRecord(
|
|
98
|
+
COST,
|
|
99
|
+
"KUBERNETES_COST_METRIC_DESCRIPTIONS",
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("right-sizing texts pass the shared rules", () => {
|
|
104
|
+
expectReadableDescriptionRecord(
|
|
105
|
+
RIGHT_SIZING,
|
|
106
|
+
"KUBERNETES_RIGHT_SIZING_METRIC_DESCRIPTIONS",
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("the records cover exactly the metrics the pages show", () => {
|
|
111
|
+
expect(Object.keys(CLUSTER).sort()).toEqual(
|
|
112
|
+
[
|
|
113
|
+
"agentStatus",
|
|
114
|
+
"availability",
|
|
115
|
+
"availabilityChart",
|
|
116
|
+
"clusterHealth",
|
|
117
|
+
"cpu",
|
|
118
|
+
"cpuChart",
|
|
119
|
+
"diskPressure",
|
|
120
|
+
"filesystem",
|
|
121
|
+
"filesystemChart",
|
|
122
|
+
"inventoryCounts",
|
|
123
|
+
"memory",
|
|
124
|
+
"memoryChart",
|
|
125
|
+
"memoryPressure",
|
|
126
|
+
"namespaces",
|
|
127
|
+
"network",
|
|
128
|
+
"networkChart",
|
|
129
|
+
"networkThroughput",
|
|
130
|
+
"nodes",
|
|
131
|
+
"nodesNotReady",
|
|
132
|
+
"pidPressure",
|
|
133
|
+
"podHealth",
|
|
134
|
+
"pods",
|
|
135
|
+
"podsFailed",
|
|
136
|
+
"podsPending",
|
|
137
|
+
"podsRunning",
|
|
138
|
+
"topCpuPods",
|
|
139
|
+
"topMemoryPods",
|
|
140
|
+
].sort(),
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
expect(Object.keys(COST).sort()).toEqual(
|
|
144
|
+
[
|
|
145
|
+
"clusterEfficiency",
|
|
146
|
+
"clusterIdleCost",
|
|
147
|
+
"clusterTotalCost",
|
|
148
|
+
"clusterWorkloadCost",
|
|
149
|
+
"efficiency",
|
|
150
|
+
"fleetIdlePercent",
|
|
151
|
+
"fleetIdleSpend",
|
|
152
|
+
"fleetSpendTrend",
|
|
153
|
+
"fleetTotalSpend",
|
|
154
|
+
"fleetWorkloadSpend",
|
|
155
|
+
"idlePercent",
|
|
156
|
+
"idleSpend",
|
|
157
|
+
"namespaceCpuCost",
|
|
158
|
+
"namespaceMemoryCost",
|
|
159
|
+
"namespaceOtherCost",
|
|
160
|
+
"namespaceStorageCost",
|
|
161
|
+
"namespaceTotalCost",
|
|
162
|
+
"spendTrend",
|
|
163
|
+
"totalSpend",
|
|
164
|
+
"workloadSpend",
|
|
165
|
+
"workloadTotalCost",
|
|
166
|
+
].sort(),
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
expect(Object.keys(RIGHT_SIZING).sort()).toEqual(
|
|
170
|
+
[
|
|
171
|
+
"analyzed",
|
|
172
|
+
"cpuRequest",
|
|
173
|
+
"estimatedSaving",
|
|
174
|
+
"memoryRequest",
|
|
175
|
+
"overprovisioned",
|
|
176
|
+
"potentialSaving",
|
|
177
|
+
"underprovisioned",
|
|
178
|
+
].sort(),
|
|
179
|
+
);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test("no text is shared across the three records either", () => {
|
|
183
|
+
const all: Array<string> = [
|
|
184
|
+
...Object.values(CLUSTER),
|
|
185
|
+
...Object.values(COST),
|
|
186
|
+
...Object.values(RIGHT_SIZING),
|
|
187
|
+
];
|
|
188
|
+
|
|
189
|
+
expect(new Set(all).size).toBe(all.length);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("every text is short enough for the small tooltip (aim: 260 chars)", () => {
|
|
193
|
+
for (const text of [
|
|
194
|
+
...Object.values(CLUSTER),
|
|
195
|
+
...Object.values(COST),
|
|
196
|
+
...Object.values(RIGHT_SIZING),
|
|
197
|
+
]) {
|
|
198
|
+
expect({ text, length: text.length <= 260 }).toEqual({
|
|
199
|
+
text,
|
|
200
|
+
length: true,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
/*
|
|
207
|
+
* The title a customer sees beside each (i), as the pages render it. A title
|
|
208
|
+
* that names a percentile must get a text that explains it.
|
|
209
|
+
*/
|
|
210
|
+
const TITLED: Array<[string, string]> = [
|
|
211
|
+
["Availability", CLUSTER.availability],
|
|
212
|
+
["CPU", CLUSTER.cpu],
|
|
213
|
+
["Memory", CLUSTER.memory],
|
|
214
|
+
["Filesystem", CLUSTER.filesystem],
|
|
215
|
+
["Network", CLUSTER.network],
|
|
216
|
+
["Availability", CLUSTER.availabilityChart],
|
|
217
|
+
["CPU", CLUSTER.cpuChart],
|
|
218
|
+
["Memory", CLUSTER.memoryChart],
|
|
219
|
+
["Filesystem", CLUSTER.filesystemChart],
|
|
220
|
+
["Network", CLUSTER.networkChart],
|
|
221
|
+
["Cluster inventory counts", CLUSTER.inventoryCounts],
|
|
222
|
+
["Running", CLUSTER.podsRunning],
|
|
223
|
+
["Pending", CLUSTER.podsPending],
|
|
224
|
+
["Failed", CLUSTER.podsFailed],
|
|
225
|
+
["Nodes Not Ready", CLUSTER.nodesNotReady],
|
|
226
|
+
["Cluster Health", CLUSTER.clusterHealth],
|
|
227
|
+
["Nodes", CLUSTER.nodes],
|
|
228
|
+
["Pods", CLUSTER.pods],
|
|
229
|
+
["Namespaces", CLUSTER.namespaces],
|
|
230
|
+
["Agent Status", CLUSTER.agentStatus],
|
|
231
|
+
["Memory Pressure", CLUSTER.memoryPressure],
|
|
232
|
+
["Disk Pressure", CLUSTER.diskPressure],
|
|
233
|
+
["PID Pressure", CLUSTER.pidPressure],
|
|
234
|
+
["Pod Health", CLUSTER.podHealth],
|
|
235
|
+
["CPU Usage", CLUSTER.topCpuPods],
|
|
236
|
+
["Memory Usage", CLUSTER.topMemoryPods],
|
|
237
|
+
["Network", CLUSTER.networkThroughput],
|
|
238
|
+
["Total Spend", COST.totalSpend],
|
|
239
|
+
["Workload Spend", COST.workloadSpend],
|
|
240
|
+
["Idle Spend", COST.idleSpend],
|
|
241
|
+
["Idle %", COST.idlePercent],
|
|
242
|
+
["Spend", COST.spendTrend],
|
|
243
|
+
["CPU", COST.namespaceCpuCost],
|
|
244
|
+
["Memory", COST.namespaceMemoryCost],
|
|
245
|
+
["Storage", COST.namespaceStorageCost],
|
|
246
|
+
["Other", COST.namespaceOtherCost],
|
|
247
|
+
["Total", COST.namespaceTotalCost],
|
|
248
|
+
["Total", COST.workloadTotalCost],
|
|
249
|
+
["Efficiency", COST.efficiency],
|
|
250
|
+
["Total Spend", COST.fleetTotalSpend],
|
|
251
|
+
["Workload Spend", COST.fleetWorkloadSpend],
|
|
252
|
+
["Idle Spend", COST.fleetIdleSpend],
|
|
253
|
+
["Idle %", COST.fleetIdlePercent],
|
|
254
|
+
["Kubernetes Spend", COST.fleetSpendTrend],
|
|
255
|
+
["Workload", COST.clusterWorkloadCost],
|
|
256
|
+
["Idle", COST.clusterIdleCost],
|
|
257
|
+
["Total", COST.clusterTotalCost],
|
|
258
|
+
["Efficiency", COST.clusterEfficiency],
|
|
259
|
+
["Potential Saving", RIGHT_SIZING.potentialSaving],
|
|
260
|
+
["Over-provisioned", RIGHT_SIZING.overprovisioned],
|
|
261
|
+
["Under-provisioned", RIGHT_SIZING.underprovisioned],
|
|
262
|
+
["Analyzed", RIGHT_SIZING.analyzed],
|
|
263
|
+
["CPU Request", RIGHT_SIZING.cpuRequest],
|
|
264
|
+
["Memory Request", RIGHT_SIZING.memoryRequest],
|
|
265
|
+
["Est. Saving", RIGHT_SIZING.estimatedSaving],
|
|
266
|
+
];
|
|
267
|
+
|
|
268
|
+
describe("each title is explained by the text beside it", () => {
|
|
269
|
+
test.each(TITLED)("%s", (title: string, text: string) => {
|
|
270
|
+
expectTitleExplained(title, text);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("every description appears beside some title", () => {
|
|
274
|
+
const shown: Set<string> = new Set(
|
|
275
|
+
TITLED.map((pair: [string, string]): string => {
|
|
276
|
+
return pair[1];
|
|
277
|
+
}),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
for (const text of [
|
|
281
|
+
...Object.values(CLUSTER),
|
|
282
|
+
...Object.values(COST),
|
|
283
|
+
...Object.values(RIGHT_SIZING),
|
|
284
|
+
]) {
|
|
285
|
+
expect(shown.has(text)).toBe(true);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
describe("accuracy: the golden tiles and the charts under them", () => {
|
|
291
|
+
/*
|
|
292
|
+
* The tiles average only the last few minutes of the selected range
|
|
293
|
+
* (TILE_WINDOW_MINUTES in the page, pinned against the source in the App
|
|
294
|
+
* wiring test); a tile text that said "over the selected range" would
|
|
295
|
+
* promise a number the page never computes.
|
|
296
|
+
*/
|
|
297
|
+
test.each(["cpu", "memory", "filesystem", "network"] as const)(
|
|
298
|
+
"the %s tile says it averages the last 5 minutes of the range",
|
|
299
|
+
(key: KubernetesClusterMetric) => {
|
|
300
|
+
expect(CLUSTER[key]).toContain("last 5 minutes of the selected range");
|
|
301
|
+
},
|
|
302
|
+
);
|
|
303
|
+
|
|
304
|
+
/*
|
|
305
|
+
* meanInRecentWindow keeps the points whose bucket START is inside the
|
|
306
|
+
* last 5 minutes and falls back to the whole range when none is (pinned in
|
|
307
|
+
* the App wiring test). Each of the four tile texts has to say so - and say
|
|
308
|
+
* when it happens, which the next test pins against the bucket widths.
|
|
309
|
+
*/
|
|
310
|
+
test.each(["cpu", "memory", "filesystem", "network"] as const)(
|
|
311
|
+
"the %s tile says when it shows the whole range instead",
|
|
312
|
+
(key: KubernetesClusterMetric) => {
|
|
313
|
+
expect(CLUSTER[key]).toContain(
|
|
314
|
+
"often the whole range on ranges over 12 hours or without recent data",
|
|
315
|
+
);
|
|
316
|
+
},
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
/*
|
|
320
|
+
* Buckets are stamped with their start. Up to 12 hours they are at most 5
|
|
321
|
+
* minutes wide, so one always starts inside the 5-minute tile window; past
|
|
322
|
+
* 12 hours they are 15 minutes or wider, so for most of each bucket no
|
|
323
|
+
* point starts inside the window and the tile falls back to the whole
|
|
324
|
+
* range. That is the "over 12 hours" the texts quote.
|
|
325
|
+
*/
|
|
326
|
+
test("past 12 hours, buckets outgrow the 5-minute tile window", () => {
|
|
327
|
+
const TILE_WINDOW_MS: number = 5 * 60 * 1000;
|
|
328
|
+
const end: Date = new Date("2026-09-24T12:00:00.000Z");
|
|
329
|
+
const bucketMsFor: (hours: number) => number = (hours: number): number => {
|
|
330
|
+
return AggregationIntervalUtil.getAggregationIntervalMs(
|
|
331
|
+
AggregationIntervalUtil.getAggregationIntervalForWindow({
|
|
332
|
+
startDate: new Date(end.getTime() - hours * 60 * 60 * 1000),
|
|
333
|
+
endDate: end,
|
|
334
|
+
}),
|
|
335
|
+
);
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
for (const hours of [0.5, 1, 3, 6, 12]) {
|
|
339
|
+
expect({ hours, fits: bucketMsFor(hours) <= TILE_WINDOW_MS }).toEqual({
|
|
340
|
+
hours,
|
|
341
|
+
fits: true,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
for (const hours of [12.5, 24, 72, 168]) {
|
|
346
|
+
expect({ hours, fits: bucketMsFor(hours) <= TILE_WINDOW_MS }).toEqual({
|
|
347
|
+
hours,
|
|
348
|
+
fits: false,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
test("availability covers the whole range, not the last 5 minutes", () => {
|
|
354
|
+
expect(CLUSTER.availability).toContain("selected range");
|
|
355
|
+
expect(CLUSTER.availability).not.toContain("5 minutes");
|
|
356
|
+
// It measures the agent reporting, not the customer's apps.
|
|
357
|
+
expect(CLUSTER.availability).toContain("heartbeat");
|
|
358
|
+
expect(CLUSTER.availability).toContain("not whether your apps were up");
|
|
359
|
+
// Trailing buckets still in the ingest window are excluded.
|
|
360
|
+
expect(CLUSTER.availability).toContain("may still be arriving");
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
test("the availability chart names the bridged minute and the newest intervals left out", () => {
|
|
364
|
+
/*
|
|
365
|
+
* The same builder as the Host and container host charts
|
|
366
|
+
* (HeartbeatAvailabilityUtil): a single empty minute between up ones is
|
|
367
|
+
* bridged, and silent trailing buckets are left out of the badge.
|
|
368
|
+
*/
|
|
369
|
+
expect(CLUSTER.availabilityChart).toContain(
|
|
370
|
+
"a lone missed minute between Up ones counts as Up",
|
|
371
|
+
);
|
|
372
|
+
expect(CLUSTER.availabilityChart).toContain(
|
|
373
|
+
"leaving out the newest ones still waiting for data",
|
|
374
|
+
);
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test("CPU is a share of allocatable CPU, not of node capacity or of cores", () => {
|
|
378
|
+
expect(CLUSTER.cpu).toContain("allocatable CPU");
|
|
379
|
+
expect(CLUSTER.cpuChart).toContain("allocatable CPU");
|
|
380
|
+
// The chart has no series at all when allocatable is not reported.
|
|
381
|
+
expect(CLUSTER.cpuChart).toContain("empty");
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
test("memory is an absolute total across nodes that includes cache", () => {
|
|
385
|
+
expect(CLUSTER.memory).toContain("added together");
|
|
386
|
+
expect(CLUSTER.memory).toContain("cache");
|
|
387
|
+
expect(CLUSTER.memoryChart).toContain("bytes");
|
|
388
|
+
expect(CLUSTER.memoryChart).toContain("cache");
|
|
389
|
+
// Not a percentage - there is no denominator.
|
|
390
|
+
expect(CLUSTER.memory).not.toContain("%");
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
/*
|
|
394
|
+
* kubeletstats reports k8s.node.filesystem.usage / .available once per
|
|
395
|
+
* node (the kubelet's root filesystem, no mountpoint or device attribute),
|
|
396
|
+
* so the page's per-(node, mount) join collapses to one fraction per node
|
|
397
|
+
* and the tile is an unweighted average across nodes - not across disks.
|
|
398
|
+
*/
|
|
399
|
+
test("filesystem is an unweighted average of per-node disk fullness", () => {
|
|
400
|
+
expect(CLUSTER.filesystem).toContain(
|
|
401
|
+
"Used space divided by used plus free space on each node's disk",
|
|
402
|
+
);
|
|
403
|
+
expect(CLUSTER.filesystem).toContain("averaged across nodes");
|
|
404
|
+
expect(CLUSTER.filesystem).toContain("nearly full node can hide");
|
|
405
|
+
expect(CLUSTER.filesystem).not.toContain("across disks");
|
|
406
|
+
expect(CLUSTER.filesystemChart).toContain("averaged across the nodes");
|
|
407
|
+
expect(CLUSTER.filesystemChart).not.toContain("across the disks");
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
test("network is received plus sent, summed over nodes and interfaces", () => {
|
|
411
|
+
expect(CLUSTER.network).toContain("received plus sent");
|
|
412
|
+
expect(CLUSTER.network).toContain("every node and network interface");
|
|
413
|
+
expect(CLUSTER.networkChart).toContain("(In)");
|
|
414
|
+
expect(CLUSTER.networkChart).toContain("(Out)");
|
|
415
|
+
expect(CLUSTER.networkChart).toContain("byte counters");
|
|
416
|
+
expect(CLUSTER.networkThroughput).toContain("received and transmitted");
|
|
417
|
+
expect(CLUSTER.networkThroughput).toContain("byte counters");
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
test.each([
|
|
421
|
+
"availabilityChart",
|
|
422
|
+
"cpuChart",
|
|
423
|
+
"memoryChart",
|
|
424
|
+
"filesystemChart",
|
|
425
|
+
"networkChart",
|
|
426
|
+
"networkThroughput",
|
|
427
|
+
] as const)(
|
|
428
|
+
"the %s text describes one point per interval",
|
|
429
|
+
(key: KubernetesClusterMetric) => {
|
|
430
|
+
expect(CLUSTER[key]).toContain("each interval");
|
|
431
|
+
},
|
|
432
|
+
);
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
describe("accuracy: inventory-snapshot numbers ignore the time range", () => {
|
|
436
|
+
test.each([
|
|
437
|
+
"clusterHealth",
|
|
438
|
+
"nodes",
|
|
439
|
+
"pods",
|
|
440
|
+
"namespaces",
|
|
441
|
+
"inventoryCounts",
|
|
442
|
+
"podHealth",
|
|
443
|
+
] as const)(
|
|
444
|
+
"%s says it comes from the latest inventory",
|
|
445
|
+
(key: KubernetesClusterMetric) => {
|
|
446
|
+
expect(CLUSTER[key]).toContain("latest inventory");
|
|
447
|
+
},
|
|
448
|
+
);
|
|
449
|
+
|
|
450
|
+
const IGNORES_PICKER: Array<[KubernetesClusterMetric, string]> = [
|
|
451
|
+
["clusterHealth", "not the selected range"],
|
|
452
|
+
["nodes", "not the selected range"],
|
|
453
|
+
["pods", "not limited to the selected range"],
|
|
454
|
+
["inventoryCounts", "ignore the time range picker"],
|
|
455
|
+
["podHealth", "Not tied to the time range"],
|
|
456
|
+
];
|
|
457
|
+
|
|
458
|
+
test.each(IGNORES_PICKER)(
|
|
459
|
+
"%s says the time picker does not change it",
|
|
460
|
+
(key: KubernetesClusterMetric, phrase: string) => {
|
|
461
|
+
expect(CLUSTER[key]).toContain(phrase);
|
|
462
|
+
},
|
|
463
|
+
);
|
|
464
|
+
|
|
465
|
+
test("cluster health spells out the page's exact rule", () => {
|
|
466
|
+
// Unhealthy: failed pods or not-ready nodes.
|
|
467
|
+
expect(CLUSTER.clusterHealth).toContain(
|
|
468
|
+
"Unhealthy if any pod has failed or any node is not ready",
|
|
469
|
+
);
|
|
470
|
+
// Degraded: pending pods or any node pressure.
|
|
471
|
+
expect(CLUSTER.clusterHealth).toContain(
|
|
472
|
+
"Degraded if any pod is pending or a node reports memory, disk or process pressure",
|
|
473
|
+
);
|
|
474
|
+
expect(CLUSTER.clusterHealth).toContain("otherwise Healthy");
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
test("the chips that feed the health rule say which state they cause", () => {
|
|
478
|
+
expect(CLUSTER.podsPending).toContain("marks the cluster Degraded");
|
|
479
|
+
expect(CLUSTER.podsFailed).toContain("marks the cluster Unhealthy");
|
|
480
|
+
expect(CLUSTER.nodesNotReady).toContain("marks the cluster Unhealthy");
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
test("pods count every phase, and the container count excludes init containers", () => {
|
|
484
|
+
expect(CLUSTER.pods).toContain("in any phase");
|
|
485
|
+
expect(CLUSTER.inventoryCounts).toContain("pods in any phase");
|
|
486
|
+
expect(CLUSTER.inventoryCounts).toContain(
|
|
487
|
+
"init containers are not counted",
|
|
488
|
+
);
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
/*
|
|
492
|
+
* Run the real inventory extractor: the counts on the page are sums of the
|
|
493
|
+
* columns it writes, so the words have to match what it does with a node
|
|
494
|
+
* whose kubelet went silent and with a pod's init containers.
|
|
495
|
+
*/
|
|
496
|
+
test("a node whose Ready condition is Unknown (kubelet silent) counts as not ready", () => {
|
|
497
|
+
const record: ExtractedInventoryRecord | null = extractInventoryResource({
|
|
498
|
+
resourceType: "nodes",
|
|
499
|
+
logBody: JSON.stringify(
|
|
500
|
+
toOtlpValue({
|
|
501
|
+
kind: "Node",
|
|
502
|
+
metadata: { name: "node-a", uid: "node-a-uid" },
|
|
503
|
+
status: { conditions: [{ type: "Ready", status: "Unknown" }] },
|
|
504
|
+
}),
|
|
505
|
+
),
|
|
506
|
+
lastSeenAt: new Date(),
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
expect(record?.resource.isReady).toBe(false);
|
|
510
|
+
expect(CLUSTER.nodesNotReady).toContain("has stopped reporting");
|
|
511
|
+
expect(CLUSTER.nodesNotReady).toContain("Ready check is not passing");
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
test("the container count is spec.containers only - init containers are left out", () => {
|
|
515
|
+
const record: ExtractedInventoryRecord | null = extractInventoryResource({
|
|
516
|
+
resourceType: "pods",
|
|
517
|
+
logBody: JSON.stringify(
|
|
518
|
+
toOtlpValue({
|
|
519
|
+
kind: "Pod",
|
|
520
|
+
metadata: { name: "api-7d9f", namespace: "shop", uid: "api-uid" },
|
|
521
|
+
spec: {
|
|
522
|
+
initContainers: [{ name: "migrate", image: "busybox" }],
|
|
523
|
+
containers: [
|
|
524
|
+
{ name: "api", image: "nginx" },
|
|
525
|
+
{ name: "proxy", image: "envoy" },
|
|
526
|
+
],
|
|
527
|
+
},
|
|
528
|
+
status: { phase: "Running" },
|
|
529
|
+
}),
|
|
530
|
+
),
|
|
531
|
+
lastSeenAt: new Date(),
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
expect(record?.resource.containerCount).toBe(2);
|
|
535
|
+
expect(CLUSTER.inventoryCounts).toContain(
|
|
536
|
+
"init containers are not counted",
|
|
537
|
+
);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
test("the agent status names the disconnect threshold", () => {
|
|
541
|
+
// The same words as Proxmox and VMware, which disconnect the same way.
|
|
542
|
+
expect(CLUSTER.agentStatus).toContain(
|
|
543
|
+
"about 15 to 20 minutes after data stops arriving",
|
|
544
|
+
);
|
|
545
|
+
expect(CLUSTER.agentStatus).toContain("keep their last reported values");
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
test("each node pressure condition is explained on its own", () => {
|
|
549
|
+
expect(CLUSTER.memoryPressure).toContain("low on memory");
|
|
550
|
+
expect(CLUSTER.diskPressure).toContain("low on disk space");
|
|
551
|
+
expect(CLUSTER.pidPressure).toContain("processes (PIDs)");
|
|
552
|
+
|
|
553
|
+
for (const text of [
|
|
554
|
+
CLUSTER.memoryPressure,
|
|
555
|
+
CLUSTER.diskPressure,
|
|
556
|
+
CLUSTER.pidPressure,
|
|
557
|
+
]) {
|
|
558
|
+
expect(text).toContain("evict");
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
test("pod health names all four phases the bar draws", () => {
|
|
563
|
+
for (const phase of ["Running", "Succeeded", "Pending", "Failed"]) {
|
|
564
|
+
expect(CLUSTER.podHealth).toContain(phase);
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
});
|
|
568
|
+
|
|
569
|
+
describe("accuracy: top resource consumers", () => {
|
|
570
|
+
test("both lists read each pod's latest minute from the past hour, not the picker", () => {
|
|
571
|
+
for (const text of [CLUSTER.topCpuPods, CLUSTER.topMemoryPods]) {
|
|
572
|
+
expect(text).toContain("latest minute of data from the past hour");
|
|
573
|
+
expect(text).toContain("ignores the time range picker");
|
|
574
|
+
expect(text).toContain("The 5 pods");
|
|
575
|
+
}
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
test("both lists say what allocatable means", () => {
|
|
579
|
+
for (const text of [CLUSTER.topCpuPods, CLUSTER.topMemoryPods]) {
|
|
580
|
+
expect(text).toContain("(what the node can hand out to pods)");
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test("the denominator is the allocatable capacity of each pod's own node", () => {
|
|
585
|
+
expect(CLUSTER.topCpuPods).toContain(
|
|
586
|
+
"allocatable CPU of the node each runs on",
|
|
587
|
+
);
|
|
588
|
+
expect(CLUSTER.topMemoryPods).toContain(
|
|
589
|
+
"allocatable memory of the node each runs on",
|
|
590
|
+
);
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
test("the CPU list admits the value is in cores when allocatable is unknown", () => {
|
|
594
|
+
expect(CLUSTER.topCpuPods).toContain("or in cores where that is unknown");
|
|
595
|
+
});
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
describe("accuracy: costs", () => {
|
|
599
|
+
test("the cluster page folds unallocated cost into idle, and says so", () => {
|
|
600
|
+
expect(COST.workloadSpend).toContain(
|
|
601
|
+
"total spend minus idle and unallocated capacity",
|
|
602
|
+
);
|
|
603
|
+
expect(COST.idleSpend).toContain("unallocated");
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
test("the project page counts only idle capacity as idle, and says so", () => {
|
|
607
|
+
expect(COST.fleetWorkloadSpend).toContain(
|
|
608
|
+
"Total spend minus idle capacity",
|
|
609
|
+
);
|
|
610
|
+
expect(COST.fleetWorkloadSpend).toContain(
|
|
611
|
+
"unallocated is counted here rather than as idle",
|
|
612
|
+
);
|
|
613
|
+
expect(COST.fleetIdleSpend).toContain("Unallocated cost is not included");
|
|
614
|
+
expect(COST.clusterWorkloadCost).toContain(
|
|
615
|
+
"total cost minus idle capacity",
|
|
616
|
+
);
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
test("totals include idle capacity", () => {
|
|
620
|
+
expect(COST.totalSpend).toContain("including capacity no workload used");
|
|
621
|
+
expect(COST.fleetTotalSpend).toContain(
|
|
622
|
+
"including capacity no workload used",
|
|
623
|
+
);
|
|
624
|
+
expect(COST.spendTrend).toContain("idle capacity included");
|
|
625
|
+
expect(COST.fleetSpendTrend).toContain("idle capacity included");
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
test("the trend explains why points grow with the range (bucketed sums)", () => {
|
|
629
|
+
expect(COST.spendTrend).toContain(
|
|
630
|
+
"adds up the cost records that start in that interval",
|
|
631
|
+
);
|
|
632
|
+
expect(COST.spendTrend).toContain("taller points");
|
|
633
|
+
expect(COST.fleetSpendTrend).toContain("taller points");
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
test("the idle % texts name the bar's thresholds", () => {
|
|
637
|
+
expect(COST.idlePercent).toContain("amber at 25% and red at 40%");
|
|
638
|
+
expect(COST.fleetIdlePercent).toContain("amber at 25% and red at 40%");
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
test("each Total column says what its share is a share of", () => {
|
|
642
|
+
expect(COST.namespaceTotalCost).toContain(
|
|
643
|
+
"share of the cluster's total spend, idle capacity included",
|
|
644
|
+
);
|
|
645
|
+
expect(COST.workloadTotalCost).toContain(
|
|
646
|
+
"share of workload spend, which leaves idle capacity out",
|
|
647
|
+
);
|
|
648
|
+
expect(COST.clusterTotalCost).toContain(
|
|
649
|
+
"share of spend across all clusters",
|
|
650
|
+
);
|
|
651
|
+
});
|
|
652
|
+
|
|
653
|
+
test("efficiency is used-versus-requested, can pass 100%, and names the pill colours", () => {
|
|
654
|
+
expect(COST.efficiency).toContain("requested CPU and memory");
|
|
655
|
+
expect(COST.efficiency).toContain("above 100% means more was used");
|
|
656
|
+
expect(COST.efficiency).toContain("Green from 70%, red below 40%");
|
|
657
|
+
expect(COST.clusterEfficiency).toContain("Green from 70%, red below 40%");
|
|
658
|
+
// The project table's average includes the idle rows.
|
|
659
|
+
expect(COST.clusterEfficiency).toContain("idle-capacity records included");
|
|
660
|
+
});
|
|
661
|
+
|
|
662
|
+
test("other = total minus the three named components", () => {
|
|
663
|
+
expect(COST.namespaceOtherCost).toContain("not CPU, memory or storage");
|
|
664
|
+
});
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
describe("accuracy: right-sizing numbers come from the recommender's constants", () => {
|
|
668
|
+
test("the saving is projected to the recommender's month", () => {
|
|
669
|
+
expect(RIGHT_SIZING.potentialSaving).toContain(
|
|
670
|
+
`${HOURS_IN_MONTH}-hour month`,
|
|
671
|
+
);
|
|
672
|
+
expect(RIGHT_SIZING.estimatedSaving).toContain(
|
|
673
|
+
`${HOURS_IN_MONTH}-hour month`,
|
|
674
|
+
);
|
|
675
|
+
// Increases are not netted against the headline saving.
|
|
676
|
+
expect(RIGHT_SIZING.potentialSaving).toContain("not subtracted");
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
test("the verdict band is the recommender's significance ratio", () => {
|
|
680
|
+
const band: string = percentOf(SIGNIFICANCE_RATIO);
|
|
681
|
+
|
|
682
|
+
/*
|
|
683
|
+
* Over: recommended / request < 1 - band, i.e. the recommendation is
|
|
684
|
+
* more than the band below the request.
|
|
685
|
+
*/
|
|
686
|
+
expect(RIGHT_SIZING.overprovisioned).toContain(`more than ${band} below`);
|
|
687
|
+
expect(RIGHT_SIZING.underprovisioned).toContain(`more than ${band} above`);
|
|
688
|
+
expect(RIGHT_SIZING.cpuRequest).toContain(`within ${band}`);
|
|
689
|
+
});
|
|
690
|
+
|
|
691
|
+
/*
|
|
692
|
+
* A request is a reservation, not a cap: CPU throttling and OOM kills at a
|
|
693
|
+
* container's own ceiling come from its LIMIT. A container using more than
|
|
694
|
+
* it requested is slowed when the node is busy and is among the first the
|
|
695
|
+
* kernel or kubelet kills or evicts when node memory runs short.
|
|
696
|
+
*/
|
|
697
|
+
test("under-provisioned describes what a too-small request risks, not a limit", () => {
|
|
698
|
+
expect(RIGHT_SIZING.underprovisioned).toContain(
|
|
699
|
+
"use more than they reserve",
|
|
700
|
+
);
|
|
701
|
+
expect(RIGHT_SIZING.underprovisioned).toContain("busy node can slow them");
|
|
702
|
+
expect(RIGHT_SIZING.underprovisioned).toContain("killed or evicted");
|
|
703
|
+
expect(RIGHT_SIZING.underprovisioned).not.toContain("throttling");
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
test("the headroom is the recommender's headroom", () => {
|
|
707
|
+
expect(RIGHT_SIZING.overprovisioned).toContain(
|
|
708
|
+
`${percentOf(CPU_HEADROOM_RATIO)} headroom`,
|
|
709
|
+
);
|
|
710
|
+
expect(RIGHT_SIZING.cpuRequest).toContain(
|
|
711
|
+
`${percentOf(CPU_HEADROOM_RATIO)} headroom`,
|
|
712
|
+
);
|
|
713
|
+
expect(RIGHT_SIZING.memoryRequest).toContain(
|
|
714
|
+
`${percentOf(MEMORY_HEADROOM_RATIO)} headroom`,
|
|
715
|
+
);
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
test("CPU is sized from a 95th percentile, and the text explains it", () => {
|
|
719
|
+
expect(RIGHT_SIZING.cpuRequest).toContain("95th percentile");
|
|
720
|
+
expect(RIGHT_SIZING.cpuRequest).toContain("95% of hourly readings");
|
|
721
|
+
});
|
|
722
|
+
|
|
723
|
+
test("memory is sized from a peak, and says where peaks come from", () => {
|
|
724
|
+
expect(RIGHT_SIZING.memoryRequest).toContain("highest memory peak");
|
|
725
|
+
expect(RIGHT_SIZING.memoryRequest).toContain("Prometheus");
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
test("both request columns name the minimum history", () => {
|
|
729
|
+
expect(RIGHT_SIZING.cpuRequest).toContain(`${MIN_OBSERVED_HOURS} hours`);
|
|
730
|
+
expect(RIGHT_SIZING.memoryRequest).toContain(`${MIN_OBSERVED_HOURS} hours`);
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
test("analyzed counts a workload's container once, not per replica", () => {
|
|
734
|
+
expect(RIGHT_SIZING.analyzed).toContain("counts once");
|
|
735
|
+
expect(RIGHT_SIZING.analyzed).toContain("replicas");
|
|
736
|
+
expect(RIGHT_SIZING.analyzed).toContain("already right-sized");
|
|
737
|
+
});
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
/*
|
|
741
|
+
* The texts say how the verdicts and the saving are decided; the recommender
|
|
742
|
+
* is pure, so run it and check the words against what it actually does.
|
|
743
|
+
*/
|
|
744
|
+
describe("accuracy: the right-sizing texts match the recommender's behaviour", () => {
|
|
745
|
+
const OBSERVED_HOURS: number = 48;
|
|
746
|
+
|
|
747
|
+
function cpuOnly(
|
|
748
|
+
request: number,
|
|
749
|
+
p95Usage: number,
|
|
750
|
+
): RightSizingRecommendation {
|
|
751
|
+
const observation: RightSizingObservation = {
|
|
752
|
+
namespace: "shop",
|
|
753
|
+
controllerKind: "Deployment",
|
|
754
|
+
controllerName: "api",
|
|
755
|
+
containerName: "api",
|
|
756
|
+
sampleCount: OBSERVED_HOURS,
|
|
757
|
+
cpuCoreRequestAverage: request,
|
|
758
|
+
cpuCoreUsageP95: p95Usage,
|
|
759
|
+
cpuCost: 10,
|
|
760
|
+
ramBytesRequestAverage: 0,
|
|
761
|
+
ramBytesUsagePeak: 0,
|
|
762
|
+
ramCost: 0,
|
|
763
|
+
};
|
|
764
|
+
|
|
765
|
+
return buildRightSizingRecommendation(observation, OBSERVED_HOURS);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
test("recommendation = observed 95th-percentile demand plus the headroom", () => {
|
|
769
|
+
const recommendation: RightSizingRecommendation = cpuOnly(1, 0.5);
|
|
770
|
+
|
|
771
|
+
// 0.5 cores * 1.25, rounded up to the 10m step.
|
|
772
|
+
expect(recommendation.cpu.recommended).toBeCloseTo(0.63, 5);
|
|
773
|
+
expect(recommendation.cpu.observedDemand).toBe(0.5);
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
test("over-provisioned: the recommendation is more than the band BELOW the request", () => {
|
|
777
|
+
// 0.63 is 37% below a 1-core request.
|
|
778
|
+
expect(cpuOnly(1, 0.5).cpu.verdict).toBe(
|
|
779
|
+
RightSizingVerdict.Overprovisioned,
|
|
780
|
+
);
|
|
781
|
+
// A request only 10% above the recommendation is right-sized.
|
|
782
|
+
expect(cpuOnly(0.7, 0.5).cpu.verdict).toBe(RightSizingVerdict.Optimal);
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
test("under-provisioned: the recommendation is more than the band ABOVE the request", () => {
|
|
786
|
+
// Recommendation 0.63 vs a 0.5 request: 26% above.
|
|
787
|
+
expect(cpuOnly(0.5, 0.5).cpu.verdict).toBe(
|
|
788
|
+
RightSizingVerdict.Underprovisioned,
|
|
789
|
+
);
|
|
790
|
+
// 0.63 vs 0.56: 12.5% above - inside the band, right-sized.
|
|
791
|
+
expect(cpuOnly(0.56, 0.5).cpu.verdict).toBe(RightSizingVerdict.Optimal);
|
|
792
|
+
});
|
|
793
|
+
|
|
794
|
+
test("the saving is the window's change scaled to a 730-hour month", () => {
|
|
795
|
+
const recommendation: RightSizingRecommendation = cpuOnly(1, 0.5);
|
|
796
|
+
// $10 of CPU over the window, request cut from 1 to 0.63 cores.
|
|
797
|
+
const windowSaving: number = 10 * (1 - 0.63);
|
|
798
|
+
|
|
799
|
+
expect(recommendation.estimatedMonthlySavings).toBeCloseTo(
|
|
800
|
+
(windowSaving * HOURS_IN_MONTH) / OBSERVED_HOURS,
|
|
801
|
+
5,
|
|
802
|
+
);
|
|
803
|
+
expect(recommendation.estimatedMonthlyIncrease).toBe(0);
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
test("an under-provisioned container shows an increase, never a negative saving", () => {
|
|
807
|
+
const recommendation: RightSizingRecommendation = cpuOnly(0.5, 0.5);
|
|
808
|
+
|
|
809
|
+
expect(recommendation.estimatedMonthlySavings).toBe(0);
|
|
810
|
+
expect(recommendation.estimatedMonthlyIncrease).toBeGreaterThan(0);
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
test("without a memory peak, memory is unavailable (the '-' the text mentions)", () => {
|
|
814
|
+
expect(cpuOnly(1, 0.5).memory.verdict).toBe(RightSizingVerdict.Unavailable);
|
|
815
|
+
});
|
|
816
|
+
|
|
817
|
+
test("with less than the minimum history, nothing is sized", () => {
|
|
818
|
+
const observation: RightSizingObservation = {
|
|
819
|
+
namespace: "shop",
|
|
820
|
+
controllerKind: "Deployment",
|
|
821
|
+
controllerName: "api",
|
|
822
|
+
containerName: "api",
|
|
823
|
+
sampleCount: MIN_OBSERVED_HOURS - 1,
|
|
824
|
+
cpuCoreRequestAverage: 1,
|
|
825
|
+
cpuCoreUsageP95: 0.5,
|
|
826
|
+
cpuCost: 10,
|
|
827
|
+
ramBytesRequestAverage: 0,
|
|
828
|
+
ramBytesUsagePeak: 0,
|
|
829
|
+
ramCost: 0,
|
|
830
|
+
};
|
|
831
|
+
|
|
832
|
+
expect(
|
|
833
|
+
buildRightSizingRecommendation(observation, MIN_OBSERVED_HOURS - 1).cpu
|
|
834
|
+
.verdict,
|
|
835
|
+
).toBe(RightSizingVerdict.Unavailable);
|
|
836
|
+
});
|
|
837
|
+
});
|