dd-trace 5.98.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 (123) hide show
  1. package/LICENSE-3rdparty.csv +0 -1
  2. package/ext/tags.js +1 -0
  3. package/index.d.ts +9 -1
  4. package/package.json +48 -46
  5. package/packages/datadog-instrumentations/src/crypto.js +45 -0
  6. package/packages/datadog-instrumentations/src/cypress-config.js +122 -16
  7. package/packages/datadog-instrumentations/src/dns.js +24 -56
  8. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  9. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +74 -0
  10. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +4 -1
  11. package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
  12. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +10 -3
  13. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
  14. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/modelcontextprotocol-sdk.js +59 -0
  15. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +11 -2
  16. package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +7 -0
  17. package/packages/datadog-instrumentations/src/pino.js +4 -28
  18. package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +27 -0
  19. package/packages/datadog-instrumentations/src/playwright.js +5 -17
  20. package/packages/datadog-instrumentations/src/stripe.js +38 -24
  21. package/packages/datadog-instrumentations/src/vitest.js +32 -4
  22. package/packages/datadog-instrumentations/src/zlib.js +29 -0
  23. package/packages/datadog-plugin-aws-sdk/src/base.js +1 -2
  24. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +8 -15
  25. package/packages/datadog-plugin-azure-service-bus/src/producer.js +4 -9
  26. package/packages/datadog-plugin-cucumber/src/index.js +2 -2
  27. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +5 -5
  28. package/packages/datadog-plugin-cypress/src/source-map-utils.js +48 -1
  29. package/packages/datadog-plugin-http/src/server.js +11 -11
  30. package/packages/datadog-plugin-jest/src/index.js +2 -2
  31. package/packages/datadog-plugin-mocha/src/index.js +1 -2
  32. package/packages/datadog-plugin-modelcontextprotocol-sdk/src/index.js +24 -0
  33. package/packages/datadog-plugin-modelcontextprotocol-sdk/src/tracing.js +55 -0
  34. package/packages/datadog-plugin-mongodb-core/src/index.js +1 -6
  35. package/packages/datadog-plugin-playwright/src/index.js +2 -3
  36. package/packages/datadog-plugin-vitest/src/index.js +14 -6
  37. package/packages/datadog-plugin-ws/src/close.js +2 -0
  38. package/packages/datadog-plugin-ws/src/producer.js +2 -0
  39. package/packages/datadog-plugin-ws/src/receiver.js +1 -0
  40. package/packages/dd-trace/src/aiguard/channels.js +8 -0
  41. package/packages/dd-trace/src/aiguard/index.js +7 -3
  42. package/packages/dd-trace/src/aiguard/sdk.js +44 -0
  43. package/packages/dd-trace/src/aiguard/tags.js +1 -0
  44. package/packages/dd-trace/src/appsec/graphql.js +6 -6
  45. package/packages/dd-trace/src/appsec/index.js +9 -11
  46. package/packages/dd-trace/src/appsec/rasp/command_injection.js +4 -5
  47. package/packages/dd-trace/src/appsec/rasp/lfi.js +8 -4
  48. package/packages/dd-trace/src/appsec/rasp/sql_injection.js +5 -10
  49. package/packages/dd-trace/src/appsec/rasp/ssrf.js +5 -6
  50. package/packages/dd-trace/src/appsec/recommended.json +2438 -13
  51. package/packages/dd-trace/src/appsec/reporter.js +6 -5
  52. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +4 -8
  53. package/packages/dd-trace/src/appsec/store.js +50 -0
  54. package/packages/dd-trace/src/appsec/waf/index.js +3 -5
  55. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
  56. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
  57. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -2
  58. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  59. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -4
  60. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
  61. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -5
  62. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +3 -4
  63. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +6 -6
  64. package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +2 -2
  65. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
  66. package/packages/dd-trace/src/config/config-types.d.ts +0 -4
  67. package/packages/dd-trace/src/config/defaults.js +10 -10
  68. package/packages/dd-trace/src/config/generated-config-types.d.ts +13 -12
  69. package/packages/dd-trace/src/config/index.js +25 -35
  70. package/packages/dd-trace/src/config/parsers.js +26 -9
  71. package/packages/dd-trace/src/config/supported-configurations.json +32 -36
  72. package/packages/dd-trace/src/debugger/config.js +2 -0
  73. package/packages/dd-trace/src/debugger/devtools_client/send.js +25 -5
  74. package/packages/dd-trace/src/encode/0.4.js +4 -5
  75. package/packages/dd-trace/src/exporters/agent/index.js +0 -1
  76. package/packages/dd-trace/src/exporters/agent/writer.js +1 -2
  77. package/packages/dd-trace/src/exporters/agentless/writer.js +3 -3
  78. package/packages/dd-trace/src/exporters/common/util.js +2 -2
  79. package/packages/dd-trace/src/id.js +2 -0
  80. package/packages/dd-trace/src/index.js +2 -5
  81. package/packages/dd-trace/src/lambda/handler.js +1 -3
  82. package/packages/dd-trace/src/llmobs/plugins/{anthropic.js → anthropic/index.js} +5 -63
  83. package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +106 -0
  84. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +3 -2
  85. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +3 -2
  86. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +2 -1
  87. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +0 -49
  88. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +2 -1
  89. package/packages/dd-trace/src/llmobs/plugins/langchain/messages.js +76 -0
  90. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -26
  91. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/index.js +68 -0
  92. package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +57 -0
  93. package/packages/dd-trace/src/llmobs/sdk.js +2 -2
  94. package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +103 -0
  95. package/packages/dd-trace/src/openfeature/flagging_provider.js +3 -0
  96. package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
  97. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +3 -2
  98. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  99. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +3 -2
  100. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +19 -66
  101. package/packages/dd-trace/src/opentelemetry/trace/index.js +11 -16
  102. package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +11 -3
  103. package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +51 -41
  104. package/packages/dd-trace/src/opentelemetry/tracer.js +9 -11
  105. package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -10
  106. package/packages/dd-trace/src/opentracing/span.js +1 -1
  107. package/packages/dd-trace/src/opentracing/tracer.js +12 -5
  108. package/packages/dd-trace/src/plugins/index.js +1 -0
  109. package/packages/dd-trace/src/plugins/util/test.js +126 -5
  110. package/packages/dd-trace/src/plugins/util/url.js +2 -1
  111. package/packages/dd-trace/src/profiling/profilers/event_plugins/crypto.js +32 -0
  112. package/packages/dd-trace/src/profiling/profilers/event_plugins/zlib.js +19 -0
  113. package/packages/dd-trace/src/profiling/profilers/events.js +35 -0
  114. package/packages/dd-trace/src/proxy.js +2 -8
  115. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +2 -2
  116. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  117. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  118. package/packages/dd-trace/src/span_processor.js +1 -2
  119. package/packages/dd-trace/src/tagger.js +2 -2
  120. package/packages/dd-trace/src/telemetry/send-data.js +5 -7
  121. package/packages/dd-trace/src/tracer.js +2 -2
  122. package/vendor/dist/ignore/LICENSE +0 -21
  123. package/vendor/dist/ignore/index.js +0 -1
@@ -131,7 +131,13 @@ function setAndTrack (config, name, value, rawValue = value, source = 'calculate
131
131
  }
132
132
  changeTracker[source].add(name)
133
133
  } else {
134
- const copy = typeof value === 'object' && value !== null ? rfdc(value) : value
134
+ // Programmatic-only options (e.g. logger, lookup, plugins) have no row in
135
+ // `configurationsTable` and hold opaque user-supplied references that may
136
+ // carry cycles or non-plain prototypes — for example a winston Logger
137
+ // extends a Transform stream. Use a reference for these instead of cloning.
138
+ const copy = typeof value === 'object' && value !== null && name in configurationsTable
139
+ ? rfdc(value)
140
+ : value
135
141
  changeTracker.baseValuesByPath[name] = { value: copy, source }
136
142
  }
137
143
  set(config, name, value)
@@ -358,21 +364,9 @@ class Config extends ConfigBase {
358
364
  setAndTrack(this, 'otelMetricsEnabled', false)
359
365
  }
360
366
 
361
- const otelTracesEnabled = trackedConfigOrigins.has('OTEL_TRACES_EXPORTER') &&
362
- this.OTEL_TRACES_EXPORTER === 'otlp'
363
- if (this.protocolVersion && this.protocolVersion !== '0.4' && otelTracesEnabled) {
367
+ if (this.OTEL_TRACES_EXPORTER === 'otlp' && this.protocolVersion && this.protocolVersion !== '0.4') {
364
368
  log.warn('DD_TRACE_AGENT_PROTOCOL_VERSION is set, disabling OTLP traces export')
365
- setAndTrack(this, 'otelTracesEnabled', false)
366
- } else {
367
- setAndTrack(this, 'otelTracesEnabled', otelTracesEnabled)
368
- }
369
-
370
- if (this.otelTracesProtocol && this.otelTracesProtocol !== 'http/json') {
371
- log.warn(
372
- 'OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=%s is not yet supported; only http/json is currently implemented',
373
- this.otelTracesProtocol
374
- )
375
- setAndTrack(this, 'otelTracesProtocol', 'http/json')
369
+ setAndTrack(this, 'OTEL_TRACES_EXPORTER', 'none')
376
370
  }
377
371
 
378
372
  if (this.telemetry.heartbeatInterval) {
@@ -441,16 +435,13 @@ class Config extends ConfigBase {
441
435
  setAndTrack(this, 'runtimeMetrics.enabled', false)
442
436
  }
443
437
 
444
- if (!trackedConfigOrigins.has('sampleRate')) {
445
- const effectiveSampler = (trackedConfigOrigins.has('OTEL_TRACES_EXPORTER') &&
446
- this.OTEL_TRACES_EXPORTER === 'otlp' &&
447
- !trackedConfigOrigins.has('OTEL_TRACES_SAMPLER'))
448
- ? 'parentbased_always_on'
449
- : this.OTEL_TRACES_SAMPLER
450
- if (effectiveSampler && (trackedConfigOrigins.has('OTEL_TRACES_SAMPLER') ||
451
- trackedConfigOrigins.has('OTEL_TRACES_EXPORTER'))) {
452
- setAndTrack(this, 'sampleRate', getFromOtelSamplerMap(effectiveSampler, this.OTEL_TRACES_SAMPLER_ARG))
453
- }
438
+ // Apply the OTel sampler when the user opted into OTel traces or explicitly set the sampler.
439
+ // OTEL_TRACES_SAMPLER has `default: parentbased_always_on` (per OTel spec), so opt-in users
440
+ // that don't set the sampler still get parent-based sampling.
441
+ if (!trackedConfigOrigins.has('sampleRate') &&
442
+ (trackedConfigOrigins.has('OTEL_TRACES_SAMPLER') || this.OTEL_TRACES_EXPORTER === 'otlp')) {
443
+ setAndTrack(this, 'sampleRate',
444
+ getFromOtelSamplerMap(this.OTEL_TRACES_SAMPLER, this.OTEL_TRACES_SAMPLER_ARG))
454
445
  }
455
446
 
456
447
  if (this.DD_SPAN_SAMPLING_RULES_FILE) {
@@ -605,19 +596,18 @@ class Config extends ConfigBase {
605
596
  }
606
597
  }
607
598
 
608
- const DEFAULT_OTLP_PORT = '4318'
599
+ // TODO: This could likely be moved to the base class and allow easier GRPC handling
600
+ // Default OTLP endpoints follow the configured agent host so users who point DD at a custom
601
+ // agent (DD_AGENT_HOST / DD_TRACE_AGENT_URL) also reach OTLP on that host.
602
+ const defaultOtlpBase = this.OTEL_EXPORTER_OTLP_ENDPOINT?.replace(/\/$/, '') ?? `http://${agentHostname}:4318`
609
603
  if (!this.otelLogsUrl) {
610
- setAndTrack(this, 'otelLogsUrl', `http://${agentHostname}:${DEFAULT_OTLP_PORT}`)
604
+ setAndTrack(this, 'otelLogsUrl', `${defaultOtlpBase}/v1/logs`)
611
605
  }
612
606
  if (!this.otelMetricsUrl) {
613
- setAndTrack(this, 'otelMetricsUrl', `http://${agentHostname}:${DEFAULT_OTLP_PORT}/v1/metrics`)
614
- }
615
- if (!trackedConfigOrigins.has('otelTracesUrl') && this.OTEL_EXPORTER_OTLP_ENDPOINT) {
616
- // Generic OTLP endpoint: per spec, append /v1/traces signal-specific subpath
617
- setAndTrack(this, 'otelTracesUrl', this.OTEL_EXPORTER_OTLP_ENDPOINT.replace(/\/$/, '') + '/v1/traces')
618
- } else if (!this.otelTracesUrl) {
619
- const tracesHostname = agentHostname === '127.0.0.1' ? 'localhost' : agentHostname
620
- setAndTrack(this, 'otelTracesUrl', `http://${tracesHostname}:${DEFAULT_OTLP_PORT}/v1/traces`)
607
+ setAndTrack(this, 'otelMetricsUrl', `${defaultOtlpBase}/v1/metrics`)
608
+ }
609
+ if (!this.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) {
610
+ setAndTrack(this, 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT', `${defaultOtlpBase}/v1/traces`)
621
611
  }
622
612
 
623
613
  if (process.platform === 'win32') {
@@ -13,6 +13,15 @@ const VALID_PROPAGATION_STYLES = new Set([
13
13
  'datadog', 'tracecontext', 'b3', 'b3 single header', 'b3multi', 'baggage', 'none',
14
14
  ])
15
15
 
16
+ const RENAMED_OTEL_TAGS = new Map(
17
+ [
18
+ ['deployment.environment.name', 'env'],
19
+ ['deployment.environment', 'env'],
20
+ ['service.name', 'service'],
21
+ ['service.version', 'version'],
22
+ ]
23
+ )
24
+
16
25
  function toCase (value, methodName) {
17
26
  if (Array.isArray(value)) {
18
27
  return value.map(item => {
@@ -66,12 +75,12 @@ const transformers = {
66
75
  }
67
76
  return value
68
77
  },
69
- parseOtelTags (value, optionName) {
70
- return parsers.MAP(value
71
- ?.replace(/(^|,)deployment\.environment=/, '$1env:')
72
- .replace(/(^|,)service\.name=/, '$1service:')
73
- .replace(/(^|,)service\.version=/, '$1version:')
74
- .replaceAll('=', ':'), optionName)
78
+ parseOtelTags (object) {
79
+ const tags = {}
80
+ for (const [key, value] of Object.entries(object)) {
81
+ tags[RENAMED_OTEL_TAGS.get(key) ?? key] = value
82
+ }
83
+ return tags
75
84
  },
76
85
  normalizeProfilingEnabled (configValue) {
77
86
  if (configValue == null) {
@@ -225,11 +234,19 @@ const parsers = {
225
234
  if (!raw) {
226
235
  return entries
227
236
  }
228
- // DD_TAGS is a special case. It may be a map of key-value pairs separated by spaces.
229
- if (optionName === 'DD_TAGS' && !raw.includes(',')) {
237
+ let valueSeparator = ':'
238
+ if (optionName.startsWith('OTEL_')) {
239
+ // OTEL spec uses `key=value,key=value`
240
+ // (https://opentelemetry.io/docs/specs/otel/protocol/exporter/#specifying-headers-via-environment-variables),
241
+ // while DD uses `key:value,key:value`. Parse OTEL-prefixed options with `=` so downstream code
242
+ // receives a proper map and telemetry reports the parsed entries. The char-by-char loop
243
+ // avoids the allocations that `split(',')` + `indexOf('=')` do per pair.
244
+ valueSeparator = '='
245
+ } else if (optionName === 'DD_TAGS' && !raw.includes(',')) {
246
+ // DD_TAGS is a special case. It may be a map of key-value pairs separated by spaces.
230
247
  raw = raw.replaceAll(/\s+/g, ',')
231
248
  }
232
- tagger.add(entries, raw)
249
+ tagger.add(entries, raw, valueSeparator)
233
250
  return entries
234
251
  },
235
252
  JSON (raw) {
@@ -179,7 +179,8 @@
179
179
  {
180
180
  "implementation": "A",
181
181
  "type": "int",
182
- "default": "100"
182
+ "default": "100",
183
+ "allowed": "\\d+"
183
184
  }
184
185
  ],
185
186
  "DD_APM_TRACING_ENABLED": [
@@ -189,7 +190,10 @@
189
190
  "configurationNames": [
190
191
  "apmTracingEnabled"
191
192
  ],
192
- "default": "true"
193
+ "default": "true",
194
+ "aliases": [
195
+ "DD_TRACING_ENABLED"
196
+ ]
193
197
  }
194
198
  ],
195
199
  "DD_APPSEC_AUTO_USER_INSTRUMENTATION_MODE": [
@@ -445,9 +449,9 @@
445
449
  ],
446
450
  "DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER": [
447
451
  {
448
- "implementation": "B",
449
- "type": "boolean",
450
- "default": "false"
452
+ "implementation": "A",
453
+ "type": "string",
454
+ "default": null
451
455
  }
452
456
  ],
453
457
  "DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE": [
@@ -2509,10 +2513,7 @@
2509
2513
  "implementation": "A",
2510
2514
  "type": "boolean",
2511
2515
  "default": "true",
2512
- "internalPropertyName": "tracing",
2513
- "aliases": [
2514
- "DD_TRACING_ENABLED"
2515
- ]
2516
+ "internalPropertyName": "tracing"
2516
2517
  }
2517
2518
  ],
2518
2519
  "DD_TRACE_ENCODING_DEBUG": [
@@ -3110,6 +3111,13 @@
3110
3111
  "default": "true"
3111
3112
  }
3112
3113
  ],
3114
+ "DD_TRACE_MODELCONTEXTPROTOCOL_SDK_ENABLED": [
3115
+ {
3116
+ "implementation": "A",
3117
+ "type": "boolean",
3118
+ "default": "true"
3119
+ }
3120
+ ],
3113
3121
  "DD_TRACE_MOLECULER_ENABLED": [
3114
3122
  {
3115
3123
  "implementation": "A",
@@ -3896,18 +3904,16 @@
3896
3904
  ],
3897
3905
  "OTEL_EXPORTER_OTLP_HEADERS": [
3898
3906
  {
3899
- "implementation": "C",
3900
- "type": "string",
3901
- "default": null,
3902
- "internalPropertyName": "otelHeaders"
3907
+ "implementation": "B",
3908
+ "type": "map",
3909
+ "default": null
3903
3910
  }
3904
3911
  ],
3905
3912
  "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT": [
3906
3913
  {
3907
3914
  "implementation": "A",
3908
3915
  "type": "string",
3909
- "default": null,
3910
- "internalPropertyName": "otelTracesUrl"
3916
+ "default": null
3911
3917
  }
3912
3918
  ],
3913
3919
  "OTEL_EXPORTER_OTLP_TRACES_HEADERS": [
@@ -3915,7 +3921,6 @@
3915
3921
  "implementation": "B",
3916
3922
  "type": "map",
3917
3923
  "default": null,
3918
- "internalPropertyName": "otelTracesHeaders",
3919
3924
  "aliases": [
3920
3925
  "OTEL_EXPORTER_OTLP_HEADERS"
3921
3926
  ]
@@ -3926,7 +3931,7 @@
3926
3931
  "implementation": "B",
3927
3932
  "type": "string",
3928
3933
  "default": "http/json",
3929
- "internalPropertyName": "otelTracesProtocol",
3934
+ "allowed": "http/json",
3930
3935
  "aliases": [
3931
3936
  "OTEL_EXPORTER_OTLP_PROTOCOL"
3932
3937
  ]
@@ -3936,7 +3941,6 @@
3936
3941
  {
3937
3942
  "implementation": "B",
3938
3943
  "type": "int",
3939
- "internalPropertyName": "otelTracesTimeout",
3940
3944
  "default": "10000",
3941
3945
  "aliases": [
3942
3946
  "OTEL_EXPORTER_OTLP_TIMEOUT"
@@ -3948,18 +3952,14 @@
3948
3952
  "implementation": "A",
3949
3953
  "type": "string",
3950
3954
  "default": null,
3951
- "internalPropertyName": "otelLogsUrl",
3952
- "aliases": [
3953
- "OTEL_EXPORTER_OTLP_ENDPOINT"
3954
- ]
3955
+ "internalPropertyName": "otelLogsUrl"
3955
3956
  }
3956
3957
  ],
3957
3958
  "OTEL_EXPORTER_OTLP_LOGS_HEADERS": [
3958
3959
  {
3959
- "implementation": "A",
3960
- "type": "string",
3960
+ "implementation": "B",
3961
+ "type": "map",
3961
3962
  "default": null,
3962
- "internalPropertyName": "otelLogsHeaders",
3963
3963
  "aliases": [
3964
3964
  "OTEL_EXPORTER_OTLP_HEADERS"
3965
3965
  ]
@@ -3993,18 +3993,14 @@
3993
3993
  "implementation": "A",
3994
3994
  "type": "string",
3995
3995
  "default": null,
3996
- "internalPropertyName": "otelMetricsUrl",
3997
- "aliases": [
3998
- "OTEL_EXPORTER_OTLP_ENDPOINT"
3999
- ]
3996
+ "internalPropertyName": "otelMetricsUrl"
4000
3997
  }
4001
3998
  ],
4002
3999
  "OTEL_EXPORTER_OTLP_METRICS_HEADERS": [
4003
4000
  {
4004
- "implementation": "B",
4005
- "type": "string",
4001
+ "implementation": "C",
4002
+ "type": "map",
4006
4003
  "default": null,
4007
- "internalPropertyName": "otelMetricsHeaders",
4008
4004
  "aliases": [
4009
4005
  "OTEL_EXPORTER_OTLP_HEADERS"
4010
4006
  ]
@@ -4098,8 +4094,8 @@
4098
4094
  ],
4099
4095
  "OTEL_RESOURCE_ATTRIBUTES": [
4100
4096
  {
4101
- "implementation": "B",
4102
- "type": "string",
4097
+ "implementation": "A",
4098
+ "type": "map",
4103
4099
  "default": "",
4104
4100
  "transform": "parseOtelTags"
4105
4101
  }
@@ -4113,9 +4109,9 @@
4113
4109
  ],
4114
4110
  "OTEL_TRACES_EXPORTER": [
4115
4111
  {
4116
- "implementation": "F",
4112
+ "implementation": "H",
4117
4113
  "type": "string",
4118
- "default": "otlp",
4114
+ "default": null,
4119
4115
  "allowed": "none|otlp",
4120
4116
  "transform": "toLowerCase"
4121
4117
  }
@@ -5,6 +5,7 @@ module.exports = function getDebuggerConfig (config, inputPath) {
5
5
  commitSHA: config.commitSHA,
6
6
  debug: config.debug,
7
7
  dynamicInstrumentation: config.dynamicInstrumentation,
8
+ env: config.env,
8
9
  hostname: config.hostname,
9
10
  logLevel: config.logLevel,
10
11
  port: config.port,
@@ -13,6 +14,7 @@ module.exports = function getDebuggerConfig (config, inputPath) {
13
14
  runtimeId: config.tags['runtime-id'],
14
15
  service: config.service,
15
16
  url: config.url?.toString(),
17
+ version: config.version,
16
18
  inputPath,
17
19
  }
18
20
  }
@@ -6,7 +6,6 @@ const { stringify } = require('querystring')
6
6
  const { version } = require('../../../../../package.json')
7
7
  const request = require('../../exporters/common/request')
8
8
  const { GIT_COMMIT_SHA, GIT_REPOSITORY_URL } = require('../../plugins/util/tags')
9
- const { getValueFromEnvSources } = require('../../config/helper')
10
9
  const { DEBUGGER_DIAGNOSTICS_V1, DEBUGGER_INPUT_V2 } = require('../constants')
11
10
  const log = require('./log')
12
11
  const JSONBuffer = require('./json-buffer')
@@ -23,14 +22,14 @@ const ddsource = 'dd_debugger'
23
22
  const hostname = getHostname()
24
23
  const service = config.service
25
24
 
26
- const ddtags = [
27
- ['env', getValueFromEnvSources('DD_ENV')],
28
- ['version', getValueFromEnvSources('DD_VERSION')],
25
+ const ddtags = buildTags([
26
+ ['env', config.env],
27
+ ['version', config.version],
29
28
  ['debugger_version', version],
30
29
  ['host_name', hostname],
31
30
  [GIT_COMMIT_SHA, config.commitSHA],
32
31
  [GIT_REPOSITORY_URL, config.repositoryUrl],
33
- ].filter(([, value]) => value !== undefined).map((pair) => pair.join(':')).join(',')
32
+ ])
34
33
 
35
34
  let path
36
35
  setInputPath(config.inputPath)
@@ -136,3 +135,24 @@ function setInputPath (newPath) {
136
135
  config.inputPath = newPath
137
136
  path = `${newPath}?${stringify({ ddtags })}`
138
137
  }
138
+
139
+ /**
140
+ * @param {Array<[string, unknown]>} tags - The tags to serialize.
141
+ * @returns {string} The serialized tags.
142
+ */
143
+ function buildTags (tags) {
144
+ const serializedTags = []
145
+
146
+ for (const [key, rawValue] of tags) {
147
+ if (rawValue === undefined) continue
148
+
149
+ if (String(rawValue).includes(',')) {
150
+ log.warn('[debugger:devtools_client] Skipping invalid tag value for %s', key)
151
+ continue
152
+ }
153
+
154
+ serializedTags.push(`${key}:${rawValue}`)
155
+ }
156
+
157
+ return serializedTags.join(',')
158
+ }
@@ -1,9 +1,8 @@
1
1
  'use strict'
2
2
 
3
+ const getConfig = require('../config')
3
4
  const { MsgpackChunk, MsgpackEncoder } = require('../msgpack')
4
5
  const log = require('../log')
5
- const { isTrue } = require('../util')
6
- const { getValueFromEnvSources } = require('../config/helper')
7
6
  const { truncateSpan, normalizeSpan } = require('./tags-processors')
8
7
 
9
8
  const SOFT_LIMIT = 8 * 1024 * 1024 // 8MB
@@ -12,7 +11,7 @@ function formatSpan (span, config) {
12
11
  span = normalizeSpan(truncateSpan(span, false))
13
12
  if (span.span_events) {
14
13
  // ensure span events are encoded as tags if agent doesn't support native top level span events
15
- if (config?.trace?.nativeSpanEvents) {
14
+ if (config.trace.nativeSpanEvents) {
16
15
  formatSpanEvents(span)
17
16
  } else {
18
17
  span.meta.events = JSON.stringify(span.span_events)
@@ -30,8 +29,8 @@ class AgentEncoder {
30
29
  this._stringBytes = new MsgpackChunk()
31
30
  this._writer = writer
32
31
  this._reset()
33
- this._debugEncoding = isTrue(getValueFromEnvSources('DD_TRACE_ENCODING_DEBUG'))
34
- this._config = this._writer?._config
32
+ this._config = getConfig()
33
+ this._debugEncoding = this._config.DD_TRACE_ENCODING_DEBUG
35
34
  }
36
35
 
37
36
  count () {
@@ -24,7 +24,6 @@ class AgentExporter {
24
24
  lookup,
25
25
  protocolVersion,
26
26
  headers,
27
- config,
28
27
  })
29
28
 
30
29
  globalThis[Symbol.for('dd-trace')].beforeExitHandlers.add(this.flush.bind(this))
@@ -20,14 +20,13 @@ class AgentWriter extends BaseWriter {
20
20
  ...args[0],
21
21
  beforeFirstFlush: () => firstFlushChannel.publish(),
22
22
  })
23
- const { prioritySampler, lookup, protocolVersion, headers, config = {} } = args[0]
23
+ const { prioritySampler, lookup, protocolVersion, headers } = args[0]
24
24
  const AgentEncoder = getEncoder(protocolVersion)
25
25
 
26
26
  this._prioritySampler = prioritySampler
27
27
  this._lookup = lookup
28
28
  this._protocolVersion = protocolVersion
29
29
  this._headers = headers
30
- this._config = config
31
30
  this._encoder = new AgentEncoder(this)
32
31
  }
33
32
 
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const { getValueFromEnvSources } = require('../../config/helper')
3
+ const getConfig = require('../../config')
4
4
  const log = require('../../log')
5
5
  const request = require('../common/request')
6
6
  const tracerVersion = require('../../../../../package.json').version
@@ -39,7 +39,7 @@ class AgentlessWriter extends BaseWriter {
39
39
  }
40
40
  }
41
41
 
42
- if (!getValueFromEnvSources('DD_API_KEY')) {
42
+ if (!getConfig().apiKey) {
43
43
  this.#apiKeyMissing = true
44
44
  log.error('DD_API_KEY is required for agentless trace intake. Set DD_API_KEY. Traces will not be sent.')
45
45
  }
@@ -108,7 +108,7 @@ class AgentlessWriter extends BaseWriter {
108
108
  return
109
109
  }
110
110
 
111
- const apiKey = getValueFromEnvSources('DD_API_KEY')
111
+ const apiKey = getConfig().apiKey
112
112
  if (!apiKey) {
113
113
  if (!this.#apiKeyMissing) {
114
114
  this.#apiKeyMissing = true
@@ -1,12 +1,12 @@
1
1
  'use strict'
2
2
 
3
- const { getValueFromEnvSources } = require('../../config/helper')
3
+ const getConfig = require('../../config')
4
4
 
5
5
  function safeJSONStringify (value) {
6
6
  return JSON.stringify(
7
7
  value,
8
8
  (key, value) => key === 'dd-api-key' ? undefined : value,
9
- getValueFromEnvSources('DD_TRACE_BEAUTIFUL_LOGS') ? 2 : undefined
9
+ getConfig().DD_TRACE_BEAUTIFUL_LOGS ? 2 : undefined
10
10
  )
11
11
  }
12
12
 
@@ -245,3 +245,5 @@ function writeUInt32BE (buffer, value, offset) {
245
245
  module.exports = function createIdentifier (value, radix) {
246
246
  return new Identifier(value ?? '', radix)
247
247
  }
248
+
249
+ module.exports.Identifier = Identifier
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { getValueFromEnvSources } = require('./config/helper')
4
- const { isFalse, isTrue } = require('./util')
4
+ const { isFalse } = require('./util')
5
5
 
6
6
  // Global `jest` is only present in Jest workers.
7
7
  const inJestWorker = typeof jest !== 'undefined'
@@ -9,10 +9,7 @@ const inJestWorker = typeof jest !== 'undefined'
9
9
  const ddTraceDisabled = getValueFromEnvSources('DD_TRACE_ENABLED')
10
10
  ? isFalse(getValueFromEnvSources('DD_TRACE_ENABLED'))
11
11
  : String(getValueFromEnvSources('OTEL_TRACES_EXPORTER')).toLowerCase() === 'none'
12
- const shouldUseProxyWhenTracingDisabled =
13
- isTrue(getValueFromEnvSources('DD_DYNAMIC_INSTRUMENTATION_ENABLED')) ||
14
- isTrue(getValueFromEnvSources('DD_EXPERIMENTAL_APPSEC_STANDALONE_ENABLED'))
15
12
 
16
- module.exports = (ddTraceDisabled && !shouldUseProxyWhenTracingDisabled) || inJestWorker
13
+ module.exports = ddTraceDisabled || inJestWorker
17
14
  ? require('./noop/proxy')
18
15
  : require('./proxy')
@@ -3,7 +3,6 @@
3
3
  const log = require('../log')
4
4
  const { channel } = require('../../../datadog-instrumentations/src/helpers/instrument')
5
5
  const { ERROR_MESSAGE, ERROR_TYPE } = require('../constants')
6
- const { getValueFromEnvSources } = require('../config/helper')
7
6
  const { ImpendingTimeout } = require('./runtime/errors')
8
7
  const { extractContext } = require('./context')
9
8
 
@@ -27,8 +26,7 @@ let __lambdaTimeout
27
26
  function checkTimeout (context) {
28
27
  const remainingTimeInMillis = context.getRemainingTimeInMillis()
29
28
 
30
- let apmFlushDeadline = Number.parseInt(getValueFromEnvSources('DD_APM_FLUSH_DEADLINE_MILLISECONDS')) || 100
31
- apmFlushDeadline = apmFlushDeadline < 0 ? 100 : apmFlushDeadline
29
+ const apmFlushDeadline = tracer._config.DD_APM_FLUSH_DEADLINE_MILLISECONDS
32
30
 
33
31
  __lambdaTimeout = setTimeout(() => {
34
32
  timeoutChannel.publish()
@@ -1,7 +1,8 @@
1
1
  'use strict'
2
2
 
3
- const { UNKNOWN_MODEL_PROVIDER } = require('../constants/tags')
4
- const LLMObsPlugin = require('./base')
3
+ const { UNKNOWN_MODEL_PROVIDER } = require('../../constants/tags')
4
+ const LLMObsPlugin = require('../base')
5
+ const { appendMessage } = require('./util')
5
6
 
6
7
  const ALLOWED_METADATA_KEYS = new Set([
7
8
  'max_tokens',
@@ -144,51 +145,11 @@ class AnthropicLLMObsPlugin extends LLMObsPlugin {
144
145
  const inputMessages = []
145
146
 
146
147
  if (system) {
147
- messages.unshift({ content: system, role: 'system' })
148
+ appendMessage(inputMessages, { role: 'system', content: system })
148
149
  }
149
150
 
150
151
  for (const message of messages) {
151
- const { content, role } = message
152
-
153
- if (typeof content === 'string') {
154
- inputMessages.push({ content, role })
155
- continue
156
- }
157
-
158
- for (const block of content) {
159
- if (block.type === 'text') {
160
- inputMessages.push({ content: block.text, role })
161
- } else if (block.type === 'image') {
162
- inputMessages.push({ content: '([IMAGE DETECTED])', role })
163
- } else if (block.type === 'tool_use') {
164
- const { text, name, id, type } = block
165
- let input = block.input
166
- if (typeof input === 'string') {
167
- input = JSON.parse(input)
168
- }
169
-
170
- const toolCall = {
171
- name,
172
- arguments: input,
173
- toolId: id,
174
- type,
175
- }
176
-
177
- inputMessages.push({ content: text ?? '', role, toolCalls: [toolCall] })
178
- } else if (block.type === 'tool_result') {
179
- const { content } = block
180
- const formattedContent = this.#formatAnthropicToolResultContent(content)
181
- const toolResult = {
182
- result: formattedContent,
183
- toolId: block.tool_use_id,
184
- type: 'tool_result',
185
- }
186
-
187
- inputMessages.push({ content: '', role, toolResults: [toolResult] })
188
- } else {
189
- inputMessages.push({ content: JSON.stringify(block), role })
190
- }
191
- }
152
+ appendMessage(inputMessages, message)
192
153
  }
193
154
 
194
155
  this._tagger.tagLLMIO(span, inputMessages)
@@ -273,25 +234,6 @@ class AnthropicLLMObsPlugin extends LLMObsPlugin {
273
234
 
274
235
  this._tagger.tagMetrics(span, metrics)
275
236
  }
276
-
277
- // maybe can make into a util file
278
- #formatAnthropicToolResultContent (content) {
279
- if (typeof content === 'string') {
280
- return content
281
- } else if (Array.isArray(content)) {
282
- const formattedContent = []
283
- for (const toolResultBlock of content) {
284
- if (toolResultBlock.text) {
285
- formattedContent.push(toolResultBlock.text)
286
- } else if (toolResultBlock.type === 'image') {
287
- formattedContent.push('([IMAGE DETECTED])')
288
- }
289
- }
290
-
291
- return formattedContent.join(',')
292
- }
293
- return JSON.stringify(content)
294
- }
295
237
  }
296
238
 
297
239
  module.exports = AnthropicLLMObsPlugin