dd-trace 5.97.0 → 5.99.0

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 (175) hide show
  1. package/LICENSE-3rdparty.csv +0 -1
  2. package/ext/tags.js +1 -0
  3. package/index.d.ts +35 -3
  4. package/package.json +48 -46
  5. package/packages/datadog-instrumentations/src/crypto.js +45 -0
  6. package/packages/datadog-instrumentations/src/cucumber.js +65 -3
  7. package/packages/datadog-instrumentations/src/cypress-config.js +153 -53
  8. package/packages/datadog-instrumentations/src/dns.js +24 -56
  9. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  10. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +74 -0
  11. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +4 -1
  12. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  13. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +10 -3
  14. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  15. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/modelcontextprotocol-sdk.js +59 -0
  16. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +11 -2
  17. package/packages/datadog-instrumentations/src/jest.js +104 -12
  18. package/packages/datadog-instrumentations/src/mocha/utils.js +8 -0
  19. package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +7 -0
  20. package/packages/datadog-instrumentations/src/pino.js +4 -28
  21. package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +27 -0
  22. package/packages/datadog-instrumentations/src/playwright.js +5 -17
  23. package/packages/datadog-instrumentations/src/redis.js +12 -6
  24. package/packages/datadog-instrumentations/src/stripe.js +38 -24
  25. package/packages/datadog-instrumentations/src/vitest.js +32 -4
  26. package/packages/datadog-instrumentations/src/zlib.js +29 -0
  27. package/packages/datadog-plugin-aws-sdk/src/base.js +2 -3
  28. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
  29. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
  30. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
  31. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
  32. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
  33. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
  34. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +8 -15
  35. package/packages/datadog-plugin-azure-service-bus/src/producer.js +4 -9
  36. package/packages/datadog-plugin-cucumber/src/index.js +8 -2
  37. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +114 -6
  38. package/packages/datadog-plugin-cypress/src/index.js +59 -2
  39. package/packages/datadog-plugin-cypress/src/source-map-utils.js +48 -1
  40. package/packages/datadog-plugin-fs/src/index.js +1 -1
  41. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
  42. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
  43. package/packages/datadog-plugin-http/src/client.js +1 -1
  44. package/packages/datadog-plugin-http/src/server.js +21 -13
  45. package/packages/datadog-plugin-http2/src/client.js +1 -1
  46. package/packages/datadog-plugin-http2/src/server.js +10 -2
  47. package/packages/datadog-plugin-jest/src/index.js +2 -2
  48. package/packages/datadog-plugin-mocha/src/index.js +1 -2
  49. package/packages/datadog-plugin-modelcontextprotocol-sdk/src/index.js +24 -0
  50. package/packages/datadog-plugin-modelcontextprotocol-sdk/src/tracing.js +55 -0
  51. package/packages/datadog-plugin-mongodb-core/src/index.js +4 -9
  52. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  53. package/packages/datadog-plugin-next/src/index.js +8 -2
  54. package/packages/datadog-plugin-pg/src/index.js +1 -1
  55. package/packages/datadog-plugin-playwright/src/index.js +2 -3
  56. package/packages/datadog-plugin-tedious/src/index.js +1 -1
  57. package/packages/datadog-plugin-vitest/src/index.js +14 -6
  58. package/packages/datadog-plugin-ws/src/close.js +3 -1
  59. package/packages/datadog-plugin-ws/src/producer.js +2 -0
  60. package/packages/datadog-plugin-ws/src/receiver.js +2 -1
  61. package/packages/dd-trace/src/aiguard/channels.js +8 -0
  62. package/packages/dd-trace/src/aiguard/index.js +7 -3
  63. package/packages/dd-trace/src/aiguard/sdk.js +66 -22
  64. package/packages/dd-trace/src/aiguard/tags.js +1 -0
  65. package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
  66. package/packages/dd-trace/src/appsec/blocking.js +62 -34
  67. package/packages/dd-trace/src/appsec/graphql.js +6 -6
  68. package/packages/dd-trace/src/appsec/index.js +9 -11
  69. package/packages/dd-trace/src/appsec/rasp/command_injection.js +4 -5
  70. package/packages/dd-trace/src/appsec/rasp/lfi.js +8 -4
  71. package/packages/dd-trace/src/appsec/rasp/sql_injection.js +5 -10
  72. package/packages/dd-trace/src/appsec/rasp/ssrf.js +5 -6
  73. package/packages/dd-trace/src/appsec/recommended.json +2438 -13
  74. package/packages/dd-trace/src/appsec/reporter.js +6 -5
  75. package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
  76. package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
  77. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +6 -10
  78. package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
  79. package/packages/dd-trace/src/appsec/store.js +50 -0
  80. package/packages/dd-trace/src/appsec/waf/index.js +3 -5
  81. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
  82. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
  83. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -2
  84. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  85. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -4
  86. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
  87. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -5
  88. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +3 -4
  89. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +6 -6
  90. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +2 -2
  91. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
  92. package/packages/dd-trace/src/config/config-types.d.ts +0 -4
  93. package/packages/dd-trace/src/config/defaults.js +10 -11
  94. package/packages/dd-trace/src/config/generated-config-types.d.ts +14 -8
  95. package/packages/dd-trace/src/config/index.js +49 -32
  96. package/packages/dd-trace/src/config/parsers.js +26 -9
  97. package/packages/dd-trace/src/config/supported-configurations.json +86 -33
  98. package/packages/dd-trace/src/constants.js +1 -0
  99. package/packages/dd-trace/src/debugger/config.js +2 -0
  100. package/packages/dd-trace/src/debugger/devtools_client/send.js +25 -5
  101. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
  102. package/packages/dd-trace/src/encode/0.4.js +11 -11
  103. package/packages/dd-trace/src/encode/span-stats.js +4 -1
  104. package/packages/dd-trace/src/exporters/agent/index.js +0 -1
  105. package/packages/dd-trace/src/exporters/agent/writer.js +1 -2
  106. package/packages/dd-trace/src/exporters/agentless/writer.js +3 -3
  107. package/packages/dd-trace/src/exporters/common/util.js +2 -2
  108. package/packages/dd-trace/src/id.js +2 -0
  109. package/packages/dd-trace/src/index.js +2 -5
  110. package/packages/dd-trace/src/lambda/handler.js +1 -3
  111. package/packages/dd-trace/src/llmobs/plugins/{anthropic.js → anthropic/index.js} +5 -63
  112. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +106 -0
  113. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +3 -2
  114. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +3 -2
  115. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +2 -1
  116. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +0 -49
  117. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +2 -1
  118. package/packages/dd-trace/src/llmobs/plugins/langchain/messages.js +76 -0
  119. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -26
  120. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/index.js +68 -0
  121. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +57 -0
  122. package/packages/dd-trace/src/llmobs/sdk.js +2 -2
  123. package/packages/dd-trace/src/log/index.js +0 -10
  124. package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +103 -0
  125. package/packages/dd-trace/src/openfeature/flagging_provider.js +3 -0
  126. package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
  127. package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
  128. package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
  129. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +3 -2
  130. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  131. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +3 -2
  132. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +19 -51
  133. package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
  134. package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
  135. package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
  136. package/packages/dd-trace/src/opentelemetry/trace/index.js +70 -0
  137. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +74 -0
  138. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +342 -0
  139. package/packages/dd-trace/src/opentelemetry/tracer.js +9 -11
  140. package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -10
  141. package/packages/dd-trace/src/opentracing/span.js +1 -1
  142. package/packages/dd-trace/src/opentracing/tracer.js +17 -5
  143. package/packages/dd-trace/src/plugins/index.js +1 -0
  144. package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
  145. package/packages/dd-trace/src/plugins/plugin.js +6 -11
  146. package/packages/dd-trace/src/plugins/storage.js +2 -2
  147. package/packages/dd-trace/src/plugins/tracing.js +22 -5
  148. package/packages/dd-trace/src/plugins/util/test.js +128 -5
  149. package/packages/dd-trace/src/plugins/util/url.js +2 -1
  150. package/packages/dd-trace/src/plugins/util/web.js +6 -88
  151. package/packages/dd-trace/src/profiling/profiler.js +34 -77
  152. package/packages/dd-trace/src/profiling/profilers/event_plugins/crypto.js +32 -0
  153. package/packages/dd-trace/src/profiling/profilers/event_plugins/zlib.js +19 -0
  154. package/packages/dd-trace/src/profiling/profilers/events.js +35 -0
  155. package/packages/dd-trace/src/proxy.js +3 -4
  156. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +17 -13
  157. package/packages/dd-trace/src/service-naming/index.js +1 -1
  158. package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
  159. package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
  160. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
  161. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
  162. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +21 -1
  163. package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
  164. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
  165. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +15 -1
  166. package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
  167. package/packages/dd-trace/src/span_processor.js +1 -2
  168. package/packages/dd-trace/src/span_stats.js +5 -1
  169. package/packages/dd-trace/src/tagger.js +2 -2
  170. package/packages/dd-trace/src/telemetry/send-data.js +5 -7
  171. package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
  172. package/vendor/dist/protobufjs/index.js +1 -1
  173. package/packages/dd-trace/src/log/utils.js +0 -16
  174. package/vendor/dist/ignore/LICENSE +0 -21
  175. package/vendor/dist/ignore/index.js +0 -1
@@ -0,0 +1,57 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Formats tool call input as a JSON string.
5
+ * @param {string} toolName - The name of the tool being called
6
+ * @param {object} toolArguments - The arguments passed to the tool
7
+ * @returns {string} Formatted input string
8
+ */
9
+ function formatInput (toolName, toolArguments) {
10
+ if (!toolName && !toolArguments) return ''
11
+
12
+ if (toolArguments === undefined || toolArguments === null) {
13
+ return toolName || ''
14
+ }
15
+
16
+ try {
17
+ return JSON.stringify({ name: toolName, arguments: toolArguments })
18
+ } catch {
19
+ return toolName || ''
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Formats MCP tool call result as a structured object matching Python's output format.
25
+ * MCP tool results contain a `content` array with items like:
26
+ * `[{ type: 'text', text: '...' }, { type: 'image', data: '...', mimeType: '...' }]`
27
+ * @param {object} result - The MCP CallToolResult
28
+ * @returns {string} JSON string of `{ content: Array<{type, text, annotations, meta}>, isError: boolean }`
29
+ */
30
+ function formatOutput (result) {
31
+ if (!result) return ''
32
+
33
+ const content = result.content
34
+ const isError = result.isError || false
35
+
36
+ const processed = []
37
+ if (Array.isArray(content)) {
38
+ for (const item of content) {
39
+ if (item.type !== 'text') continue
40
+ const contentBlock = {
41
+ type: item.type,
42
+ text: item.text || '',
43
+ annotations: item.annotations || {},
44
+ meta: item._meta || {},
45
+ }
46
+ processed.push(contentBlock)
47
+ }
48
+ }
49
+
50
+ try {
51
+ return JSON.stringify({ content: processed, isError })
52
+ } catch {
53
+ return ''
54
+ }
55
+ }
56
+
57
+ module.exports = { formatInput, formatOutput }
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { channel } = require('dc-polyfill')
4
4
 
5
- const { isTrue, isError } = require('../util')
5
+ const { isError, isTrue } = require('../util')
6
6
  const tracerVersion = require('../../../../package.json').version
7
7
  const logger = require('../log')
8
8
  const { getValueFromEnvSources } = require('../config/helper')
@@ -427,7 +427,7 @@ class LLMObs extends NoopLLMObs {
427
427
  }
428
428
 
429
429
  // When OTel tracing is enabled, add source:otel tag to allow backend to wait for OTel span conversion
430
- if (isTrue(getValueFromEnvSources('DD_TRACE_OTEL_ENABLED'))) {
430
+ if (this._config.DD_TRACE_OTEL_ENABLED) {
431
431
  evaluationTags.source = 'otel'
432
432
  }
433
433
 
@@ -8,7 +8,6 @@ const { getValueFromEnvSources } = require('../config/helper')
8
8
  const { traceChannel, debugChannel, infoChannel, warnChannel, errorChannel } = require('./channels')
9
9
  const logWriter = require('./writer')
10
10
  const { Log, LogConfig, NoTransmitError } = require('./log')
11
- const { memoize } = require('./utils')
12
11
 
13
12
  const config = {
14
13
  enabled: defaults.DD_TRACE_DEBUG,
@@ -16,11 +15,6 @@ const config = {
16
15
  logLevel: defaults.logLevel,
17
16
  }
18
17
 
19
- const deprecate = memoize((code, message) => {
20
- publishFormatted(errorChannel, null, message)
21
- return true
22
- })
23
-
24
18
  // In most places where we know we want to mute a log we use log.error() directly
25
19
  const NO_TRANSMIT = new LogConfig(false)
26
20
 
@@ -82,10 +76,6 @@ const log = {
82
76
  return log
83
77
  },
84
78
 
85
- deprecate (code, message) {
86
- return deprecate(code, message)
87
- },
88
-
89
79
  configure (options) {
90
80
  config.logger = options.logger
91
81
  config.logLevel = options.logLevel ??
@@ -0,0 +1,103 @@
1
+ 'use strict'
2
+
3
+ const log = require('../log')
4
+
5
+ const METER_NAME = 'dd-trace-js/openfeature'
6
+ const COUNTER_NAME = 'feature_flag.evaluations'
7
+ const COUNTER_DESCRIPTION = 'Number of feature flag evaluations'
8
+ const COUNTER_UNIT = '{evaluation}'
9
+
10
+ /**
11
+ * OpenFeature hook that tracks feature flag evaluation metrics using an
12
+ * OpenTelemetry counter.
13
+ *
14
+ * Implements the OpenFeature `finally` hook interface so it can be pushed
15
+ * directly onto a provider's `hooks` array. We use the `finally` stage
16
+ * (not diagnostic channels inside the provider's `resolve*` methods) because
17
+ * the OpenFeature SDK short-circuits before calling the provider when it is in
18
+ * NOT_READY state; the `finally` hook still fires, ensuring all evaluations are
19
+ * captured. It also catches type-mismatch errors detected by the SDK client
20
+ * after the provider returns.
21
+ *
22
+ * The counter is created lazily on the first successful `finally()` call rather
23
+ * than in the constructor. This is necessary because `FlaggingProvider` is
24
+ * constructed eagerly by `proxy.js#updateTracing()`, which runs *before*
25
+ * `initializeOpenTelemetryMetrics()` sets the global OTel meter provider.
26
+ * Calling `getMeter()` in the constructor would return the noop meter and
27
+ * produce a noop counter that silently discards all measurements. By deferring
28
+ * to `finally()` time we give the meter provider a chance to be set up first.
29
+ *
30
+ * If counter creation fails (e.g. the OTel API is not yet available), the call
31
+ * is silently skipped and retried on the next `finally()` invocation.
32
+ *
33
+ * When `config.otelMetricsEnabled` is false, `finally()` is always a no-op.
34
+ */
35
+ class EvalMetricsHook {
36
+ #enabled = false
37
+ #counter = null
38
+
39
+ /**
40
+ * @param {import('../config')} config - Tracer configuration object
41
+ */
42
+ constructor (config) {
43
+ this.#enabled = config.otelMetricsEnabled === true
44
+ }
45
+
46
+ /**
47
+ * Returns the OTel counter, creating it on first successful call.
48
+ * Returns `null` if counter creation fails; will retry on next call.
49
+ *
50
+ * @returns {import('@opentelemetry/api').Counter | null}
51
+ */
52
+ #getCounter () {
53
+ if (this.#counter) return this.#counter
54
+
55
+ try {
56
+ const { metrics } = require('@opentelemetry/api')
57
+ const meter = metrics.getMeter(METER_NAME)
58
+ this.#counter = meter.createCounter(COUNTER_NAME, {
59
+ description: COUNTER_DESCRIPTION,
60
+ unit: COUNTER_UNIT,
61
+ })
62
+ } catch (e) {
63
+ log.warn('EvalMetricsHook: failed to create counter: %s', e.message)
64
+ }
65
+
66
+ return this.#counter
67
+ }
68
+
69
+ /**
70
+ * Called by the OpenFeature SDK after every flag evaluation (success or error).
71
+ *
72
+ * @param {{ flagKey: string }} hookContext - Hook context containing the flag key
73
+ * @param {{ variant?: string, reason?: string, errorCode?: string, flagMetadata?: object }} evaluationDetails
74
+ * - Full evaluation details
75
+ * @returns {void}
76
+ */
77
+ finally (hookContext, evaluationDetails) {
78
+ if (!this.#enabled) return
79
+
80
+ const counter = this.#getCounter()
81
+ if (!counter) return
82
+
83
+ const attributes = {
84
+ 'feature_flag.key': hookContext?.flagKey ?? '',
85
+ 'feature_flag.result.variant': evaluationDetails?.variant ?? '',
86
+ 'feature_flag.result.reason': evaluationDetails?.reason?.toLowerCase() ?? 'unknown',
87
+ }
88
+
89
+ const errorCode = evaluationDetails?.errorCode
90
+ if (errorCode) {
91
+ attributes['error.type'] = errorCode.toLowerCase()
92
+ }
93
+
94
+ const allocationKey = evaluationDetails?.flagMetadata?.allocationKey
95
+ if (allocationKey) {
96
+ attributes['feature_flag.result.allocation_key'] = allocationKey
97
+ }
98
+
99
+ counter.add(1, attributes)
100
+ }
101
+ }
102
+
103
+ module.exports = EvalMetricsHook
@@ -4,6 +4,7 @@ const { DatadogNodeServerProvider } = require('@datadog/openfeature-node-server'
4
4
  const { channel } = require('dc-polyfill')
5
5
  const log = require('../log')
6
6
  const { EXPOSURE_CHANNEL } = require('./constants/constants')
7
+ const EvalMetricsHook = require('./eval-metrics-hook')
7
8
 
8
9
  /**
9
10
  * OpenFeature provider that integrates with Datadog's feature flagging system.
@@ -24,6 +25,8 @@ class FlaggingProvider extends DatadogNodeServerProvider {
24
25
  this._tracer = tracer
25
26
  this._config = config
26
27
 
28
+ this.hooks.push(new EvalMetricsHook(config))
29
+
27
30
  log.debug('%s created with timeout: %dms', this.constructor.name,
28
31
  config.experimental.flaggingProvider.initializationTimeoutMs)
29
32
  }
@@ -19,9 +19,14 @@ function enable (rc, config, getOpenfeatureProxy) {
19
19
 
20
20
  // Set product handler for FFE_FLAGS
21
21
  rc.setProductHandler('FFE_FLAGS', (action, conf) => {
22
- // Feed UFC config directly to OpenFeature provider
23
22
  if (action === 'apply' || action === 'modify') {
23
+ // Feed UFC config directly to OpenFeature provider
24
24
  getOpenfeatureProxy()._setConfiguration(conf)
25
+ } else if (action === 'unapply') {
26
+ // Clear the configuration so evaluations return PROVIDER_NOT_READY,
27
+ // consistent with Go and Python which also set config to null on RC deletion.
28
+ // The evaluator returns PROVIDER_NOT_READY when config is null/undefined.
29
+ getOpenfeatureProxy()._setConfiguration(null)
25
30
  }
26
31
  })
27
32
  }
@@ -4,7 +4,6 @@ const { trace, ROOT_CONTEXT, propagation } = require('@opentelemetry/api')
4
4
  const { storage } = require('../../../datadog-core')
5
5
  const { getAllBaggageItems, setBaggageItem, removeAllBaggageItems } = require('../baggage')
6
6
 
7
- const tracer = require('../../')
8
7
  const SpanContext = require('./span_context')
9
8
 
10
9
  class ContextManager {
@@ -16,7 +15,7 @@ class ContextManager {
16
15
  active () {
17
16
  const store = this._store.getStore()
18
17
  const baseContext = store || ROOT_CONTEXT
19
- const activeSpan = tracer.scope().active()
18
+ const activeSpan = storage('legacy').getStore()?.span
20
19
 
21
20
  const storedSpan = store ? trace.getSpan(store) : null
22
21
 
@@ -60,7 +59,6 @@ class ContextManager {
60
59
  // converts otel to dd
61
60
  with (context, fn, thisArg, ...args) {
62
61
  const span = trace.getSpan(context)
63
- const ddScope = tracer.scope()
64
62
  const run = () => {
65
63
  const cb = thisArg == null ? fn : fn.bind(thisArg)
66
64
  return this._store.run(context, cb, ...args)
@@ -74,7 +72,11 @@ class ContextManager {
74
72
  for (const baggage of baggageItems) {
75
73
  setBaggageItem(baggage[0], baggage[1].value)
76
74
  }
77
- if (span && span._ddSpan) return ddScope.activate(span._ddSpan, run)
75
+ if (span && span._ddSpan) {
76
+ const ddSpan = span._ddSpan
77
+ const parentStore = storage('legacy').getStore(ddSpan._store) ?? storage('legacy').getStore()
78
+ return storage('legacy').run({ ...parentStore, span: ddSpan }, run)
79
+ }
78
80
  return run()
79
81
  }
80
82
 
@@ -61,7 +61,7 @@ function initializeOpenTelemetryLogs (config) {
61
61
  // Create OTLP exporter using resolved config values
62
62
  const exporter = new OtlpHttpLogExporter(
63
63
  config.otelLogsUrl,
64
- config.otelLogsHeaders,
64
+ config.OTEL_EXPORTER_OTLP_LOGS_HEADERS,
65
65
  config.otelLogsTimeout,
66
66
  config.otelLogsProtocol,
67
67
  resourceAttributes
@@ -22,13 +22,14 @@ class OtlpHttpLogExporter extends OtlpHttpExporterBase {
22
22
  * Creates a new OtlpHttpLogExporter instance.
23
23
  *
24
24
  * @param {string} url - OTLP endpoint URL
25
- * @param {string} headers - Additional HTTP headers as comma-separated key=value string
25
+ * @param {Record<string, string>|undefined} headers - Additional HTTP headers parsed from the
26
+ * corresponding `OTEL_EXPORTER_OTLP_*_HEADERS` env by the MAP parser.
26
27
  * @param {number} timeout - Request timeout in milliseconds
27
28
  * @param {string} protocol - OTLP protocol (http/protobuf or http/json)
28
29
  * @param {Resource} resource - Resource attributes
29
30
  */
30
31
  constructor (url, headers, timeout, protocol, resource) {
31
- super(url, headers, timeout, protocol, '/v1/logs', 'logs')
32
+ super(url, headers, timeout, protocol, 'logs')
32
33
  this.transformer = new OtlpTransformer(resource, protocol)
33
34
  }
34
35
 
@@ -58,7 +58,7 @@ function initializeOpenTelemetryMetrics (config) {
58
58
 
59
59
  const exporter = new OtlpHttpMetricExporter(
60
60
  config.otelMetricsUrl,
61
- config.otelMetricsHeaders,
61
+ config.OTEL_EXPORTER_OTLP_METRICS_HEADERS,
62
62
  config.otelMetricsTimeout,
63
63
  config.otelMetricsProtocol,
64
64
  resourceAttributes
@@ -18,13 +18,14 @@ class OtlpHttpMetricExporter extends OtlpHttpExporterBase {
18
18
  * Creates a new OtlpHttpMetricExporter instance.
19
19
  *
20
20
  * @param {string} url - OTLP endpoint URL
21
- * @param {string} headers - Additional HTTP headers as comma-separated key=value string
21
+ * @param {Record<string, string>|undefined} headers - Additional HTTP headers parsed from the
22
+ * corresponding `OTEL_EXPORTER_OTLP_*_HEADERS` env by the MAP parser.
22
23
  * @param {number} timeout - Request timeout in milliseconds
23
24
  * @param {string} protocol - OTLP protocol (http/protobuf or http/json)
24
25
  * @param {Resource} resource - Resource attributes
25
26
  */
26
27
  constructor (url, headers, timeout, protocol, resource) {
27
- super(url, headers, timeout, protocol, '/v1/metrics', 'metrics')
28
+ super(url, headers, timeout, protocol, 'metrics')
28
29
  this.transformer = new OtlpTransformer(resource, protocol)
29
30
  }
30
31
 
@@ -19,34 +19,31 @@ class OtlpHttpExporterBase {
19
19
  /**
20
20
  * Creates a new OtlpHttpExporterBase instance.
21
21
  *
22
- * @param {string} url - OTLP endpoint URL
23
- * @param {string|undefined} headers - Additional HTTP headers as comma-separated key=value string
22
+ * @param {string} url - OTLP endpoint URL (callers are expected to supply the full signal URL)
23
+ * @param {Record<string, string>|undefined} headers - Additional HTTP headers parsed from the
24
+ * corresponding `OTEL_EXPORTER_OTLP_*_HEADERS` env by the MAP parser.
24
25
  * @param {number} timeout - Request timeout in milliseconds
25
26
  * @param {string} protocol - OTLP protocol (http/protobuf or http/json)
26
- * @param {string} defaultPath - Default path to use if URL has no path
27
27
  * @param {string} signalType - Signal type for error messages (e.g., 'logs', 'metrics')
28
28
  */
29
- constructor (url, headers, timeout, protocol, defaultPath, signalType) {
30
- const parsedUrl = new URL(url)
31
-
29
+ constructor (url, headers, timeout, protocol, signalType) {
32
30
  this.protocol = protocol
33
31
  this.signalType = signalType
34
32
 
35
- // If no path is provided, use default path
36
- const path = parsedUrl.pathname === '/' ? defaultPath : parsedUrl.pathname
37
33
  const isJson = protocol === 'http/json'
38
34
 
35
+ // Initialize fields setUrl doesn't touch; it fills in hostname/port/path below.
39
36
  this.options = {
40
- hostname: parsedUrl.hostname,
41
- port: parsedUrl.port,
42
- path: path + parsedUrl.search,
43
37
  method: 'POST',
44
38
  timeout,
45
39
  headers: {
46
40
  'Content-Type': isJson ? 'application/json' : 'application/x-protobuf',
47
- ...this.#parseAdditionalHeaders(headers),
41
+ ...headers,
48
42
  },
49
43
  }
44
+
45
+ this.setUrl(url)
46
+
50
47
  this.telemetryTags = [
51
48
  'protocol:http',
52
49
  `encoding:${isJson ? 'json' : 'protobuf'}`,
@@ -61,6 +58,7 @@ class OtlpHttpExporterBase {
61
58
  * @protected
62
59
  */
63
60
  recordTelemetry (metricName, count, additionalTags) {
61
+ // @ts-expect-error - additionalTags is optional and can be undefined
64
62
  if (additionalTags?.length > 0) {
65
63
  tracerMetrics.count(metricName, [...this.telemetryTags, ...additionalTags || []]).inc(count)
66
64
  } else {
@@ -91,6 +89,7 @@ class OtlpHttpExporterBase {
91
89
  })
92
90
 
93
91
  res.once('end', () => {
92
+ // @ts-expect-error - res.statusCode can be undefined
94
93
  if (res.statusCode >= 200 && res.statusCode < 300) {
95
94
  resultCallback({ code: 0 })
96
95
  } else {
@@ -116,46 +115,15 @@ class OtlpHttpExporterBase {
116
115
  }
117
116
 
118
117
  /**
119
- * Parses additional HTTP headers from a comma-separated string.
120
- * @param {string} [headersString=''] - Comma-separated key=value pairs
121
- * @returns {Record<string, string>} Parsed headers object
118
+ * Updates the target URL used by this exporter. The URL is used as-is per the OTel spec: the
119
+ * caller is responsible for including the signal-specific path (`/v1/traces` etc.).
120
+ * @param {string} url - New OTLP endpoint URL
122
121
  */
123
- #parseAdditionalHeaders (headersString = '') {
124
- const headers = {}
125
- let key = ''
126
- let value = ''
127
- let readingKey = true
128
-
129
- for (const char of headersString) {
130
- if (readingKey) {
131
- if (char === '=') {
132
- readingKey = false
133
- key = key.trim()
134
- } else {
135
- key += char
136
- }
137
- } else if (char === ',') {
138
- value = value.trim()
139
- if (key && value) {
140
- headers[key] = value
141
- }
142
- key = ''
143
- value = ''
144
- readingKey = true
145
- } else {
146
- value += char
147
- }
148
- }
149
-
150
- // Add the last pair if present
151
- if (!readingKey) {
152
- value = value.trim()
153
- if (value) {
154
- headers[key] = value
155
- }
156
- }
157
-
158
- return headers
122
+ setUrl (url) {
123
+ const parsedUrl = new URL(url)
124
+ this.options.hostname = parsedUrl.hostname
125
+ this.options.port = parsedUrl.port
126
+ this.options.path = parsedUrl.pathname + parsedUrl.search
159
127
  }
160
128
 
161
129
  /**
@@ -1,9 +1,9 @@
1
1
  'use strict'
2
2
 
3
3
  /**
4
- * Protobuf Loader for OpenTelemetry Logs and Metrics
4
+ * Protobuf Loader for OpenTelemetry Logs, Traces, and Metrics
5
5
  *
6
- * This module loads protobuf definitions for OpenTelemetry logs and metrics.
6
+ * This module loads protobuf definitions for OpenTelemetry logs, traces, and metrics.
7
7
  *
8
8
  * VERSION SUPPORT:
9
9
  * - OTLP Protocol: v1.7.0
@@ -20,6 +20,8 @@ const protobuf = require('../../../../../vendor/dist/protobufjs')
20
20
  let _root = null
21
21
  let protoLogsService = null
22
22
  let protoSeverityNumber = null
23
+ let protoTraceService = null
24
+ let protoSpanKind = null
23
25
  let protoMetricsService = null
24
26
  let protoAggregationTemporality = null
25
27
 
@@ -28,6 +30,8 @@ function getProtobufTypes () {
28
30
  return {
29
31
  protoLogsService,
30
32
  protoSeverityNumber,
33
+ protoTraceService,
34
+ protoSpanKind,
31
35
  protoMetricsService,
32
36
  protoAggregationTemporality,
33
37
  }
@@ -39,6 +43,8 @@ function getProtobufTypes () {
39
43
  'resource.proto',
40
44
  'logs.proto',
41
45
  'logs_service.proto',
46
+ 'trace.proto',
47
+ 'trace_service.proto',
42
48
  'metrics.proto',
43
49
  'metrics_service.proto',
44
50
  ].map(file => path.join(protoDir, file))
@@ -49,6 +55,10 @@ function getProtobufTypes () {
49
55
  protoLogsService = _root.lookupType('opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest')
50
56
  protoSeverityNumber = _root.lookupEnum('opentelemetry.proto.logs.v1.SeverityNumber')
51
57
 
58
+ // Get the message types for traces
59
+ protoTraceService = _root.lookupType('opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest')
60
+ protoSpanKind = _root.lookupEnum('opentelemetry.proto.trace.v1.SpanKind')
61
+
52
62
  // Get the message types for metrics
53
63
  protoMetricsService = _root.lookupType('opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest')
54
64
  protoAggregationTemporality = _root.lookupEnum('opentelemetry.proto.metrics.v1.AggregationTemporality')
@@ -56,6 +66,8 @@ function getProtobufTypes () {
56
66
  return {
57
67
  protoLogsService,
58
68
  protoSeverityNumber,
69
+ protoTraceService,
70
+ protoSpanKind,
59
71
  protoMetricsService,
60
72
  protoAggregationTemporality,
61
73
  }