@oneuptime/common 12.0.23 → 12.0.25
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/AnalyticsModels/Span.ts +101 -0
- package/Models/DatabaseModels/DetectionRule.ts +55 -0
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +27 -7
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +67 -0
- package/Models/DatabaseModels/Project.ts +68 -0
- package/Models/DatabaseModels/User.ts +68 -0
- package/Server/API/BaseAPI.ts +0 -24
- package/Server/API/SlackAPI.ts +0 -2
- package/Server/API/TelemetryAPI.ts +29 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/GzipRequestBody.ts +311 -0
- package/Server/Middleware/MultipartFormData.ts +87 -3
- package/Server/Middleware/SlackAuthorization.ts +96 -18
- package/Server/Services/DetectionRuleService.ts +73 -6
- package/Server/Services/Index.ts +205 -0
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
- package/Server/Services/NetworkDeviceService.ts +148 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
- package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
- package/Server/Services/ProjectService.ts +29 -19
- package/Server/Services/SecurityEventService.ts +90 -13
- package/Server/Services/StatusPageResourceService.ts +223 -0
- package/Server/Services/TelemetryAttributeService.ts +17 -0
- package/Server/Services/UserService.ts +4 -6
- package/Server/Types/Markdown.ts +161 -67
- package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
- package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
- package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
- package/Server/Utils/Attribution.ts +4 -0
- package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
- package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
- package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
- package/Server/Utils/StartServer.ts +12 -32
- package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
- package/Server/Utils/Telemetry/LlmMetricSpend.ts +181 -0
- package/Server/Utils/Telemetry/LlmSpan.ts +46 -0
- package/Server/Utils/Workspace/Slack/Actions/Auth.ts +0 -12
- package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
- package/Server/Views/Partials/Head.ejs +2 -1
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
- package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
- package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
- package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
- package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
- package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
- package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
- package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
- package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
- package/Tests/App/Dashboard/LlmCallsTableIdentity.test.tsx +322 -0
- package/Tests/App/Dashboard/LlmOverview.test.tsx +335 -0
- package/Tests/App/Dashboard/LlmSpanDisplay.test.ts +391 -0
- package/Tests/App/Dashboard/LlmUsageBreakdown.test.tsx +1007 -0
- package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
- package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
- package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
- package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
- package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
- package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
- package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
- package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
- package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
- package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
- package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
- package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
- package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
- package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
- package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
- package/Tests/Server/API/BaseAPI.test.ts +41 -0
- package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +9 -16
- package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
- package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
- package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
- package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
- package/Tests/Server/Middleware/SlackAuthorization.test.ts +262 -5
- package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
- package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
- package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
- package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
- package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
- package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
- package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
- package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
- package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
- package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
- package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
- package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
- package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
- package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
- package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +387 -4
- package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +386 -0
- package/Tests/Server/Utils/Telemetry/LlmSpan.test.ts +804 -0
- package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
- package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
- package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
- package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
- package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
- package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +584 -0
- package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
- package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
- package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
- package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
- package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
- package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
- package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
- package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
- package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
- package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
- package/Tests/UI/Components/SideOver.test.tsx +1 -1
- package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
- package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
- package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
- package/Tests/UI/Components/Toggle.test.tsx +25 -0
- package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
- package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
- package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
- package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
- package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +770 -0
- package/Types/Code/YamlSyntax.ts +396 -0
- package/Types/Exception/ExceptionCode.ts +1 -0
- package/Types/Exception/PayloadTooLargeException.ts +8 -0
- package/Types/Marketing/Attribution.ts +10 -0
- package/Types/Marketing/MarketingEvent.ts +4 -0
- package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
- package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
- package/Types/Telemetry/LlmConventions.ts +255 -0
- package/Types/Telemetry/LlmMetricConventions.ts +329 -0
- package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
- package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
- package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
- package/UI/Components/Detail/Detail.tsx +10 -0
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
- package/UI/Components/Forms/Fields/FormField.tsx +31 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
- package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
- package/UI/Components/Forms/Validation.ts +46 -0
- package/UI/Components/Input/Input.tsx +3 -0
- package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
- package/UI/Components/ModelTable/Column.ts +8 -0
- package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
- package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
- package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
- package/UI/Components/SideOver/SideOver.tsx +5 -5
- package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
- package/UI/Components/StatusPage/ResourceList.tsx +197 -38
- package/UI/Components/Toggle/Toggle.tsx +9 -1
- package/UI/Components/Types/FieldType.ts +1 -0
- package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
- package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
- package/Utils/StatusPage/ResourceExplorer.ts +258 -0
- package/Utils/Telemetry/LlmMetricQuery.ts +287 -0
- package/build/dist/Models/AnalyticsModels/Span.js +89 -0
- package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
- package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +27 -7
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +69 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +76 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/User.js +76 -0
- package/build/dist/Models/DatabaseModels/User.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +3 -19
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/SlackAPI.js +0 -2
- package/build/dist/Server/API/SlackAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +17 -0
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
- package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
- package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
- package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
- package/build/dist/Server/Middleware/SlackAuthorization.js +58 -7
- package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
- package/build/dist/Server/Services/DetectionRuleService.js +49 -4
- package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +204 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +25 -45
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/SecurityEventService.js +57 -5
- package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
- package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
- package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +2 -12
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +147 -61
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
- package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
- package/build/dist/Server/Utils/Attribution.js.map +1 -1
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
- package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
- package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
- package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +12 -21
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
- package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +151 -0
- package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/LlmSpan.js +24 -1
- package/build/dist/Server/Utils/Telemetry/LlmSpan.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +0 -10
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
- package/build/dist/Types/Code/YamlSyntax.js +212 -0
- package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
- package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
- package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
- package/build/dist/Types/Marketing/Attribution.js +10 -0
- package/build/dist/Types/Marketing/Attribution.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
- package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
- package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
- package/build/dist/Types/Telemetry/LlmConventions.js +236 -0
- package/build/dist/Types/Telemetry/LlmConventions.js.map +1 -1
- package/build/dist/Types/Telemetry/LlmMetricConventions.js +290 -0
- package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
- package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
- package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
- package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
- package/build/dist/UI/Components/Detail/Detail.js +9 -0
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
- package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
- package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +27 -0
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +1 -1
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
- package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
- package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
- package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
- package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
- package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
- package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
- package/build/dist/UI/Components/Types/FieldType.js +1 -0
- package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
- package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
- package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
- package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
- package/build/dist/Utils/Telemetry/LlmMetricQuery.js +175 -0
- package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
- package/jest.config.json +2 -0
- package/package.json +1 -1
- package/tsconfig.json +2 -1
- package/Tests/UI/Components/Toast.test.tsx +0 -197
- package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
- package/UI/Components/Toast/Toast.tsx +0 -189
- package/UI/Components/Toast/ToastInit.tsx +0 -110
- package/build/dist/UI/Components/Toast/Toast.js +0 -123
- package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
- package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
- package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
|
@@ -68,7 +68,14 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
68
68
|
filters: [
|
|
69
69
|
{
|
|
70
70
|
checkOn: CheckOn.IsOnline,
|
|
71
|
-
|
|
71
|
+
/*
|
|
72
|
+
* Seed the condition too, matching
|
|
73
|
+
* getNewMonitorCriteriaInstanceAsJSON. A filter with no filter
|
|
74
|
+
* type shows an empty "Filter Condition" dropdown in the form
|
|
75
|
+
* and never matches anything at evaluation time, because every
|
|
76
|
+
* comparator in CompareCriteria switches on the filter type.
|
|
77
|
+
*/
|
|
78
|
+
filterType: FilterType.True,
|
|
72
79
|
value: undefined,
|
|
73
80
|
},
|
|
74
81
|
],
|
|
@@ -83,6 +90,35 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
83
90
|
};
|
|
84
91
|
}
|
|
85
92
|
|
|
93
|
+
/*
|
|
94
|
+
* The monitor types whose criteria MonitorCriteriaEvaluator hands to
|
|
95
|
+
* MetricMonitorCriteria. That evaluator reads exactly one thing -
|
|
96
|
+
* CheckOn.MetricValue - so these types share a single pair of defaults:
|
|
97
|
+
* a metric that is reporting a value means online, a metric that has
|
|
98
|
+
* gone to zero means offline.
|
|
99
|
+
*
|
|
100
|
+
* Kept in step with the routing list in MonitorCriteriaEvaluator and
|
|
101
|
+
* with the check-on narrowing in the dashboard's CriteriaFilter util,
|
|
102
|
+
* which offers these types the metric value and nothing else. A type
|
|
103
|
+
* missing here falls through to `new MonitorCriteriaInstance()` and
|
|
104
|
+
* ships an unnamed criteria whose "Is Online" filter no evaluator on
|
|
105
|
+
* this path reads - a rule that can never fire and cannot be saved,
|
|
106
|
+
* since getValidationError requires a name and a description.
|
|
107
|
+
*/
|
|
108
|
+
public static isMetricBackedMonitorType(monitorType: MonitorType): boolean {
|
|
109
|
+
return (
|
|
110
|
+
monitorType === MonitorType.Metrics ||
|
|
111
|
+
monitorType === MonitorType.Kubernetes ||
|
|
112
|
+
monitorType === MonitorType.Docker ||
|
|
113
|
+
monitorType === MonitorType.Host ||
|
|
114
|
+
monitorType === MonitorType.Podman ||
|
|
115
|
+
monitorType === MonitorType.DockerSwarm ||
|
|
116
|
+
monitorType === MonitorType.Proxmox ||
|
|
117
|
+
monitorType === MonitorType.Ceph ||
|
|
118
|
+
monitorType === MonitorType.IoTDevice
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
86
122
|
public static getDefaultOnlineMonitorCriteriaInstance(arg: {
|
|
87
123
|
monitorType: MonitorType;
|
|
88
124
|
monitorStatusId: ObjectID;
|
|
@@ -232,7 +268,7 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
232
268
|
return monitorCriteriaInstance;
|
|
233
269
|
}
|
|
234
270
|
|
|
235
|
-
if (arg.monitorType
|
|
271
|
+
if (MonitorCriteriaInstance.isMetricBackedMonitorType(arg.monitorType)) {
|
|
236
272
|
const monitorCriteriaInstance: MonitorCriteriaInstance =
|
|
237
273
|
new MonitorCriteriaInstance();
|
|
238
274
|
|
|
@@ -254,7 +290,7 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
254
290
|
? arg.metricOptions.metricAliases[0]
|
|
255
291
|
: undefined,
|
|
256
292
|
},
|
|
257
|
-
value: 0, //
|
|
293
|
+
value: 0, // the metric is reporting above zero, so the monitor is online.
|
|
258
294
|
},
|
|
259
295
|
],
|
|
260
296
|
incidents: [],
|
|
@@ -269,7 +305,7 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
269
305
|
return monitorCriteriaInstance;
|
|
270
306
|
}
|
|
271
307
|
|
|
272
|
-
if (arg.monitorType === MonitorType.
|
|
308
|
+
if (arg.monitorType === MonitorType.Profiles) {
|
|
273
309
|
const monitorCriteriaInstance: MonitorCriteriaInstance =
|
|
274
310
|
new MonitorCriteriaInstance();
|
|
275
311
|
|
|
@@ -279,19 +315,9 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
279
315
|
filterCondition: FilterCondition.Any,
|
|
280
316
|
filters: [
|
|
281
317
|
{
|
|
282
|
-
checkOn: CheckOn.
|
|
318
|
+
checkOn: CheckOn.ProfileCount,
|
|
283
319
|
filterType: FilterType.GreaterThan,
|
|
284
|
-
|
|
285
|
-
metricMonitorOptions: {
|
|
286
|
-
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
287
|
-
metricAlias:
|
|
288
|
-
arg.metricOptions &&
|
|
289
|
-
arg.metricOptions.metricAliases &&
|
|
290
|
-
arg.metricOptions.metricAliases.length > 0
|
|
291
|
-
? arg.metricOptions.metricAliases[0]
|
|
292
|
-
: undefined,
|
|
293
|
-
},
|
|
294
|
-
value: 0,
|
|
320
|
+
value: 0, // if profiles are arriving then the monitor is online.
|
|
295
321
|
},
|
|
296
322
|
],
|
|
297
323
|
incidents: [],
|
|
@@ -1130,7 +1156,7 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
1130
1156
|
};
|
|
1131
1157
|
}
|
|
1132
1158
|
|
|
1133
|
-
if (arg.monitorType
|
|
1159
|
+
if (MonitorCriteriaInstance.isMetricBackedMonitorType(arg.monitorType)) {
|
|
1134
1160
|
monitorCriteriaInstance.data = {
|
|
1135
1161
|
id: ObjectID.generate().toString(),
|
|
1136
1162
|
monitorStatusId: arg.monitorStatusId,
|
|
@@ -1148,7 +1174,15 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
1148
1174
|
? arg.metricOptions.metricAliases[0]
|
|
1149
1175
|
: undefined,
|
|
1150
1176
|
},
|
|
1151
|
-
|
|
1177
|
+
/*
|
|
1178
|
+
* A reported value of zero, not an absent one. When the window
|
|
1179
|
+
* holds no samples at all the evaluator honours
|
|
1180
|
+
* metricMonitorOptions.onNoDataPolicy, which defaults to
|
|
1181
|
+
* Ignore, so silence alone does not fire this - a user who
|
|
1182
|
+
* wants "stopped reporting" to page has to opt into
|
|
1183
|
+
* NoDataPolicy.Trigger or TreatAsZero on the filter.
|
|
1184
|
+
*/
|
|
1185
|
+
value: 0,
|
|
1152
1186
|
},
|
|
1153
1187
|
],
|
|
1154
1188
|
incidents: [
|
|
@@ -1179,25 +1213,16 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
1179
1213
|
};
|
|
1180
1214
|
}
|
|
1181
1215
|
|
|
1182
|
-
if (arg.monitorType === MonitorType.
|
|
1216
|
+
if (arg.monitorType === MonitorType.Profiles) {
|
|
1183
1217
|
monitorCriteriaInstance.data = {
|
|
1184
1218
|
id: ObjectID.generate().toString(),
|
|
1185
1219
|
monitorStatusId: arg.monitorStatusId,
|
|
1186
1220
|
filterCondition: FilterCondition.Any,
|
|
1187
1221
|
filters: [
|
|
1188
1222
|
{
|
|
1189
|
-
checkOn: CheckOn.
|
|
1223
|
+
checkOn: CheckOn.ProfileCount,
|
|
1190
1224
|
filterType: FilterType.EqualTo,
|
|
1191
|
-
|
|
1192
|
-
metricAggregationType: EvaluateOverTimeType.AnyValue,
|
|
1193
|
-
metricAlias:
|
|
1194
|
-
arg.metricOptions &&
|
|
1195
|
-
arg.metricOptions.metricAliases &&
|
|
1196
|
-
arg.metricOptions.metricAliases.length > 0
|
|
1197
|
-
? arg.metricOptions.metricAliases[0]
|
|
1198
|
-
: undefined,
|
|
1199
|
-
},
|
|
1200
|
-
value: 0,
|
|
1225
|
+
value: 0, // if no profiles are arriving then the monitor is offline
|
|
1201
1226
|
},
|
|
1202
1227
|
],
|
|
1203
1228
|
incidents: [
|
|
@@ -1482,39 +1507,62 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
1482
1507
|
return `Description is required for criteria "${value.data.name}"`;
|
|
1483
1508
|
}
|
|
1484
1509
|
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1510
|
+
/*
|
|
1511
|
+
* Each "when filters match, ..." action is validated only while its own
|
|
1512
|
+
* switch is on.
|
|
1513
|
+
*
|
|
1514
|
+
* The criteria form keeps the incident / alert rows it seeded when a
|
|
1515
|
+
* switch was turned on, so that turning the switch back on restores what
|
|
1516
|
+
* was typed - the same retained-but-inert config that
|
|
1517
|
+
* MonitorStepsReferenceExtractor documents for project references. The
|
|
1518
|
+
* evaluator ignores those rows entirely while the flag is off
|
|
1519
|
+
* (MonitorIncident.criteriaMetCreateIncidentsAndUpdateMonitorStatus,
|
|
1520
|
+
* MonitorAlert.criteriaMetCreateAlertsAndUpdateMonitorStatus), so
|
|
1521
|
+
* validating them anyway only blocked the form: the row is rendered only
|
|
1522
|
+
* while its switch is on, which left the user staring at "Incident title
|
|
1523
|
+
* is required" with no field on screen to type it into and no way past
|
|
1524
|
+
* Next (issues #3410, #3413).
|
|
1525
|
+
*
|
|
1526
|
+
* The predicate is the falsy one the evaluator uses, not `!== false`, so
|
|
1527
|
+
* a criteria saved before these flags existed - populated rows, no flag -
|
|
1528
|
+
* is treated as off here exactly as it already is at runtime.
|
|
1529
|
+
*
|
|
1530
|
+
* Title and severity are the two fields the form marks required; the
|
|
1531
|
+
* description is not one of them. It sits in a collapsed section labelled
|
|
1532
|
+
* "Optional incident description" / "Optional alert description", and both
|
|
1533
|
+
* Incident.description and Alert.description are nullable columns. So it is
|
|
1534
|
+
* not required here either - demanding it stuck the form on a field the UI
|
|
1535
|
+
* calls optional and keeps folded away, which is the second half of #3410.
|
|
1536
|
+
*/
|
|
1537
|
+
if (value.data.createIncidents) {
|
|
1538
|
+
for (const incident of value.data.incidents) {
|
|
1539
|
+
if (!incident) {
|
|
1540
|
+
continue;
|
|
1541
|
+
}
|
|
1493
1542
|
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1543
|
+
if (!incident.title) {
|
|
1544
|
+
return `Incident title is required for criteria "${value.data.name}"`;
|
|
1545
|
+
}
|
|
1497
1546
|
|
|
1498
|
-
|
|
1499
|
-
|
|
1547
|
+
if (!incident.incidentSeverityId) {
|
|
1548
|
+
return `Incident severity is required for criteria "${value.data.name}"`;
|
|
1549
|
+
}
|
|
1500
1550
|
}
|
|
1501
1551
|
}
|
|
1502
1552
|
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
if (!alert.title) {
|
|
1509
|
-
return `Alert title is required for criteria "${value.data.name}"`;
|
|
1510
|
-
}
|
|
1553
|
+
if (value.data.createAlerts) {
|
|
1554
|
+
for (const alert of value.data.alerts) {
|
|
1555
|
+
if (!alert) {
|
|
1556
|
+
continue;
|
|
1557
|
+
}
|
|
1511
1558
|
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1559
|
+
if (!alert.title) {
|
|
1560
|
+
return `Alert title is required for criteria "${value.data.name}"`;
|
|
1561
|
+
}
|
|
1515
1562
|
|
|
1516
|
-
|
|
1517
|
-
|
|
1563
|
+
if (!alert.alertSeverityId) {
|
|
1564
|
+
return `Alert severity is required for criteria "${value.data.name}"`;
|
|
1565
|
+
}
|
|
1518
1566
|
}
|
|
1519
1567
|
}
|
|
1520
1568
|
|
|
@@ -1523,6 +1571,18 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
|
|
|
1523
1571
|
return `Filter Type is required for criteria "${value.data.name}"`;
|
|
1524
1572
|
}
|
|
1525
1573
|
|
|
1574
|
+
/*
|
|
1575
|
+
* A filter with no condition is silently dead: every comparator in
|
|
1576
|
+
* CompareCriteria switches on the filter type and returns "no
|
|
1577
|
+
* match" for one it does not recognise, so the criteria never
|
|
1578
|
+
* fires. The empty dropdown is easy to walk past when every field
|
|
1579
|
+
* around it is filled in, so refuse the save instead of accepting
|
|
1580
|
+
* a rule that can never be true.
|
|
1581
|
+
*/
|
|
1582
|
+
if (!filter.filterType) {
|
|
1583
|
+
return `Filter Condition is required for criteria "${value.data.name}" on filter type: ${filter.checkOn}`;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1526
1586
|
if (
|
|
1527
1587
|
monitorType === MonitorType.Ping &&
|
|
1528
1588
|
filter.checkOn !== CheckOn.IsOnline &&
|
|
@@ -108,7 +108,8 @@ export default class MonitorRecommendationSeverityMapper {
|
|
|
108
108
|
*
|
|
109
109
|
* Returns undefined when the mapping has no entry, which callers must treat
|
|
110
110
|
* as "leave the template's own severity alone" rather than as "no severity"
|
|
111
|
-
* — a criteria instance
|
|
111
|
+
* — a criteria instance that creates incidents (`createIncidents`) and has a
|
|
112
|
+
* populated incident with no severity id fails
|
|
112
113
|
* `MonitorCriteriaInstance.getValidationError` and the whole create fails.
|
|
113
114
|
*/
|
|
114
115
|
public static resolveSeverityId(data: {
|
|
@@ -18,6 +18,17 @@ export const DETECTION_RULE_NAME_ATTRIBUTE: string =
|
|
|
18
18
|
"oneuptime.detection.rule_name";
|
|
19
19
|
export const DETECTION_MATCH_COUNT_ATTRIBUTE: string =
|
|
20
20
|
"oneuptime.detection.match_count";
|
|
21
|
+
// Present only on findings from rules with a distinctCountField set.
|
|
22
|
+
export const DETECTION_DISTINCT_COUNT_ATTRIBUTE: string =
|
|
23
|
+
"oneuptime.detection.distinct_count";
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* Save-time bounds for DetectionRule.matchCountThreshold — one home for
|
|
27
|
+
* the server validator and the dashboard form, so the two ranges cannot
|
|
28
|
+
* drift apart.
|
|
29
|
+
*/
|
|
30
|
+
export const DETECTION_MATCH_COUNT_THRESHOLD_MIN: number = 1;
|
|
31
|
+
export const DETECTION_MATCH_COUNT_THRESHOLD_MAX: number = 1000000;
|
|
21
32
|
export const DETECTION_GROUP_VALUE_ATTRIBUTE: string =
|
|
22
33
|
"oneuptime.detection.group_value";
|
|
23
34
|
export const DETECTION_SIGMA_ID_ATTRIBUTE: string =
|
|
@@ -16,6 +16,65 @@
|
|
|
16
16
|
* lookup helpers return the first key that is present.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* The prefix OTLP ingest stamps onto every RESOURCE attribute before the
|
|
21
|
+
* attributes map reaches any extractor.
|
|
22
|
+
*
|
|
23
|
+
* This is not cosmetic and it is the difference between a feature that works
|
|
24
|
+
* and one that silently reports nothing. All three ingest services flatten
|
|
25
|
+
* resource attributes through
|
|
26
|
+
* `TelemetryUtil.getAttributes({ items, prefixKeysWithString: "resource" })`
|
|
27
|
+
* — OtelTracesIngestService, OtelMetricsIngestService and
|
|
28
|
+
* OtelLogsIngestService alike. So an operator who sets
|
|
29
|
+
* `OTEL_RESOURCE_ATTRIBUTES=team.id=platform` does NOT produce an attribute
|
|
30
|
+
* called `team.id`; they produce one called `resource.team.id`.
|
|
31
|
+
*
|
|
32
|
+
* OtelTracesIngestService already learned this the hard way for session
|
|
33
|
+
* replay (see its `sessionIdAttributeKeys`, which lists both spellings and
|
|
34
|
+
* whose comment notes that reading only the bare key "would look correct in a
|
|
35
|
+
* unit test and fail in production"). Identity is the same trap, one tier
|
|
36
|
+
* worse: identity is precisely the kind of value a fleet stamps ONCE on the
|
|
37
|
+
* resource rather than on every span, and Cursor documents `cursor.user.id` /
|
|
38
|
+
* `cursor.team.id` as resource attributes outright.
|
|
39
|
+
*/
|
|
40
|
+
export const RESOURCE_ATTRIBUTE_KEY_PREFIX: string = "resource.";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Widen a key list so it matches both the span-attribute spelling and the
|
|
44
|
+
* resource-attribute spelling of every key in it.
|
|
45
|
+
*
|
|
46
|
+
* The bare block comes FIRST in its entirety, then the resource-prefixed
|
|
47
|
+
* block, because a span attribute is strictly more specific than a resource
|
|
48
|
+
* attribute: the resource describes the whole process, the span describes one
|
|
49
|
+
* call. Preserving each block's internal order keeps the documented
|
|
50
|
+
* preference ordering intact within each tier.
|
|
51
|
+
*
|
|
52
|
+
* Pure and exported so the widening is one tested function rather than a
|
|
53
|
+
* hand-maintained second copy of every list that drifts the first time
|
|
54
|
+
* somebody adds a key.
|
|
55
|
+
*/
|
|
56
|
+
export function withResourcePrefixedKeys(keys: Array<string>): Array<string> {
|
|
57
|
+
return [
|
|
58
|
+
...keys,
|
|
59
|
+
...keys.map((key: string) => {
|
|
60
|
+
return `${RESOURCE_ATTRIBUTE_KEY_PREFIX}${key}`;
|
|
61
|
+
}),
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/*
|
|
66
|
+
* Note what is deliberately NOT widened: every list below that carries a
|
|
67
|
+
* per-CALL value — system, operation, models, tokens, cost, conversation id,
|
|
68
|
+
* tool name, request parameters, prompts and completions. Those describe one
|
|
69
|
+
* LLM request and have no business being set on a resource, which describes
|
|
70
|
+
* the whole process; a resource-scoped `gen_ai.request.model` would be a
|
|
71
|
+
* misconfiguration, not a convention to support. Widening them would double
|
|
72
|
+
* the number of map lookups on the hottest ingest path to chase a spelling
|
|
73
|
+
* nobody emits. Only the IDENTITY lists — user id, user email, team, and the
|
|
74
|
+
* end-user EXCLUSION list — are widened, because identity is exactly the
|
|
75
|
+
* value an operator sets once via OTEL_RESOURCE_ATTRIBUTES.
|
|
76
|
+
*/
|
|
77
|
+
|
|
19
78
|
// Provider / system, e.g. "openai", "anthropic", "aws.bedrock".
|
|
20
79
|
export const LlmSystemAttributeKeys: Array<string> = [
|
|
21
80
|
"gen_ai.system",
|
|
@@ -96,6 +155,202 @@ export const LlmAgentNameAttributeKeys: Array<string> = [
|
|
|
96
155
|
"agent.name",
|
|
97
156
|
];
|
|
98
157
|
|
|
158
|
+
/*
|
|
159
|
+
* ---------------------------------------------------------------------------
|
|
160
|
+
* WHO ran this call — the EMPLOYEE, never the employee's own customer.
|
|
161
|
+
* ---------------------------------------------------------------------------
|
|
162
|
+
*
|
|
163
|
+
* The LLM feature was born trace-only and had no concept of a human being, so
|
|
164
|
+
* "which of our engineers burned $4k on Opus last month" was unanswerable. The
|
|
165
|
+
* three lists below make the human actor a first-class span dimension, so
|
|
166
|
+
* spend can be grouped by person and by cost centre.
|
|
167
|
+
*
|
|
168
|
+
* THE CORRECTNESS RULE, and it is not a stylistic one: an LLM span can carry
|
|
169
|
+
* TWO different humans. The employee who made the call, and the DOWNSTREAM
|
|
170
|
+
* CUSTOMER on whose behalf the call was made (OpenAI's `user` request
|
|
171
|
+
* parameter, which instrumentations echo back as gen_ai.user / llm.user, and
|
|
172
|
+
* LiteLLM's end-user id). Those two are not interchangeable. Mapping a
|
|
173
|
+
* downstream customer into the employee columns produces internal chargeback
|
|
174
|
+
* that is not merely imprecise but WRONG — a support bot serving 40k
|
|
175
|
+
* customers would manufacture 40k phantom "employees", and the engineer who
|
|
176
|
+
* actually owns that spend would appear to have spent nothing.
|
|
177
|
+
*
|
|
178
|
+
* So the customer-identity keys are enumerated separately in
|
|
179
|
+
* LlmEndUserAttributeKeys below and are deliberately NOT read into any
|
|
180
|
+
* column. The exclusion is pinned by a test; if someone later wants
|
|
181
|
+
* downstream-customer analytics it must land in its OWN column, never by
|
|
182
|
+
* appending a key to the lists below.
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
/*
|
|
186
|
+
* The employee / internal actor id.
|
|
187
|
+
*
|
|
188
|
+
* Provenance, preferred first:
|
|
189
|
+
* - user.id OTel general semantic conventions; THE canonical key for
|
|
190
|
+
* the human actor and the one to standardize on.
|
|
191
|
+
* - enduser.id Also still an ACTIVE semconv attribute — the 1.25
|
|
192
|
+
* deprecation removed enduser.role and enduser.scope only,
|
|
193
|
+
* so this remains a legitimate, widely-emitted spelling.
|
|
194
|
+
* - litellm.metadata.user_api_key_user_id / metadata.user_api_key_user_id
|
|
195
|
+
* LiteLLM proxy: the internal user who OWNS the virtual key
|
|
196
|
+
* the request authenticated with. Note the sibling key
|
|
197
|
+
* user_api_key_end_user_id is the CUSTOMER and is excluded.
|
|
198
|
+
*
|
|
199
|
+
* BOTH spellings are required, and the bare one is the one
|
|
200
|
+
* that actually fires for most deployments. LiteLLM's
|
|
201
|
+
* default `otel` callback (v1) stamps its metadata with a
|
|
202
|
+
* bare "metadata." prefix — see METRIC_METADATA_KEYS and the
|
|
203
|
+
* `common_attrs[f"metadata.{key}"]` assignment in
|
|
204
|
+
* litellm/integrations/opentelemetry.py. The "litellm."
|
|
205
|
+
* namespace only appears under OpenTelemetry v2, which is
|
|
206
|
+
* OFF by default (LITELLM_OTEL_V2, `enabled: default=False`).
|
|
207
|
+
* Recognizing only the v2 spelling meant a stock LiteLLM
|
|
208
|
+
* proxy — the exact "one virtual key per employee" setup our
|
|
209
|
+
* docs recommend as the cleanest chargeback architecture —
|
|
210
|
+
* produced ZERO attribution, silently, with every gateway
|
|
211
|
+
* dollar landing in Unattributed and no error to explain it.
|
|
212
|
+
* - traceloop.association.properties.user_id OpenLLMetry.
|
|
213
|
+
* - langfuse.user.id Langfuse.
|
|
214
|
+
* - user.account_uuid / user.account_id Claude Code (and Codex for
|
|
215
|
+
* the latter) stamp the signed-in account onto every span.
|
|
216
|
+
* - cursor.user.id Cursor's OTel export; an opaque team-scoped integer,
|
|
217
|
+
* which is why it sorts last — it needs the Cursor admin API
|
|
218
|
+
* to resolve to a person, unlike the keys above.
|
|
219
|
+
*
|
|
220
|
+
* The `Base` list is the SPAN-attribute spelling only. Consumers must import
|
|
221
|
+
* LlmUserIdAttributeKeys, which adds the resource-attribute tier — see
|
|
222
|
+
* withResourcePrefixedKeys. The base list is exported solely so tests and
|
|
223
|
+
* docs can cross-check the two tiers against each other.
|
|
224
|
+
*/
|
|
225
|
+
export const LlmUserIdBaseAttributeKeys: Array<string> = [
|
|
226
|
+
"user.id",
|
|
227
|
+
"enduser.id",
|
|
228
|
+
// LiteLLM OTel v2 spelling, then the v1 default. Both are needed — see above.
|
|
229
|
+
"litellm.metadata.user_api_key_user_id",
|
|
230
|
+
"metadata.user_api_key_user_id",
|
|
231
|
+
"traceloop.association.properties.user_id",
|
|
232
|
+
"langfuse.user.id",
|
|
233
|
+
"user.account_uuid",
|
|
234
|
+
"user.account_id",
|
|
235
|
+
"cursor.user.id",
|
|
236
|
+
];
|
|
237
|
+
|
|
238
|
+
export const LlmUserIdAttributeKeys: Array<string> = withResourcePrefixedKeys(
|
|
239
|
+
LlmUserIdBaseAttributeKeys,
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
/*
|
|
243
|
+
* The employee's email address — in practice the only identity value a
|
|
244
|
+
* manager can read without a lookup table, which is why it gets its own
|
|
245
|
+
* column rather than being folded into the id.
|
|
246
|
+
*
|
|
247
|
+
* user.email is the OTel general-semconv key and is emitted NATIVELY by
|
|
248
|
+
* Claude Code, Gemini CLI and OpenAI Codex, so for the coding-agent fleet
|
|
249
|
+
* this list is usually the one that hits.
|
|
250
|
+
*
|
|
251
|
+
* The two LiteLLM spellings matter more than their position suggests: the
|
|
252
|
+
* proxy carries the key owner's email in its metadata (user_api_key_user_email
|
|
253
|
+
* is in METRIC_METADATA_KEYS), so a gateway issuing one virtual key per
|
|
254
|
+
* employee yields a real, human-readable email with no lookup table and no
|
|
255
|
+
* per-application instrumentation. That is the cleanest chargeback setup
|
|
256
|
+
* available today, and it is what our AI-gateway guide recommends. As with
|
|
257
|
+
* the id list, the bare "metadata." spelling is the DEFAULT one and the
|
|
258
|
+
* "litellm." namespace only appears under the opt-in OpenTelemetry v2 mode.
|
|
259
|
+
*
|
|
260
|
+
* Because this column holds real PII, TraceScrubRuleService scrubs it under
|
|
261
|
+
* the Attributes scope exactly as it scrubs the attribute it was derived from
|
|
262
|
+
* — see the identity-column pass in scrubSpan. A denormalized column that
|
|
263
|
+
* skipped the scrub pass would make a customer's email-redaction rule
|
|
264
|
+
* silently ineffective on the very column most likely to hold an email.
|
|
265
|
+
*/
|
|
266
|
+
export const LlmUserEmailBaseAttributeKeys: Array<string> = [
|
|
267
|
+
"user.email",
|
|
268
|
+
// LiteLLM OTel v2 spelling, then the v1 default. Both are needed — see above.
|
|
269
|
+
"litellm.metadata.user_api_key_user_email",
|
|
270
|
+
"metadata.user_api_key_user_email",
|
|
271
|
+
"traceloop.association.properties.user_email",
|
|
272
|
+
"enduser.email",
|
|
273
|
+
];
|
|
274
|
+
|
|
275
|
+
export const LlmUserEmailAttributeKeys: Array<string> =
|
|
276
|
+
withResourcePrefixedKeys(LlmUserEmailBaseAttributeKeys);
|
|
277
|
+
|
|
278
|
+
/*
|
|
279
|
+
* The team / cost centre the spend charges to.
|
|
280
|
+
*
|
|
281
|
+
* The first four are not emitted by any instrumentation on their own: they
|
|
282
|
+
* are what an organization sets via OTEL_RESOURCE_ATTRIBUTES on the agent
|
|
283
|
+
* process (OTEL_RESOURCE_ATTRIBUTES=team.id=platform,cost_center=RD-114), and
|
|
284
|
+
* are conventionally the ONLY way a coding-agent CLI learns which budget it
|
|
285
|
+
* belongs to. The remaining entries are the gateway/vendor spellings that
|
|
286
|
+
* arrive without any operator configuration.
|
|
287
|
+
*
|
|
288
|
+
* That first sentence is exactly why the resource tier is not optional here:
|
|
289
|
+
* OTEL_RESOURCE_ATTRIBUTES sets a RESOURCE attribute, which ingest delivers
|
|
290
|
+
* as `resource.team.id`. A list of bare keys alone would mean the one
|
|
291
|
+
* mechanism the docs present as THE way to attribute spend to a cost centre
|
|
292
|
+
* never matches a single row.
|
|
293
|
+
*/
|
|
294
|
+
export const LlmTeamBaseAttributeKeys: Array<string> = [
|
|
295
|
+
"team.id",
|
|
296
|
+
"team",
|
|
297
|
+
"cost_center",
|
|
298
|
+
"department",
|
|
299
|
+
// LiteLLM OTel v2 spellings, then the v1 default. See the id list above.
|
|
300
|
+
"litellm.metadata.user_api_key_team_id",
|
|
301
|
+
"litellm.team.id",
|
|
302
|
+
"metadata.user_api_key_team_id",
|
|
303
|
+
"cursor.team.id",
|
|
304
|
+
];
|
|
305
|
+
|
|
306
|
+
export const LlmTeamAttributeKeys: Array<string> = withResourcePrefixedKeys(
|
|
307
|
+
LlmTeamBaseAttributeKeys,
|
|
308
|
+
);
|
|
309
|
+
|
|
310
|
+
/*
|
|
311
|
+
* DELIBERATELY EXCLUDED — the DOWNSTREAM CUSTOMER, not the employee.
|
|
312
|
+
*
|
|
313
|
+
* Exported so the exclusion is a documented, testable decision rather than an
|
|
314
|
+
* omission somebody "fixes" later:
|
|
315
|
+
*
|
|
316
|
+
* - gen_ai.user / llm.user
|
|
317
|
+
* Both carry the OpenAI `user` REQUEST PARAMETER, which the API
|
|
318
|
+
* documents as the caller's own end user, sent for abuse monitoring. On
|
|
319
|
+
* a SaaS product's spans this is the SaaS product's customer.
|
|
320
|
+
* - litellm.metadata.user_api_key_end_user_id /
|
|
321
|
+
* metadata.user_api_key_end_user_id / litellm.end_user.id
|
|
322
|
+
* LiteLLM's explicit end-user id, distinct from the key-owner id above
|
|
323
|
+
* (which IS the employee and IS recognized). All three spellings are
|
|
324
|
+
* listed for the same reason the employee lists carry two: the bare
|
|
325
|
+
* "metadata." form is what the DEFAULT v1 otel callback emits, while
|
|
326
|
+
* "litellm.end_user.id" is the dedicated attribute the opt-in v2 mode
|
|
327
|
+
* defines in litellm/integrations/otel/model/semconv.py. Excluding only
|
|
328
|
+
* the v2 metadata spelling would leave the two spellings a real
|
|
329
|
+
* deployment actually produces free to be mistaken for an employee.
|
|
330
|
+
*
|
|
331
|
+
* None of these is denormalized into a column by this change. They remain
|
|
332
|
+
* available in the raw attributes map for anyone who queries them directly.
|
|
333
|
+
*
|
|
334
|
+
* This list is resource-widened too, and for the OPPOSITE reason to the
|
|
335
|
+
* lists above. Here the widening does not make anything match — it makes the
|
|
336
|
+
* EXCLUSION hold. The exclusion is enforced as a set relation ("no end-user
|
|
337
|
+
* key appears in an employee list"), so if this list stopped at the bare
|
|
338
|
+
* spellings while the employee lists carried both tiers, a future
|
|
339
|
+
* `resource.gen_ai.user` could be appended to an employee list and every
|
|
340
|
+
* exclusion test would still pass. Both tiers here, both tiers there.
|
|
341
|
+
*/
|
|
342
|
+
export const LlmEndUserBaseAttributeKeys: Array<string> = [
|
|
343
|
+
"gen_ai.user",
|
|
344
|
+
"llm.user",
|
|
345
|
+
"litellm.metadata.user_api_key_end_user_id",
|
|
346
|
+
"metadata.user_api_key_end_user_id",
|
|
347
|
+
"litellm.end_user.id",
|
|
348
|
+
];
|
|
349
|
+
|
|
350
|
+
export const LlmEndUserAttributeKeys: Array<string> = withResourcePrefixedKeys(
|
|
351
|
+
LlmEndUserBaseAttributeKeys,
|
|
352
|
+
);
|
|
353
|
+
|
|
99
354
|
export const LlmToolNameAttributeKeys: Array<string> = [
|
|
100
355
|
"gen_ai.tool.name",
|
|
101
356
|
"tool.name",
|