@oneuptime/common 14.0.10 → 14.0.11

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 (837) hide show
  1. package/Models/DatabaseModels/AIConversation.ts +127 -1
  2. package/Models/DatabaseModels/CephCluster.ts +12 -0
  3. package/Models/DatabaseModels/CloudResource.ts +12 -0
  4. package/Models/DatabaseModels/DatabaseServer.ts +12 -0
  5. package/Models/DatabaseModels/DockerHost.ts +12 -0
  6. package/Models/DatabaseModels/DockerSwarmCluster.ts +12 -0
  7. package/Models/DatabaseModels/GlobalOidc.ts +0 -4
  8. package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
  9. package/Models/DatabaseModels/GlobalSso.ts +0 -4
  10. package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
  11. package/Models/DatabaseModels/Host.ts +12 -0
  12. package/Models/DatabaseModels/IncidentForm.ts +594 -0
  13. package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
  14. package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
  15. package/Models/DatabaseModels/Index.ts +14 -0
  16. package/Models/DatabaseModels/IoTFleet.ts +12 -0
  17. package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
  18. package/Models/DatabaseModels/MessageQueue.ts +1102 -0
  19. package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
  20. package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
  21. package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
  22. package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
  23. package/Models/DatabaseModels/PodmanHost.ts +12 -0
  24. package/Models/DatabaseModels/Project.ts +59 -0
  25. package/Models/DatabaseModels/ProjectOidc.ts +0 -4
  26. package/Models/DatabaseModels/ProjectSso.ts +0 -4
  27. package/Models/DatabaseModels/ProxmoxCluster.ts +12 -0
  28. package/Models/DatabaseModels/RumApplication.ts +12 -0
  29. package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
  30. package/Models/DatabaseModels/Service.ts +12 -0
  31. package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
  32. package/Models/DatabaseModels/StatusPageSso.ts +0 -4
  33. package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
  34. package/Models/DatabaseModels/VMwareVCenter.ts +12 -0
  35. package/Server/API/AIChatAPI.ts +13 -114
  36. package/Server/API/AIInvestigationAPI.ts +3 -3
  37. package/Server/API/AIInvestigationConversationAPI.ts +266 -0
  38. package/Server/API/IncidentFormAPI.ts +376 -0
  39. package/Server/API/ProjectOIDC.ts +16 -25
  40. package/Server/API/ProjectSSO.ts +16 -24
  41. package/Server/API/StatusPageAPI.ts +42 -77
  42. package/Server/Enterprise/EnterpriseEdition.ts +93 -28
  43. package/Server/Enterprise/EnterpriseFeature.ts +25 -3
  44. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
  45. package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
  46. package/Server/EnvironmentConfig.ts +1 -1
  47. package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
  48. package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
  49. package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
  50. package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
  51. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  52. package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
  53. package/Server/Middleware/UserAuthorization.ts +16 -38
  54. package/Server/Services/AIService.ts +10 -13
  55. package/Server/Services/IncidentCustomFieldService.ts +112 -2
  56. package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
  57. package/Server/Services/IncidentEpisodeService.ts +10 -1
  58. package/Server/Services/IncidentFormService.ts +1566 -0
  59. package/Server/Services/IncidentFormSubmissionService.ts +97 -0
  60. package/Server/Services/IncidentGroupingEngineService.ts +45 -8
  61. package/Server/Services/IncidentService.ts +123 -5
  62. package/Server/Services/IncidentTemplateService.ts +22 -0
  63. package/Server/Services/Index.ts +14 -0
  64. package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
  65. package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
  66. package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
  67. package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
  68. package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
  69. package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
  70. package/Server/Services/MessageQueueService.ts +1463 -0
  71. package/Server/Services/OpenTelemetryIngestService.ts +37 -4
  72. package/Server/Services/ProjectService.ts +0 -59
  73. package/Server/Services/StatusPagePrivateUserService.ts +1 -4
  74. package/Server/Services/StatusPageService.ts +1 -51
  75. package/Server/Services/TeamComplianceSettingService.ts +163 -42
  76. package/Server/Services/UserNotificationRuleService.ts +8 -1
  77. package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
  78. package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
  79. package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
  80. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
  81. package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
  82. package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
  83. package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
  84. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
  85. package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
  86. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
  87. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  88. package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
  89. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
  90. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
  91. package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
  92. package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
  93. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +7 -1
  94. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +34 -14
  95. package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +69 -24
  96. package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +9 -0
  97. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +53 -10
  98. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +27 -10
  99. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +27 -10
  100. package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
  101. package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
  102. package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
  103. package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
  104. package/Server/Utils/EditionEnforcement.ts +19 -202
  105. package/Server/Utils/LLM/LLMService.ts +259 -63
  106. package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
  107. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
  108. package/Server/Utils/SameOriginRequest.ts +203 -0
  109. package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
  110. package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
  111. package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
  112. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
  113. package/Server/Utils/VendorAssets.ts +3 -3
  114. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +3 -1
  115. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +3 -1
  116. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +10 -1
  117. package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
  118. package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
  119. package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
  120. package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
  121. package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
  122. package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
  123. package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
  124. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
  125. package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
  126. package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
  127. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
  128. package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
  129. package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
  130. package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
  131. package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
  132. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +174 -12
  133. package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
  134. package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
  135. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
  136. package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
  137. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +5 -0
  138. package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
  139. package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
  140. package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
  141. package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
  142. package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
  143. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
  144. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
  145. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
  146. package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
  147. package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
  148. package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
  149. package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
  150. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
  151. package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
  152. package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
  153. package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
  154. package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
  155. package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
  156. package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
  157. package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
  158. package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
  159. package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
  160. package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
  161. package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
  162. package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
  163. package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
  164. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
  165. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
  166. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
  167. package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
  168. package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
  169. package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
  170. package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
  171. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
  172. package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
  173. package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
  174. package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
  175. package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
  176. package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
  177. package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
  178. package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
  179. package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
  180. package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
  181. package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
  182. package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
  183. package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
  184. package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
  185. package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
  186. package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
  187. package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
  188. package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
  189. package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
  190. package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
  191. package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
  192. package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
  193. package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
  194. package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
  195. package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
  196. package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
  197. package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
  198. package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
  199. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
  200. package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
  201. package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
  202. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
  203. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
  204. package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
  205. package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
  206. package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
  207. package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
  208. package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
  209. package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
  210. package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +298 -9
  211. package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +453 -0
  212. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
  213. package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
  214. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
  215. package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
  216. package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
  217. package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
  218. package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
  219. package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
  220. package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
  221. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
  222. package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
  223. package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
  224. package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
  225. package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
  226. package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
  227. package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
  228. package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
  229. package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
  230. package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
  231. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
  232. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +28 -9
  233. package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
  234. package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
  235. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  236. package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
  237. package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
  238. package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
  239. package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
  240. package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
  241. package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
  242. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
  243. package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
  244. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
  245. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
  246. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
  247. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
  248. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
  249. package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
  250. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  251. package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
  252. package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
  253. package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
  254. package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
  255. package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
  256. package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
  257. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
  258. package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
  259. package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
  260. package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
  261. package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
  262. package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
  263. package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
  264. package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
  265. package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
  266. package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
  267. package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
  268. package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
  269. package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
  270. package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
  271. package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
  272. package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
  273. package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
  274. package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
  275. package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
  276. package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
  277. package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
  278. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
  279. package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
  280. package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
  281. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
  282. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
  283. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
  284. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
  285. package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
  286. package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
  287. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
  288. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
  289. package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
  290. package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
  291. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
  292. package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
  293. package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
  294. package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
  295. package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
  296. package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
  297. package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
  298. package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
  299. package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
  300. package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
  301. package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
  302. package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
  303. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
  304. package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +266 -25
  305. package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
  306. package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
  307. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
  308. package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
  309. package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
  310. package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
  311. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
  312. package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +2 -0
  313. package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +297 -15
  314. package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +10 -6
  315. package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
  316. package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
  317. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
  318. package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
  319. package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
  320. package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
  321. package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
  322. package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
  323. package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
  324. package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
  325. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
  326. package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
  327. package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
  328. package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
  329. package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
  330. package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
  331. package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
  332. package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
  333. package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
  334. package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
  335. package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
  336. package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
  337. package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
  338. package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
  339. package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
  340. package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
  341. package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
  342. package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
  343. package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
  344. package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +5 -3
  345. package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
  346. package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
  347. package/Tests/Types/XML.test.ts +51 -0
  348. package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
  349. package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
  350. package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
  351. package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
  352. package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
  353. package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
  354. package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
  355. package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
  356. package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
  357. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
  358. package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
  359. package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
  360. package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
  361. package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
  362. package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
  363. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
  364. package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
  365. package/Tests/UI/Components/Icon.test.tsx +32 -0
  366. package/Tests/UI/Components/Input.test.tsx +31 -0
  367. package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
  368. package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
  369. package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
  370. package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
  371. package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
  372. package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
  373. package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
  374. package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
  375. package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
  376. package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
  377. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  378. package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
  379. package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
  380. package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
  381. package/Tests/UI/Components/TextArea.test.tsx +19 -0
  382. package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
  383. package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
  384. package/Tests/UI/EsbuildConfig.test.ts +115 -39
  385. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
  386. package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
  387. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
  388. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
  389. package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
  390. package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
  391. package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
  392. package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
  393. package/Types/AI/AIAgentRunLimits.ts +146 -0
  394. package/Types/Code/CodeType.ts +2 -0
  395. package/Types/Code/JsonSyntax.ts +923 -0
  396. package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
  397. package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
  398. package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
  399. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
  400. package/Types/Icon/IconProp.ts +2 -0
  401. package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
  402. package/Types/Incident/IncidentFormPublic.ts +1145 -0
  403. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
  404. package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
  405. package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
  406. package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
  407. package/Types/MessageQueue/MessagingSystem.ts +518 -0
  408. package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
  409. package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
  410. package/Types/Permission.ts +310 -0
  411. package/Types/ResourceAiAgent/ResourceAiAccess.ts +10 -4
  412. package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
  413. package/Types/Rules/RuleRun.ts +4 -0
  414. package/Types/Team/ComplianceNotificationChannel.ts +4 -3
  415. package/Types/Team/ComplianceRule.ts +71 -18
  416. package/Types/Team/ComplianceRuleType.ts +2 -2
  417. package/Types/Team/TeamComplianceStatus.ts +6 -2
  418. package/Types/Telemetry/EntityType.ts +16 -0
  419. package/Types/Telemetry/LockedFilterDetail.ts +22 -0
  420. package/Types/XML.ts +26 -0
  421. package/UI/Components/CodeEditor/CodeEditor.css +379 -0
  422. package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
  423. package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
  424. package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
  425. package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
  426. package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
  427. package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
  428. package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
  429. package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
  430. package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
  431. package/UI/Components/Forms/Fields/FormField.tsx +8 -0
  432. package/UI/Components/Forms/Types/Field.ts +8 -0
  433. package/UI/Components/Icon/Icon.tsx +18 -0
  434. package/UI/Components/Input/Input.tsx +11 -4
  435. package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
  436. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
  437. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  438. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
  439. package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
  440. package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
  441. package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
  442. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
  443. package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
  444. package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
  445. package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
  446. package/UI/Components/Table/EmptyTableMessage.ts +81 -0
  447. package/UI/Components/Table/Table.tsx +50 -21
  448. package/UI/Components/Table/TableRow.tsx +9 -1
  449. package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
  450. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
  451. package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
  452. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
  453. package/UI/Components/TextArea/TextArea.tsx +9 -2
  454. package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
  455. package/UI/Styles/Theme.css +8 -0
  456. package/UI/esbuild-config.js +2 -32
  457. package/Utils/LabelRuleImportExport.ts +2 -0
  458. package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
  459. package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
  460. package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
  461. package/Utils/Telemetry/EntityKey.ts +48 -0
  462. package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
  463. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
  464. package/build/dist/Models/DatabaseModels/CephCluster.js +12 -0
  465. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  466. package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
  467. package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
  468. package/build/dist/Models/DatabaseModels/DatabaseServer.js +12 -0
  469. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
  470. package/build/dist/Models/DatabaseModels/DockerHost.js +12 -0
  471. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  472. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +12 -0
  473. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  474. package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
  475. package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
  476. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
  477. package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
  478. package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
  479. package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
  480. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
  481. package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
  482. package/build/dist/Models/DatabaseModels/Host.js +12 -0
  483. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  484. package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
  485. package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
  486. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
  487. package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
  488. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
  489. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  490. package/build/dist/Models/DatabaseModels/Index.js +14 -0
  491. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  492. package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
  493. package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
  494. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
  495. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  496. package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
  497. package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
  498. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
  499. package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
  500. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
  501. package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
  502. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
  503. package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
  504. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
  505. package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
  506. package/build/dist/Models/DatabaseModels/PodmanHost.js +12 -0
  507. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  508. package/build/dist/Models/DatabaseModels/Project.js +61 -0
  509. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  510. package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
  511. package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
  512. package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
  513. package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
  514. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +12 -0
  515. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  516. package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
  517. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  518. package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
  519. package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
  520. package/build/dist/Models/DatabaseModels/Service.js +12 -0
  521. package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
  522. package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
  523. package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
  524. package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
  525. package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
  526. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
  527. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
  528. package/build/dist/Models/DatabaseModels/VMwareVCenter.js +12 -0
  529. package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
  530. package/build/dist/Server/API/AIChatAPI.js +9 -103
  531. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  532. package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
  533. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  534. package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
  535. package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
  536. package/build/dist/Server/API/IncidentFormAPI.js +245 -0
  537. package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
  538. package/build/dist/Server/API/ProjectOIDC.js +16 -24
  539. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  540. package/build/dist/Server/API/ProjectSSO.js +16 -24
  541. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  542. package/build/dist/Server/API/StatusPageAPI.js +42 -75
  543. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  544. package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
  545. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
  546. package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
  547. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
  548. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
  549. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
  550. package/build/dist/Server/EnvironmentConfig.js +1 -1
  551. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
  552. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
  553. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
  554. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
  555. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
  556. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
  557. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
  558. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
  559. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  560. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  561. package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
  562. package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
  563. package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
  564. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  565. package/build/dist/Server/Services/AIService.js +10 -13
  566. package/build/dist/Server/Services/AIService.js.map +1 -1
  567. package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
  568. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  569. package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
  570. package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
  571. package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
  572. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  573. package/build/dist/Server/Services/IncidentFormService.js +1202 -0
  574. package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
  575. package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
  576. package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
  577. package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
  578. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  579. package/build/dist/Server/Services/IncidentService.js +106 -4
  580. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  581. package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
  582. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  583. package/build/dist/Server/Services/Index.js +14 -0
  584. package/build/dist/Server/Services/Index.js.map +1 -1
  585. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
  586. package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
  587. package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
  588. package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
  589. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
  590. package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
  591. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
  592. package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
  593. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
  594. package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
  595. package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
  596. package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
  597. package/build/dist/Server/Services/MessageQueueService.js +1140 -0
  598. package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
  599. package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
  600. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  601. package/build/dist/Server/Services/ProjectService.js +0 -54
  602. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  603. package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
  604. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  605. package/build/dist/Server/Services/StatusPageService.js +0 -46
  606. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  607. package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
  608. package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
  609. package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
  610. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  611. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
  612. package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
  613. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
  614. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  615. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
  616. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  617. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
  618. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  619. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
  620. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
  621. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  622. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
  623. package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
  624. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
  625. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  626. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
  627. package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
  628. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
  629. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  630. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  631. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
  632. package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
  633. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
  634. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
  635. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
  636. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
  637. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
  638. package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
  639. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
  640. package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
  641. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +7 -2
  642. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  643. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +29 -14
  644. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  645. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +38 -14
  646. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -1
  647. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +2 -0
  648. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -1
  649. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +40 -10
  650. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  651. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +19 -7
  652. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  653. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +19 -7
  654. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  655. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
  656. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  657. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
  658. package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
  659. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
  660. package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
  661. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
  662. package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
  663. package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
  664. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
  665. package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
  666. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  667. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
  668. package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
  669. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
  670. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  671. package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
  672. package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
  673. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
  674. package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
  675. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
  676. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  677. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
  678. package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
  679. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
  680. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
  681. package/build/dist/Server/Utils/VendorAssets.js +3 -3
  682. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +3 -1
  683. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  684. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +3 -1
  685. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  686. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +10 -1
  687. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  688. package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
  689. package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
  690. package/build/dist/Types/Code/CodeType.js +2 -0
  691. package/build/dist/Types/Code/CodeType.js.map +1 -1
  692. package/build/dist/Types/Code/JsonSyntax.js +604 -0
  693. package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
  694. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
  695. package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
  696. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
  697. package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
  698. package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
  699. package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
  700. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
  701. package/build/dist/Types/Icon/IconProp.js +2 -0
  702. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  703. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
  704. package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
  705. package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
  706. package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
  707. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
  708. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
  709. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
  710. package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
  711. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
  712. package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
  713. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
  714. package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
  715. package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
  716. package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
  717. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
  718. package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
  719. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
  720. package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
  721. package/build/dist/Types/Permission.js +274 -0
  722. package/build/dist/Types/Permission.js.map +1 -1
  723. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +10 -4
  724. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -1
  725. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
  726. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  727. package/build/dist/Types/Rules/RuleRun.js +4 -0
  728. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  729. package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
  730. package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
  731. package/build/dist/Types/Team/ComplianceRule.js +48 -14
  732. package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
  733. package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
  734. package/build/dist/Types/Telemetry/EntityType.js +16 -0
  735. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  736. package/build/dist/Types/XML.js +23 -0
  737. package/build/dist/Types/XML.js.map +1 -1
  738. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
  739. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  740. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
  741. package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
  742. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
  743. package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
  744. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
  745. package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
  746. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
  747. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -1
  748. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
  749. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
  750. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +5 -14
  751. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
  752. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
  753. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  754. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
  755. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  756. package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
  757. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  758. package/build/dist/UI/Components/Icon/Icon.js +8 -0
  759. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  760. package/build/dist/UI/Components/Input/Input.js +11 -3
  761. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  762. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
  763. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  764. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
  765. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  766. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  767. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  768. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
  769. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
  770. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
  771. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
  772. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
  773. package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
  774. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
  775. package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
  776. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
  777. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  778. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
  779. package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
  780. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
  781. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  782. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
  783. package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
  784. package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
  785. package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
  786. package/build/dist/UI/Components/Table/Table.js +30 -11
  787. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  788. package/build/dist/UI/Components/Table/TableRow.js +9 -2
  789. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  790. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
  791. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
  792. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
  793. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  794. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
  795. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
  796. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
  797. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  798. package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
  799. package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
  800. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
  801. package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
  802. package/build/dist/Utils/LabelRuleImportExport.js +2 -0
  803. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  804. package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
  805. package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
  806. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
  807. package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
  808. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
  809. package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
  810. package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
  811. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  812. package/package.json +1 -3
  813. package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
  814. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
  815. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
  816. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
  817. package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
  818. package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
  819. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
  820. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
  821. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
  822. package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
  823. package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
  824. package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
  825. package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
  826. package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
  827. package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
  828. package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
  829. package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
  830. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
  831. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
  832. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
  833. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
  834. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
  835. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
  836. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
  837. package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
@@ -0,0 +1,1758 @@
1
+ import {
2
+ MESSAGE_QUEUE_METRIC_ADDRESS_ATTRIBUTES,
3
+ MESSAGE_QUEUE_METRIC_EXCLUDED_SERIES_ATTRIBUTES,
4
+ MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES,
5
+ MESSAGING_RESOLVER_INPUT_ATTRIBUTES,
6
+ ResolvedMessagingDestination,
7
+ resolveMessagingMetricDatapoint,
8
+ resolveMessagingSpan,
9
+ } from "../../../Types/MessageQueue/MessagingTelemetryResolver";
10
+ import {
11
+ MESSAGE_QUEUE_METRICS,
12
+ MessageQueueMetricDescriptor,
13
+ MESSAGING_CLIENT_METRIC_NAMES,
14
+ MESSAGING_SDK_METRIC_SYSTEMS,
15
+ } from "../../../Types/MessageQueue/MessageQueueMetricCatalog";
16
+ import {
17
+ destinationOf,
18
+ FixtureAttributes,
19
+ METRIC_FIXTURES,
20
+ MetricFixture,
21
+ toStoredColumns,
22
+ } from "./MessagingTelemetryFixtures";
23
+ import { describe, expect, test } from "@jest/globals";
24
+
25
+ function resolveDatapoint(
26
+ metricName: string,
27
+ attributes: FixtureAttributes,
28
+ ): ResolvedMessagingDestination | null {
29
+ return resolveMessagingMetricDatapoint({
30
+ metricName,
31
+ getAttribute: (key: string): unknown => {
32
+ return attributes[key];
33
+ },
34
+ });
35
+ }
36
+
37
+ function resolveRecordingReads(
38
+ metricName: string,
39
+ attributes: FixtureAttributes,
40
+ reads: Set<string>,
41
+ ): ResolvedMessagingDestination | null {
42
+ return resolveMessagingMetricDatapoint({
43
+ metricName,
44
+ getAttribute: (key: string): unknown => {
45
+ reads.add(key);
46
+ return attributes[key];
47
+ },
48
+ });
49
+ }
50
+
51
+ const SERVICE_BUS: FixtureAttributes = {
52
+ "azuremonitor.resource_id":
53
+ "/subscriptions/s/resourceGroups/rg/providers/Microsoft.ServiceBus/namespaces/orders-prod",
54
+ name: "orders-prod",
55
+ type: "Microsoft.ServiceBus/namespaces",
56
+ metadata_entityname: "orders",
57
+ };
58
+
59
+ const SQS_JSON: FixtureAttributes = {
60
+ "resource.cloud.provider": "aws",
61
+ "resource.cloud.region": "us-east-1",
62
+ "resource.service.namespace": "AWS",
63
+ "resource.service.name": "SQS",
64
+ QueueName: "orders",
65
+ };
66
+
67
+ describe("resolveMessagingMetricDatapoint — every curated metric, from a realistic stored datapoint", () => {
68
+ test("the corpus names are unique", () => {
69
+ expect(
70
+ new Set(
71
+ METRIC_FIXTURES.map((fixture: MetricFixture): string => {
72
+ return `${fixture.metricName} — ${fixture.name}`;
73
+ }),
74
+ ).size,
75
+ ).toBe(METRIC_FIXTURES.length);
76
+ });
77
+
78
+ test.each(
79
+ METRIC_FIXTURES.map((fixture: MetricFixture): [string, MetricFixture] => {
80
+ return [`${fixture.metricName} — ${fixture.name}`, fixture];
81
+ }),
82
+ )("%s", (_name: string, fixture: MetricFixture) => {
83
+ expect(resolveDatapoint(fixture.metricName, fixture.attributes)).toEqual(
84
+ fixture.expected,
85
+ );
86
+ });
87
+
88
+ test.each(
89
+ METRIC_FIXTURES.map((fixture: MetricFixture): [string, MetricFixture] => {
90
+ return [`${fixture.metricName} — ${fixture.name}`, fixture];
91
+ }),
92
+ )(
93
+ "%s — resolves identically read back from ClickHouse",
94
+ (_name: string, fixture: MetricFixture) => {
95
+ const row: Record<string, string> = toStoredColumns(
96
+ fixture.attributes,
97
+ MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES,
98
+ );
99
+ expect(
100
+ resolveMessagingMetricDatapoint({
101
+ metricName: fixture.metricName,
102
+ getAttribute: (key: string): unknown => {
103
+ return row[key];
104
+ },
105
+ }),
106
+ ).toEqual(resolveDatapoint(fixture.metricName, fixture.attributes));
107
+ },
108
+ );
109
+
110
+ test("a curated metric's direction follows its signal", () => {
111
+ for (const fixture of METRIC_FIXTURES) {
112
+ const descriptor: MessageQueueMetricDescriptor | undefined =
113
+ MESSAGE_QUEUE_METRICS.find(
114
+ (candidate: MessageQueueMetricDescriptor): boolean => {
115
+ return (
116
+ candidate.metricName === fixture.metricName &&
117
+ candidate.system === fixture.expected?.system
118
+ );
119
+ },
120
+ );
121
+ if (!descriptor || !fixture.expected) {
122
+ continue;
123
+ }
124
+ const expected: string =
125
+ descriptor.signal === "published"
126
+ ? "publish"
127
+ : descriptor.signal === "consumed"
128
+ ? "consume"
129
+ : "unknown";
130
+ expect({
131
+ fixture: fixture.name,
132
+ direction: fixture.expected.direction,
133
+ }).toEqual({ fixture: fixture.name, direction: expected });
134
+ }
135
+ });
136
+
137
+ test("the metric name is trimmed and lowercased first", () => {
138
+ expect(
139
+ resolveDatapoint(" Azure_ActiveMessages_Average ", SERVICE_BUS),
140
+ ).toEqual(resolveDatapoint("azure_activemessages_average", SERVICE_BUS));
141
+ expect(
142
+ resolveDatapoint(" Azure_ActiveMessages_Average ", SERVICE_BUS),
143
+ ).not.toBeNull();
144
+ });
145
+ });
146
+
147
+ describe("Azure Monitor datapoints", () => {
148
+ test.each([
149
+ ["Microsoft.ServiceBus/namespaces"],
150
+ ["Microsoft.ServiceBus/Namespaces"],
151
+ ["microsoft.servicebus/namespaces"],
152
+ ["MICROSOFT.SERVICEBUS/NAMESPACES"],
153
+ [" Microsoft.ServiceBus/namespaces "],
154
+ ])("the resource type %j is compared case-insensitively", (type: string) => {
155
+ expect(
156
+ resolveDatapoint("azure_activemessages_average", {
157
+ ...SERVICE_BUS,
158
+ type,
159
+ }),
160
+ ).toEqual(
161
+ destinationOf({
162
+ system: "servicebus",
163
+ destination: "orders",
164
+ brokerScope: "orders-prod",
165
+ }),
166
+ );
167
+ });
168
+
169
+ test("the documented PascalCase dimension key is read too", () => {
170
+ const attributes: FixtureAttributes = { ...SERVICE_BUS };
171
+ delete attributes["metadata_entityname"];
172
+ attributes["metadata_EntityName"] = "orders";
173
+ expect(
174
+ resolveDatapoint("azure_activemessages_average", attributes)?.destination,
175
+ ).toBe("orders");
176
+ });
177
+
178
+ test("the lowercase key wins when both spellings are present", () => {
179
+ expect(
180
+ resolveDatapoint("azure_activemessages_average", {
181
+ ...SERVICE_BUS,
182
+ metadata_entityname: "orders",
183
+ metadata_EntityName: "other",
184
+ })?.destination,
185
+ ).toBe("orders");
186
+ });
187
+
188
+ test("an entity name keeps its casing; the namespace scope is lowercased", () => {
189
+ expect(
190
+ resolveDatapoint("azure_activemessages_average", {
191
+ ...SERVICE_BUS,
192
+ name: "Orders-Prod",
193
+ metadata_entityname: "Orders",
194
+ }),
195
+ ).toEqual(
196
+ destinationOf({
197
+ system: "servicebus",
198
+ destination: "Orders",
199
+ brokerScope: "orders-prod",
200
+ }),
201
+ );
202
+ });
203
+
204
+ test("a namespace host in `name` is reduced to the namespace; anything else is no scope", () => {
205
+ expect(
206
+ resolveDatapoint("azure_activemessages_average", {
207
+ ...SERVICE_BUS,
208
+ name: "orders-prod.servicebus.windows.net",
209
+ })?.brokerScope,
210
+ ).toBe("orders-prod");
211
+ expect(
212
+ resolveDatapoint("azure_activemessages_average", {
213
+ ...SERVICE_BUS,
214
+ name: "not a namespace",
215
+ })?.brokerScope,
216
+ ).toBe("");
217
+ const unnamed: FixtureAttributes = { ...SERVICE_BUS };
218
+ delete unnamed["name"];
219
+ expect(
220
+ resolveDatapoint("azure_activemessages_average", unnamed)?.brokerScope,
221
+ ).toBe("");
222
+ });
223
+
224
+ test("the same name resolves to Service Bus or Event Hubs by the resource type", () => {
225
+ expect(
226
+ resolveDatapoint("azure_incomingmessages_total", SERVICE_BUS)?.system,
227
+ ).toBe("servicebus");
228
+ expect(
229
+ resolveDatapoint("azure_incomingmessages_total", {
230
+ ...SERVICE_BUS,
231
+ type: "Microsoft.EventHub/Namespaces",
232
+ })?.system,
233
+ ).toBe("eventhubs");
234
+ });
235
+
236
+ test("a metric only Service Bus has does not resolve for an Event Hubs namespace", () => {
237
+ expect(
238
+ resolveDatapoint("azure_activemessages_average", {
239
+ ...SERVICE_BUS,
240
+ type: "Microsoft.EventHub/namespaces",
241
+ }),
242
+ ).toBeNull();
243
+ });
244
+
245
+ test.each([
246
+ [{ type: "Microsoft.Storage/storageAccounts/queueServices" }],
247
+ [{ type: "Microsoft.EventGrid/topics" }],
248
+ [{ type: "" }],
249
+ [{ type: undefined }],
250
+ [{ type: "Microsoft.ServiceBus" }],
251
+ ])(
252
+ "a datapoint whose resource type does not match (%j) is rejected",
253
+ (override: FixtureAttributes) => {
254
+ expect(
255
+ resolveDatapoint("azure_incomingmessages_total", {
256
+ ...SERVICE_BUS,
257
+ ...override,
258
+ }),
259
+ ).toBeNull();
260
+ },
261
+ );
262
+
263
+ test("a namespace-level value or a missing entity is no queue", () => {
264
+ expect(
265
+ resolveDatapoint("azure_incomingmessages_total", {
266
+ ...SERVICE_BUS,
267
+ metadata_entityname: "-NamespaceOnlyMetric-",
268
+ }),
269
+ ).toBeNull();
270
+ const withoutEntity: FixtureAttributes = { ...SERVICE_BUS };
271
+ delete withoutEntity["metadata_entityname"];
272
+ expect(
273
+ resolveDatapoint("azure_incomingmessages_total", withoutEntity),
274
+ ).toBeNull();
275
+ });
276
+ });
277
+
278
+ describe("CloudWatch datapoints", () => {
279
+ test("the JSON shape needs the SQS service on the resource", () => {
280
+ expect(
281
+ resolveDatapoint("approximatenumberofmessagesvisible", SQS_JSON),
282
+ ).toEqual(destinationOf({ system: "aws_sqs", destination: "orders" }));
283
+ for (const service of ["Sqs", "sqs", " SQS "]) {
284
+ expect(
285
+ resolveDatapoint("approximatenumberofmessagesvisible", {
286
+ ...SQS_JSON,
287
+ "resource.service.name": service,
288
+ })?.system,
289
+ ).toBe("aws_sqs");
290
+ }
291
+ const withoutService: FixtureAttributes = { ...SQS_JSON };
292
+ delete withoutService["resource.service.name"];
293
+ expect(
294
+ resolveDatapoint("approximatenumberofmessagesvisible", withoutService),
295
+ ).toBeNull();
296
+ // Another namespace's metric of the same bare name.
297
+ expect(
298
+ resolveDatapoint("approximatenumberofmessagesvisible", {
299
+ ...SQS_JSON,
300
+ "resource.service.name": "SNS",
301
+ }),
302
+ ).toBeNull();
303
+ // A datapoint key is not the resource key.
304
+ const datapointService: FixtureAttributes = { ...withoutService };
305
+ datapointService["service.name"] = "SQS";
306
+ expect(
307
+ resolveDatapoint("approximatenumberofmessagesvisible", datapointService),
308
+ ).toBeNull();
309
+ });
310
+
311
+ test("the namespaced shape reads the flattened Dimensions kvlist key only", () => {
312
+ expect(
313
+ resolveDatapoint(
314
+ "amazonaws.com/aws/sqs/approximatenumberofmessagesvisible",
315
+ { "Dimensions.QueueName": "orders" },
316
+ )?.destination,
317
+ ).toBe("orders");
318
+ expect(
319
+ resolveDatapoint(
320
+ "amazonaws.com/aws/sqs/approximatenumberofmessagesvisible",
321
+ { QueueName: "orders" },
322
+ ),
323
+ ).toBeNull();
324
+ // Stored keys keep their case: the dimension key is case-sensitive.
325
+ expect(
326
+ resolveDatapoint(
327
+ "amazonaws.com/aws/sqs/approximatenumberofmessagesvisible",
328
+ { "dimensions.queuename": "orders" },
329
+ ),
330
+ ).toBeNull();
331
+ });
332
+
333
+ test("an SNS datapoint without a TopicName (push, SMS, account-wide) is no queue", () => {
334
+ expect(
335
+ resolveDatapoint("amazonaws.com/aws/sns/numberofmessagespublished", {
336
+ "Dimensions.Application": "my-app",
337
+ "Dimensions.Platform": "APNS",
338
+ }),
339
+ ).toBeNull();
340
+ expect(
341
+ resolveDatapoint("numberofmessagespublished", {
342
+ "resource.service.name": "SNS",
343
+ PhoneNumber: "+15555550100",
344
+ }),
345
+ ).toBeNull();
346
+ });
347
+
348
+ test("an SQS queue named like a URL or an ARN is reduced to its name", () => {
349
+ expect(
350
+ resolveDatapoint("amazonaws.com/aws/sqs/numberofmessagessent", {
351
+ "Dimensions.QueueName":
352
+ "https://sqs.us-east-1.amazonaws.com/123456789012/orders",
353
+ })?.destination,
354
+ ).toBe("orders");
355
+ });
356
+ });
357
+
358
+ describe("the other broker sources", () => {
359
+ test("RabbitMQ queue names are taken exactly: no exchange:routing-key parsing", () => {
360
+ expect(
361
+ resolveDatapoint("rabbitmq.message.current", {
362
+ "resource.rabbitmq.queue.name": "tenant:orders",
363
+ state: "ready",
364
+ })?.destination,
365
+ ).toBe("tenant:orders");
366
+ expect(
367
+ resolveDatapoint("rabbitmq.message.current", {
368
+ "resource.rabbitmq.queue.name": "amq.default",
369
+ })?.destination,
370
+ ).toBe("amq.default");
371
+ });
372
+
373
+ test("RabbitMQ's generated and reply-to queues are no queues", () => {
374
+ for (const name of [
375
+ "amq.gen-JzTY20BRgKO-HjmUJj0wLg",
376
+ "amq.rabbitmq.reply-to",
377
+ "orders.anonymous.X8o1yfRBQXSp5Bdd09ls7w",
378
+ "5f2b7c1e-8d3a-4b6f-9c0d-1e2f3a4b5c6d",
379
+ ]) {
380
+ expect(
381
+ resolveDatapoint("rabbitmq.message.current", {
382
+ "resource.rabbitmq.queue.name": name,
383
+ }),
384
+ ).toBeNull();
385
+ }
386
+ });
387
+
388
+ /*
389
+ * Each broker's metrics list every queue it has, MassTransit's per-process
390
+ * endpoints among them: the bus endpoint of every process that uses a
391
+ * request client (`{machine}_{process}_bus_{NewId}`), temporary endpoints,
392
+ * a service's `Instance_{NewId}`. One datapoint of a curated broker metric
393
+ * creates a queue, so each process start would add one.
394
+ */
395
+ test("MassTransit's per-process endpoints are no queues on any broker's metrics; its named endpoints are", () => {
396
+ const podA: string =
397
+ "ordersapi7d9f8c6b5xk2lq_OrdersApi_bus_kd4oyqbeynuojexybdxt7414fx";
398
+ const podB: string =
399
+ "ordersapi7d9f8c6b5mnp4r_OrdersApi_bus_kawyb4raybmxtdeybdxt7hihry";
400
+ const instance: string = "Instance_axhob3yrynqhyacybdxt6jeg8m";
401
+ const brokerSeries: Array<[string, (name: string) => FixtureAttributes]> = [
402
+ [
403
+ "rabbitmq.message.current",
404
+ (name: string): FixtureAttributes => {
405
+ return {
406
+ "resource.rabbitmq.queue.name": name,
407
+ "resource.rabbitmq.vhost.name": "/",
408
+ "resource.rabbitmq.node.name": "rabbit@rabbitmq-0",
409
+ state: "ready",
410
+ };
411
+ },
412
+ ],
413
+ [
414
+ "rabbitmq.consumer.count",
415
+ (name: string): FixtureAttributes => {
416
+ return { "resource.rabbitmq.queue.name": name };
417
+ },
418
+ ],
419
+ [
420
+ "azure_activemessages_average",
421
+ (name: string): FixtureAttributes => {
422
+ return { ...SERVICE_BUS, metadata_entityname: name };
423
+ },
424
+ ],
425
+ [
426
+ "approximatenumberofmessagesvisible",
427
+ (name: string): FixtureAttributes => {
428
+ return { ...SQS_JSON, QueueName: name };
429
+ },
430
+ ],
431
+ [
432
+ "amazonaws.com/aws/sqs/approximatenumberofmessagesvisible",
433
+ (name: string): FixtureAttributes => {
434
+ return { "Dimensions.QueueName": name };
435
+ },
436
+ ],
437
+ [
438
+ "activemq.message.queue.size",
439
+ (name: string): FixtureAttributes => {
440
+ return {
441
+ "activemq.broker.name": "localhost",
442
+ "activemq.destination.type": "queue",
443
+ "messaging.destination.name": name,
444
+ };
445
+ },
446
+ ],
447
+ ];
448
+ for (const [metricName, attributesOf] of brokerSeries) {
449
+ for (const name of [podA, podB, instance]) {
450
+ expect({
451
+ metricName,
452
+ name,
453
+ resolved: resolveDatapoint(metricName, attributesOf(name)),
454
+ }).toEqual({ metricName, name, resolved: null });
455
+ }
456
+ expect({
457
+ metricName,
458
+ destination:
459
+ resolveDatapoint(metricName, attributesOf("submit-order"))
460
+ ?.destination ?? null,
461
+ }).toEqual({ metricName, destination: "submit-order" });
462
+ }
463
+ });
464
+
465
+ test("the RabbitMQ queue must be the resource attribute, not a datapoint one", () => {
466
+ expect(
467
+ resolveDatapoint("rabbitmq.message.current", {
468
+ "rabbitmq.queue.name": "orders",
469
+ }),
470
+ ).toBeNull();
471
+ });
472
+
473
+ test("a Kafka topic named per tenant is templated", () => {
474
+ expect(
475
+ resolveDatapoint("kafka.consumer_group.lag_sum", {
476
+ group: "billing",
477
+ topic: "events-5f2b7c1e-8d3a-4b6f-9c0d-1e2f3a4b5c6d",
478
+ })?.destination,
479
+ ).toBe("events-{uuid}");
480
+ });
481
+
482
+ test("the ActiveMQ scraper's current key wins over the legacy one", () => {
483
+ expect(
484
+ resolveDatapoint("activemq.message.enqueued", {
485
+ "messaging.destination.name": "current",
486
+ destination: "legacy",
487
+ })?.destination,
488
+ ).toBe("current");
489
+ });
490
+
491
+ test("a metric whose name spelling belongs to one scraper generation reads only its key", () => {
492
+ expect(
493
+ resolveDatapoint("activemq.message.queue.size", {
494
+ destination: "orders",
495
+ }),
496
+ ).toBeNull();
497
+ expect(
498
+ resolveDatapoint("activemq.message.current", {
499
+ "messaging.destination.name": "orders",
500
+ }),
501
+ ).toBeNull();
502
+ });
503
+
504
+ test("a Pub/Sub subscription metric reads the subscription, a topic metric the topic", () => {
505
+ const both: FixtureAttributes = {
506
+ "resource.subscription_id": "billing-sub",
507
+ "resource.topic_id": "orders",
508
+ };
509
+ expect(
510
+ resolveDatapoint(
511
+ "pubsub.googleapis.com/subscription/num_undelivered_messages",
512
+ both,
513
+ )?.destination,
514
+ ).toBe("billing-sub");
515
+ expect(
516
+ resolveDatapoint("pubsub.googleapis.com/topic/send_request_count", both)
517
+ ?.destination,
518
+ ).toBe("orders");
519
+ expect(
520
+ resolveDatapoint(
521
+ "pubsub.googleapis.com/subscription/num_undelivered_messages",
522
+ { "resource.topic_id": "orders" },
523
+ ),
524
+ ).toBeNull();
525
+ // The bare monitored-resource label is a resource attribute once stored.
526
+ expect(
527
+ resolveDatapoint(
528
+ "pubsub.googleapis.com/subscription/num_undelivered_messages",
529
+ { subscription_id: "billing-sub" },
530
+ ),
531
+ ).toBeNull();
532
+ });
533
+
534
+ test("Pulsar partitions fold into one topic; short names expand", () => {
535
+ for (const topic of [
536
+ "persistent://public/default/payments",
537
+ "persistent://public/default/payments-partition-0",
538
+ "persistent://public/default/payments-partition-17",
539
+ "payments",
540
+ "payments-partition-3",
541
+ ]) {
542
+ expect(
543
+ resolveDatapoint("pulsar_msg_backlog", { topic })?.destination,
544
+ ).toBe("persistent://public/default/payments");
545
+ }
546
+ });
547
+
548
+ test("Pulsar's per-consumer copy of pulsar_out_messages_total belongs to no queue, so the topic's rate is not counted twice", () => {
549
+ const subscriptionSeries: FixtureAttributes = {
550
+ cluster: "standalone",
551
+ namespace: "public/default",
552
+ topic: "persistent://public/default/orders",
553
+ subscription: "billing",
554
+ };
555
+ expect(
556
+ resolveDatapoint("pulsar_out_messages_total", subscriptionSeries),
557
+ ).toEqual(
558
+ destinationOf({
559
+ system: "pulsar",
560
+ destination: "persistent://public/default/orders",
561
+ direction: "consume",
562
+ }),
563
+ );
564
+ // exposeConsumerLevelMetricsInPrometheus=true repeats it per consumer.
565
+ for (const marker of [
566
+ { consumer_name: "billing-worker-7", consumer_id: "3" },
567
+ { consumer_name: "billing-worker-7" },
568
+ { consumer_id: "0" },
569
+ ]) {
570
+ expect(
571
+ resolveDatapoint("pulsar_out_messages_total", {
572
+ ...subscriptionSeries,
573
+ ...marker,
574
+ }),
575
+ ).toBeNull();
576
+ }
577
+ // A blank marker is no marker.
578
+ expect(
579
+ resolveDatapoint("pulsar_out_messages_total", {
580
+ ...subscriptionSeries,
581
+ consumer_name: " ",
582
+ }),
583
+ ).not.toBeNull();
584
+ // Only the metric that declares the markers drops them.
585
+ expect(
586
+ resolveDatapoint("pulsar_msg_backlog", {
587
+ ...subscriptionSeries,
588
+ consumer_name: "billing-worker-7",
589
+ })?.destination,
590
+ ).toBe("persistent://public/default/orders");
591
+ });
592
+
593
+ test("the reporting broker's scrape target is the display address", () => {
594
+ expect(
595
+ resolveDatapoint("pulsar_msg_backlog", {
596
+ topic: "orders",
597
+ "resource.server.address": "pulsar-broker-1",
598
+ "resource.server.port": "8080",
599
+ })?.brokerAddress,
600
+ ).toBe("pulsar-broker-1:8080");
601
+ expect(
602
+ resolveDatapoint("pulsar_msg_backlog", { topic: "orders" })
603
+ ?.brokerAddress,
604
+ ).toBeNull();
605
+ // A datapoint server.address (the scraped app's own label) is not read.
606
+ expect(
607
+ resolveDatapoint("pulsar_msg_backlog", {
608
+ topic: "orders",
609
+ "server.address": "somewhere-else",
610
+ })?.brokerAddress,
611
+ ).toBeNull();
612
+ });
613
+
614
+ test("RocketMQ dead-letter topics are flagged", () => {
615
+ expect(
616
+ resolveDatapoint("rocketmq_consumer_lag_messages", {
617
+ topic: "%DLQ%billing-group",
618
+ consumer_group: "billing-group",
619
+ }),
620
+ ).toEqual(
621
+ destinationOf({
622
+ system: "rocketmq",
623
+ destination: "%DLQ%billing-group",
624
+ isDeadLetter: true,
625
+ }),
626
+ );
627
+ });
628
+ });
629
+
630
+ describe("a curated name never falls through to the attribute path", () => {
631
+ test("even with messaging.system on the datapoint, a curated name that none of its entries resolves is null", () => {
632
+ expect(
633
+ resolveDatapoint("azure_incomingmessages_total", {
634
+ "messaging.system": "servicebus",
635
+ "messaging.destination.name": "orders",
636
+ type: "Microsoft.Storage/storageAccounts",
637
+ }),
638
+ ).toBeNull();
639
+ expect(
640
+ resolveDatapoint("rabbitmq.message.current", {
641
+ "messaging.system": "rabbitmq",
642
+ "messaging.destination.name": "orders",
643
+ }),
644
+ ).toBeNull();
645
+ });
646
+ });
647
+
648
+ describe("messaging-client metrics and application gauges (the attribute path)", () => {
649
+ test.each([
650
+ ["messaging.client.sent.messages", "publish"],
651
+ ["messaging.client.published.messages", "publish"],
652
+ ["messaging.publish.duration", "publish"],
653
+ ["messaging.publish.messages", "publish"],
654
+ ["messaging.client.consumed.messages", "consume"],
655
+ ["messaging.process.duration", "consume"],
656
+ ["messaging.receive.duration", "consume"],
657
+ ["messaging.receive.messages", "consume"],
658
+ ["messaging.process.messages", "consume"],
659
+ ["Messaging.Client.Sent.Messages", "publish"],
660
+ ["myapp_messages_sent_total", "publish"],
661
+ ["myapp/jobs/processed", "consume"],
662
+ ["queue.size", "unknown"],
663
+ ["messaging.client.operation.duration", "unknown"],
664
+ ])(
665
+ "%s → direction %s from its name",
666
+ (metricName: string, direction: string) => {
667
+ expect(
668
+ resolveDatapoint(metricName, {
669
+ "messaging.system": "kafka",
670
+ "messaging.destination.name": "orders",
671
+ })?.direction,
672
+ ).toBe(direction);
673
+ },
674
+ );
675
+
676
+ test("with no word in the name, the direction comes from the attributes", () => {
677
+ expect(
678
+ resolveDatapoint("messaging.client.operation.duration", {
679
+ "messaging.system": "kafka",
680
+ "messaging.destination.name": "orders",
681
+ "messaging.operation.type": "send",
682
+ })?.direction,
683
+ ).toBe("publish");
684
+ expect(
685
+ resolveDatapoint("messaging.client.operation.duration", {
686
+ "messaging.system": "servicebus",
687
+ "messaging.destination.name": "orders",
688
+ "messaging.operation.name": "complete",
689
+ })?.direction,
690
+ ).toBe("settle");
691
+ });
692
+
693
+ test("the name's direction wins over the attributes", () => {
694
+ expect(
695
+ resolveDatapoint("messaging.client.sent.messages", {
696
+ "messaging.system": "kafka",
697
+ "messaging.destination.name": "orders",
698
+ "messaging.operation.type": "receive",
699
+ })?.direction,
700
+ ).toBe("publish");
701
+ });
702
+
703
+ test("the name's words are whole words", () => {
704
+ expect(
705
+ resolveDatapoint("messaging.resend_attempts", {
706
+ "messaging.system": "kafka",
707
+ "messaging.destination.name": "orders",
708
+ })?.direction,
709
+ ).toBe("unknown");
710
+ });
711
+
712
+ test("no messaging trigger, no queue — whatever the name", () => {
713
+ expect(resolveDatapoint("messaging.client.sent.messages", {})).toBeNull();
714
+ expect(
715
+ resolveDatapoint("queue.size", {
716
+ state: "waiting",
717
+ "resource.messaging.system": "bullmq",
718
+ }),
719
+ ).toBeNull();
720
+ });
721
+
722
+ test("the destination template, the Azure namespace and the temporary rules apply as on spans", () => {
723
+ expect(
724
+ resolveDatapoint("messaging.client.sent.messages", {
725
+ "messaging.system": "nats",
726
+ "messaging.destination.template": "orders.{id}",
727
+ })?.destination,
728
+ ).toBe("orders.{id}");
729
+ expect(
730
+ resolveDatapoint("messaging.client.sent.messages", {
731
+ "messaging.system": "rabbitmq",
732
+ "messaging.destination.name": "amq.gen-JzTY20BRgKO-HjmUJj0wLg",
733
+ }),
734
+ ).toBeNull();
735
+ expect(
736
+ resolveDatapoint("messaging.client.sent.messages", {
737
+ "messaging.system": "eventhubs",
738
+ "messaging.destination.name": "telemetry",
739
+ "server.address": "ingest-prod.servicebus.windows.net",
740
+ })?.brokerScope,
741
+ ).toBe("ingest-prod");
742
+ });
743
+
744
+ test.each([
745
+ ["messaging.destination.temporary", true],
746
+ ["messaging.destination.temporary", "true"],
747
+ ["messaging.destination.anonymous", true],
748
+ ["messaging.destination.anonymous", "TRUE"],
749
+ ["messaging.source.temporary", "true"],
750
+ ["messaging.source.anonymous", true],
751
+ ])(
752
+ "a datapoint flagged %s = %j is no queue, as a span would not be",
753
+ (flag: string, value: unknown) => {
754
+ for (const metricName of [
755
+ "messaging.client.sent.messages",
756
+ "messaging.process.duration",
757
+ "queue.size",
758
+ ]) {
759
+ expect(
760
+ resolveDatapoint(metricName, {
761
+ "messaging.system": "rabbitmq",
762
+ "messaging.destination.name": "reply",
763
+ [flag]: value,
764
+ }),
765
+ ).toBeNull();
766
+ }
767
+ // The same datapoint without the flag is a queue.
768
+ expect(
769
+ resolveDatapoint("messaging.client.sent.messages", {
770
+ "messaging.system": "rabbitmq",
771
+ "messaging.destination.name": "reply",
772
+ [flag]: false,
773
+ })?.destination,
774
+ ).toBe("reply");
775
+ },
776
+ );
777
+
778
+ test("an excluded system is no queue", () => {
779
+ expect(
780
+ resolveDatapoint("messaging.client.sent.messages", {
781
+ "messaging.system": "spring_integration",
782
+ "messaging.destination.name": "inputChannel",
783
+ }),
784
+ ).toBeNull();
785
+ });
786
+
787
+ test.each([
788
+ ["messaging.servicebus.messages.sent", "publish"],
789
+ ["messaging.servicebus.receiver.lag", "consume"],
790
+ ["messaging.servicebus.settlement.request.duration", "settle"],
791
+ ["messaging.servicebus.settlement.sequence_number", "settle"],
792
+ ])(
793
+ "the Azure SDK for Java's %s names no system: its name says Service Bus (direction %s)",
794
+ (metricName: string, direction: string) => {
795
+ expect(MESSAGING_SDK_METRIC_SYSTEMS.get(metricName)).toBe("servicebus");
796
+ expect(MESSAGING_CLIENT_METRIC_NAMES.has(metricName)).toBe(true);
797
+ // ServiceBusMeter's attributes, as azure-core-metrics-opentelemetry renames them.
798
+ expect(
799
+ resolveDatapoint(metricName, {
800
+ "server.address": "billing-prod.servicebus.windows.net",
801
+ "messaging.destination.name": "invoices",
802
+ "messaging.servicebus.subscription_name": "audit",
803
+ "messaging.servicebus.disposition_status": "complete",
804
+ }),
805
+ ).toEqual(
806
+ destinationOf({
807
+ system: "servicebus",
808
+ destination: "invoices",
809
+ brokerScope: "billing-prod",
810
+ brokerAddress: "billing-prod.servicebus.windows.net",
811
+ direction: direction as ResolvedMessagingDestination["direction"],
812
+ consumerGroup: "audit",
813
+ }),
814
+ );
815
+ },
816
+ );
817
+
818
+ test("a system the datapoint names wins over the one its name implies; an excluded one is kept", () => {
819
+ expect(
820
+ resolveDatapoint("messaging.servicebus.messages.sent", {
821
+ "messaging.system": "eventhubs",
822
+ "messaging.destination.name": "telemetry",
823
+ })?.system,
824
+ ).toBe("eventhubs");
825
+ expect(
826
+ resolveDatapoint("messaging.servicebus.messages.sent", {
827
+ "messaging.system": "spring_integration",
828
+ "messaging.destination.name": "invoices",
829
+ }),
830
+ ).toBeNull();
831
+ // The implied system needs the metric's exact name.
832
+ expect(
833
+ resolveDatapoint("messaging.servicebus.messages.dropped", {
834
+ "messaging.destination.name": "invoices",
835
+ }),
836
+ ).toBeNull();
837
+ // No name, no implied system.
838
+ expect(
839
+ resolveDatapoint("", { "messaging.destination.name": "invoices" }),
840
+ ).toBeNull();
841
+ });
842
+
843
+ test.each([
844
+ /*
845
+ * Client metrics carry semconv 1.30's joined RabbitMQ names but never
846
+ * the routing key (no metric attribute): with a 1.26+ operation key —
847
+ * the type here — a consumer's names its queue, a producer's its
848
+ * exchange.
849
+ */
850
+ [
851
+ "messaging.client.operation.duration",
852
+ { "messaging.operation.type": "send" },
853
+ "orders.topic:orders.eu.created",
854
+ "orders.topic",
855
+ ],
856
+ [
857
+ "messaging.client.sent.messages",
858
+ { "messaging.operation.type": "send" },
859
+ "orders.topic:orders.eu.created",
860
+ "orders.topic",
861
+ ],
862
+ [
863
+ "messaging.process.duration",
864
+ { "messaging.operation.type": "process" },
865
+ "direct_logs:warning",
866
+ "warning",
867
+ ],
868
+ [
869
+ "messaging.client.consumed.messages",
870
+ { "messaging.operation.type": "receive" },
871
+ "logs:logs-audit",
872
+ "logs-audit",
873
+ ],
874
+ [
875
+ "messaging.client.operation.duration",
876
+ { "messaging.operation.type": "settle" },
877
+ "direct_logs:warning:my_queue",
878
+ "my_queue",
879
+ ],
880
+ /*
881
+ * Attributes exactly as the Java agent records its consumer metrics
882
+ * (MessagingMetricsAdvice): the operation name, never the operation
883
+ * type. A consumer's three parts still name its queue — also an
884
+ * exchange named with a colon, its empty routing key left out.
885
+ */
886
+ [
887
+ "messaging.client.consumed.messages",
888
+ { "messaging.operation.name": "process" },
889
+ "direct_logs:warning:my_queue",
890
+ "my_queue",
891
+ ],
892
+ [
893
+ "messaging.process.duration",
894
+ { "messaging.operation.name": "process" },
895
+ "MyApp.Contracts:OrderSubmitted:billing",
896
+ "billing",
897
+ ],
898
+ /*
899
+ * ...and two parts split as its span's do, a producer's too: the
900
+ * operation name is the one 1.26+ key the Java agent keeps on its
901
+ * sent-messages, consumed-messages and process-duration metrics.
902
+ */
903
+ [
904
+ "messaging.client.sent.messages",
905
+ { "messaging.operation.name": "publish" },
906
+ "orders.topic:orders.eu.created",
907
+ "orders.topic",
908
+ ],
909
+ [
910
+ "messaging.process.duration",
911
+ { "messaging.operation.name": "process" },
912
+ "direct_logs:warning",
913
+ "warning",
914
+ ],
915
+ [
916
+ "messaging.client.consumed.messages",
917
+ { "messaging.operation.name": "process" },
918
+ "logs:logs-audit",
919
+ "logs-audit",
920
+ ],
921
+ [
922
+ "messaging.client.consumed.messages",
923
+ { "messaging.operation.name": "receive" },
924
+ "invoices.direct:invoices-audit",
925
+ "invoices-audit",
926
+ ],
927
+ // A blank operation name is none.
928
+ [
929
+ "messaging.client.sent.messages",
930
+ { "messaging.operation.name": " " },
931
+ "orders.topic:orders.eu.created",
932
+ "orders.topic:orders.eu.created",
933
+ ],
934
+ [
935
+ "messaging.process.duration",
936
+ { "messaging.operation.name": "" },
937
+ "direct_logs:warning",
938
+ "direct_logs:warning",
939
+ ],
940
+ // RabbitMQ.Client for .NET's protocol name: the exchange alone, as on its spans.
941
+ [
942
+ "messaging.client.consumed.messages",
943
+ {
944
+ "messaging.operation.name": "deliver",
945
+ "network.protocol.name": "amqp",
946
+ },
947
+ "MyApp.Contracts:OrderSubmitted",
948
+ "MyApp.Contracts:OrderSubmitted",
949
+ ],
950
+ [
951
+ "messaging.client.consumed.messages",
952
+ {
953
+ "messaging.operation.name": "deliver",
954
+ "network.protocol.name": "amqp",
955
+ },
956
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
957
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
958
+ ],
959
+ /*
960
+ * The one thing a datapoint cannot tell: a producer's two parts are
961
+ * `{exchange}:{routing key}`, as the Java agent names every publish
962
+ * with a routing key, or an exchange named with a colon published to
963
+ * with an empty one — which its span tells apart by the routing-key
964
+ * attribute. A datapoint takes the joined reading, whichever 1.26+ key
965
+ * shows it.
966
+ */
967
+ [
968
+ "messaging.client.sent.messages",
969
+ { "messaging.operation.name": "publish" },
970
+ "MyApp.Contracts:OrderSubmitted",
971
+ "MyApp.Contracts",
972
+ ],
973
+ [
974
+ "messaging.client.operation.duration",
975
+ { "messaging.operation.type": "send" },
976
+ "MyApp.Contracts:OrderSubmitted",
977
+ "MyApp.Contracts",
978
+ ],
979
+ /*
980
+ * Semconv joins three parts on a consumer only: a producer's three are
981
+ * one exchange name, as its span says — MassTransit's Fault<T> exchange,
982
+ * published to with an empty routing key.
983
+ */
984
+ [
985
+ "messaging.client.sent.messages",
986
+ { "messaging.operation.name": "publish" },
987
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
988
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
989
+ ],
990
+ [
991
+ "messaging.client.operation.duration",
992
+ {
993
+ "messaging.operation.name": "publish",
994
+ "messaging.operation.type": "send",
995
+ },
996
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
997
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
998
+ ],
999
+ // An application's gauge states no direction: its three parts are one name.
1000
+ [
1001
+ "queue.size",
1002
+ {},
1003
+ "direct_logs:warning:my_queue",
1004
+ "direct_logs:warning:my_queue",
1005
+ ],
1006
+ // The older conventions' metrics name one exchange, colon and all.
1007
+ [
1008
+ "messaging.publish.duration",
1009
+ { "messaging.operation": "publish" },
1010
+ "MyApp.Contracts:OrderSubmitted",
1011
+ "MyApp.Contracts:OrderSubmitted",
1012
+ ],
1013
+ [
1014
+ "messaging.process.duration",
1015
+ { "messaging.operation": "process" },
1016
+ "MyApp.Contracts:OrderSubmitted",
1017
+ "MyApp.Contracts:OrderSubmitted",
1018
+ ],
1019
+ /*
1020
+ * Three parts too, on a consumer as much as a producer: without a 1.26+
1021
+ * operation key a datapoint is read as its span would be — one name,
1022
+ * MassTransit's Fault<T> exchange among them.
1023
+ */
1024
+ [
1025
+ "messaging.receive.messages",
1026
+ { "messaging.operation": "receive" },
1027
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
1028
+ "MassTransit:Fault--Sample.Contracts:SubmitOrder--",
1029
+ ],
1030
+ [
1031
+ "messaging.process.duration",
1032
+ { "messaging.operation": "process" },
1033
+ "direct_logs:warning:my_queue",
1034
+ "direct_logs:warning:my_queue",
1035
+ ],
1036
+ [
1037
+ "messaging.client.consumed.messages",
1038
+ {},
1039
+ "direct_logs:warning:my_queue",
1040
+ "direct_logs:warning:my_queue",
1041
+ ],
1042
+ ])(
1043
+ "RabbitMQ client metric %s %j of %s names %s",
1044
+ (
1045
+ metricName: string,
1046
+ conventions: FixtureAttributes,
1047
+ destination: string,
1048
+ expected: string,
1049
+ ) => {
1050
+ expect(
1051
+ resolveDatapoint(metricName, {
1052
+ "messaging.system": "rabbitmq",
1053
+ "messaging.destination.name": destination,
1054
+ ...conventions,
1055
+ })?.destination,
1056
+ ).toBe(expected);
1057
+ },
1058
+ );
1059
+
1060
+ test("a destination named phone_number… is a queue for every broker but an SNS SMS placeholder", () => {
1061
+ expect(
1062
+ resolveDatapoint(
1063
+ "amazonaws.com/aws/sqs/approximatenumberofmessagesvisible",
1064
+ { "Dimensions.QueueName": "phone_number_updates" },
1065
+ )?.destination,
1066
+ ).toBe("phone_number_updates");
1067
+ expect(
1068
+ resolveDatapoint("kafka.consumer_group.lag_sum", {
1069
+ group: "billing",
1070
+ topic: "phone_numbers",
1071
+ })?.destination,
1072
+ ).toBe("phone_numbers");
1073
+ expect(
1074
+ resolveDatapoint("messaging.client.sent.messages", {
1075
+ "messaging.system": "aws.sns",
1076
+ "messaging.destination.name": "phone_number:**",
1077
+ }),
1078
+ ).toBeNull();
1079
+ });
1080
+
1081
+ test("a broker destination or scrubbed value no queue could hold is no queue", () => {
1082
+ expect(
1083
+ resolveDatapoint("kafka.consumer_group.lag_sum", {
1084
+ group: "billing",
1085
+ topic: "orders\u0000x",
1086
+ }),
1087
+ ).toBeNull();
1088
+ expect(
1089
+ resolveDatapoint("rabbitmq.message.current", {
1090
+ "resource.rabbitmq.queue.name": "orders\u001fx",
1091
+ state: "ready",
1092
+ }),
1093
+ ).toBeNull();
1094
+ // A metric pipeline rule's default redaction.
1095
+ expect(
1096
+ resolveDatapoint("rabbitmq.message.current", {
1097
+ "resource.rabbitmq.queue.name": "[REDACTED]",
1098
+ state: "ready",
1099
+ }),
1100
+ ).toBeNull();
1101
+ expect(
1102
+ resolveDatapoint("pulsar_msg_backlog", { topic: "[REDACTED]" }),
1103
+ ).toBeNull();
1104
+ });
1105
+
1106
+ test("an empty metric name resolves by the attributes", () => {
1107
+ expect(
1108
+ resolveDatapoint("", {
1109
+ "messaging.system": "kafka",
1110
+ "messaging.destination.name": "orders",
1111
+ }),
1112
+ ).toEqual(destinationOf({ system: "kafka", destination: "orders" }));
1113
+ });
1114
+
1115
+ test("every messaging-client metric name takes the attribute path", () => {
1116
+ for (const metricName of MESSAGING_CLIENT_METRIC_NAMES) {
1117
+ expect(
1118
+ resolveDatapoint(metricName, {
1119
+ "messaging.system": "kafka",
1120
+ "messaging.destination.name": "orders",
1121
+ })?.destination,
1122
+ ).toBe("orders");
1123
+ }
1124
+ });
1125
+ });
1126
+
1127
+ /*
1128
+ * The Java agent is the one instrumentation found recording RabbitMQ client
1129
+ * metrics — rabbitmq-2.7 and spring-rabbit-1.0, from 2.31.0 — and only in
1130
+ * its opt-in mode, whose names join exchange, routing key and queue. Here
1131
+ * it is as its source has it (opentelemetry-java-instrumentation): the name
1132
+ * a span and its metrics share (RabbitInstrumenterHelper
1133
+ * .producerDestinationName / .consumerDestinationName), what each
1134
+ * operation's span carries (MessagingAttributesExtractor; the routing key
1135
+ * only when non-empty), the metrics each operation records
1136
+ * (RabbitSingletons), and what each metric keeps of the span's attributes
1137
+ * (MessagingMetricsAdvice: no destination when it is anonymous, never the
1138
+ * routing key, the operation type on messaging.client.operation.duration
1139
+ * alone). Whatever the route, a span and every metric of its operation
1140
+ * resolve alike, to the queue the research says.
1141
+ */
1142
+ describe("a Java agent RabbitMQ span and the client metrics of its operation", () => {
1143
+ // MessagingMetricsAdvice.buildAttributes, instrument by instrument.
1144
+ const SENT_MESSAGES_ADVICE: ReadonlyArray<string> = [
1145
+ "messaging.operation.name",
1146
+ "messaging.system",
1147
+ "error.type",
1148
+ "messaging.destination.name",
1149
+ "messaging.destination.template",
1150
+ "messaging.destination.partition.id",
1151
+ "server.address",
1152
+ "server.port",
1153
+ ];
1154
+ const CONSUMER_METRIC_ADVICE: ReadonlyArray<string> = [
1155
+ ...SENT_MESSAGES_ADVICE,
1156
+ "messaging.consumer.group.name",
1157
+ "messaging.destination.subscription.name",
1158
+ ];
1159
+ const METRIC_ADVICE: ReadonlyMap<string, ReadonlyArray<string>> = new Map<
1160
+ string,
1161
+ ReadonlyArray<string>
1162
+ >([
1163
+ [
1164
+ "messaging.client.operation.duration",
1165
+ [...CONSUMER_METRIC_ADVICE, "messaging.operation.type"],
1166
+ ],
1167
+ ["messaging.client.sent.messages", SENT_MESSAGES_ADVICE],
1168
+ ["messaging.client.consumed.messages", CONSUMER_METRIC_ADVICE],
1169
+ ["messaging.process.duration", CONSUMER_METRIC_ADVICE],
1170
+ ]);
1171
+
1172
+ interface AgentOperation {
1173
+ // messaging.operation.name and messaging.operation.type.
1174
+ name: string;
1175
+ type: string;
1176
+ kind: string;
1177
+ publishes: boolean;
1178
+ // What RabbitSingletons records for it.
1179
+ metrics: ReadonlyArray<string>;
1180
+ }
1181
+
1182
+ const PUBLISH: AgentOperation = {
1183
+ name: "publish",
1184
+ type: "send",
1185
+ kind: "SPAN_KIND_PRODUCER",
1186
+ publishes: true,
1187
+ metrics: [
1188
+ "messaging.client.operation.duration",
1189
+ "messaging.client.sent.messages",
1190
+ ],
1191
+ };
1192
+
1193
+ const OPERATIONS: ReadonlyArray<AgentOperation> = [
1194
+ PUBLISH,
1195
+ // basic.get
1196
+ {
1197
+ name: "receive",
1198
+ type: "receive",
1199
+ kind: "SPAN_KIND_CLIENT",
1200
+ publishes: false,
1201
+ metrics: [
1202
+ "messaging.client.operation.duration",
1203
+ "messaging.client.consumed.messages",
1204
+ ],
1205
+ },
1206
+ // A delivery to a consumer.
1207
+ {
1208
+ name: "process",
1209
+ type: "process",
1210
+ kind: "SPAN_KIND_CONSUMER",
1211
+ publishes: false,
1212
+ metrics: [
1213
+ "messaging.process.duration",
1214
+ "messaging.client.consumed.messages",
1215
+ ],
1216
+ },
1217
+ ];
1218
+
1219
+ interface Route {
1220
+ label: string;
1221
+ exchange: string;
1222
+ routingKey: string;
1223
+ queue: string;
1224
+ // The queue the research says a publisher's and a consumer's name.
1225
+ publishesTo: string | null;
1226
+ consumesFrom: string | null;
1227
+ }
1228
+
1229
+ const ROUTES: ReadonlyArray<Route> = [
1230
+ {
1231
+ label: "the default exchange",
1232
+ exchange: "",
1233
+ routingKey: "invoices",
1234
+ queue: "invoices",
1235
+ publishesTo: "invoices",
1236
+ consumesFrom: "invoices",
1237
+ },
1238
+ {
1239
+ label: "a topic exchange",
1240
+ exchange: "orders.topic",
1241
+ routingKey: "orders.eu.created",
1242
+ queue: "orders-eu",
1243
+ publishesTo: "orders.topic",
1244
+ consumesFrom: "orders-eu",
1245
+ },
1246
+ {
1247
+ label: "a direct exchange to the queue named by its key",
1248
+ exchange: "direct_logs",
1249
+ routingKey: "warning",
1250
+ queue: "warning",
1251
+ publishesTo: "direct_logs",
1252
+ consumesFrom: "warning",
1253
+ },
1254
+ {
1255
+ label: "a fanout exchange",
1256
+ exchange: "logs",
1257
+ routingKey: "",
1258
+ queue: "logs-audit",
1259
+ publishesTo: "logs",
1260
+ consumesFrom: "logs-audit",
1261
+ },
1262
+ {
1263
+ label: "the default exchange to a server-named queue",
1264
+ exchange: "",
1265
+ routingKey: "amq.gen-JzTY20BRgKO-HjmUJj0wLg",
1266
+ queue: "amq.gen-JzTY20BRgKO-HjmUJj0wLg",
1267
+ publishesTo: null,
1268
+ consumesFrom: null,
1269
+ },
1270
+ ];
1271
+
1272
+ /*
1273
+ * A MassTransit message type's exchange, named with a colon, bound with
1274
+ * an empty routing key. Its consumers are routed above; its publishers
1275
+ * are the one case a metric cannot tell apart (see the last test).
1276
+ */
1277
+ const MASSTRANSIT_ROUTE: Route = {
1278
+ label: "a MassTransit message-type exchange",
1279
+ exchange: "Contoso.Billing.Contracts:InvoiceIssued",
1280
+ routingKey: "",
1281
+ queue: "invoice-issued",
1282
+ publishesTo: "Contoso.Billing.Contracts:InvoiceIssued",
1283
+ consumesFrom: "invoice-issued",
1284
+ };
1285
+
1286
+ // appendDestinationPart: the non-empty parts, joined with ":".
1287
+ function joinDestination(parts: ReadonlyArray<string>): string {
1288
+ return parts
1289
+ .filter((part: string): boolean => {
1290
+ return part.length > 0;
1291
+ })
1292
+ .join(":");
1293
+ }
1294
+
1295
+ // The part of isGeneratedQueueName these routes need.
1296
+ function isGeneratedQueueName(name: string): boolean {
1297
+ return name.startsWith("amq.gen-");
1298
+ }
1299
+
1300
+ function spanAttributes(
1301
+ operation: AgentOperation,
1302
+ route: Route,
1303
+ ): FixtureAttributes {
1304
+ const destination: string = operation.publishes
1305
+ ? joinDestination([route.exchange, route.routingKey]) || "amq.default"
1306
+ : joinDestination([
1307
+ route.exchange,
1308
+ route.routingKey,
1309
+ route.queue === route.routingKey ? "" : route.queue,
1310
+ ]);
1311
+ const anonymous: boolean = operation.publishes
1312
+ ? route.exchange === "" && isGeneratedQueueName(route.routingKey)
1313
+ : isGeneratedQueueName(route.queue);
1314
+ return {
1315
+ "messaging.system": "rabbitmq",
1316
+ ...(destination ? { "messaging.destination.name": destination } : {}),
1317
+ ...(anonymous ? { "messaging.destination.anonymous": true } : {}),
1318
+ "messaging.operation.name": operation.name,
1319
+ "messaging.operation.type": operation.type,
1320
+ ...(route.routingKey
1321
+ ? { "messaging.rabbitmq.destination.routing_key": route.routingKey }
1322
+ : {}),
1323
+ ...(operation.publishes
1324
+ ? {}
1325
+ : { "messaging.rabbitmq.message.delivery_tag": 7 }),
1326
+ "server.address": "rabbitmq.internal",
1327
+ "server.port": 5672,
1328
+ "network.peer.address": "10.0.3.17",
1329
+ "network.peer.port": 5672,
1330
+ };
1331
+ }
1332
+
1333
+ // MessagingMetricsAdvice.filterAttributes, then the instrument's advice.
1334
+ function metricAttributes(
1335
+ metricName: string,
1336
+ span: FixtureAttributes,
1337
+ ): FixtureAttributes {
1338
+ const dropsName: boolean =
1339
+ span["messaging.destination.template"] !== undefined ||
1340
+ span["messaging.destination.anonymous"] === true ||
1341
+ span["messaging.destination.temporary"] === true;
1342
+ const kept: FixtureAttributes = {};
1343
+ for (const key of METRIC_ADVICE.get(metricName) || []) {
1344
+ if (
1345
+ span[key] !== undefined &&
1346
+ !(dropsName && key === "messaging.destination.name")
1347
+ ) {
1348
+ kept[key] = span[key];
1349
+ }
1350
+ }
1351
+ return kept;
1352
+ }
1353
+
1354
+ function resolveSpan(
1355
+ operation: AgentOperation,
1356
+ span: FixtureAttributes,
1357
+ ): ResolvedMessagingDestination | null {
1358
+ return resolveMessagingSpan({
1359
+ getAttribute: (key: string): unknown => {
1360
+ return span[key];
1361
+ },
1362
+ kind: operation.kind,
1363
+ });
1364
+ }
1365
+
1366
+ const CASES: Array<[string, AgentOperation, Route, string]> = [];
1367
+ for (const operation of OPERATIONS) {
1368
+ const routes: ReadonlyArray<Route> = operation.publishes
1369
+ ? ROUTES
1370
+ : [...ROUTES, MASSTRANSIT_ROUTE];
1371
+ for (const route of routes) {
1372
+ for (const metricName of operation.metrics) {
1373
+ CASES.push([
1374
+ `${operation.name} through ${route.label}: ${metricName}`,
1375
+ operation,
1376
+ route,
1377
+ metricName,
1378
+ ]);
1379
+ }
1380
+ }
1381
+ }
1382
+
1383
+ test("the metrics keep no routing key, and the operation type only on the operation duration", () => {
1384
+ for (const [metricName, advice] of METRIC_ADVICE) {
1385
+ expect({
1386
+ metricName,
1387
+ routingKey: advice.includes(
1388
+ "messaging.rabbitmq.destination.routing_key",
1389
+ ),
1390
+ operationName: advice.includes("messaging.operation.name"),
1391
+ operationType: advice.includes("messaging.operation.type"),
1392
+ }).toEqual({
1393
+ metricName,
1394
+ routingKey: false,
1395
+ operationName: true,
1396
+ operationType: metricName === "messaging.client.operation.duration",
1397
+ });
1398
+ }
1399
+ });
1400
+
1401
+ test.each(CASES)(
1402
+ "%s names the queue its span does",
1403
+ (
1404
+ _name: string,
1405
+ operation: AgentOperation,
1406
+ route: Route,
1407
+ metricName: string,
1408
+ ) => {
1409
+ const span: FixtureAttributes = spanAttributes(operation, route);
1410
+ const fromSpan: ResolvedMessagingDestination | null = resolveSpan(
1411
+ operation,
1412
+ span,
1413
+ );
1414
+ expect(fromSpan?.destination ?? null).toBe(
1415
+ operation.publishes ? route.publishesTo : route.consumesFrom,
1416
+ );
1417
+ expect(
1418
+ resolveDatapoint(metricName, metricAttributes(metricName, span)),
1419
+ ).toEqual(fromSpan);
1420
+ },
1421
+ );
1422
+
1423
+ test("the names are the agent's: joined on both sides, the default exchange and a key equal to the queue left out", () => {
1424
+ const names: Array<unknown> = [PUBLISH, OPERATIONS[2]!].map(
1425
+ (operation: AgentOperation): unknown => {
1426
+ return ROUTES.map((route: Route): unknown => {
1427
+ return spanAttributes(operation, route)["messaging.destination.name"];
1428
+ });
1429
+ },
1430
+ );
1431
+ expect(names).toEqual([
1432
+ [
1433
+ "invoices",
1434
+ "orders.topic:orders.eu.created",
1435
+ "direct_logs:warning",
1436
+ "logs",
1437
+ "amq.gen-JzTY20BRgKO-HjmUJj0wLg",
1438
+ ],
1439
+ [
1440
+ "invoices",
1441
+ "orders.topic:orders.eu.created:orders-eu",
1442
+ "direct_logs:warning",
1443
+ "logs:logs-audit",
1444
+ "amq.gen-JzTY20BRgKO-HjmUJj0wLg",
1445
+ ],
1446
+ ]);
1447
+ });
1448
+
1449
+ /*
1450
+ * A publish to an exchange named with a colon, with no routing key: its
1451
+ * span knows the key is empty (the attribute is missing), so the name is
1452
+ * one exchange; its metrics cannot know, and read `{exchange}:{routing
1453
+ * key}` like every other publish's — both of them alike.
1454
+ */
1455
+ test("a publish to an exchange named with a colon: its metrics agree with each other, not with its span", () => {
1456
+ const span: FixtureAttributes = spanAttributes(PUBLISH, MASSTRANSIT_ROUTE);
1457
+ expect(resolveSpan(PUBLISH, span)?.destination).toBe(
1458
+ "Contoso.Billing.Contracts:InvoiceIssued",
1459
+ );
1460
+ expect(
1461
+ PUBLISH.metrics.map((metricName: string): string | null => {
1462
+ return (
1463
+ resolveDatapoint(metricName, metricAttributes(metricName, span))
1464
+ ?.destination ?? null
1465
+ );
1466
+ }),
1467
+ ).toEqual(["Contoso.Billing.Contracts", "Contoso.Billing.Contracts"]);
1468
+ });
1469
+ });
1470
+
1471
+ describe("MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES", () => {
1472
+ test("covers the span keys, every catalog key and the broker address", () => {
1473
+ const keys: Set<string> = new Set<string>(
1474
+ MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES,
1475
+ );
1476
+ expect(keys.size).toBe(MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES.length);
1477
+ for (const key of MESSAGING_RESOLVER_INPUT_ATTRIBUTES) {
1478
+ expect(keys.has(key)).toBe(true);
1479
+ }
1480
+ for (const descriptor of MESSAGE_QUEUE_METRICS) {
1481
+ for (const key of [
1482
+ ...descriptor.destinationAttributes,
1483
+ ...(descriptor.scopeAttributes || []),
1484
+ ...Object.keys(descriptor.requiredAttributes || {}),
1485
+ ]) {
1486
+ expect({ key, listed: keys.has(key) }).toEqual({ key, listed: true });
1487
+ }
1488
+ }
1489
+ for (const attribute of MESSAGE_QUEUE_METRIC_ADDRESS_ATTRIBUTES) {
1490
+ expect(keys.has(attribute.address)).toBe(true);
1491
+ if (attribute.port) {
1492
+ expect(keys.has(attribute.port)).toBe(true);
1493
+ }
1494
+ }
1495
+ });
1496
+
1497
+ /*
1498
+ * A RabbitMQ datapoint's joined name splits by the 1.26+ operation key it
1499
+ * carries, so the cron must group by both keys, as ingest's memo does.
1500
+ */
1501
+ test("holds both operation keys that decide how a RabbitMQ name splits", () => {
1502
+ for (const key of [
1503
+ "messaging.operation.type",
1504
+ "messaging.operation.name",
1505
+ ]) {
1506
+ expect({
1507
+ key,
1508
+ spans: MESSAGING_RESOLVER_INPUT_ATTRIBUTES.includes(key),
1509
+ datapoints: MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES.includes(key),
1510
+ }).toEqual({ key, spans: true, datapoints: true });
1511
+ }
1512
+ });
1513
+
1514
+ test("series keys are for charts, not identity: none is read", () => {
1515
+ const listed: Set<string> = new Set<string>(
1516
+ MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES,
1517
+ );
1518
+ for (const key of [
1519
+ "state",
1520
+ "group",
1521
+ "partition",
1522
+ "subscription",
1523
+ "consumer_group",
1524
+ "is_retry",
1525
+ "metadata_operationresult",
1526
+ "response_code",
1527
+ "delivery_type",
1528
+ ]) {
1529
+ expect(listed.has(key)).toBe(false);
1530
+ }
1531
+ });
1532
+
1533
+ test("the resolver never reads a key outside the list, over every fixture", () => {
1534
+ /*
1535
+ * Besides the list, only the repeat markers, which merely drop a
1536
+ * datapoint (see the test below).
1537
+ */
1538
+ const allowed: Set<string> = new Set<string>([
1539
+ ...MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES,
1540
+ ...MESSAGE_QUEUE_METRIC_EXCLUDED_SERIES_ATTRIBUTES,
1541
+ ]);
1542
+ const outside: Array<string> = [];
1543
+ for (const fixture of METRIC_FIXTURES) {
1544
+ const reads: Set<string> = new Set<string>();
1545
+ resolveRecordingReads(fixture.metricName, fixture.attributes, reads);
1546
+ for (const key of reads) {
1547
+ if (!allowed.has(key)) {
1548
+ outside.push(`${fixture.name}: ${key}`);
1549
+ }
1550
+ }
1551
+ }
1552
+ expect(outside).toEqual([]);
1553
+ });
1554
+
1555
+ test("the repeat markers are per instance, so the discovery cron never groups by them", () => {
1556
+ expect(MESSAGE_QUEUE_METRIC_EXCLUDED_SERIES_ATTRIBUTES).toEqual([
1557
+ "consumer_name",
1558
+ "consumer_id",
1559
+ ]);
1560
+ for (const key of MESSAGE_QUEUE_METRIC_EXCLUDED_SERIES_ATTRIBUTES) {
1561
+ expect(MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES).not.toContain(key);
1562
+ }
1563
+ /*
1564
+ * And leaving them out of the stored row never changes WHICH queue a
1565
+ * row finds: the per-consumer copy resolves, from the discovery row, to
1566
+ * the queue its subscription's own series already names.
1567
+ */
1568
+ const subscriptionSeries: FixtureAttributes = {
1569
+ cluster: "standalone",
1570
+ namespace: "public/default",
1571
+ topic: "persistent://public/default/orders-partition-0",
1572
+ subscription: "billing",
1573
+ };
1574
+ const consumerCopy: FixtureAttributes = {
1575
+ ...subscriptionSeries,
1576
+ consumer_name: "billing-worker-7",
1577
+ consumer_id: "3",
1578
+ };
1579
+ const fromSubscription: ResolvedMessagingDestination | null =
1580
+ resolveDatapoint("pulsar_out_messages_total", subscriptionSeries);
1581
+ expect(fromSubscription?.destination).toBe(
1582
+ "persistent://public/default/orders",
1583
+ );
1584
+ const storedCopy: Record<string, string> = toStoredColumns(
1585
+ consumerCopy,
1586
+ MESSAGING_METRIC_RESOLVER_INPUT_ATTRIBUTES,
1587
+ );
1588
+ expect(
1589
+ resolveMessagingMetricDatapoint({
1590
+ metricName: "pulsar_out_messages_total",
1591
+ getAttribute: (key: string): unknown => {
1592
+ return storedCopy[key];
1593
+ },
1594
+ }),
1595
+ ).toEqual(fromSubscription);
1596
+ });
1597
+
1598
+ test("every catalog key is read by some fixture", () => {
1599
+ const read: Set<string> = new Set<string>();
1600
+ for (const fixture of METRIC_FIXTURES) {
1601
+ resolveRecordingReads(fixture.metricName, fixture.attributes, read);
1602
+ }
1603
+ // The second Azure spelling is read only when the first is absent.
1604
+ resolveRecordingReads(
1605
+ "azure_activemessages_average",
1606
+ { type: "Microsoft.ServiceBus/namespaces" },
1607
+ read,
1608
+ );
1609
+ const catalogKeys: Set<string> = new Set<string>();
1610
+ for (const descriptor of MESSAGE_QUEUE_METRICS) {
1611
+ for (const key of [
1612
+ ...descriptor.destinationAttributes,
1613
+ ...(descriptor.scopeAttributes || []),
1614
+ ...Object.keys(descriptor.requiredAttributes || {}),
1615
+ ]) {
1616
+ catalogKeys.add(key);
1617
+ }
1618
+ }
1619
+ expect(
1620
+ [...catalogKeys].filter((key: string): boolean => {
1621
+ return !read.has(key);
1622
+ }),
1623
+ ).toEqual([]);
1624
+ });
1625
+ });
1626
+
1627
+ describe("the metric resolver never throws", () => {
1628
+ test("bad input is null", () => {
1629
+ expect(
1630
+ resolveMessagingMetricDatapoint(
1631
+ null as unknown as {
1632
+ metricName: string;
1633
+ getAttribute: (key: string) => unknown;
1634
+ },
1635
+ ),
1636
+ ).toBeNull();
1637
+ expect(
1638
+ resolveMessagingMetricDatapoint({
1639
+ metricName: "rabbitmq.message.current",
1640
+ getAttribute: null as unknown as (key: string) => unknown,
1641
+ }),
1642
+ ).toBeNull();
1643
+ expect(
1644
+ resolveMessagingMetricDatapoint({
1645
+ metricName: 42 as unknown as string,
1646
+ getAttribute: (): unknown => {
1647
+ return undefined;
1648
+ },
1649
+ }),
1650
+ ).toBeNull();
1651
+ });
1652
+
1653
+ test("odd attribute values on every curated metric resolve or are null", () => {
1654
+ const odd: Array<unknown> = [
1655
+ null,
1656
+ undefined,
1657
+ "",
1658
+ " ",
1659
+ 0,
1660
+ true,
1661
+ [],
1662
+ ["x"],
1663
+ {},
1664
+ "[]",
1665
+ "https://",
1666
+ "arn:",
1667
+ ];
1668
+ for (const descriptor of MESSAGE_QUEUE_METRICS) {
1669
+ for (const value of odd) {
1670
+ const attributes: FixtureAttributes = {};
1671
+ for (const key of [
1672
+ ...descriptor.destinationAttributes,
1673
+ ...(descriptor.scopeAttributes || []),
1674
+ ...Object.keys(descriptor.requiredAttributes || {}),
1675
+ ]) {
1676
+ attributes[key] = value;
1677
+ }
1678
+ let threw: boolean = false;
1679
+ try {
1680
+ resolveDatapoint(descriptor.metricName, attributes);
1681
+ } catch {
1682
+ threw = true;
1683
+ }
1684
+ expect({
1685
+ metric: descriptor.metricName,
1686
+ value: String(value),
1687
+ threw,
1688
+ }).toEqual({
1689
+ metric: descriptor.metricName,
1690
+ value: String(value),
1691
+ threw: false,
1692
+ });
1693
+ }
1694
+ }
1695
+ });
1696
+ });
1697
+
1698
+ describe("a known limit: a RabbitMQ queue named with a colon, reached through the default exchange", () => {
1699
+ /*
1700
+ * The OpenTelemetry Java agent (opt-in messaging conventions) names a
1701
+ * default-exchange publish and delivery after the routing key, which is
1702
+ * the queue — here `app:orders`, colon and all — and its spans carry that
1703
+ * key as messaging.rabbitmq.destination.routing_key, so a span resolves to
1704
+ * the whole name. Its client metrics drop the routing-key attribute
1705
+ * (MessagingMetricsAdvice), and without it `app:orders` reads exactly like
1706
+ * the `{exchange}:{routing key}` name the agent gives every other publish,
1707
+ * so a datapoint takes the far commoner joined reading. Both readings lose
1708
+ * only a client metric's attachment to a queue — client metrics never
1709
+ * create queues — and this pins which one is lost, so a change to it is a
1710
+ * decision.
1711
+ */
1712
+ const COMMON: FixtureAttributes = {
1713
+ "messaging.system": "rabbitmq",
1714
+ "messaging.destination.name": "app:orders",
1715
+ };
1716
+
1717
+ test("the spans resolve to the whole queue name", () => {
1718
+ const publish: ResolvedMessagingDestination | null = resolveMessagingSpan({
1719
+ getAttribute: (key: string): unknown => {
1720
+ return {
1721
+ ...COMMON,
1722
+ "messaging.operation.type": "send",
1723
+ "messaging.operation.name": "publish",
1724
+ "messaging.rabbitmq.destination.routing_key": "app:orders",
1725
+ }[key];
1726
+ },
1727
+ kind: "SPAN_KIND_PRODUCER",
1728
+ });
1729
+ const deliver: ResolvedMessagingDestination | null = resolveMessagingSpan({
1730
+ getAttribute: (key: string): unknown => {
1731
+ return {
1732
+ ...COMMON,
1733
+ "messaging.operation.type": "process",
1734
+ "messaging.operation.name": "process",
1735
+ "messaging.rabbitmq.destination.routing_key": "app:orders",
1736
+ }[key];
1737
+ },
1738
+ kind: "SPAN_KIND_CONSUMER",
1739
+ });
1740
+ expect(publish?.destination).toBe("app:orders");
1741
+ expect(deliver?.destination).toBe("app:orders");
1742
+ });
1743
+
1744
+ test("the client metrics, which carry no routing key, take the joined reading", () => {
1745
+ const sent: ResolvedMessagingDestination | null = resolveDatapoint(
1746
+ "messaging.client.sent.messages",
1747
+ { ...COMMON, "messaging.operation.name": "publish" },
1748
+ );
1749
+ const consumed: ResolvedMessagingDestination | null = resolveDatapoint(
1750
+ "messaging.client.consumed.messages",
1751
+ { ...COMMON, "messaging.operation.name": "receive" },
1752
+ );
1753
+ // `{exchange}:{routing key}` on the publishing side: the exchange.
1754
+ expect(sent?.destination).toBe("app");
1755
+ // `{exchange}:{queue}` on the consuming side: the queue part.
1756
+ expect(consumed?.destination).toBe("orders");
1757
+ });
1758
+ });