Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ require,@datadog/openfeature-node-server,Apache license 2.0,Copyright 2024 Datad
require,@datadog/pprof,Apache license 2.0,Copyright 2019 Google Inc.
require,@datadog/sketches-js,Apache license 2.0,Copyright 2020 Datadog Inc.
require,@datadog/wasm-js-rewriter,Apache license 2.0,Copyright 2018 Datadog Inc.
require,@opentelemetry/api,Apache license 2.0,Copyright OpenTelemetry Authors
require,@opentelemetry/api-logs,Apache license 2.0,Copyright OpenTelemetry Authors
require,@opentelemetry/core,Apache license 2.0,Copyright OpenTelemetry Authors
require,@opentelemetry/resources,Apache license 2.0,Copyright OpenTelemetry Authors
require,@isaacs/ttlcache,Blue Oak,Copyright Isaac Z. Schlueter and Contributors
require,crypto-randomuuid,MIT,Copyright 2021 Node.js Foundation and contributors
require,dc-polyfill,MIT,Copyright 2023 Datadog Inc.
Expand All @@ -36,6 +32,10 @@ require,semifies,Apache license 2.0,Copyright Authors
require,shell-quote,mit,Copyright (c) 2013 James Halliday
require,source-map,BSD-3-Clause,Copyright (c) 2009-2011, Mozilla Foundation and contributors
require,ttl-set,MIT,Copyright (c) 2024 Thomas Watson
dev,@opentelemetry/api,Apache license 2.0,Copyright OpenTelemetry Authors
dev,@opentelemetry/api-logs,Apache license 2.0,Copyright OpenTelemetry Authors
dev,@opentelemetry/core,Apache license 2.0,Copyright OpenTelemetry Authors
dev,@opentelemetry/resources,Apache license 2.0,Copyright OpenTelemetry Authors
dev,@babel/helpers,MIT,Copyright (c) 2014-present Sebastian McKenzie and other contributors
dev,@types/chai,MIT,Copyright (c) Microsoft Corp.
dev,@types/mocha,MIT,Copyright (c) Microsoft Corp.
Expand Down
16 changes: 14 additions & 2 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,17 @@ The following tags are available to override Datadog-specific options:

<h2 id="opentelemetry-api">OpenTelemetry Compatibility</h2>

This library is OpenTelemetry compliant. Use the [OpenTelemetry API](https://opentelemetry.io/docs/instrumentation/js/) and the Datadog Tracer (dd-trace) library to measure execution times for specific pieces of code. In the following example, a Datadog TracerProvider is registered with @opentelemetry/api:
This library is OpenTelemetry compliant. The OpenTelemetry API packages (`@opentelemetry/api` and `@opentelemetry/api-logs`) are peer dependencies and must be installed separately.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add a warning in case a user tries to use any of the otel APIs with a missing dependency and a potential fix?

@rochdev or @bengl PTAL. I am uncertain in what way it is fine to log the warning or not.


Install the required packages:

```bash
npm install @opentelemetry/api
# For OpenTelemetry logs support (optional)
npm install @opentelemetry/api-logs
```

Use the [OpenTelemetry API](https://opentelemetry.io/docs/instrumentation/js/) and the Datadog Tracer (dd-trace) library to measure execution times for specific pieces of code. In the following example, a Datadog TracerProvider is registered with @opentelemetry/api:

```javascript
const tracer = require('dd-trace').init()
Expand All @@ -381,7 +391,9 @@ The following attributes are available to override Datadog-specific options:

<h3 id="opentelemetry-logs">OpenTelemetry Logs</h3>

dd-trace-js includes experimental support for OpenTelemetry logs, designed as a drop-in replacement for the OpenTelemetry SDK. This support is primarily intended for logging libraries rather than direct user configuration. Enable it by setting `DD_LOGS_OTEL_ENABLED=true` and use the [OpenTelemetry Logs API](https://open-telemetry.github.io/opentelemetry-js/modules/_opentelemetry_api-logs.html) to emit structured log data:
dd-trace-js includes experimental support for OpenTelemetry logs, designed as a drop-in replacement for the OpenTelemetry SDK. This support is primarily intended for logging libraries rather than direct user configuration. The `@opentelemetry/api-logs` package is a peer dependency and must be installed separately. If it is not installed, OpenTelemetry logs functionality is not available.

Enable it by setting `DD_LOGS_OTEL_ENABLED=true` and use the [OpenTelemetry Logs API](https://open-telemetry.github.io/opentelemetry-js/modules/_opentelemetry_api-logs.html) to emit structured log data:

```javascript
require('dd-trace').init()
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/opentelemetry.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe('opentelemetry', () => {
let cwd
const timeout = 5000
const dependencies = [
'@opentelemetry/api@1.8.0',
'@opentelemetry/api@1.9.0',
'@opentelemetry/instrumentation',
'@opentelemetry/instrumentation-http',
'@opentelemetry/[email protected]',
Expand Down
28 changes: 24 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,6 @@
"@datadog/sketches-js": "2.1.1",
"@datadog/wasm-js-rewriter": "5.0.1",
"@isaacs/ttlcache": "^2.0.1",
"@opentelemetry/api": ">=1.0.0 <1.10.0",
"@opentelemetry/api-logs": "<1.0.0",
"@opentelemetry/core": ">=1.14.0 <1.31.0",
"@opentelemetry/resources": ">=1.0.0 <1.31.0",
"crypto-randomuuid": "^1.0.0",
"dc-polyfill": "^0.1.10",
"escape-string-regexp": "^5.0.0",
Expand All @@ -161,13 +157,37 @@
"tlhunter-sorted-set": "^0.1.0",
"ttl-set": "^1.0.0"
},
"peerDependencies": {
"@opentelemetry/api": ">=1.0.0 <1.10.0",
"@opentelemetry/api-logs": "<1.0.0",
"@opentelemetry/core": ">=1.14.0 <1.31.0",
"@opentelemetry/resources": ">=1.0.0 <1.31.0"
},
"peerDependenciesMeta": {
"@opentelemetry/api": {
"optional": true
},
"@opentelemetry/api-logs": {
"optional": true
},
"@opentelemetry/core": {
"optional": true
},
"@opentelemetry/resources": {
"optional": true
}
},
"devDependencies": {
"@babel/helpers": "^7.28.4",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.39.0",
"@msgpack/msgpack": "^3.1.2",
"@openfeature/core": "^1.9.0",
"@openfeature/server-sdk": "~1.20.0",
"@opentelemetry/api": ">=1.0.0 <1.10.0",
"@opentelemetry/api-logs": "<1.0.0",
"@opentelemetry/core": ">=1.14.0 <1.31.0",
"@opentelemetry/resources": ">=1.0.0 <1.31.0",
"@stylistic/eslint-plugin": "^5.5.0",
"@types/chai": "^4.3.16",
"@types/mocha": "^10.0.10",
Expand Down
33 changes: 33 additions & 0 deletions packages/datadog-esbuild/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,39 @@ ${build.initialOptions.banner.js}`
} catch (error) {
build.initialOptions.external ??= []
build.initialOptions.external.push('@openfeature/core')
externalModules.add('@openfeature/core')
}

try {
require.resolve('@opentelemetry/api')
} catch (error) {
build.initialOptions.external ??= []
build.initialOptions.external.push('@opentelemetry/api')
externalModules.add('@opentelemetry/api')
}

try {
require.resolve('@opentelemetry/api-logs')
} catch (error) {
build.initialOptions.external ??= []
build.initialOptions.external.push('@opentelemetry/api-logs')
externalModules.add('@opentelemetry/api-logs')
}

try {
require.resolve('@opentelemetry/core')
} catch (error) {
build.initialOptions.external ??= []
build.initialOptions.external.push('@opentelemetry/core')
externalModules.add('@opentelemetry/core')
}

try {
require.resolve('@opentelemetry/resources')
} catch (error) {
build.initialOptions.external ??= []
build.initialOptions.external.push('@opentelemetry/resources')
externalModules.add('@opentelemetry/resources')
}

const esmBuild = isESMBuild(build)
Expand Down
6 changes: 5 additions & 1 deletion packages/dd-trace/src/noop/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ class NoopProxy {
}

get TracerProvider () {
return require('../opentelemetry/tracer_provider')
const { checkOpenTelemetryAPIDeps } = require('../opentelemetry/check_peer_deps')
if (checkOpenTelemetryAPIDeps()) {
return require('../opentelemetry/tracer_provider')
}
return require('../opentelemetry/noop/tracer_provider')
}
}

Expand Down
59 changes: 59 additions & 0 deletions packages/dd-trace/src/opentelemetry/check_peer_deps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict'

const log = require('../log')

/**
* Checks if OpenTelemetry Core and Resources peer dependencies are available.
* @returns {boolean} True if dependencies are available, false otherwise
*/
function checkOpenTelemetryHelpers () {
let available = true
try {
require.resolve('@opentelemetry/core')
} catch {
log.warn('Failed to resolve @opentelemetry/core. Install it with: npm install @opentelemetry/core')
available = false
}
try {
require.resolve('@opentelemetry/resources')
} catch {
log.warn('Failed to resolve @opentelemetry/resources. Install it with: npm install @opentelemetry/resources')
available = false
}
return available
}

/**
* Checks if OpenTelemetry peer dependencies are available.
* @returns {boolean} True if dependencies are available, false otherwise
*/
function checkOpenTelemetryAPIDeps () {
try {
require.resolve('@opentelemetry/api')
} catch {
log.warn('Failed to resolve @opentelemetry/api. Install it with: npm install @opentelemetry/api')
checkOpenTelemetryHelpers()
return false
}
return checkOpenTelemetryHelpers()
}

/**
* Checks if OpenTelemetry API Logs peer dependency is available.
* @returns {boolean} True if dependencies are available, false otherwise
*/
function checkOpenTelemetryLogsApiDeps () {
let available = checkOpenTelemetryAPIDeps()
try {
require.resolve('@opentelemetry/api-logs')
} catch {
log.warn('Failed to resolve @opentelemetry/api-logs. Install it with: npm install @opentelemetry/api-logs')
available = false
}
return available
}

module.exports = {
checkOpenTelemetryAPIDeps,
checkOpenTelemetryLogsApiDeps
}
49 changes: 49 additions & 0 deletions packages/dd-trace/src/opentelemetry/noop/tracer_provider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict'

const noopSpan = {
spanContext: () => ({}),
setAttribute: () => {},
setAttributes: () => {},
addEvent: () => {},
updateName: () => {},
setStatus: () => {},
end: () => {},
isRecording: () => false
}

const noopTracer = {
startSpan: () => noopSpan,
startActiveSpan: () => noopSpan,
}

const noopSpanProcessor = {
onStart: () => {},
onEnd: () => {},
shutdown: () => Promise.resolve(),
forceFlush: () => Promise.resolve()
}

class NoopTracerProvider {
constructor (config = {}) {
this.config = config
this.resource = config.resource
}

getTracer () {
return noopTracer
}

addSpanProcessor () {}

getActiveSpanProcessor () {
return noopSpanProcessor
}

register () {}

forceFlush () {}

shutdown () {}
}

module.exports = NoopTracerProvider
12 changes: 9 additions & 3 deletions packages/dd-trace/src/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,10 @@ class Tracer extends NoopProxy {
}

if (config.otelLogsEnabled) {
const { initializeOpenTelemetryLogs } = require('./opentelemetry/logs')
initializeOpenTelemetryLogs(config)
const { checkOpenTelemetryLogsApiDeps } = require('./opentelemetry/check_peer_deps')
if (checkOpenTelemetryLogsApiDeps()) {
require('./opentelemetry/logs').initializeOpenTelemetryLogs(config)
}
}

if (config.isTestDynamicInstrumentationEnabled) {
Expand Down Expand Up @@ -311,7 +313,11 @@ class Tracer extends NoopProxy {
* @override
*/
get TracerProvider () {
return require('./opentelemetry/tracer_provider')
const { checkOpenTelemetryAPIDeps } = require('./opentelemetry/check_peer_deps')
if (checkOpenTelemetryAPIDeps()) {
return require('./opentelemetry/tracer_provider')
}
return require('./opentelemetry/noop/tracer_provider')
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ describe('typescript', () => {
// TODO: Figure out the real version without using `npm show` as it causes rate limit errors.
context(`with version ${version}`, () => {
useSandbox(
[`typescript@${version}`], false, ['./packages/dd-trace/test/llmobs/sdk/typescript/*']
[`typescript@${version}`, '@opentelemetry/api'], false, ['./packages/dd-trace/test/llmobs/sdk/typescript/*']
)

beforeEach(async () => {
Expand Down
Loading
Loading