diff --git a/integration-tests/opentelemetry.spec.js b/integration-tests/opentelemetry.spec.js index 4e6864a40ab..94fb4856b2f 100644 --- a/integration-tests/opentelemetry.spec.js +++ b/integration-tests/opentelemetry.spec.js @@ -45,7 +45,12 @@ describe('opentelemetry', () => { const timeout = 5000 before(async () => { - sandbox = await createSandbox() + sandbox = await createSandbox([ + '@opentelemetry/api', + '@opentelemetry/sdk-node', + // Needed because sdk-node doesn't start a tracer without an exporter + '@opentelemetry/exporter-jaeger' + ]) cwd = sandbox.folder agent = await new FakeAgent().start() }) @@ -102,4 +107,23 @@ describe('opentelemetry', () => { assert.strictEqual(ddSpan.parent_id.toString(), otelSpan.span_id.toString()) }) }) + + it('should auto-instrument @opentelemetry/sdk-node', async () => { + proc = fork(join(cwd, 'opentelemetry/env-var.js'), { + cwd, + env: { + DD_TRACE_AGENT_PORT: agent.port + } + }) + return check(agent, proc, timeout, ({ payload }) => { + // Should have a single trace with a single span + assert.strictEqual(payload.length, 1) + const [trace] = payload + assert.strictEqual(trace.length, 1) + const [span] = trace + + // Should be the expected otel span + assert.strictEqual(span.name, 'otel-sub') + }) + }) }) diff --git a/integration-tests/opentelemetry/env-var.js b/integration-tests/opentelemetry/env-var.js new file mode 100644 index 00000000000..42148bcfc3e --- /dev/null +++ b/integration-tests/opentelemetry/env-var.js @@ -0,0 +1,24 @@ +'use strict' + +process.env.DD_TRACE_OTEL_ENABLED = '1' + +require('dd-trace').init() + +const opentelemetry = require('@opentelemetry/sdk-node') +const { JaegerExporter } = require('@opentelemetry/exporter-jaeger') + +const sdk = new opentelemetry.NodeSDK({ + traceExporter: new JaegerExporter() +}) + +sdk.start() + +const otelTracer = opentelemetry.api.trace.getTracer( + 'my-service-tracer' +) + +otelTracer.startActiveSpan('otel-sub', otelSpan => { + setImmediate(() => { + otelSpan.end() + }) +}) diff --git a/packages/datadog-instrumentations/src/helpers/hooks.js b/packages/datadog-instrumentations/src/helpers/hooks.js index ed63465ac40..a717b484a0f 100644 --- a/packages/datadog-instrumentations/src/helpers/hooks.js +++ b/packages/datadog-instrumentations/src/helpers/hooks.js @@ -14,6 +14,7 @@ module.exports = { '@koa/router': () => require('../koa'), '@node-redis/client': () => require('../redis'), '@opensearch-project/opensearch': () => require('../opensearch'), + '@opentelemetry/sdk-trace-node': () => require('../otel-sdk-trace'), '@redis/client': () => require('../redis'), 'amqp10': () => require('../amqp10'), 'amqplib': () => require('../amqplib'), diff --git a/packages/datadog-instrumentations/src/otel-sdk-trace.js b/packages/datadog-instrumentations/src/otel-sdk-trace.js new file mode 100644 index 00000000000..319a2fda2f3 --- /dev/null +++ b/packages/datadog-instrumentations/src/otel-sdk-trace.js @@ -0,0 +1,18 @@ +'use strict' + +const { addHook } = require('./helpers/instrument') +const shimmer = require('../../datadog-shimmer') +const tracer = require('../../dd-trace') + +if (process.env.DD_TRACE_OTEL_ENABLED) { + addHook({ + name: '@opentelemetry/sdk-trace-node', + file: 'build/src/NodeTracerProvider.js', + versions: ['*'] + }, (mod) => { + shimmer.wrap(mod, 'NodeTracerProvider', () => { + return tracer.TracerProvider + }) + return mod + }) +} diff --git a/packages/dd-trace/src/noop/proxy.js b/packages/dd-trace/src/noop/proxy.js index 30a1d0602d2..90107eb6a79 100644 --- a/packages/dd-trace/src/noop/proxy.js +++ b/packages/dd-trace/src/noop/proxy.js @@ -85,6 +85,10 @@ class Tracer { this.appsec.setUser(user) return this } + + get TracerProvider () { + return require('../opentelemetry/tracer_provider') + } } module.exports = Tracer diff --git a/packages/dd-trace/src/opentelemetry/context_manager.js b/packages/dd-trace/src/opentelemetry/context_manager.js index c751a5d6fe3..03e9bf8f647 100644 --- a/packages/dd-trace/src/opentelemetry/context_manager.js +++ b/packages/dd-trace/src/opentelemetry/context_manager.js @@ -62,7 +62,7 @@ class ContextManager { bind (context, target) { const self = this return function (...args) { - return self.with(context, target, this, args) + return self.with(context, target, this, ...args) } } diff --git a/yarn.lock b/yarn.lock index f522f3d62da..48e9a84167f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -557,17 +557,17 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.1.tgz#ff22eb2e5d476fbc2450a196e40dd243cc20c28f" integrity sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA== -"@opentelemetry/core@<1.4.0": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.3.1.tgz#6eef5c5efca9a4cd7daa0cd4c7ff28ca2317c8d7" - integrity sha512-k7lOC86N7WIyUZsUuSKZfFIrUtINtlauMGQsC1r7jNmcr0vVJGqK1ROBvt7WWMxLbpMnt1q2pXJO8tKu0b9auA== +"@opentelemetry/core@^1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.14.0.tgz#64e876b29cb736c984d54164cd47433f513eafd3" + integrity sha512-MnMZ+sxsnlzloeuXL2nm5QcNczt/iO82UOeQQDHhV83F2fP3sgntW2evvtoxJki0MBLxEsh5ADD7PR/Hn5uzjw== dependencies: - "@opentelemetry/semantic-conventions" "1.3.1" + "@opentelemetry/semantic-conventions" "1.14.0" -"@opentelemetry/semantic-conventions@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.3.1.tgz#ba07b864a3c955f061aa30ea3ef7f4ae4449794a" - integrity sha512-wU5J8rUoo32oSef/rFpOT1HIjLjAv3qIDHkw1QIhODV3OpAVHi5oVzlouozg9obUmZKtbZ0qUe/m7FP0y0yBzA== +"@opentelemetry/semantic-conventions@1.14.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.14.0.tgz#6a729b7f372ce30f77a3f217c09bc216f863fccb" + integrity sha512-rJfCY8rCWz3cb4KI6pEofnytvMPuj3YLQwoscCCYZ5DkdiPjo15IQ0US7+mjcWy9H3fcZIzf2pbJZ7ck/h4tug== "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2"