@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.
Files changed (323) hide show
  1. package/Models/AnalyticsModels/Span.ts +101 -0
  2. package/Models/DatabaseModels/DetectionRule.ts +55 -0
  3. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +27 -7
  4. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +67 -0
  5. package/Models/DatabaseModels/Project.ts +68 -0
  6. package/Models/DatabaseModels/User.ts +68 -0
  7. package/Server/API/BaseAPI.ts +0 -24
  8. package/Server/API/SlackAPI.ts +0 -2
  9. package/Server/API/TelemetryAPI.ts +29 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  14. package/Server/Middleware/GzipRequestBody.ts +311 -0
  15. package/Server/Middleware/MultipartFormData.ts +87 -3
  16. package/Server/Middleware/SlackAuthorization.ts +96 -18
  17. package/Server/Services/DetectionRuleService.ts +73 -6
  18. package/Server/Services/Index.ts +205 -0
  19. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
  20. package/Server/Services/NetworkDeviceService.ts +148 -0
  21. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  22. package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
  23. package/Server/Services/ProjectService.ts +29 -19
  24. package/Server/Services/SecurityEventService.ts +90 -13
  25. package/Server/Services/StatusPageResourceService.ts +223 -0
  26. package/Server/Services/TelemetryAttributeService.ts +17 -0
  27. package/Server/Services/UserService.ts +4 -6
  28. package/Server/Types/Markdown.ts +161 -67
  29. package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
  30. package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
  31. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
  32. package/Server/Utils/Attribution.ts +4 -0
  33. package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
  34. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
  35. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
  36. package/Server/Utils/StartServer.ts +12 -32
  37. package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
  38. package/Server/Utils/Telemetry/LlmMetricSpend.ts +181 -0
  39. package/Server/Utils/Telemetry/LlmSpan.ts +46 -0
  40. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +0 -12
  41. package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
  42. package/Server/Views/Partials/Head.ejs +2 -1
  43. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
  44. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
  45. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
  46. package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
  47. package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
  48. package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
  49. package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
  50. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
  51. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
  52. package/Tests/App/Dashboard/LlmCallsTableIdentity.test.tsx +322 -0
  53. package/Tests/App/Dashboard/LlmOverview.test.tsx +335 -0
  54. package/Tests/App/Dashboard/LlmSpanDisplay.test.ts +391 -0
  55. package/Tests/App/Dashboard/LlmUsageBreakdown.test.tsx +1007 -0
  56. package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
  57. package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
  58. package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
  59. package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
  60. package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
  61. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
  62. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
  63. package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
  64. package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
  65. package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
  66. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
  67. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
  68. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
  69. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
  70. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
  71. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
  72. package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
  73. package/Tests/Server/API/BaseAPI.test.ts +41 -0
  74. package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +9 -16
  75. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
  76. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
  77. package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
  78. package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
  79. package/Tests/Server/Middleware/SlackAuthorization.test.ts +262 -5
  80. package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
  81. package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
  82. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
  83. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
  84. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
  85. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
  86. package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
  87. package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
  88. package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
  89. package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
  90. package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
  91. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
  92. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
  93. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
  94. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
  95. package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
  96. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +387 -4
  97. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +386 -0
  98. package/Tests/Server/Utils/Telemetry/LlmSpan.test.ts +804 -0
  99. package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
  100. package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
  101. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
  102. package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
  103. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
  104. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
  105. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
  106. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
  107. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +584 -0
  108. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
  109. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
  110. package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
  111. package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
  112. package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
  113. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
  114. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
  115. package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
  116. package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
  117. package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
  118. package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
  119. package/Tests/UI/Components/SideOver.test.tsx +1 -1
  120. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
  121. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
  122. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
  123. package/Tests/UI/Components/Toggle.test.tsx +25 -0
  124. package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
  125. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
  126. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
  127. package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
  128. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
  129. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +770 -0
  130. package/Types/Code/YamlSyntax.ts +396 -0
  131. package/Types/Exception/ExceptionCode.ts +1 -0
  132. package/Types/Exception/PayloadTooLargeException.ts +8 -0
  133. package/Types/Marketing/Attribution.ts +10 -0
  134. package/Types/Marketing/MarketingEvent.ts +4 -0
  135. package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
  136. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
  137. package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
  138. package/Types/Telemetry/LlmConventions.ts +255 -0
  139. package/Types/Telemetry/LlmMetricConventions.ts +329 -0
  140. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
  141. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
  142. package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
  143. package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
  144. package/UI/Components/Detail/Detail.tsx +10 -0
  145. package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
  146. package/UI/Components/Forms/Fields/FormField.tsx +31 -0
  147. package/UI/Components/Forms/Types/Field.ts +8 -0
  148. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  149. package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
  150. package/UI/Components/Forms/Validation.ts +46 -0
  151. package/UI/Components/Input/Input.tsx +3 -0
  152. package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
  153. package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
  154. package/UI/Components/ModelTable/Column.ts +8 -0
  155. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
  156. package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
  157. package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
  158. package/UI/Components/SideOver/SideOver.tsx +5 -5
  159. package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
  160. package/UI/Components/StatusPage/ResourceList.tsx +197 -38
  161. package/UI/Components/Toggle/Toggle.tsx +9 -1
  162. package/UI/Components/Types/FieldType.ts +1 -0
  163. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
  164. package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
  165. package/Utils/StatusPage/ResourceExplorer.ts +258 -0
  166. package/Utils/Telemetry/LlmMetricQuery.ts +287 -0
  167. package/build/dist/Models/AnalyticsModels/Span.js +89 -0
  168. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  169. package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
  170. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  171. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +27 -7
  172. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  173. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +69 -0
  174. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  175. package/build/dist/Models/DatabaseModels/Project.js +76 -0
  176. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  177. package/build/dist/Models/DatabaseModels/User.js +76 -0
  178. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  179. package/build/dist/Server/API/BaseAPI.js +3 -19
  180. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  181. package/build/dist/Server/API/SlackAPI.js +0 -2
  182. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  183. package/build/dist/Server/API/TelemetryAPI.js +17 -0
  184. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  185. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
  188. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
  189. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
  190. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
  191. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  192. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  193. package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
  194. package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
  195. package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
  196. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  197. package/build/dist/Server/Middleware/SlackAuthorization.js +58 -7
  198. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  199. package/build/dist/Server/Services/DetectionRuleService.js +49 -4
  200. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  201. package/build/dist/Server/Services/Index.js +204 -0
  202. package/build/dist/Server/Services/Index.js.map +1 -1
  203. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
  204. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  205. package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
  206. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  207. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
  208. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  209. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
  210. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
  211. package/build/dist/Server/Services/ProjectService.js +25 -45
  212. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  213. package/build/dist/Server/Services/SecurityEventService.js +57 -5
  214. package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
  215. package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
  216. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  217. package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
  218. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  219. package/build/dist/Server/Services/UserService.js +2 -12
  220. package/build/dist/Server/Services/UserService.js.map +1 -1
  221. package/build/dist/Server/Types/Markdown.js +147 -61
  222. package/build/dist/Server/Types/Markdown.js.map +1 -1
  223. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
  224. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
  225. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
  226. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  227. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
  228. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  229. package/build/dist/Server/Utils/Attribution.js.map +1 -1
  230. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
  231. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  232. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
  233. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  234. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
  235. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  236. package/build/dist/Server/Utils/StartServer.js +12 -21
  237. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  238. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
  239. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
  240. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +151 -0
  241. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
  242. package/build/dist/Server/Utils/Telemetry/LlmSpan.js +24 -1
  243. package/build/dist/Server/Utils/Telemetry/LlmSpan.js.map +1 -1
  244. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +0 -10
  245. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  246. package/build/dist/Types/Code/YamlSyntax.js +212 -0
  247. package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
  248. package/build/dist/Types/Exception/ExceptionCode.js +1 -0
  249. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  250. package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
  251. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
  252. package/build/dist/Types/Marketing/Attribution.js +10 -0
  253. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  254. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
  255. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  256. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
  257. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  258. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
  259. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  260. package/build/dist/Types/Telemetry/LlmConventions.js +236 -0
  261. package/build/dist/Types/Telemetry/LlmConventions.js.map +1 -1
  262. package/build/dist/Types/Telemetry/LlmMetricConventions.js +290 -0
  263. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
  264. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  265. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  266. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
  267. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  268. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
  269. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  270. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
  271. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
  272. package/build/dist/UI/Components/Detail/Detail.js +9 -0
  273. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  274. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
  275. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  276. package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
  277. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  278. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  279. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  280. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  281. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
  282. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
  283. package/build/dist/UI/Components/Forms/Validation.js +27 -0
  284. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  285. package/build/dist/UI/Components/Input/Input.js +1 -1
  286. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  287. package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
  288. package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
  289. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
  290. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  291. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
  292. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  293. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
  294. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
  295. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
  296. package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
  297. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
  298. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  299. package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
  300. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  301. package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
  302. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  303. package/build/dist/UI/Components/Types/FieldType.js +1 -0
  304. package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
  305. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
  306. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  307. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
  308. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
  309. package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
  310. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
  311. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +175 -0
  312. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
  313. package/jest.config.json +2 -0
  314. package/package.json +1 -1
  315. package/tsconfig.json +2 -1
  316. package/Tests/UI/Components/Toast.test.tsx +0 -197
  317. package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
  318. package/UI/Components/Toast/Toast.tsx +0 -189
  319. package/UI/Components/Toast/ToastInit.tsx +0 -110
  320. package/build/dist/UI/Components/Toast/Toast.js +0 -123
  321. package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
  322. package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
  323. package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
@@ -9,6 +9,7 @@ import {
9
9
  } from "../EnvironmentConfig";
10
10
  import LocalCache from "../Infrastructure/LocalCache";
11
11
  import HttpMetricsMiddleware from "../Middleware/HttpMetricsMiddleware";
12
+ import GzipRequestBodyMiddleware from "../Middleware/GzipRequestBody";
12
13
  import CorsOptions, {
13
14
  CORS_EXPOSED_HEADERS,
14
15
  CORS_PREFLIGHT_MAX_AGE_SECONDS,
@@ -41,7 +42,6 @@ import StatusCode from "../../Types/API/StatusCode";
41
42
  import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
42
43
  import Exception from "../../Types/Exception/Exception";
43
44
  import NotFoundException from "../../Types/Exception/NotFoundException";
44
- import ServerException from "../../Types/Exception/ServerException";
45
45
  import { PromiseVoidFunction } from "../../Types/FunctionTypes";
46
46
  import { JSONObject } from "../../Types/JSON";
47
47
  import JSONFunctions from "../../Types/JSONFunctions";
@@ -49,7 +49,6 @@ import Port from "../../Types/Port";
49
49
  import Typeof from "../../Types/Typeof";
50
50
  import CookieParser from "cookie-parser";
51
51
  import cors from "cors";
52
- import zlib from "zlib";
53
52
  import crypto from "crypto";
54
53
  import path from "path";
55
54
  import "ejs";
@@ -206,10 +205,11 @@ app.use((req: OneUptimeRequest, res: ExpressResponse, next: NextFunction) => {
206
205
  * several prefixes, so /telemetry/otlp/v1/... and
207
206
  * /telemetry/session-replay/v1/... are equally live. A prefix-anchored
208
207
  * test would let the prefixed path fall into the gzip fast-path below,
209
- * which has NO size limit and no content-length pre-check (a zip-bomb
210
- * vector on a public browser endpoint) and which sets req.body to the
211
- * DECOMPRESSED buffer that in turn trips the ingest middleware's
212
- * "already parsed" early-out, so its byte cap would never run at all.
208
+ * which sets req.body to the DECOMPRESSED buffer that in turn trips
209
+ * the ingest middleware's "already parsed" early-out, so its own,
210
+ * tighter, byte cap would never run at all. (The fast path has its own
211
+ * limits since GHSA-cp58-wc9q-qv53, but they are the generic 50 MiB
212
+ * body-parser numbers, not the 4 MiB these routes are sized for.)
213
213
  */
214
214
  if (
215
215
  req.path.includes("/otlp/v1/") ||
@@ -226,32 +226,12 @@ app.use((req: OneUptimeRequest, res: ExpressResponse, next: NextFunction) => {
226
226
  );
227
227
 
228
228
  if (contentEncoding?.includes("gzip")) {
229
- const buffers: any = [];
230
-
231
- req.on("data", (chunk: any) => {
232
- buffers.push(chunk);
233
- });
234
-
235
- req.on("end", () => {
236
- const buffer: Buffer = Buffer.concat(buffers);
237
- zlib.gunzip(buffer as Uint8Array, (err: unknown, decoded: Buffer) => {
238
- if (err) {
239
- logger.error(
240
- err,
241
- getLogAttributesFromRequest(req as OneUptimeRequest),
242
- );
243
- return Response.sendErrorResponse(
244
- req,
245
- res,
246
- new ServerException("Error decompressing data"),
247
- );
248
- }
249
-
250
- req.body = decoded;
251
-
252
- next();
253
- });
254
- });
229
+ /*
230
+ * Bounded on both sides - see GzipRequestBody. This used to buffer the
231
+ * whole compressed body and hand it to an unbounded zlib.gunzip, which
232
+ * turned 130 KB of anonymous request into 128 MiB of resident Buffer.
233
+ */
234
+ GzipRequestBodyMiddleware.parseBody(req, res, next);
255
235
  } else if (
256
236
  contentType &&
257
237
  (contentType.includes("application/x-protobuf") ||
@@ -19,14 +19,22 @@ import MetricService from "../../Services/MetricService";
19
19
  import SpanService from "../../Services/SpanService";
20
20
  import logger, { LogAttributes } from "../Logger";
21
21
  import CaptureSpan from "../Telemetry/CaptureSpan";
22
+ import LlmMetricSpend, { LlmMetricScope } from "./LlmMetricSpend";
22
23
  import TelemetryUtil from "./Telemetry";
23
24
 
24
25
  /*
25
- * Evaluates LLM cost budgets against the day's LLM span spend.
26
+ * Evaluates LLM cost budgets against the day's LLM spend.
27
+ *
28
+ * Spend is sourced from GenAI trace spans first and, when a scope produced no
29
+ * span spend at all, from the GenAI metric stream instead (see resolveSpend
30
+ * and Common/Server/Utils/Telemetry/LlmMetricSpend.ts). That second source is
31
+ * what lets a metrics-only emitter — an SDK exporting metrics without traces,
32
+ * or a gateway that publishes spend counters and no spans — hold a budget at
33
+ * all. The two are never summed; see resolveSpend for why.
26
34
  *
27
35
  * The worker job (App/FeatureSet/Workers/Jobs/Llm/EvaluateLlmCostBudgets.ts)
28
36
  * calls evaluateAllBudgets() on a 15-minute tick. For each enabled budget it
29
- * sums the UTC day's llmCost from ClickHouse (scoped by the budget's optional
37
+ * sums the UTC day's spend from ClickHouse (scoped by the budget's optional
30
38
  * service / provider / model filters), stamps the spend back onto the budget
31
39
  * row for the dashboard, and publishes two gauge metrics:
32
40
  *
@@ -65,6 +73,17 @@ export const LLM_BUDGET_SERVICE_ID_ATTRIBUTE: string =
65
73
  */
66
74
  const BUDGET_METRIC_RETENTION_IN_DAYS: number = 15;
67
75
 
76
+ /*
77
+ * Which telemetry signal a budget's spend figure came from. "none" means both
78
+ * sources were empty — a genuinely idle scope, not a failure.
79
+ */
80
+ export type LlmSpendSource = "spans" | "metrics" | "none";
81
+
82
+ export interface LlmResolvedSpend {
83
+ spendInUSD: number;
84
+ source: LlmSpendSource;
85
+ }
86
+
68
87
  export default class LlmCostBudgetEvaluator {
69
88
  /**
70
89
  * Percent of the daily budget consumed. 0 when the budget is missing or
@@ -262,12 +281,18 @@ export default class LlmCostBudgetEvaluator {
262
281
 
263
282
  const dayStart: Date = this.getUtcDayStart(data.now);
264
283
 
265
- const spendInUSD: number = await this.getSpendInUSD({
284
+ const resolved: LlmResolvedSpend = await this.resolveSpend({
266
285
  budget: budget,
267
286
  dayStart: dayStart,
268
287
  now: data.now,
269
288
  });
270
289
 
290
+ const spendInUSD: number = resolved.spendInUSD;
291
+
292
+ logger.debug(
293
+ `LLM cost budget ${budget.id.toString()}: spend ${spendInUSD} USD sourced from ${resolved.source}`,
294
+ );
295
+
271
296
  const percentUsed: number = this.computePercentUsed({
272
297
  spendInUSD: spendInUSD,
273
298
  dailyBudgetInUSD: budget.dailyBudgetInUSD,
@@ -293,11 +318,83 @@ export default class LlmCostBudgetEvaluator {
293
318
  });
294
319
  }
295
320
 
321
+ /**
322
+ * Translate a budget's scope into the equivalent metric-stream scope, so
323
+ * the span query and the metric query narrow to the same slice of traffic.
324
+ *
325
+ * Service scoping is exact — Span.primaryEntityId and Metric.primaryEntityId
326
+ * are the same telemetry-service id. Provider/model scoping matches the
327
+ * primary semantic-convention attribute keys only; see the caveat on
328
+ * LlmMetricSpend.
329
+ */
330
+ public static buildMetricScope(data: {
331
+ budget: LlmCostBudget;
332
+ dayStart: Date;
333
+ now: Date;
334
+ }): LlmMetricScope {
335
+ return {
336
+ projectId: data.budget.projectId!,
337
+ startTime: data.dayStart,
338
+ endTime: data.now,
339
+ serviceId: data.budget.serviceId,
340
+ llmSystem: data.budget.llmSystem,
341
+ llmModel: data.budget.llmModel,
342
+ };
343
+ }
344
+
345
+ /**
346
+ * The day's spend for a budget, and which telemetry signal it came from.
347
+ *
348
+ * Spans are authoritative: a GenAI span carries model, tokens and cost on
349
+ * one row, and it is the only source that can also back the per-call views.
350
+ * Metrics are consulted ONLY when the span-sourced total is zero.
351
+ *
352
+ * That ordering is a deliberate fallback rather than a sum. Instrumentations
353
+ * that emit both signals (OpenLLMetry is the common case) would otherwise be
354
+ * counted twice, and for a budget that gates alerting an inflated figure is
355
+ * worse than a missing one — it fires on spend that never happened. The
356
+ * fallback turns on exactly for the emitters that need it: those publishing
357
+ * GenAI metrics and no GenAI spans, whose span total is structurally zero.
358
+ *
359
+ * Known limit, documented rather than papered over: a scope where SOME
360
+ * services emit spans and others emit only metrics resolves to "spans" and
361
+ * under-counts the metrics-only services. Splitting a budget per service is
362
+ * the workaround; scoping each to its own service gives each the source it
363
+ * actually has.
364
+ *
365
+ * A metric-query failure is allowed to propagate for the same reason the
366
+ * span aggregate passes timeoutOverflowMode 'throw': returning 0 on error
367
+ * would silently suppress a real breach. evaluateAllBudgets isolates the
368
+ * failure to the one budget.
369
+ */
370
+ @CaptureSpan()
371
+ public static async resolveSpend(data: {
372
+ budget: LlmCostBudget;
373
+ dayStart: Date;
374
+ now: Date;
375
+ }): Promise<LlmResolvedSpend> {
376
+ const spanSpend: number = await this.getSpanSpendInUSD(data);
377
+
378
+ if (spanSpend > 0) {
379
+ return { spendInUSD: spanSpend, source: "spans" };
380
+ }
381
+
382
+ const metricSpend: number = await LlmMetricSpend.getCostInUSD(
383
+ this.buildMetricScope(data),
384
+ );
385
+
386
+ if (metricSpend > 0) {
387
+ return { spendInUSD: metricSpend, source: "metrics" };
388
+ }
389
+
390
+ return { spendInUSD: 0, source: "none" };
391
+ }
392
+
296
393
  /**
297
394
  * Sum the day's llmCost for the budget's scope from ClickHouse.
298
395
  */
299
396
  @CaptureSpan()
300
- private static async getSpendInUSD(data: {
397
+ private static async getSpanSpendInUSD(data: {
301
398
  budget: LlmCostBudget;
302
399
  dayStart: Date;
303
400
  now: Date;
@@ -0,0 +1,181 @@
1
+ import Metric from "../../../Models/AnalyticsModels/Metric";
2
+ import AggregatedResult from "../../../Types/BaseDatabase/AggregatedResult";
3
+ import AggregationInterval from "../../../Types/BaseDatabase/AggregationInterval";
4
+ import AggregationType from "../../../Types/BaseDatabase/AggregationType";
5
+ import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
6
+ import { LlmTokenTypeAttributeKeys } from "../../../Types/Telemetry/LlmMetricConventions";
7
+ import LlmMetricQuery, {
8
+ LlmMetricScope,
9
+ LlmMetricTokenTotals,
10
+ } from "../../../Utils/Telemetry/LlmMetricQuery";
11
+ import AggregateBy from "../../Types/AnalyticsDatabase/AggregateBy";
12
+ import MetricService from "../../Services/MetricService";
13
+ import CaptureSpan from "./CaptureSpan";
14
+
15
+ /*
16
+ * Metric-sourced LLM token and cost totals.
17
+ *
18
+ * The LLM feature reads spans first — a GenAI span carries model, tokens and
19
+ * cost on one row, which is the richest source and the only one that can back
20
+ * the per-call views. This module is the SECOND source, for the emitters that
21
+ * publish GenAI metrics but no GenAI spans:
22
+ *
23
+ * - An OpenTelemetry SDK wired for metrics without tracing.
24
+ * - AI gateways and vendor exporters that publish spend/usage counters and
25
+ * never export traces.
26
+ *
27
+ * Callers must not add these totals to the span-sourced ones. Instrumentations
28
+ * that emit both (OpenLLMetry is the common case) would then be counted twice,
29
+ * and for a cost budget that gates alerting a doubled figure is worse than a
30
+ * missing one. LlmCostBudgetEvaluator therefore treats this as a FALLBACK: it
31
+ * is consulted only when the span-sourced total for the same scope is zero.
32
+ *
33
+ * Query construction and result folding live in the isomorphic
34
+ * Common/Utils/Telemetry/LlmMetricQuery, so the dashboard's AI / LLM overview
35
+ * asks the same questions of the same data. This module only adds the
36
+ * AggregateBy envelope and executes them with root props.
37
+ */
38
+
39
+ export { LlmMetricScope, LlmMetricTokenTotals };
40
+
41
+ export default class LlmMetricSpend {
42
+ /**
43
+ * Aggregate descriptor for the cost sum: one total over the whole window.
44
+ *
45
+ * `value` is the right column for every point type here — for a histogram
46
+ * ClickHouse stores the bucket sum in it, and MetricService resolves the
47
+ * point type before building the statement so distribution metrics skip the
48
+ * materialized views. Cost metrics are counters (delta or cumulative spend),
49
+ * so summing them across the window is the intended reduction.
50
+ */
51
+ public static buildCostAggregateBy(
52
+ scope: LlmMetricScope,
53
+ ): AggregateBy<Metric> {
54
+ return {
55
+ query: LlmMetricQuery.buildCostQuery(scope),
56
+ aggregationType: AggregationType.Sum,
57
+ aggregateColumnName: "value",
58
+ aggregationTimestampColumnName: "time",
59
+ startTimestamp: scope.startTime,
60
+ endTimestamp: scope.endTime,
61
+ // One total over the whole window — no time bucketing.
62
+ aggregationInterval: AggregationInterval.Total,
63
+ /*
64
+ * Same reasoning as the span path: this figure feeds budget monitors, so
65
+ * a query timeout must fail loudly rather than return a
66
+ * silently-partial sum that would understate spend and suppress a real
67
+ * breach.
68
+ */
69
+ timeoutOverflowMode: "throw",
70
+ limit: LIMIT_PER_PROJECT,
71
+ skip: 0,
72
+ props: {
73
+ isRoot: true,
74
+ },
75
+ } as AggregateBy<Metric>;
76
+ }
77
+
78
+ /**
79
+ * Aggregate descriptor for the micro-USD cost sum.
80
+ *
81
+ * Identical in shape to buildCostAggregateBy, deliberately a SECOND query
82
+ * rather than a wider name list on the first: the two name lists carry
83
+ * different units, and a single Sum over both would add micro-USD figures
84
+ * to USD ones with no way to recover the unit afterwards. Codex spend would
85
+ * arrive a million times too large and trip every cost budget in the
86
+ * project. getCostInUSD scales this total once, via
87
+ * LlmMetricQuery.combineCostTotals.
88
+ */
89
+ public static buildMicroUsdCostAggregateBy(
90
+ scope: LlmMetricScope,
91
+ ): AggregateBy<Metric> {
92
+ return {
93
+ query: LlmMetricQuery.buildMicroUsdCostQuery(scope),
94
+ aggregationType: AggregationType.Sum,
95
+ aggregateColumnName: "value",
96
+ aggregationTimestampColumnName: "time",
97
+ startTimestamp: scope.startTime,
98
+ endTimestamp: scope.endTime,
99
+ aggregationInterval: AggregationInterval.Total,
100
+ // Same fail-loud reasoning as the USD query above.
101
+ timeoutOverflowMode: "throw",
102
+ limit: LIMIT_PER_PROJECT,
103
+ skip: 0,
104
+ props: {
105
+ isRoot: true,
106
+ },
107
+ } as AggregateBy<Metric>;
108
+ }
109
+
110
+ /**
111
+ * Aggregate descriptor for the token sum.
112
+ *
113
+ * Grouping by every candidate token-type attribute key in ONE query —
114
+ * rather than issuing a query per key and per direction — is what keeps this
115
+ * both complete and free of double counting: each returned group carries the
116
+ * attribute values that produced it, so LlmMetricQuery.reduceTokenRows
117
+ * classifies them against the full set of recognized spellings instead of
118
+ * the query having to pick one.
119
+ */
120
+ public static buildTokenAggregateBy(
121
+ scope: LlmMetricScope,
122
+ ): AggregateBy<Metric> {
123
+ return {
124
+ query: LlmMetricQuery.buildTokenQuery(scope),
125
+ aggregationType: AggregationType.Sum,
126
+ aggregateColumnName: "value",
127
+ aggregationTimestampColumnName: "time",
128
+ startTimestamp: scope.startTime,
129
+ endTimestamp: scope.endTime,
130
+ aggregationInterval: AggregationInterval.Total,
131
+ groupByAttributeKeys: [...LlmTokenTypeAttributeKeys],
132
+ timeoutOverflowMode: "throw",
133
+ limit: LIMIT_PER_PROJECT,
134
+ skip: 0,
135
+ props: {
136
+ isRoot: true,
137
+ },
138
+ } as AggregateBy<Metric>;
139
+ }
140
+
141
+ /**
142
+ * Metric-sourced spend in USD for the scope, or 0 when nothing matched.
143
+ *
144
+ * Two aggregates, not one, because the recognized cost metrics come in two
145
+ * UNITS: dollars (the gateways, Claude Code, Cursor) and millionths of a
146
+ * dollar (the Codex CLI). They are queried apart and scaled before being
147
+ * added, in LlmMetricQuery.combineCostTotals — the one place the 1e-6
148
+ * factor lives. Folding the micro-USD names into the USD query would report
149
+ * Codex spend a million times too high, which for a figure that gates
150
+ * budget alerting is far worse than reporting nothing.
151
+ *
152
+ * The two run in parallel: they hit the same table with disjoint name
153
+ * filters, and serializing them would double the latency of every budget
154
+ * evaluation for no benefit.
155
+ */
156
+ @CaptureSpan()
157
+ public static async getCostInUSD(scope: LlmMetricScope): Promise<number> {
158
+ const [usdResult, microUsdResult]: [AggregatedResult, AggregatedResult] =
159
+ await Promise.all([
160
+ MetricService.aggregateBy(this.buildCostAggregateBy(scope)),
161
+ MetricService.aggregateBy(this.buildMicroUsdCostAggregateBy(scope)),
162
+ ]);
163
+
164
+ return LlmMetricQuery.combineCostTotals({
165
+ usd: LlmMetricQuery.sumAggregatedRows(usdResult?.data),
166
+ microUsd: LlmMetricQuery.sumAggregatedRows(microUsdResult?.data),
167
+ });
168
+ }
169
+
170
+ /** Metric-sourced input/output token totals for the scope. */
171
+ @CaptureSpan()
172
+ public static async getTokenTotals(
173
+ scope: LlmMetricScope,
174
+ ): Promise<LlmMetricTokenTotals> {
175
+ const result: AggregatedResult = await MetricService.aggregateBy(
176
+ this.buildTokenAggregateBy(scope),
177
+ );
178
+
179
+ return LlmMetricQuery.reduceTokenRows(result?.data);
180
+ }
181
+ }
@@ -14,8 +14,11 @@ import {
14
14
  LlmRequestModelAttributeKeys,
15
15
  LlmResponseModelAttributeKeys,
16
16
  LlmSystemAttributeKeys,
17
+ LlmTeamAttributeKeys,
17
18
  LlmToolNameAttributeKeys,
18
19
  LlmTotalTokenAttributeKeys,
20
+ LlmUserEmailAttributeKeys,
21
+ LlmUserIdAttributeKeys,
19
22
  } from "../../../Types/Telemetry/LlmConventions";
20
23
  import { AttributeType } from "./Telemetry";
21
24
 
@@ -61,6 +64,20 @@ export interface LlmSpanFields {
61
64
  llmToolName: string;
62
65
  // Conversation / session id grouping calls of one interaction (gen_ai.conversation.id).
63
66
  llmConversationId: string;
67
+ /*
68
+ * WHO ran the call — the EMPLOYEE / internal actor, never the caller's own
69
+ * downstream customer. See the block comment above
70
+ * LlmUserIdAttributeKeys in Common/Types/Telemetry/LlmConventions.ts for
71
+ * why that distinction is load-bearing rather than pedantic.
72
+ *
73
+ * "" when the instrumentation reports no identity, which is still the
74
+ * common case for library-instrumented server code — only the coding-agent
75
+ * CLIs and the gateways stamp identity by default.
76
+ */
77
+ llmUserId: string;
78
+ llmUserEmail: string;
79
+ // Team / cost centre the spend charges to (team.id, cost_center, ...).
80
+ llmTeam: string;
64
81
  }
65
82
 
66
83
  type SpanAttributes = Dictionary<AttributeType | Array<AttributeType>>;
@@ -83,6 +100,9 @@ export default class LlmSpanUtil {
83
100
  llmAgentName: "",
84
101
  llmToolName: "",
85
102
  llmConversationId: "",
103
+ llmUserId: "",
104
+ llmUserEmail: "",
105
+ llmTeam: "",
86
106
  };
87
107
  }
88
108
 
@@ -184,6 +204,32 @@ export default class LlmSpanUtil {
184
204
  attributes,
185
205
  LlmConversationIdAttributeKeys,
186
206
  );
207
+
208
+ /*
209
+ * Identity is gated on isLlmSpan for exactly the reason the
210
+ * conversation id above is. "user.id", "user.email" and "team.id" are
211
+ * GENERIC OTel general-semconv keys — RUM browser spans and ordinary
212
+ * backend HTTP spans routinely carry them, and those are the
213
+ * highest-volume span classes there are. Stamping them onto every such
214
+ * span would copy the value (and pay for its skip index) across the
215
+ * whole fleet to serve a reader that only ever asks "which employee
216
+ * spent what on LLM calls". The LLM spans are the only rows that
217
+ * question reads, so they are the only rows that carry the columns.
218
+ *
219
+ * The keys that carry the caller's DOWNSTREAM CUSTOMER rather than the
220
+ * employee (gen_ai.user, llm.user,
221
+ * litellm.metadata.user_api_key_end_user_id) are deliberately absent
222
+ * from these lists — see LlmEndUserAttributeKeys. Reading one of them
223
+ * here would silently misattribute internal chargeback.
224
+ */
225
+ fields.llmUserId = this.getString(attributes, LlmUserIdAttributeKeys);
226
+
227
+ fields.llmUserEmail = this.getString(
228
+ attributes,
229
+ LlmUserEmailAttributeKeys,
230
+ );
231
+
232
+ fields.llmTeam = this.getString(attributes, LlmTeamAttributeKeys);
187
233
  }
188
234
 
189
235
  /*
@@ -65,8 +65,6 @@ export default class SlackAuthAction {
65
65
  const { req } = data;
66
66
 
67
67
  logger.debug("Starting Slack request authorization");
68
- logger.debug(`Request body: `);
69
- logger.debug(req.body);
70
68
 
71
69
  let payload: JSONObject = req.body;
72
70
 
@@ -74,9 +72,6 @@ export default class SlackAuthAction {
74
72
  payload = JSON.parse(payload["payload"]);
75
73
  }
76
74
 
77
- logger.debug(`Payload: `);
78
- logger.debug(payload);
79
-
80
75
  let slackUserId: string | undefined = (
81
76
  (payload as JSONObject)["user"] as JSONObject
82
77
  )?.["id"] as string;
@@ -216,11 +211,6 @@ export default class SlackAuthAction {
216
211
  };
217
212
 
218
213
  actions.push(action);
219
- logger.debug("View values: ");
220
- logger.debug(viewValues);
221
-
222
- logger.debug("Actions: ");
223
- logger.debug(actions);
224
214
  }
225
215
 
226
216
  if (payload["callback_id"]) {
@@ -296,8 +286,6 @@ export default class SlackAuthAction {
296
286
  logger.debug("Slack request authorized successfully", {
297
287
  projectId: projectId.toString(),
298
288
  });
299
- logger.debug("Slack request: ");
300
- logger.debug(slackRequest);
301
289
 
302
290
  return slackRequest;
303
291
  }