dd-trace 5.54.0 → 5.56.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 (191) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/ci/cypress/plugin.js +8 -0
  3. package/ci/cypress/polyfills.js +23 -0
  4. package/ci/init.js +8 -7
  5. package/initialize.mjs +2 -2
  6. package/package.json +10 -9
  7. package/packages/datadog-code-origin/index.js +22 -4
  8. package/packages/datadog-core/src/utils/src/kebabcase.js +3 -3
  9. package/packages/datadog-core/src/utils/src/set.js +8 -10
  10. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -6
  11. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +2 -3
  12. package/packages/datadog-instrumentations/src/cookie-parser.js +1 -1
  13. package/packages/datadog-instrumentations/src/couchbase.js +3 -6
  14. package/packages/datadog-instrumentations/src/cucumber.js +21 -28
  15. package/packages/datadog-instrumentations/src/dns.js +4 -4
  16. package/packages/datadog-instrumentations/src/elasticsearch.js +9 -10
  17. package/packages/datadog-instrumentations/src/fastify.js +7 -9
  18. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +14 -16
  19. package/packages/datadog-instrumentations/src/hapi.js +10 -11
  20. package/packages/datadog-instrumentations/src/helpers/fetch.js +4 -5
  21. package/packages/datadog-instrumentations/src/helpers/hook.js +1 -2
  22. package/packages/datadog-instrumentations/src/helpers/register.js +6 -5
  23. package/packages/datadog-instrumentations/src/jest.js +421 -376
  24. package/packages/datadog-instrumentations/src/koa.js +2 -3
  25. package/packages/datadog-instrumentations/src/mariadb.js +11 -4
  26. package/packages/datadog-instrumentations/src/mocha/main.js +79 -75
  27. package/packages/datadog-instrumentations/src/mocha.js +3 -1
  28. package/packages/datadog-instrumentations/src/mysql.js +11 -2
  29. package/packages/datadog-instrumentations/src/nyc.js +2 -1
  30. package/packages/datadog-instrumentations/src/openai.js +2 -2
  31. package/packages/datadog-instrumentations/src/otel-sdk-trace.js +4 -3
  32. package/packages/datadog-instrumentations/src/pg.js +2 -3
  33. package/packages/datadog-instrumentations/src/playwright.js +19 -22
  34. package/packages/datadog-instrumentations/src/protobufjs.js +3 -4
  35. package/packages/datadog-instrumentations/src/redis.js +1 -1
  36. package/packages/datadog-instrumentations/src/restify.js +9 -13
  37. package/packages/datadog-instrumentations/src/router.js +12 -11
  38. package/packages/datadog-instrumentations/src/tedious.js +1 -2
  39. package/packages/datadog-instrumentations/src/vitest.js +15 -29
  40. package/packages/datadog-plugin-avsc/src/schema_iterator.js +12 -12
  41. package/packages/datadog-plugin-aws-sdk/src/base.js +12 -8
  42. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +3 -5
  43. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +12 -20
  44. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -5
  45. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +3 -5
  46. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +3 -5
  47. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +3 -5
  48. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -2
  49. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +7 -10
  50. package/packages/datadog-plugin-azure-functions/src/index.js +5 -4
  51. package/packages/datadog-plugin-cucumber/src/index.js +3 -2
  52. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +2 -1
  53. package/packages/datadog-plugin-dd-trace-api/src/index.js +2 -1
  54. package/packages/datadog-plugin-elasticsearch/src/index.js +1 -1
  55. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +1 -1
  56. package/packages/datadog-plugin-graphql/src/index.js +3 -2
  57. package/packages/datadog-plugin-graphql/src/resolve.js +17 -10
  58. package/packages/datadog-plugin-http/src/client.js +5 -6
  59. package/packages/datadog-plugin-http2/src/client.js +7 -8
  60. package/packages/datadog-plugin-jest/src/index.js +3 -2
  61. package/packages/datadog-plugin-mocha/src/index.js +6 -1
  62. package/packages/datadog-plugin-mongodb-core/src/index.js +2 -1
  63. package/packages/datadog-plugin-mysql/src/index.js +11 -0
  64. package/packages/datadog-plugin-next/src/index.js +1 -1
  65. package/packages/datadog-plugin-openai/src/tracing.js +2 -4
  66. package/packages/datadog-plugin-oracledb/src/index.js +2 -1
  67. package/packages/datadog-plugin-playwright/src/index.js +3 -2
  68. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +8 -9
  69. package/packages/datadog-plugin-redis/src/index.js +1 -3
  70. package/packages/datadog-plugin-vitest/src/index.js +5 -4
  71. package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +0 -1
  72. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +0 -1
  73. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +0 -1
  74. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +0 -1
  75. package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +1 -2
  76. package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +1 -1
  77. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +12 -13
  78. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +44 -1
  79. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +2 -1
  80. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +8 -3
  81. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -1
  82. package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +1 -1
  83. package/packages/dd-trace/src/appsec/iast/telemetry/verbosity.js +1 -2
  84. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/range-utils.js +10 -11
  85. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +0 -4
  86. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +0 -1
  87. package/packages/dd-trace/src/appsec/index.js +16 -5
  88. package/packages/dd-trace/src/appsec/reporter.js +11 -11
  89. package/packages/dd-trace/src/appsec/sdk/set_user.js +2 -2
  90. package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -3
  91. package/packages/dd-trace/src/appsec/telemetry/index.js +31 -1
  92. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +6 -2
  93. package/packages/dd-trace/src/azure_metadata.js +8 -3
  94. package/packages/dd-trace/src/baggage.js +2 -2
  95. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +8 -7
  96. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -1
  97. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -1
  98. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -1
  99. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -1
  100. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +4 -3
  101. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +7 -6
  102. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -1
  103. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -3
  104. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +4 -3
  105. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -1
  106. package/packages/dd-trace/src/config-helper.js +89 -0
  107. package/packages/dd-trace/src/config.js +120 -115
  108. package/packages/dd-trace/src/config_stable.js +7 -4
  109. package/packages/dd-trace/src/datastreams/fnv.js +1 -1
  110. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +6 -6
  111. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -2
  112. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -2
  113. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -1
  114. package/packages/dd-trace/src/debugger/devtools_client/send.js +8 -3
  115. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +1 -2
  116. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +3 -4
  117. package/packages/dd-trace/src/debugger/devtools_client/snapshot/redaction.js +1 -1
  118. package/packages/dd-trace/src/debugger/devtools_client/status.js +5 -1
  119. package/packages/dd-trace/src/debugger/index.js +1 -0
  120. package/packages/dd-trace/src/dogstatsd.js +2 -2
  121. package/packages/dd-trace/src/encode/0.4.js +5 -2
  122. package/packages/dd-trace/src/encode/0.5.js +3 -5
  123. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +5 -5
  124. package/packages/dd-trace/src/exporter.js +2 -1
  125. package/packages/dd-trace/src/exporters/agent/writer.js +3 -1
  126. package/packages/dd-trace/src/exporters/common/docker.js +3 -2
  127. package/packages/dd-trace/src/exporters/common/request.js +4 -1
  128. package/packages/dd-trace/src/exporters/common/util.js +3 -1
  129. package/packages/dd-trace/src/id.js +3 -3
  130. package/packages/dd-trace/src/index.js +4 -3
  131. package/packages/dd-trace/src/lambda/handler.js +2 -1
  132. package/packages/dd-trace/src/lambda/index.js +2 -1
  133. package/packages/dd-trace/src/lambda/runtime/patch.js +3 -2
  134. package/packages/dd-trace/src/lambda/runtime/ritm.js +3 -2
  135. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
  136. package/packages/dd-trace/src/llmobs/index.js +21 -5
  137. package/packages/dd-trace/src/llmobs/noop.js +18 -20
  138. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +11 -13
  139. package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -2
  140. package/packages/dd-trace/src/llmobs/sdk.js +2 -1
  141. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  142. package/packages/dd-trace/src/llmobs/tagger.js +19 -6
  143. package/packages/dd-trace/src/llmobs/writers/base.js +1 -1
  144. package/packages/dd-trace/src/log/index.js +5 -4
  145. package/packages/dd-trace/src/log/writer.js +1 -2
  146. package/packages/dd-trace/src/msgpack/encoder.js +3 -3
  147. package/packages/dd-trace/src/noop/span.js +1 -1
  148. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  149. package/packages/dd-trace/src/opentracing/propagation/log.js +4 -5
  150. package/packages/dd-trace/src/opentracing/propagation/text_map.js +35 -42
  151. package/packages/dd-trace/src/opentracing/span.js +7 -6
  152. package/packages/dd-trace/src/payload-tagging/config/index.js +17 -21
  153. package/packages/dd-trace/src/plugin_manager.js +4 -3
  154. package/packages/dd-trace/src/plugins/ci_plugin.js +25 -1
  155. package/packages/dd-trace/src/plugins/plugin.js +1 -1
  156. package/packages/dd-trace/src/plugins/util/ci.js +7 -7
  157. package/packages/dd-trace/src/plugins/util/git.js +1 -1
  158. package/packages/dd-trace/src/plugins/util/llm.js +2 -2
  159. package/packages/dd-trace/src/plugins/util/stacktrace.js +8 -1
  160. package/packages/dd-trace/src/plugins/util/test.js +4 -3
  161. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -1
  162. package/packages/dd-trace/src/plugins/util/web.js +3 -4
  163. package/packages/dd-trace/src/priority_sampler.js +46 -35
  164. package/packages/dd-trace/src/profiling/config.js +12 -32
  165. package/packages/dd-trace/src/profiling/exporter_cli.js +20 -20
  166. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  167. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +2 -1
  168. package/packages/dd-trace/src/profiling/index.js +2 -1
  169. package/packages/dd-trace/src/profiling/profiler.js +7 -4
  170. package/packages/dd-trace/src/profiling/profilers/events.js +10 -2
  171. package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +3 -1
  172. package/packages/dd-trace/src/profiling/tagger.js +22 -12
  173. package/packages/dd-trace/src/proxy.js +2 -1
  174. package/packages/dd-trace/src/ritm.js +4 -4
  175. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -2
  176. package/packages/dd-trace/src/sampler.js +10 -2
  177. package/packages/dd-trace/src/serverless.js +11 -4
  178. package/packages/dd-trace/src/span_processor.js +2 -1
  179. package/packages/dd-trace/src/standalone/tracesource.js +1 -2
  180. package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +1 -2
  181. package/packages/dd-trace/src/startup-log.js +5 -17
  182. package/packages/dd-trace/src/supported-configurations.json +440 -0
  183. package/packages/dd-trace/src/telemetry/dependencies.js +62 -57
  184. package/packages/dd-trace/src/telemetry/send-data.js +7 -6
  185. package/packages/dd-trace/src/telemetry/telemetry.js +16 -26
  186. package/packages/dd-trace/src/tracer.js +3 -7
  187. package/packages/dd-trace/src/util.js +0 -5
  188. package/packages/datadog-core/src/utils/src/get.js +0 -11
  189. package/packages/datadog-core/src/utils/src/has.js +0 -14
  190. package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +0 -120
  191. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +0 -20
@@ -170,7 +170,7 @@ async function updateBreakpointInternal (breakpoint, probe) {
170
170
  const conditionBeforeNewProbe = compileCompoundCondition([...probesAtLocation.values()])
171
171
 
172
172
  // If a probe is provided, add it to the breakpoint. If not, it's because we're removing a probe, but potentially
173
- // need to update the condtion of the breakpoint.
173
+ // need to update the condition of the breakpoint.
174
174
  if (probe) {
175
175
  probesAtLocation.set(probe.id, probe)
176
176
  probeToLocation.set(probe.id, breakpoint.locationKey)
@@ -194,7 +194,6 @@ async function updateBreakpointInternal (breakpoint, probe) {
194
194
  } catch (err) {
195
195
  throw new Error(`Error setting breakpoint for probe ${probe.id}`, { cause: err })
196
196
  }
197
- breakpoint.id = result.breakpointId
198
197
  breakpointToProbes.set(result.breakpointId, probesAtLocation)
199
198
  }
200
199
  }
@@ -105,9 +105,8 @@ function compile (node) {
105
105
  return '$dd_key'
106
106
  } else if (value === '@value') {
107
107
  return '$dd_value'
108
- } else {
109
- return assertIdentifier(value)
110
108
  }
109
+ return assertIdentifier(value)
111
110
  } else if (Array.isArray(value)) {
112
111
  const args = value.map(compile)
113
112
  switch (type) {
@@ -109,6 +109,7 @@ session.on('Debugger.paused', async ({ params }) => {
109
109
  if (probe.condition !== undefined) {
110
110
  // TODO: Bundle all conditions and evaluate them in a single call
111
111
  // TODO: Handle errors
112
+ // eslint-disable-next-line no-await-in-loop
112
113
  const { result } = await session.post('Debugger.evaluateOnCallFrame', {
113
114
  callFrameId: params.callFrames[0].callFrameId,
114
115
  expression: probe.condition,
@@ -134,7 +135,7 @@ session.on('Debugger.paused', async ({ params }) => {
134
135
 
135
136
  const timestamp = Date.now()
136
137
 
137
- let evalResults = null
138
+ let evalResults
138
139
  const { result } = await session.post('Debugger.evaluateOnCallFrame', {
139
140
  callFrameId: params.callFrames[0].callFrameId,
140
141
  expression: templateExpressions.length === 0
@@ -9,6 +9,7 @@ const request = require('../../exporters/common/request')
9
9
  const { GIT_COMMIT_SHA, GIT_REPOSITORY_URL } = require('../../plugins/util/tags')
10
10
  const log = require('../../log')
11
11
  const { version } = require('../../../../../package.json')
12
+ const { getEnvironmentVariable } = require('../../config-helper')
12
13
 
13
14
  module.exports = send
14
15
 
@@ -21,8 +22,8 @@ const hostname = getHostname()
21
22
  const service = config.service
22
23
 
23
24
  const ddtags = [
24
- ['env', process.env.DD_ENV],
25
- ['version', process.env.DD_VERSION],
25
+ ['env', getEnvironmentVariable('DD_ENV')],
26
+ ['version', getEnvironmentVariable('DD_VERSION')],
26
27
  ['debugger_version', version],
27
28
  ['host_name', hostname],
28
29
  [GIT_COMMIT_SHA, config.commitSHA],
@@ -31,7 +32,11 @@ const ddtags = [
31
32
 
32
33
  const path = `/debugger/v1/input?${stringify({ ddtags })}`
33
34
 
34
- const jsonBuffer = new JSONBuffer({ size: config.maxTotalPayloadSize, timeout: 1000, onFlush })
35
+ const jsonBuffer = new JSONBuffer({
36
+ size: config.maxTotalPayloadSize,
37
+ timeout: config.dynamicInstrumentation.uploadIntervalSeconds * 1000,
38
+ onFlush
39
+ })
35
40
 
36
41
  function send (message, logger, dd, snapshot) {
37
42
  const payload = {
@@ -77,9 +77,8 @@ function getObjectProperties (subtype, objectId, opts, depth) {
77
77
  return getProxy(objectId, opts, depth)
78
78
  } else if (subtype === 'arraybuffer') {
79
79
  return getArrayBuffer(objectId, opts, depth)
80
- } else {
81
- return getObject(objectId, opts, depth + 1, subtype === 'array' || subtype === 'typedarray')
82
80
  }
81
+ return getObject(objectId, opts, depth + 1, subtype === 'array' || subtype === 'typedarray')
83
82
  }
84
83
 
85
84
  // TODO: The following extra information from `internalProperties` might be relevant to include for functions:
@@ -129,11 +129,10 @@ function toFunctionOrClass (value, maxLength) {
129
129
  // This is a function
130
130
  // TODO: Would it make sense to detect if it's an arrow function or not?
131
131
  return toObject(value.className, value.properties, maxLength)
132
- } else {
133
- // This is a class
134
- const className = classMatch[1].trim()
135
- return { type: className ? `class ${className}` : 'class' }
136
132
  }
133
+ // This is a class
134
+ const className = classMatch[1].trim()
135
+ return { type: className ? `class ${className}` : 'class' }
137
136
  }
138
137
 
139
138
  function toString (str, maxLength) {
@@ -103,7 +103,7 @@ const REDACTED_IDENTIFIERS = new Set(
103
103
 
104
104
  function normalizeName (name, isSymbol) {
105
105
  if (isSymbol) name = name.slice(7, -1) // Remove `Symbol(` and `)`
106
- return name.toLowerCase().replace(/[-_@$.]/g, '')
106
+ return name.toLowerCase().replaceAll(/[-_@$.]/g, '')
107
107
  }
108
108
 
109
109
  module.exports = {
@@ -20,7 +20,11 @@ const runtimeId = config.runtimeId
20
20
 
21
21
  const cache = new TTLSet(60 * 60 * 1000) // 1 hour
22
22
 
23
- const jsonBuffer = new JSONBuffer({ size: config.maxTotalPayloadSize, timeout: 1000, onFlush })
23
+ const jsonBuffer = new JSONBuffer({
24
+ size: config.maxTotalPayloadSize,
25
+ timeout: config.dynamicInstrumentation.uploadIntervalSeconds * 1000,
26
+ onFlush
27
+ })
24
28
 
25
29
  const STATUSES = {
26
30
  RECEIVED: 'RECEIVED',
@@ -9,6 +9,7 @@ let worker = null
9
9
  let configChannel = null
10
10
  let ackId = 0
11
11
 
12
+ // eslint-disable-next-line eslint-rules/eslint-process-env
12
13
  const { NODE_OPTIONS, ...env } = process.env
13
14
 
14
15
  module.exports = {
@@ -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
  }
@@ -69,7 +69,9 @@ function setHeader (headers, key, value) {
69
69
  }
70
70
 
71
71
  function getEncoder (protocolVersion) {
72
- return require(`../../encode/${protocolVersion === '0.5' ? '0.5' : '0.4'}`).AgentEncoder
72
+ return protocolVersion === '0.5'
73
+ ? require('../../encode/0.5').AgentEncoder
74
+ : require('../../encode/0.4').AgentEncoder
73
75
  }
74
76
 
75
77
  function makeRequest (version, data, count, url, headers, lookup, needsStartupLog, cb) {
@@ -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}`)