dd-trace 5.54.0 → 5.55.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 (178) hide show
  1. package/ci/cypress/plugin.js +8 -0
  2. package/ci/cypress/polyfills.js +23 -0
  3. package/ci/init.js +8 -7
  4. package/initialize.mjs +2 -2
  5. package/package.json +6 -6
  6. package/packages/datadog-code-origin/index.js +22 -4
  7. package/packages/datadog-core/src/utils/src/kebabcase.js +3 -3
  8. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -6
  9. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +2 -3
  10. package/packages/datadog-instrumentations/src/cookie-parser.js +1 -1
  11. package/packages/datadog-instrumentations/src/couchbase.js +3 -6
  12. package/packages/datadog-instrumentations/src/cucumber.js +21 -28
  13. package/packages/datadog-instrumentations/src/dns.js +4 -4
  14. package/packages/datadog-instrumentations/src/elasticsearch.js +9 -10
  15. package/packages/datadog-instrumentations/src/fastify.js +7 -9
  16. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +14 -16
  17. package/packages/datadog-instrumentations/src/hapi.js +10 -11
  18. package/packages/datadog-instrumentations/src/helpers/fetch.js +4 -5
  19. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -2
  20. package/packages/datadog-instrumentations/src/helpers/register.js +6 -5
  21. package/packages/datadog-instrumentations/src/jest.js +67 -98
  22. package/packages/datadog-instrumentations/src/koa.js +2 -3
  23. package/packages/datadog-instrumentations/src/mariadb.js +11 -4
  24. package/packages/datadog-instrumentations/src/mocha/main.js +79 -75
  25. package/packages/datadog-instrumentations/src/mocha.js +3 -1
  26. package/packages/datadog-instrumentations/src/mysql.js +11 -2
  27. package/packages/datadog-instrumentations/src/nyc.js +2 -1
  28. package/packages/datadog-instrumentations/src/openai.js +2 -2
  29. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -3
  30. package/packages/datadog-instrumentations/src/pg.js +2 -3
  31. package/packages/datadog-instrumentations/src/playwright.js +19 -22
  32. package/packages/datadog-instrumentations/src/protobufjs.js +3 -4
  33. package/packages/datadog-instrumentations/src/redis.js +1 -1
  34. package/packages/datadog-instrumentations/src/restify.js +9 -13
  35. package/packages/datadog-instrumentations/src/router.js +12 -11
  36. package/packages/datadog-instrumentations/src/tedious.js +1 -2
  37. package/packages/datadog-instrumentations/src/vitest.js +15 -29
  38. package/packages/datadog-plugin-avsc/src/schema_iterator.js +12 -12
  39. package/packages/datadog-plugin-aws-sdk/src/base.js +12 -8
  40. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +3 -5
  41. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +12 -20
  42. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -5
  43. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +3 -5
  44. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -5
  45. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -5
  46. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
  47. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -10
  48. package/packages/datadog-plugin-cucumber/src/index.js +3 -2
  49. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -1
  50. package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -1
  51. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  52. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +1 -1
  53. package/packages/datadog-plugin-graphql/src/index.js +3 -2
  54. package/packages/datadog-plugin-graphql/src/resolve.js +17 -10
  55. package/packages/datadog-plugin-http/src/client.js +5 -6
  56. package/packages/datadog-plugin-http2/src/client.js +7 -8
  57. package/packages/datadog-plugin-jest/src/index.js +3 -2
  58. package/packages/datadog-plugin-mocha/src/index.js +6 -1
  59. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
  60. package/packages/datadog-plugin-mysql/src/index.js +11 -0
  61. package/packages/datadog-plugin-next/src/index.js +1 -1
  62. package/packages/datadog-plugin-openai/src/tracing.js +2 -4
  63. package/packages/datadog-plugin-playwright/src/index.js +3 -2
  64. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +8 -9
  65. package/packages/datadog-plugin-redis/src/index.js +1 -3
  66. package/packages/datadog-plugin-vitest/src/index.js +5 -4
  67. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +0 -1
  68. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +0 -1
  69. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +0 -1
  70. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -1
  71. package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +1 -2
  72. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +11 -12
  73. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +1 -1
  74. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -1
  75. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +1 -1
  76. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +1 -2
  77. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +10 -11
  78. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +0 -4
  79. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +0 -1
  80. package/packages/dd-trace/src/appsec/index.js +4 -4
  81. package/packages/dd-trace/src/appsec/reporter.js +5 -7
  82. package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
  83. package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -3
  84. package/packages/dd-trace/src/appsec/telemetry/index.js +31 -1
  85. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -2
  86. package/packages/dd-trace/src/azure_metadata.js +8 -3
  87. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +8 -7
  88. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -1
  89. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -1
  90. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -1
  91. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -1
  92. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +4 -3
  93. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +7 -6
  94. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
  95. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -3
  96. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -3
  97. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -1
  98. package/packages/dd-trace/src/config-helper.js +89 -0
  99. package/packages/dd-trace/src/config.js +77 -78
  100. package/packages/dd-trace/src/config_stable.js +7 -4
  101. package/packages/dd-trace/src/datastreams/fnv.js +1 -1
  102. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +6 -6
  103. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -2
  104. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -2
  105. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -1
  106. package/packages/dd-trace/src/debugger/devtools_client/send.js +3 -2
  107. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -2
  108. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +3 -4
  109. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +1 -1
  110. package/packages/dd-trace/src/debugger/index.js +1 -0
  111. package/packages/dd-trace/src/dogstatsd.js +2 -2
  112. package/packages/dd-trace/src/encode/0.4.js +5 -2
  113. package/packages/dd-trace/src/encode/0.5.js +3 -5
  114. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +5 -5
  115. package/packages/dd-trace/src/exporter.js +2 -1
  116. package/packages/dd-trace/src/exporters/common/docker.js +3 -2
  117. package/packages/dd-trace/src/exporters/common/request.js +4 -1
  118. package/packages/dd-trace/src/exporters/common/util.js +3 -1
  119. package/packages/dd-trace/src/id.js +3 -3
  120. package/packages/dd-trace/src/index.js +4 -3
  121. package/packages/dd-trace/src/lambda/handler.js +2 -1
  122. package/packages/dd-trace/src/lambda/index.js +2 -1
  123. package/packages/dd-trace/src/lambda/runtime/patch.js +3 -2
  124. package/packages/dd-trace/src/lambda/runtime/ritm.js +3 -2
  125. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
  126. package/packages/dd-trace/src/llmobs/index.js +21 -5
  127. package/packages/dd-trace/src/llmobs/noop.js +18 -20
  128. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +11 -13
  129. package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -2
  130. package/packages/dd-trace/src/llmobs/sdk.js +2 -1
  131. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  132. package/packages/dd-trace/src/llmobs/tagger.js +19 -6
  133. package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
  134. package/packages/dd-trace/src/log/index.js +5 -4
  135. package/packages/dd-trace/src/log/writer.js +1 -2
  136. package/packages/dd-trace/src/msgpack/encoder.js +3 -3
  137. package/packages/dd-trace/src/noop/span.js +1 -1
  138. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  139. package/packages/dd-trace/src/opentracing/propagation/log.js +4 -5
  140. package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -18
  141. package/packages/dd-trace/src/opentracing/span.js +7 -6
  142. package/packages/dd-trace/src/payload-tagging/config/index.js +17 -21
  143. package/packages/dd-trace/src/plugin_manager.js +4 -3
  144. package/packages/dd-trace/src/plugins/ci_plugin.js +25 -1
  145. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  146. package/packages/dd-trace/src/plugins/util/ci.js +7 -7
  147. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  148. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  149. package/packages/dd-trace/src/plugins/util/stacktrace.js +8 -1
  150. package/packages/dd-trace/src/plugins/util/test.js +4 -3
  151. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -1
  152. package/packages/dd-trace/src/plugins/util/web.js +3 -4
  153. package/packages/dd-trace/src/priority_sampler.js +46 -35
  154. package/packages/dd-trace/src/profiling/config.js +12 -32
  155. package/packages/dd-trace/src/profiling/exporter_cli.js +20 -20
  156. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  157. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -1
  158. package/packages/dd-trace/src/profiling/index.js +2 -1
  159. package/packages/dd-trace/src/profiling/profiler.js +7 -4
  160. package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +3 -1
  161. package/packages/dd-trace/src/profiling/tagger.js +22 -12
  162. package/packages/dd-trace/src/proxy.js +2 -1
  163. package/packages/dd-trace/src/ritm.js +4 -4
  164. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -2
  165. package/packages/dd-trace/src/sampler.js +10 -2
  166. package/packages/dd-trace/src/serverless.js +11 -4
  167. package/packages/dd-trace/src/span_processor.js +2 -1
  168. package/packages/dd-trace/src/standalone/tracesource.js +1 -2
  169. package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +1 -2
  170. package/packages/dd-trace/src/startup-log.js +5 -17
  171. package/packages/dd-trace/src/supported-configurations.json +439 -0
  172. package/packages/dd-trace/src/telemetry/dependencies.js +62 -57
  173. package/packages/dd-trace/src/telemetry/send-data.js +7 -6
  174. package/packages/dd-trace/src/telemetry/telemetry.js +12 -25
  175. package/packages/dd-trace/src/tracer.js +3 -7
  176. package/packages/dd-trace/src/util.js +0 -5
  177. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +0 -120
  178. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +0 -20
@@ -169,7 +169,7 @@ class DogStatsDClient {
169
169
  })
170
170
  .forEach(key => {
171
171
  // https://docs.datadoghq.com/tagging/#defining-tags
172
- const value = config.tags[key].replace(/[^a-z0-9_:./-]/ig, '_')
172
+ const value = config.tags[key].replaceAll(/[^a-z0-9_:./-]/ig, '_')
173
173
 
174
174
  tags.push(`${key}:${value}`)
175
175
  })
@@ -244,7 +244,7 @@ class MetricsAggregationClient {
244
244
  const container = monotonic ? this._counters : this._gauges
245
245
  const node = this._ensureTree(container, name, tags, 0)
246
246
 
247
- node.value = node.value + count
247
+ node.value += count
248
248
  }
249
249
 
250
250
  gauge (name, value, tags) {
@@ -6,6 +6,7 @@ const log = require('../log')
6
6
  const { isTrue } = require('../util')
7
7
  const coalesce = require('koalas')
8
8
  const { memoize } = require('../log/utils')
9
+ const { getEnvironmentVariable } = require('../config-helper')
9
10
 
10
11
  const SOFT_LIMIT = 8 * 1024 * 1024 // 8MB
11
12
 
@@ -32,7 +33,7 @@ class AgentEncoder {
32
33
  this._writer = writer
33
34
  this._reset()
34
35
  this._debugEncoding = isTrue(coalesce(
35
- process.env.DD_TRACE_ENCODING_DEBUG,
36
+ getEnvironmentVariable('DD_TRACE_ENCODING_DEBUG'),
36
37
  false
37
38
  ))
38
39
  this._config = this._writer?._config
@@ -349,15 +350,17 @@ const memoizedLogDebug = memoize((key, message) => {
349
350
  function formatSpanEvents (span) {
350
351
  for (const spanEvent of span.span_events) {
351
352
  if (spanEvent.attributes) {
353
+ let hasAttributes = false
352
354
  for (const [key, value] of Object.entries(spanEvent.attributes)) {
353
355
  const newValue = convertSpanEventAttributeValues(key, value)
354
356
  if (newValue === undefined) {
355
357
  delete spanEvent.attributes[key] // delete from attributes if undefined
356
358
  } else {
359
+ hasAttributes = true
357
360
  spanEvent.attributes[key] = newValue
358
361
  }
359
362
  }
360
- if (Object.keys(spanEvent.attributes).length === 0) {
363
+ if (!hasAttributes) {
361
364
  delete spanEvent.attributes
362
365
  }
363
366
  }
@@ -23,12 +23,10 @@ class AgentEncoder extends BaseEncoder {
23
23
  const traceSize = this._traceBytes.length + 5
24
24
  const buffer = Buffer.allocUnsafe(prefixSize + stringSize + traceSize)
25
25
 
26
- let offset = 0
26
+ buffer[0] = ARRAY_OF_TWO
27
27
 
28
- buffer[offset++] = ARRAY_OF_TWO
29
-
30
- offset = this._writeStrings(buffer, offset)
31
- offset = this._writeTraces(buffer, offset)
28
+ const offset = this._writeStrings(buffer, 1)
29
+ this._writeTraces(buffer, offset)
32
30
 
33
31
  this._reset()
34
32
 
@@ -161,20 +161,20 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
161
161
  _encodeEventContent (bytes, content) {
162
162
  let totalKeysLength = TEST_AND_SPAN_KEYS_LENGTH
163
163
  if (content.meta.test_session_id) {
164
- totalKeysLength = totalKeysLength + 1
164
+ totalKeysLength += 1
165
165
  }
166
166
  if (content.meta.test_module_id) {
167
- totalKeysLength = totalKeysLength + 1
167
+ totalKeysLength += 1
168
168
  }
169
169
  if (content.meta.test_suite_id) {
170
- totalKeysLength = totalKeysLength + 1
170
+ totalKeysLength += 1
171
171
  }
172
172
  const itrCorrelationId = content.meta[ITR_CORRELATION_ID]
173
173
  if (itrCorrelationId) {
174
- totalKeysLength = totalKeysLength + 1
174
+ totalKeysLength += 1
175
175
  }
176
176
  if (content.type) {
177
- totalKeysLength = totalKeysLength + 1
177
+ totalKeysLength += 1
178
178
  }
179
179
  this._encodeMapPrefix(bytes, totalKeysLength)
180
180
  if (content.type) {
@@ -3,6 +3,7 @@
3
3
  const exporters = require('../../../ext/exporters')
4
4
  const fs = require('fs')
5
5
  const constants = require('./constants')
6
+ const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
6
7
 
7
8
  module.exports = function getExporter (name) {
8
9
  switch (name) {
@@ -20,7 +21,7 @@ module.exports = function getExporter (name) {
20
21
  case exporters.PLAYWRIGHT_WORKER:
21
22
  return require('./ci-visibility/exporters/test-worker')
22
23
  default: {
23
- const inAWSLambda = process.env.AWS_LAMBDA_FUNCTION_NAME !== undefined
24
+ const inAWSLambda = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') !== undefined
24
25
  const usingLambdaExtension = inAWSLambda && fs.existsSync(constants.DATADOG_LAMBDA_EXTENSION_PATH)
25
26
  return require(inAWSLambda && !usingLambdaExtension ? './exporters/log' : './exporters/agent')
26
27
  }
@@ -1,8 +1,9 @@
1
1
  'use strict'
2
2
 
3
3
  const fs = require('fs')
4
+ const { getEnvironmentVariable } = require('../../config-helper')
4
5
 
5
- const { DD_EXTERNAL_ENV } = process.env
6
+ const DD_EXTERNAL_ENV = getEnvironmentVariable('DD_EXTERNAL_ENV')
6
7
 
7
8
  // The second part is the PCF / Garden regexp. We currently assume no suffix($) to avoid matching pod UIDs
8
9
  // See https://github.com/DataDog/datadog-agent/blob/7.40.x/pkg/util/cgroups/reader.go#L50
@@ -24,7 +25,7 @@ try {
24
25
 
25
26
  const inodePath = cgroup.match(lineReg)?.[3]
26
27
  if (inodePath) {
27
- const strippedPath = inodePath.replace(/^\/|\/$/g, '')
28
+ const strippedPath = inodePath.replaceAll(/^\/|\/$/g, '')
28
29
 
29
30
  try {
30
31
  inode = fs.statSync(`/sys/fs/cgroup/${strippedPath}`).ino
@@ -56,9 +56,12 @@ function request (data, options, callback) {
56
56
  const timeout = options.timeout || 2000
57
57
  const isSecure = options.protocol === 'https:'
58
58
  const client = isSecure ? https : http
59
- const dataArray = [].concat(data)
59
+ let dataArray = data
60
60
 
61
61
  if (!isReadable) {
62
+ if (!Array.isArray(data)) {
63
+ dataArray = [data]
64
+ }
62
65
  options.headers['Content-Length'] = byteLength(dataArray)
63
66
  }
64
67
 
@@ -1,8 +1,10 @@
1
+ const { getEnvironmentVariable } = require('../../config-helper')
2
+
1
3
  function safeJSONStringify (value) {
2
4
  return JSON.stringify(
3
5
  value,
4
6
  (key, value) => key === 'dd-api-key' ? undefined : value,
5
- process.env.DD_TRACE_BEAUTIFUL_LOGS ? 2 : undefined
7
+ getEnvironmentVariable('DD_TRACE_BEAUTIFUL_LOGS') ? 2 : undefined
6
8
  )
7
9
  }
8
10
 
@@ -174,11 +174,11 @@ function readInt32 (buffer, offset) {
174
174
  // Write unsigned integer bytes to a buffer.
175
175
  function writeUInt32BE (buffer, value, offset) {
176
176
  buffer[3 + offset] = value & 255
177
- value = value >> 8
177
+ value >>= 8
178
178
  buffer[2 + offset] = value & 255
179
- value = value >> 8
179
+ value >>= 8
180
180
  buffer[1 + offset] = value & 255
181
- value = value >> 8
181
+ value >>= 8
182
182
  buffer[0 + offset] = value & 255
183
183
  }
184
184
 
@@ -1,13 +1,14 @@
1
1
  'use strict'
2
2
 
3
3
  const { isFalse } = require('./util')
4
+ const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
4
5
 
5
6
  // Global `jest` is only present in Jest workers.
6
7
  const inJestWorker = typeof jest !== 'undefined'
7
8
 
8
- const ddTraceDisabled = process.env.DD_TRACE_ENABLED
9
- ? isFalse(process.env.DD_TRACE_ENABLED)
10
- : String(process.env.OTEL_TRACES_EXPORTER).toLowerCase() === 'none'
9
+ const ddTraceDisabled = getEnvironmentVariable('DD_TRACE_ENABLED')
10
+ ? isFalse(getEnvironmentVariable('DD_TRACE_ENABLED'))
11
+ : String(getEnvironmentVariable('OTEL_TRACES_EXPORTER')).toLowerCase() === 'none'
11
12
 
12
13
  module.exports = ddTraceDisabled || inJestWorker
13
14
  ? require('./noop/proxy')
@@ -4,6 +4,7 @@ const log = require('../log')
4
4
  const { channel } = require('../../../datadog-instrumentations/src/helpers/instrument')
5
5
  const { ERROR_MESSAGE, ERROR_TYPE } = require('../constants')
6
6
  const { ImpendingTimeout } = require('./runtime/errors')
7
+ const { getEnvironmentVariable } = require('../config-helper')
7
8
 
8
9
  const globalTracer = global._ddtrace
9
10
  const tracer = globalTracer._tracer
@@ -25,7 +26,7 @@ let __lambdaTimeout
25
26
  function checkTimeout (context) {
26
27
  const remainingTimeInMillis = context.getRemainingTimeInMillis()
27
28
 
28
- let apmFlushDeadline = Number.parseInt(process.env.DD_APM_FLUSH_DEADLINE_MILLISECONDS) || 100
29
+ let apmFlushDeadline = Number.parseInt(getEnvironmentVariable('DD_APM_FLUSH_DEADLINE_MILLISECONDS')) || 100
29
30
  apmFlushDeadline = apmFlushDeadline < 0 ? 100 : apmFlushDeadline
30
31
 
31
32
  __lambdaTimeout = setTimeout(() => {
@@ -1,12 +1,13 @@
1
1
  'use strict'
2
2
 
3
3
  const { registerLambdaHook } = require('./runtime/ritm')
4
+ const { getEnvironmentVariable } = require('../config-helper')
4
5
 
5
6
  /**
6
7
  * It is safe to do it this way, since customers will never be expected to disable
7
8
  * this specific instrumentation through the init config object.
8
9
  */
9
- const _DD_TRACE_DISABLED_INSTRUMENTATIONS = process.env.DD_TRACE_DISABLED_INSTRUMENTATIONS || ''
10
+ const _DD_TRACE_DISABLED_INSTRUMENTATIONS = getEnvironmentVariable('DD_TRACE_DISABLED_INSTRUMENTATIONS') || ''
10
11
  const _disabledInstrumentations = new Set(
11
12
  _DD_TRACE_DISABLED_INSTRUMENTATIONS ? _DD_TRACE_DISABLED_INSTRUMENTATIONS.split(',') : []
12
13
  )
@@ -6,6 +6,7 @@ const { _extractModuleNameAndHandlerPath, _extractModuleRootAndHandler, _getLamb
6
6
  const { datadog } = require('../handler')
7
7
  const { addHook } = require('../../../../datadog-instrumentations/src/helpers/instrument')
8
8
  const shimmer = require('../../../../datadog-shimmer')
9
+ const { getEnvironmentVariable } = require('../../config-helper')
9
10
 
10
11
  /**
11
12
  * Patches a Datadog Lambda module by calling `patchDatadogLambdaHandler`
@@ -57,8 +58,8 @@ function patchLambdaHandler (lambdaHandler) {
57
58
  return datadog(lambdaHandler)
58
59
  }
59
60
 
60
- const lambdaTaskRoot = process.env.LAMBDA_TASK_ROOT
61
- const originalLambdaHandler = process.env.DD_LAMBDA_HANDLER
61
+ const lambdaTaskRoot = getEnvironmentVariable('LAMBDA_TASK_ROOT')
62
+ const originalLambdaHandler = getEnvironmentVariable('DD_LAMBDA_HANDLER')
62
63
 
63
64
  if (originalLambdaHandler === undefined) {
64
65
  // Instrumentation is done manually.
@@ -10,6 +10,7 @@
10
10
  const path = require('path')
11
11
 
12
12
  const log = require('../../log')
13
+ const { getEnvironmentVariable } = require('../../config-helper')
13
14
  const Hook = require('../../../../datadog-instrumentations/src/helpers/hook')
14
15
  const instrumentations = require('../../../../datadog-instrumentations/src/helpers/instrumentations')
15
16
  const {
@@ -78,8 +79,8 @@ function _getLambdaFilePaths (lambdaStylePath) {
78
79
  * the file is required.
79
80
  */
80
81
  const registerLambdaHook = () => {
81
- const lambdaTaskRoot = process.env.LAMBDA_TASK_ROOT
82
- const originalLambdaHandler = process.env.DD_LAMBDA_HANDLER
82
+ const lambdaTaskRoot = getEnvironmentVariable('LAMBDA_TASK_ROOT')
83
+ const originalLambdaHandler = getEnvironmentVariable('DD_LAMBDA_HANDLER')
83
84
 
84
85
  if (originalLambdaHandler !== undefined && lambdaTaskRoot !== undefined) {
85
86
  const [moduleRoot, moduleAndHandler] = _extractModuleRootAndHandler(originalLambdaHandler)
@@ -10,6 +10,7 @@ module.exports = {
10
10
  METRICS: '_ml_obs.metrics',
11
11
  ML_APP: '_ml_obs.meta.ml_app',
12
12
  PROPAGATED_PARENT_ID_KEY: '_dd.p.llmobs_parent_id',
13
+ PROPAGATED_ML_APP_KEY: '_dd.p.llmobs_ml_app',
13
14
  PARENT_ID_KEY: '_ml_obs.llmobs_parent_id',
14
15
  TAGS: '_ml_obs.tags',
15
16
  NAME: '_ml_obs.name',
@@ -1,7 +1,11 @@
1
1
  'use strict'
2
2
 
3
3
  const log = require('../log')
4
- const { PROPAGATED_PARENT_ID_KEY } = require('./constants/tags')
4
+ const {
5
+ ML_APP,
6
+ PROPAGATED_ML_APP_KEY,
7
+ PROPAGATED_PARENT_ID_KEY
8
+ } = require('./constants/tags')
5
9
  const { storage } = require('./storage')
6
10
 
7
11
  const telemetry = require('./telemetry')
@@ -14,6 +18,7 @@ const flushCh = channel('llmobs:writers:flush')
14
18
  const injectCh = channel('dd-trace:span:inject')
15
19
 
16
20
  const LLMObsEvalMetricsWriter = require('./writers/evaluations')
21
+ const LLMObsTagger = require('./tagger')
17
22
  const LLMObsSpanWriter = require('./writers/spans')
18
23
  const { setAgentStrategy } = require('./writers/util')
19
24
 
@@ -35,7 +40,12 @@ let spanWriter
35
40
  /** @type {LLMObsEvalMetricsWriter | null} */
36
41
  let evalWriter
37
42
 
43
+ /** @type {import('../config')} */
44
+ let globalTracerConfig
45
+
38
46
  function enable (config) {
47
+ globalTracerConfig = config
48
+
39
49
  const startTime = performance.now()
40
50
  // create writers and eval writer append and flush channels
41
51
  // span writer append is handled by the span processor
@@ -83,14 +93,20 @@ function disable () {
83
93
  }
84
94
 
85
95
  // since LLMObs traces can extend between services and be the same trace,
86
- // we need to propogate the parent id.
96
+ // we need to propagate the parent id and mlApp.
87
97
  function handleLLMObsParentIdInjection ({ carrier }) {
88
98
  const parent = storage.getStore()?.span
89
- if (!parent) return
99
+ const mlObsSpanTags = LLMObsTagger.tagMap.get(parent)
90
100
 
91
- const parentId = parent?.context().toSpanId()
101
+ const parentContext = parent?.context()
102
+ const parentId = parentContext?.toSpanId()
103
+ const mlApp =
104
+ mlObsSpanTags?.[ML_APP] ||
105
+ parentContext?._trace?.tags?.[PROPAGATED_ML_APP_KEY] ||
106
+ globalTracerConfig.llmobs.mlApp
92
107
 
93
- carrier['x-datadog-tags'] += `,${PROPAGATED_PARENT_ID_KEY}=${parentId}`
108
+ if (parentId) carrier['x-datadog-tags'] += `,${PROPAGATED_PARENT_ID_KEY}=${parentId}`
109
+ if (mlApp) carrier['x-datadog-tags'] += `,${PROPAGATED_ML_APP_KEY}=${mlApp}`
94
110
  }
95
111
 
96
112
  function handleFlush () {
@@ -44,27 +44,25 @@ class NoopLLMObs {
44
44
  if (ctx.kind !== 'method') return target
45
45
 
46
46
  return llmobs.wrap({ name: ctx.name, _decorator: true, ...options }, target)
47
- } else {
48
- const propertyKey = ctxOrPropertyKey
49
- if (descriptor) {
50
- if (typeof descriptor.value !== 'function') return descriptor
51
-
52
- const original = descriptor.value
53
- descriptor.value = llmobs.wrap({ name: propertyKey, _decorator: true, ...options }, original)
54
-
55
- return descriptor
56
- } else {
57
- if (typeof target[propertyKey] !== 'function') return target[propertyKey]
58
-
59
- const original = target[propertyKey]
60
- Object.defineProperty(target, propertyKey, {
61
- ...Object.getOwnPropertyDescriptor(target, propertyKey),
62
- value: llmobs.wrap({ name: propertyKey, _decorator: true, ...options }, original)
63
- })
64
-
65
- return target
66
- }
67
47
  }
48
+ const propertyKey = ctxOrPropertyKey
49
+ if (descriptor) {
50
+ if (typeof descriptor.value !== 'function') return descriptor
51
+
52
+ const original = descriptor.value
53
+ descriptor.value = llmobs.wrap({ name: propertyKey, _decorator: true, ...options }, original)
54
+
55
+ return descriptor
56
+ }
57
+ if (typeof target[propertyKey] !== 'function') return target[propertyKey]
58
+
59
+ const original = target[propertyKey]
60
+ Object.defineProperty(target, propertyKey, {
61
+ ...Object.getOwnPropertyDescriptor(target, propertyKey),
62
+ value: llmobs.wrap({ name: propertyKey, _decorator: true, ...options }, original)
63
+ })
64
+
65
+ return target
68
66
  }
69
67
  }
70
68
 
@@ -23,26 +23,24 @@ class LangChainLLMObsHandler {
23
23
  return formatted
24
24
  } else if (Array.isArray(messages)) {
25
25
  return messages.map(message => this.formatIO(message))
26
- } else { // either a BaseMesage type or a string
27
- return this.getContentFromMessage(messages)
28
- }
26
+ } // either a BaseMesage type or a string
27
+ return this.getContentFromMessage(messages)
29
28
  }
30
29
 
31
30
  getContentFromMessage (message) {
32
31
  if (typeof message === 'string') {
33
32
  return message
34
- } else {
35
- try {
36
- const messageContent = {}
37
- messageContent.content = message.content || ''
33
+ }
34
+ try {
35
+ const messageContent = {}
36
+ messageContent.content = message.content || ''
38
37
 
39
- const role = this.getRole(message)
40
- if (role) messageContent.role = role
38
+ const role = this.getRole(message)
39
+ if (role) messageContent.role = role
41
40
 
42
- return messageContent
43
- } catch {
44
- return JSON.stringify(message)
45
- }
41
+ return messageContent
42
+ } catch {
43
+ return JSON.stringify(message)
46
44
  }
47
45
  }
48
46
 
@@ -68,9 +68,8 @@ class OpenAiLLMObsPlugin extends LLMObsPlugin {
68
68
  return { modelProvider: 'azure_openai', client: 'AzureOpenAI' }
69
69
  } else if (baseUrl.includes('deepseek')) {
70
70
  return { modelProvider: 'deepseek', client: 'DeepSeek' }
71
- } else {
72
- return { modelProvider: 'openai', client: 'OpenAI' }
73
71
  }
72
+ return { modelProvider: 'openai', client: 'OpenAI' }
74
73
  }
75
74
 
76
75
  _extractMetrics (response) {
@@ -14,6 +14,7 @@ const Span = require('../opentracing/span')
14
14
 
15
15
  const tracerVersion = require('../../../../package.json').version
16
16
  const logger = require('../log')
17
+ const { getEnvironmentVariable } = require('../config-helper')
17
18
  const telemetry = require('./telemetry')
18
19
 
19
20
  const LLMObsTagger = require('./tagger')
@@ -47,7 +48,7 @@ class LLMObs extends NoopLLMObs {
47
48
 
48
49
  const { mlApp, agentlessEnabled } = options
49
50
 
50
- const { DD_LLMOBS_ENABLED } = process.env
51
+ const DD_LLMOBS_ENABLED = getEnvironmentVariable('DD_LLMOBS_ENABLED')
51
52
 
52
53
  const llmobsConfig = {
53
54
  mlApp,
@@ -158,7 +158,7 @@ class LLMObsSpanProcessor {
158
158
  const add = (obj, carrier) => {
159
159
  for (const key in obj) {
160
160
  const value = obj[key]
161
- if (!Object.prototype.hasOwnProperty.call(obj, key)) continue
161
+ if (!Object.hasOwn(obj, key)) continue
162
162
  if (typeof value === 'bigint' || isCircular(value)) {
163
163
  // mark as unserializable instead of dropping
164
164
  logger.warn(`Unserializable property found in metadata: ${key}`)
@@ -24,7 +24,8 @@ const {
24
24
  OUTPUT_TOKENS_METRIC_KEY,
25
25
  TOTAL_TOKENS_METRIC_KEY,
26
26
  INTEGRATION,
27
- DECORATOR
27
+ DECORATOR,
28
+ PROPAGATED_ML_APP_KEY
28
29
  } = require('./constants/tags')
29
30
 
30
31
  // global registry of LLMObs spans
@@ -73,12 +74,24 @@ class LLMObsTagger {
73
74
  if (integration) this._setTag(span, INTEGRATION, integration)
74
75
  if (_decorator) this._setTag(span, DECORATOR, _decorator)
75
76
 
76
- if (!mlApp) mlApp = registry.get(parent)?.[ML_APP] || this._config.llmobs.mlApp
77
- this._setTag(span, ML_APP, mlApp)
77
+ const spanMlApp =
78
+ mlApp ||
79
+ registry.get(parent)?.[ML_APP] ||
80
+ span.context()._trace.tags[PROPAGATED_ML_APP_KEY] ||
81
+ this._config.llmobs.mlApp
82
+
83
+ if (!spanMlApp) {
84
+ throw new Error(
85
+ '[LLMObs] Cannot start an LLMObs span without an mlApp configured.' +
86
+ 'Ensure this configuration is set before running your application.'
87
+ )
88
+ }
89
+
90
+ this._setTag(span, ML_APP, spanMlApp)
78
91
 
79
92
  const parentId =
80
- parent?.context().toSpanId() ||
81
- span.context()._trace.tags[PROPAGATED_PARENT_ID_KEY] ||
93
+ parent?.context().toSpanId() ??
94
+ span.context()._trace.tags[PROPAGATED_PARENT_ID_KEY] ??
82
95
  ROOT_PARENT_ID
83
96
  this._setTag(span, PARENT_ID_KEY, parentId)
84
97
  }
@@ -357,7 +370,7 @@ class LLMObsTagger {
357
370
  }
358
371
 
359
372
  const tagsCarrier = registry.get(span)
360
- Object.assign(tagsCarrier, { [key]: value })
373
+ tagsCarrier[key] = value
361
374
  }
362
375
  }
363
376
 
@@ -157,7 +157,7 @@ class BaseLLMObsWriter {
157
157
  return encodeUnicode(value) // serialize unicode characters
158
158
  }
159
159
  return value
160
- }).replace(/\\\\u/g, String.raw`\u`) // remove double escaping
160
+ }).replaceAll(String.raw`\\u`, String.raw`\u`) // remove double escaping
161
161
  }
162
162
  }
163
163
 
@@ -7,6 +7,7 @@ const { traceChannel, debugChannel, infoChannel, warnChannel, errorChannel } = r
7
7
  const logWriter = require('./writer')
8
8
  const { Log } = require('./log')
9
9
  const { memoize } = require('./utils')
10
+ const { getEnvironmentVariable } = require('../config-helper')
10
11
 
11
12
  const config = {
12
13
  enabled: false,
@@ -98,8 +99,8 @@ const log = {
98
99
  isEnabled (fleetStableConfigValue, localStableConfigValue) {
99
100
  return isTrue(coalesce(
100
101
  fleetStableConfigValue,
101
- process.env?.DD_TRACE_DEBUG,
102
- process.env?.OTEL_LOG_LEVEL === 'debug' || undefined,
102
+ getEnvironmentVariable('DD_TRACE_DEBUG'),
103
+ getEnvironmentVariable('OTEL_LOG_LEVEL') === 'debug' || undefined,
103
104
  localStableConfigValue,
104
105
  config.enabled
105
106
  ))
@@ -113,8 +114,8 @@ const log = {
113
114
  return coalesce(
114
115
  optionsValue,
115
116
  fleetStableConfigValue,
116
- process.env?.DD_TRACE_LOG_LEVEL,
117
- process.env?.OTEL_LOG_LEVEL,
117
+ getEnvironmentVariable('DD_TRACE_LOG_LEVEL'),
118
+ getEnvironmentVariable('OTEL_LOG_LEVEL'),
118
119
  localStableConfigValue,
119
120
  config.logLevel
120
121
  )
@@ -57,9 +57,8 @@ function getErrorLog (err) {
57
57
  if (typeof err?.delegate === 'function') {
58
58
  const result = err.delegate()
59
59
  return Array.isArray(result) ? Log.parse(...result) : Log.parse(result)
60
- } else {
61
- return err
62
60
  }
61
+ return err
63
62
  }
64
63
 
65
64
  function setStackTraceLimitFunction (fn) {
@@ -163,7 +163,7 @@ class MsgpackEncoder {
163
163
 
164
164
  encodeLong (bytes, value) {
165
165
  const offset = bytes.length
166
- const hi = (value / Math.pow(2, 32)) >> 0
166
+ const hi = (value / 2 ** 32) >> 0
167
167
  const lo = value >>> 0
168
168
 
169
169
  bytes.reserve(9)
@@ -216,7 +216,7 @@ class MsgpackEncoder {
216
216
  bytes.buffer[offset + 3] = value >> 8
217
217
  bytes.buffer[offset + 4] = value
218
218
  } else {
219
- const hi = Math.floor(value / Math.pow(2, 32))
219
+ const hi = Math.floor(value / 2 ** 32)
220
220
  const lo = value >>> 0
221
221
 
222
222
  bytes.reserve(9)
@@ -255,7 +255,7 @@ class MsgpackEncoder {
255
255
  bytes.buffer[offset + 3] = value >> 8
256
256
  bytes.buffer[offset + 4] = value
257
257
  } else {
258
- const hi = (value / Math.pow(2, 32)) >> 0
258
+ const hi = (value / 2 ** 32) >> 0
259
259
  const lo = value >>> 0
260
260
 
261
261
  bytes.reserve(9)
@@ -36,7 +36,7 @@ class NoopSpan {
36
36
  traceId: parent._traceId,
37
37
  spanId,
38
38
  parentId: parent._spanId,
39
- baggageItems: Object.assign({}, parent._baggageItems)
39
+ baggageItems: { ...parent._baggageItems }
40
40
  })
41
41
  : new NoopSpanContext({
42
42
  noop: this,
@@ -32,7 +32,7 @@ class Tracer {
32
32
  spanId: id(),
33
33
  parentId: parentSpanContext._spanId,
34
34
  sampling: parentSpanContext._sampling,
35
- baggageItems: Object.assign({}, parentSpanContext._baggageItems),
35
+ baggageItems: { ...parentSpanContext._baggageItems },
36
36
  trace: parentSpanContext._trace,
37
37
  tracestate: parentSpanContext._tracestate
38
38
  })
@@ -43,12 +43,11 @@ class LogPropagator {
43
43
  spanContext._trace.tags['_dd.p.tid'] = hi
44
44
 
45
45
  return spanContext
46
- } else {
47
- return new DatadogSpanContext({
48
- traceId: id(carrier.dd.trace_id, 10),
49
- spanId: id(carrier.dd.span_id, 10)
50
- })
51
46
  }
47
+ return new DatadogSpanContext({
48
+ traceId: id(carrier.dd.trace_id, 10),
49
+ spanId: id(carrier.dd.span_id, 10)
50
+ })
52
51
  }
53
52
  }
54
53