From a3ab583fc19cb9df06c306081acb3c98517b58a3 Mon Sep 17 00:00:00 2001 From: Stuart McCulloch Date: Mon, 21 Oct 2024 13:56:43 +0100 Subject: [PATCH] Identify span metrics from OpenTelemetry libraries with 'otel.library' tag (#4724) Use existing 'otel' tag for other sources of spans, such as manual tracing --- integration-tests/opentelemetry.spec.js | 46 +++++++++++++++++++ packages/dd-trace/src/opentelemetry/span.js | 2 +- packages/dd-trace/src/opentelemetry/tracer.js | 1 + 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/integration-tests/opentelemetry.spec.js b/integration-tests/opentelemetry.spec.js index 73adf812360..ee307568cb4 100644 --- a/integration-tests/opentelemetry.spec.js +++ b/integration-tests/opentelemetry.spec.js @@ -348,6 +348,52 @@ describe('opentelemetry', () => { }, true) }) + it('should capture auto-instrumentation telemetry', async () => { + const SERVER_PORT = 6666 + proc = fork(join(cwd, 'opentelemetry/auto-instrumentation.js'), { + cwd, + env: { + DD_TRACE_AGENT_PORT: agent.port, + DD_TRACE_OTEL_ENABLED: 1, + SERVER_PORT, + DD_TRACE_DISABLED_INSTRUMENTATIONS: 'http,dns,express,net', + DD_TELEMETRY_HEARTBEAT_INTERVAL: 1 + } + }) + await new Promise(resolve => setTimeout(resolve, 1000)) // Adjust the delay as necessary + await axios.get(`http://localhost:${SERVER_PORT}/first-endpoint`) + + return check(agent, proc, 10000, ({ payload }) => { + assert.strictEqual(payload.request_type, 'generate-metrics') + + const metrics = payload.payload + assert.strictEqual(metrics.namespace, 'tracers') + + const spanCreated = metrics.series.find(({ metric }) => metric === 'spans_created') + const spanFinished = metrics.series.find(({ metric }) => metric === 'spans_finished') + + // Validate common fields between start and finish + for (const series of [spanCreated, spanFinished]) { + assert.ok(series) + + assert.strictEqual(series.points.length, 1) + assert.strictEqual(series.points[0].length, 2) + + const [ts, value] = series.points[0] + assert.ok(nearNow(ts, Date.now() / 1e3)) + assert.strictEqual(value, 9) + + assert.strictEqual(series.type, 'count') + assert.strictEqual(series.common, true) + assert.deepStrictEqual(series.tags, [ + 'integration_name:otel.library', + 'otel_enabled:true', + `version:${process.version}` + ]) + } + }, true) + }) + it('should work within existing datadog-traced http request', async () => { proc = fork(join(cwd, 'opentelemetry/server.js'), { cwd, diff --git a/packages/dd-trace/src/opentelemetry/span.js b/packages/dd-trace/src/opentelemetry/span.js index a62902d8457..d2c216c138e 100644 --- a/packages/dd-trace/src/opentelemetry/span.js +++ b/packages/dd-trace/src/opentelemetry/span.js @@ -142,7 +142,7 @@ class Span { context: spanContext._ddContext, startTime, hostname: _tracer._hostname, - integrationName: 'otel', + integrationName: parentTracer?._isOtelLibrary ? 'otel.library' : 'otel', tags: { [SERVICE_NAME]: _tracer._service, [RESOURCE_NAME]: spanName diff --git a/packages/dd-trace/src/opentelemetry/tracer.js b/packages/dd-trace/src/opentelemetry/tracer.js index bb9b81e6ccd..bf2a0c3f86b 100644 --- a/packages/dd-trace/src/opentelemetry/tracer.js +++ b/packages/dd-trace/src/opentelemetry/tracer.js @@ -16,6 +16,7 @@ class Tracer { this._tracerProvider = tracerProvider // Is there a reason this is public? this.instrumentationLibrary = library + this._isOtelLibrary = library?.name?.startsWith('@opentelemetry/instrumentation-') this._spanLimits = {} }