From 735e216a952670eb57eaea1229be16e89f9bf1cd Mon Sep 17 00:00:00 2001 From: Sergi Romeu Date: Fri, 20 Sep 2024 09:07:14 +0200 Subject: [PATCH] [APM UI] Fix OpenTelemetry agent names (#193134) ## Summary Fixes https://github.com/elastic/kibana/issues/180444 This PR fixes the agent names not being able to properly be retrieved by the APM UI, changing the way we map OpenTelemetry agent names. As the format changed from `(opentelemetry|otlp)/{agentName}` to `(opentelemetry|otlp)/{agentName}/{details}`, we now get the second part splitting by `/`. Added mappings for RUM, Android, and iOS OpenTelemetry client, also fixed `get_service_metadata_details` to get the correct OpenTelemetry details. |Before|After| |-|-| |![image](https://github.com/user-attachments/assets/28732018-511b-44e0-ac86-cdbe7ed0d1e0)|![image](https://github.com/user-attachments/assets/45a29cc6-f939-4c52-bcc7-54dc15b1a403)| ## How to test 1. Checkout to this branch 2. Run `node scripts/synthtrace many_otel_services.ts --live --clean` which will fill some APM Otel services. 3. Check that the icon is now rendering --- .../src/scenarios/many_otel_services.ts | 102 ++++++++++++++++++ .../agent_icon/get_agent_icon.test.ts | 10 ++ .../components/agent_icon/get_agent_icon.ts | 17 ++- packages/kbn-elastic-agent-utils/index.ts | 1 + .../src/agent_guards.test.ts | 40 ++++++- .../src/agent_guards.ts | 44 ++++++-- .../src/agent_names.ts | 63 +++++++++-- src/plugins/telemetry/schema/oss_plugins.json | 18 ++-- .../__snapshots__/apm_telemetry.test.ts.snap | 90 ++++++++++++++++ .../apm/common/agent_name.ts | 1 + .../components/shared/service_icons/index.tsx | 4 +- .../shared/service_icons/otel_details.tsx | 1 - .../apm/server/lib/apm_telemetry/schema.ts | 92 ++++++++++++++++ .../__snapshots__/queries.test.ts.snap | 9 ++ .../services/get_service_metadata_details.ts | 8 +- .../schema/xpack_plugins.json | 90 ++++++++++++++++ 16 files changed, 551 insertions(+), 39 deletions(-) create mode 100644 packages/kbn-apm-synthtrace/src/scenarios/many_otel_services.ts diff --git a/packages/kbn-apm-synthtrace/src/scenarios/many_otel_services.ts b/packages/kbn-apm-synthtrace/src/scenarios/many_otel_services.ts new file mode 100644 index 00000000000000..70825e7bf43389 --- /dev/null +++ b/packages/kbn-apm-synthtrace/src/scenarios/many_otel_services.ts @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import { ApmFields, apm, Instance } from '@kbn/apm-synthtrace-client'; +import { flatten, random, times } from 'lodash'; +import { Scenario } from '../cli/scenario'; +import { getSynthtraceEnvironment } from '../lib/utils/get_synthtrace_environment'; +import { withClient } from '../lib/utils/with_client'; +import { getRandomNameForIndex } from './helpers/random_names'; + +const ENVIRONMENT = getSynthtraceEnvironment(__filename); + +const scenario: Scenario = async ({ logger, scenarioOpts = { services: 2000 } }) => { + const numServices = scenarioOpts.services; + const transactionName = 'GET /order/{id}'; + const languages = [ + 'go', + 'dotnet', + 'java', + 'python', + 'nodejs', + 'php', + 'webjs', + 'swift', + 'android', + ]; + const agentVersions: Record = { + go: ['2.1.0', '2.0.0', '1.15.0', '1.14.0', '1.13.1'], + dotnet: ['1.18.0', '1.17.0', '1.16.1', '1.16.0', '1.15.0'], + java: ['1.34.1', '1.34.0', '1.33.0', '1.32.0', '1.32.0'], + python: ['6.12.0', '6.11.0', '6.10.2', '6.10.1', '6.10.0'], + nodejs: ['1.34.1', '1.34.0', '1.33.0', '1.32.0', '1.32.0'], + php: ['1.34.1', '1.34.0', '1.33.0', '1.32.0', '1.32.0'], + webjs: ['6.12.0', '6.11.0', '6.10.2', '6.10.1', '6.10.0'], + swift: ['1.18.0', '1.17.0', '1.16.1', '1.16.0', '1.15.0'], + android: ['6.12.0', '6.11.0', '6.10.2', '6.10.1', '6.10.0'], + }; + + return { + generate: ({ range, clients: { apmEsClient } }) => { + const instances = flatten( + times(numServices).map((index) => { + const language = languages[index % languages.length]; + const agentLanguageVersions = agentVersions[language]; + const agentVersion = agentLanguageVersions[index % agentLanguageVersions.length]; + + const numOfInstances = (index % 3) + 1; + return times(numOfInstances).map((instanceIndex) => + apm + .service({ + name: `${getRandomNameForIndex(index)}-${language}-${index}`, + environment: ENVIRONMENT, + agentName: + index % 2 ? `opentelemetry/${language}/elastic` : `otlp/${language}/elastic`, + }) + .instance(`instance-${index}-${instanceIndex}`) + .defaults({ 'agent.version': agentVersion, 'service.language.name': language }) + ); + }) + ); + + const instanceSpans = (instance: Instance) => { + const hasHighDuration = Math.random() > 0.5; + const throughput = random(1, 10); + + return range.ratePerMinute(throughput).generator((timestamp) => { + const parentDuration = hasHighDuration ? random(1000, 5000) : random(100, 1000); + const generateError = random(1, 4) % 3 === 0; + const span = instance + .transaction({ transactionName }) + .timestamp(timestamp) + .duration(parentDuration); + + return !generateError + ? span.success() + : span.failure().errors( + instance + .error({ + message: `No handler for ${transactionName}`, + type: 'No handler', + culprit: 'request', + }) + .timestamp(timestamp + 50) + ); + }); + }; + + return withClient( + apmEsClient, + logger.perf('generating_apm_events', () => instances.map(instanceSpans)) + ); + }, + }; +}; + +export default scenario; diff --git a/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.test.ts b/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.test.ts index 3018605cb2c32d..f0045b5a5a2e8f 100644 --- a/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.test.ts +++ b/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.test.ts @@ -25,6 +25,16 @@ const examples = { 'opentelemetry/python': 'python', 'opentelemetry/ruby': 'ruby', 'opentelemetry/rust': 'rust', + 'opentelemetry/cpp/elastic': 'cpp', // Tests for additional arguments on OpenTelemetry agents + 'opentelemetry/dotnet/elastic': 'dotnet', + 'opentelemetry/erlang/elastic': 'erlang', + 'opentelemetry/go/elastic': 'go', + 'opentelemetry/nodejs/elastic': 'nodejs', + 'opentelemetry/php/elastic': 'php', + 'opentelemetry/python/elastic': 'python', + 'opentelemetry/ruby/elastic': 'ruby', + 'opentelemetry/rust/elastic': 'rust', + opentelemetry: 'opentelemetry', otlp: 'opentelemetry', php: 'php', python: 'python', diff --git a/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.ts b/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.ts index 2e12d2d98aff04..8353495ac168c0 100644 --- a/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.ts +++ b/packages/kbn-custom-icons/src/components/agent_icon/get_agent_icon.ts @@ -12,6 +12,7 @@ import { isIosAgentName, isJavaAgentName, isRumAgentName, + hasOpenTelemetryPrefix, OpenTelemetryAgentName, OPEN_TELEMETRY_AGENT_NAMES, } from '@kbn/elastic-agent-utils'; @@ -66,6 +67,15 @@ const darkAgentIcons: { [key: string]: string } = { rust: darkRustIcon, }; +const sanitizeAgentName = (agentName: string) => { + if (hasOpenTelemetryPrefix(agentName)) { + // for OpenTelemetry only split the agent name by `/` and take the second part, format is `(opentelemetry|otlp)/{agentName}/{details}` + return agentName.split('/')[1]; + } + + return agentName; +}; + // This only needs to be exported for testing purposes, since we stub the SVG // import values in test. export function getAgentIconKey(agentName: string) { @@ -90,11 +100,10 @@ export function getAgentIconKey(agentName: string) { return 'android'; } - // Remove "opentelemetry/" prefix - const agentNameWithoutPrefix = lowercasedAgentName.replace(/^opentelemetry\//, ''); + const cleanAgentName = sanitizeAgentName(lowercasedAgentName); - if (Object.keys(agentIcons).includes(agentNameWithoutPrefix)) { - return agentNameWithoutPrefix; + if (Object.keys(agentIcons).includes(cleanAgentName)) { + return cleanAgentName; } // OpenTelemetry-only agents diff --git a/packages/kbn-elastic-agent-utils/index.ts b/packages/kbn-elastic-agent-utils/index.ts index e4e4bf0fb9c071..d76095a44a0d31 100644 --- a/packages/kbn-elastic-agent-utils/index.ts +++ b/packages/kbn-elastic-agent-utils/index.ts @@ -9,6 +9,7 @@ export { isOpenTelemetryAgentName, + hasOpenTelemetryPrefix, isJavaAgentName, isRumAgentName, isMobileAgentName, diff --git a/packages/kbn-elastic-agent-utils/src/agent_guards.test.ts b/packages/kbn-elastic-agent-utils/src/agent_guards.test.ts index bd88d8dbbe7cdb..655addbe73c35e 100644 --- a/packages/kbn-elastic-agent-utils/src/agent_guards.test.ts +++ b/packages/kbn-elastic-agent-utils/src/agent_guards.test.ts @@ -8,6 +8,7 @@ */ import { + hasOpenTelemetryPrefix, isAndroidAgentName, isAWSLambdaAgentName, isAzureFunctionsAgentName, @@ -22,23 +23,42 @@ import { } from './agent_guards'; describe('Agents guards', () => { + it('hasOpenTelemetryPrefix should guard if the passed agent has an OpenTelemetry prefix.', () => { + expect(hasOpenTelemetryPrefix('otlp')).toBe(false); + expect(hasOpenTelemetryPrefix('otlp/nodejs')).toBe(true); + expect(hasOpenTelemetryPrefix('otlp/nodejs/elastic')).toBe(true); + expect(hasOpenTelemetryPrefix('opentelemetry')).toBe(false); + expect(hasOpenTelemetryPrefix('opentelemetry/nodejs')).toBe(true); + expect(hasOpenTelemetryPrefix('opentelemetry/nodejs/elastic')).toBe(true); + expect(hasOpenTelemetryPrefix('not-an-agent')).toBe(false); + }); + it('isOpenTelemetryAgentName should guard if the passed agent is an OpenTelemetry one.', () => { expect(isOpenTelemetryAgentName('otlp')).toBe(true); - expect(isOpenTelemetryAgentName('opentelemetry/java')).toBe(true); - expect(isOpenTelemetryAgentName('opentelemetry/java/opentelemetry-java-instrumentation')).toBe( - true - ); + expect(isOpenTelemetryAgentName('otlp/nodejs')).toBe(true); + expect(isOpenTelemetryAgentName('otlp/nodejs/elastic')).toBe(true); + expect(isOpenTelemetryAgentName('opentelemetry')).toBe(true); + expect(isOpenTelemetryAgentName('opentelemetry/nodejs')).toBe(true); + expect(isOpenTelemetryAgentName('opentelemetry/nodejs/elastic')).toBe(true); expect(isOpenTelemetryAgentName('not-an-agent')).toBe(false); }); it('isJavaAgentName should guard if the passed agent is an Java one.', () => { expect(isJavaAgentName('java')).toBe(true); + expect(isJavaAgentName('otlp/java')).toBe(true); + expect(isJavaAgentName('otlp/java/opentelemetry-java-instrumentation')).toBe(true); expect(isJavaAgentName('opentelemetry/java')).toBe(true); expect(isJavaAgentName('opentelemetry/java/opentelemetry-java-instrumentation')).toBe(true); expect(isJavaAgentName('not-an-agent')).toBe(false); }); it('isRumAgentName should guard if the passed agent is an Rum one.', () => { + expect(isRumAgentName('otlp/webjs')).toBe(true); + expect(isRumAgentName('otlp/webjs/elastic')).toBe(true); + expect(isRumAgentName('otlp/fail')).toBe(false); + expect(isRumAgentName('opentelemetry/webjs')).toBe(true); + expect(isRumAgentName('opentelemetry/webjs/elastic')).toBe(true); + expect(isRumAgentName('opentelemetry/fail')).toBe(false); expect(isRumAgentName('rum-js')).toBe(true); expect(isRumAgentName('not-an-agent')).toBe(false); }); @@ -57,11 +77,23 @@ describe('Agents guards', () => { }); it('isIosAgentName should guard if the passed agent is an Ios one.', () => { + expect(isIosAgentName('otlp/swift/elastic')).toBe(true); + expect(isIosAgentName('otlp/swift')).toBe(true); + expect(isIosAgentName('otlp/fail')).toBe(false); + expect(isIosAgentName('opentelemetry/swift/elastic')).toBe(true); + expect(isIosAgentName('opentelemetry/swift')).toBe(true); + expect(isIosAgentName('opentelemetry/fail')).toBe(false); expect(isIosAgentName('ios/swift')).toBe(true); expect(isIosAgentName('not-an-agent')).toBe(false); }); it('isAndroidAgentName should guard if the passed agent is an Android one.', () => { + expect(isAndroidAgentName('otlp/android/elastic')).toBe(true); + expect(isAndroidAgentName('otlp/android')).toBe(true); + expect(isAndroidAgentName('otlp/fail')).toBe(false); + expect(isAndroidAgentName('opentelemetry/android/elastic')).toBe(true); + expect(isAndroidAgentName('opentelemetry/android')).toBe(true); + expect(isAndroidAgentName('opentelemetry/fail')).toBe(false); expect(isAndroidAgentName('android/java')).toBe(true); expect(isAndroidAgentName('not-an-agent')).toBe(false); }); diff --git a/packages/kbn-elastic-agent-utils/src/agent_guards.ts b/packages/kbn-elastic-agent-utils/src/agent_guards.ts index 4e50f15917b241..8402582f8d9a34 100644 --- a/packages/kbn-elastic-agent-utils/src/agent_guards.ts +++ b/packages/kbn-elastic-agent-utils/src/agent_guards.ts @@ -7,31 +7,52 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { JAVA_AGENT_NAMES, OPEN_TELEMETRY_AGENT_NAMES, RUM_AGENT_NAMES } from './agent_names'; +import { + ANDROID_AGENT_NAMES, + IOS_AGENT_NAMES, + JAVA_AGENT_NAMES, + OPEN_TELEMETRY_AGENT_NAMES, + RUM_AGENT_NAMES, +} from './agent_names'; import type { + AndroidAgentName, + IOSAgentName, JavaAgentName, OpenTelemetryAgentName, RumAgentName, ServerlessType, } from './agent_names'; +export function hasOpenTelemetryPrefix(agentName?: string, language: string = '') { + if (!agentName) { + return false; + } + + return ( + agentName.startsWith(`opentelemetry/${language}`) || agentName.startsWith(`otlp/${language}`) + ); +} + export function isOpenTelemetryAgentName(agentName: string): agentName is OpenTelemetryAgentName { return ( - agentName?.startsWith('opentelemetry/') || + hasOpenTelemetryPrefix(agentName) || OPEN_TELEMETRY_AGENT_NAMES.includes(agentName as OpenTelemetryAgentName) ); } export function isJavaAgentName(agentName?: string): agentName is JavaAgentName { return ( - agentName?.startsWith('opentelemetry/java') || + hasOpenTelemetryPrefix(agentName, 'java') || JAVA_AGENT_NAMES.includes(agentName! as JavaAgentName) ); } export function isRumAgentName(agentName?: string): agentName is RumAgentName { - return RUM_AGENT_NAMES.includes(agentName! as RumAgentName); + return ( + hasOpenTelemetryPrefix(agentName, 'webjs') || + RUM_AGENT_NAMES.includes(agentName! as RumAgentName) + ); } export function isMobileAgentName(agentName?: string) { @@ -43,12 +64,21 @@ export function isRumOrMobileAgentName(agentName?: string) { } export function isIosAgentName(agentName?: string) { - return agentName?.toLowerCase() === 'ios/swift'; + const lowercasedAgentName = agentName && agentName.toLowerCase(); + + return ( + hasOpenTelemetryPrefix(lowercasedAgentName, 'swift') || + IOS_AGENT_NAMES.includes(lowercasedAgentName! as IOSAgentName) + ); } export function isAndroidAgentName(agentName?: string) { - const lowercased = agentName && agentName.toLowerCase(); - return lowercased === 'android/java'; + const lowercasedAgentName = agentName && agentName.toLowerCase(); + + return ( + hasOpenTelemetryPrefix(lowercasedAgentName, 'android') || + ANDROID_AGENT_NAMES.includes(lowercasedAgentName! as AndroidAgentName) + ); } export function isJRubyAgentName(agentName?: string, runtimeName?: string) { diff --git a/packages/kbn-elastic-agent-utils/src/agent_names.ts b/packages/kbn-elastic-agent-utils/src/agent_names.ts index a7553c61587f87..0405da9cf2193d 100644 --- a/packages/kbn-elastic-agent-utils/src/agent_names.ts +++ b/packages/kbn-elastic-agent-utils/src/agent_names.ts @@ -39,6 +39,7 @@ export const ELASTIC_AGENT_NAMES: ElasticAgentName[] = [ export type OpenTelemetryAgentName = | 'otlp' + | 'opentelemetry' | 'opentelemetry/cpp' | 'opentelemetry/dotnet' | 'opentelemetry/erlang' @@ -51,9 +52,23 @@ export type OpenTelemetryAgentName = | 'opentelemetry/rust' | 'opentelemetry/swift' | 'opentelemetry/android' - | 'opentelemetry/webjs'; + | 'opentelemetry/webjs' + | 'otlp/cpp' + | 'otlp/dotnet' + | 'otlp/erlang' + | 'otlp/go' + | 'otlp/java' + | 'otlp/nodejs' + | 'otlp/php' + | 'otlp/python' + | 'otlp/ruby' + | 'otlp/rust' + | 'otlp/swift' + | 'otlp/android' + | 'otlp/webjs'; export const OPEN_TELEMETRY_AGENT_NAMES: OpenTelemetryAgentName[] = [ 'otlp', + 'opentelemetry', 'opentelemetry/cpp', 'opentelemetry/dotnet', 'opentelemetry/erlang', @@ -67,21 +82,57 @@ export const OPEN_TELEMETRY_AGENT_NAMES: OpenTelemetryAgentName[] = [ 'opentelemetry/swift', 'opentelemetry/android', 'opentelemetry/webjs', + 'otlp/cpp', + 'otlp/dotnet', + 'otlp/erlang', + 'otlp/go', + 'otlp/java', + 'otlp/nodejs', + 'otlp/php', + 'otlp/python', + 'otlp/ruby', + 'otlp/rust', + 'otlp/swift', + 'otlp/android', + 'otlp/webjs', ]; -export type JavaAgentName = 'java' | 'opentelemetry/java'; -export const JAVA_AGENT_NAMES: JavaAgentName[] = ['java', 'opentelemetry/java']; +export type JavaAgentName = 'java' | 'opentelemetry/java' | 'otlp/java'; +export const JAVA_AGENT_NAMES: JavaAgentName[] = ['java', 'opentelemetry/java', 'otlp/java']; -export type RumAgentName = 'js-base' | 'rum-js' | 'opentelemetry/webjs'; -export const RUM_AGENT_NAMES: RumAgentName[] = ['js-base', 'rum-js', 'opentelemetry/webjs']; +export type RumAgentName = 'js-base' | 'rum-js' | 'opentelemetry/webjs' | 'otlp/webjs'; +export const RUM_AGENT_NAMES: RumAgentName[] = [ + 'js-base', + 'rum-js', + 'opentelemetry/webjs', + 'otlp/webjs', +]; + +export type AndroidAgentName = 'android/java' | 'opentelemetry/android' | 'otlp/android'; +export const ANDROID_AGENT_NAMES: AndroidAgentName[] = [ + 'android/java', + 'opentelemetry/android', + 'otlp/android', +]; + +export type IOSAgentName = 'ios/swift' | 'opentelemetry/swift' | 'otlp/swift'; +export const IOS_AGENT_NAMES: IOSAgentName[] = ['ios/swift', 'opentelemetry/swift', 'otlp/swift']; export type ServerlessType = 'aws.lambda' | 'azure.functions'; export const SERVERLESS_TYPE: ServerlessType[] = ['aws.lambda', 'azure.functions']; -export type AgentName = ElasticAgentName | OpenTelemetryAgentName | JavaAgentName | RumAgentName; +export type AgentName = + | ElasticAgentName + | OpenTelemetryAgentName + | JavaAgentName + | RumAgentName + | AndroidAgentName + | IOSAgentName; export const AGENT_NAMES: AgentName[] = [ ...ELASTIC_AGENT_NAMES, ...OPEN_TELEMETRY_AGENT_NAMES, ...JAVA_AGENT_NAMES, ...RUM_AGENT_NAMES, + ...ANDROID_AGENT_NAMES, + ...IOS_AGENT_NAMES, ]; diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index ce626c90c2d82b..37507c50e832c7 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -10349,15 +10349,6 @@ } } }, - "observability:searchExcludedDataTiers": { - "type": "array", - "items": { - "type": "keyword", - "_meta": { - "description": "Non-default value of setting." - } - } - }, "banners:placement": { "type": "keyword", "_meta": { @@ -10633,6 +10624,15 @@ "_meta": { "description": "Non-default value of setting." } + }, + "observability:searchExcludedDataTiers": { + "type": "array", + "items": { + "type": "keyword", + "_meta": { + "description": "Non-default value of setting." + } + } } } }, diff --git a/x-pack/plugins/observability_solution/apm/common/__snapshots__/apm_telemetry.test.ts.snap b/x-pack/plugins/observability_solution/apm/common/__snapshots__/apm_telemetry.test.ts.snap index a372355d1db7c6..d0aa75c2170f1b 100644 --- a/x-pack/plugins/observability_solution/apm/common/__snapshots__/apm_telemetry.test.ts.snap +++ b/x-pack/plugins/observability_solution/apm/common/__snapshots__/apm_telemetry.test.ts.snap @@ -85,6 +85,90 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "description": "Total number of services utilizing the otlp agent within the last day" } }, + "otlp/cpp": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/cpp agent within the last day" + } + }, + "otlp/dotnet": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/dotnet agent within the last day" + } + }, + "otlp/erlang": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/erlang agent within the last day" + } + }, + "otlp/go": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/go agent within the last day" + } + }, + "otlp/java": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/java agent within the last day" + } + }, + "otlp/nodejs": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/nodejs agent within the last day" + } + }, + "otlp/php": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/php agent within the last day" + } + }, + "otlp/python": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/python agent within the last day" + } + }, + "otlp/ruby": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/ruby agent within the last day" + } + }, + "otlp/rust": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/rust agent within the last day" + } + }, + "otlp/swift": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/swift agent within the last day" + } + }, + "otlp/android": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/android agent within the last day" + } + }, + "otlp/webjs": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/webjs agent within the last day" + } + }, + "opentelemetry": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry agent within the last day" + } + }, "opentelemetry/cpp": { "type": "long", "_meta": { @@ -162,6 +246,12 @@ exports[`APM telemetry helpers getApmTelemetry generates a JSON object with the "_meta": { "description": "Total number of services utilizing the opentelemetry/webjs agent within the last day" } + }, + "ios/swift": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the ios/swift agent within the last day" + } } } }, diff --git a/x-pack/plugins/observability_solution/apm/common/agent_name.ts b/x-pack/plugins/observability_solution/apm/common/agent_name.ts index 608fdf4975353a..66ff78e3cdbe43 100644 --- a/x-pack/plugins/observability_solution/apm/common/agent_name.ts +++ b/x-pack/plugins/observability_solution/apm/common/agent_name.ts @@ -8,6 +8,7 @@ export { OPEN_TELEMETRY_AGENT_NAMES, AGENT_NAMES, isOpenTelemetryAgentName, + hasOpenTelemetryPrefix, JAVA_AGENT_NAMES, isJavaAgentName, RUM_AGENT_NAMES, diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/index.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/index.tsx index 0888c1a0f6c117..e6780927e755b2 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/index.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/index.tsx @@ -139,9 +139,7 @@ export function ServiceIcons({ start, end, serviceName, environment }: Props) { title: i18n.translate('xpack.apm.serviceIcons.opentelemetry', { defaultMessage: 'OpenTelemetry', }), - component: ( - - ), + component: , }, { key: 'container', diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/otel_details.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/otel_details.tsx index 410d6a98f76440..04aa2b6f568382 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/otel_details.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/service_icons/otel_details.tsx @@ -15,7 +15,6 @@ type ServiceDetailsReturnType = interface Props { opentelemetry: ServiceDetailsReturnType['opentelemetry']; - agentName?: string; } export function OTelDetails({ opentelemetry }: Props) { diff --git a/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/schema.ts b/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/schema.ts index 32c869beb581ff..917237963ef374 100644 --- a/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/schema.ts +++ b/x-pack/plugins/observability_solution/apm/server/lib/apm_telemetry/schema.ts @@ -264,6 +264,92 @@ const apmPerAgentSchema: Pick, 'services_per_agen description: 'Total number of services utilizing the otlp agent within the last day', }, }, + 'otlp/cpp': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/cpp agent within the last day', + }, + }, + 'otlp/dotnet': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/dotnet agent within the last day', + }, + }, + 'otlp/erlang': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/erlang agent within the last day', + }, + }, + 'otlp/go': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/go agent within the last day', + }, + }, + 'otlp/java': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/java agent within the last day', + }, + }, + 'otlp/nodejs': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/nodejs agent within the last day', + }, + }, + 'otlp/php': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/php agent within the last day', + }, + }, + 'otlp/python': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/python agent within the last day', + }, + }, + 'otlp/ruby': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/ruby agent within the last day', + }, + }, + 'otlp/rust': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/rust agent within the last day', + }, + }, + 'otlp/swift': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/swift agent within the last day', + }, + }, + 'otlp/android': { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the otlp/android agent within the last day', + }, + }, + 'otlp/webjs': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the otlp/webjs agent within the last day', + }, + }, + opentelemetry: { + type: 'long', + _meta: { + description: + 'Total number of services utilizing the opentelemetry agent within the last day', + }, + }, 'opentelemetry/cpp': { type: 'long', _meta: { @@ -355,6 +441,12 @@ const apmPerAgentSchema: Pick, 'services_per_agen 'Total number of services utilizing the opentelemetry/webjs agent within the last day', }, }, + 'ios/swift': { + type: 'long', + _meta: { + description: 'Total number of services utilizing the ios/swift agent within the last day', + }, + }, }, agents: { 'android/java': agentSchema, diff --git a/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap b/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap index 3fac4d595a274f..18dd1f4c9835a2 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/observability_solution/apm/server/routes/metrics/__snapshots__/queries.test.ts.snap @@ -174,6 +174,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -440,6 +441,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -522,6 +524,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -720,6 +723,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -998,6 +1002,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -1086,6 +1091,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -1262,6 +1268,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -1518,6 +1525,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, @@ -1595,6 +1603,7 @@ Object { "agent.name": Array [ "java", "opentelemetry/java", + "otlp/java", ], }, }, diff --git a/x-pack/plugins/observability_solution/apm/server/routes/services/get_service_metadata_details.ts b/x-pack/plugins/observability_solution/apm/server/routes/services/get_service_metadata_details.ts index d7a81a7902efb5..fb44638d8a6b0f 100644 --- a/x-pack/plugins/observability_solution/apm/server/routes/services/get_service_metadata_details.ts +++ b/x-pack/plugins/observability_solution/apm/server/routes/services/get_service_metadata_details.ts @@ -32,7 +32,7 @@ import { ContainerType } from '../../../common/service_metadata'; import { TransactionRaw } from '../../../typings/es_schemas/raw/transaction_raw'; import { APMEventClient } from '../../lib/helpers/create_es_client/create_apm_event_client'; import { should } from './get_service_metadata_icons'; -import { isOpenTelemetryAgentName } from '../../../common/agent_name'; +import { isOpenTelemetryAgentName, hasOpenTelemetryPrefix } from '../../../common/agent_name'; type ServiceMetadataDetailsRaw = Pick< TransactionRaw, @@ -190,11 +190,9 @@ export async function getServiceMetadataDetails({ }; const otelDetails = - !!agent?.name && isOpenTelemetryAgentName(agent.name) + Boolean(agent?.name) && isOpenTelemetryAgentName(agent.name) ? { - language: agent.name.startsWith('opentelemetry') - ? agent.name.replace(/^opentelemetry\//, '') - : undefined, + language: hasOpenTelemetryPrefix(agent.name) ? agent.name.split('/')[1] : undefined, sdkVersion: agent?.version, autoVersion: labels?.telemetry_auto_version as string, } diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index ff79fcf4632a37..c58018f20ebb67 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -2808,6 +2808,90 @@ "description": "Total number of services utilizing the otlp agent within the last day" } }, + "otlp/cpp": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/cpp agent within the last day" + } + }, + "otlp/dotnet": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/dotnet agent within the last day" + } + }, + "otlp/erlang": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/erlang agent within the last day" + } + }, + "otlp/go": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/go agent within the last day" + } + }, + "otlp/java": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/java agent within the last day" + } + }, + "otlp/nodejs": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/nodejs agent within the last day" + } + }, + "otlp/php": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/php agent within the last day" + } + }, + "otlp/python": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/python agent within the last day" + } + }, + "otlp/ruby": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/ruby agent within the last day" + } + }, + "otlp/rust": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/rust agent within the last day" + } + }, + "otlp/swift": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/swift agent within the last day" + } + }, + "otlp/android": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/android agent within the last day" + } + }, + "otlp/webjs": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the otlp/webjs agent within the last day" + } + }, + "opentelemetry": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the opentelemetry agent within the last day" + } + }, "opentelemetry/cpp": { "type": "long", "_meta": { @@ -2885,6 +2969,12 @@ "_meta": { "description": "Total number of services utilizing the opentelemetry/webjs agent within the last day" } + }, + "ios/swift": { + "type": "long", + "_meta": { + "description": "Total number of services utilizing the ios/swift agent within the last day" + } } } },