dd-trace 5.56.0 → 5.57.1

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 (134) hide show
  1. package/index.d.ts +44 -2
  2. package/init.js +4 -1
  3. package/package.json +20 -20
  4. package/packages/datadog-esbuild/index.js +22 -0
  5. package/packages/datadog-instrumentations/src/cassandra-driver.js +43 -60
  6. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +12 -12
  7. package/packages/datadog-instrumentations/src/cucumber.js +4 -6
  8. package/packages/datadog-instrumentations/src/elasticsearch.js +16 -19
  9. package/packages/datadog-instrumentations/src/fastify.js +91 -9
  10. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +20 -5
  11. package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +2 -2
  12. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  13. package/packages/datadog-instrumentations/src/helpers/register.js +17 -5
  14. package/packages/datadog-instrumentations/src/ioredis.js +8 -13
  15. package/packages/datadog-instrumentations/src/iovalkey.js +10 -14
  16. package/packages/datadog-instrumentations/src/jest.js +28 -6
  17. package/packages/datadog-instrumentations/src/memcached.js +17 -24
  18. package/packages/datadog-instrumentations/src/mocha/main.js +7 -6
  19. package/packages/datadog-instrumentations/src/moleculer/client.js +9 -10
  20. package/packages/datadog-instrumentations/src/moleculer/server.js +12 -13
  21. package/packages/datadog-instrumentations/src/openai.js +30 -2
  22. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  23. package/packages/datadog-instrumentations/src/prisma.js +116 -0
  24. package/packages/datadog-instrumentations/src/redis.js +32 -43
  25. package/packages/datadog-instrumentations/src/router.js +1 -1
  26. package/packages/datadog-instrumentations/src/sharedb.js +10 -16
  27. package/packages/datadog-instrumentations/src/vitest.js +4 -4
  28. package/packages/datadog-plugin-aws-sdk/src/base.js +6 -1
  29. package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +9 -4
  30. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +3 -2
  31. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +2 -1
  32. package/packages/datadog-plugin-aws-sdk/src/util.js +2 -2
  33. package/packages/datadog-plugin-bunyan/src/index.js +2 -2
  34. package/packages/datadog-plugin-cassandra-driver/src/index.js +6 -2
  35. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/batch-consumer.js +1 -1
  36. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/consumer.js +1 -1
  37. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +1 -1
  38. package/packages/datadog-plugin-confluentinc-kafka-javascript/src/producer.js +1 -1
  39. package/packages/datadog-plugin-cucumber/src/index.js +4 -2
  40. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +9 -5
  41. package/packages/datadog-plugin-elasticsearch/src/index.js +12 -4
  42. package/packages/datadog-plugin-http/src/client.js +1 -0
  43. package/packages/datadog-plugin-http/src/server.js +2 -1
  44. package/packages/datadog-plugin-http2/src/client.js +1 -0
  45. package/packages/datadog-plugin-http2/src/server.js +1 -0
  46. package/packages/datadog-plugin-jest/src/index.js +4 -3
  47. package/packages/datadog-plugin-memcached/src/index.js +6 -2
  48. package/packages/datadog-plugin-mocha/src/index.js +3 -2
  49. package/packages/datadog-plugin-moleculer/src/client.js +15 -9
  50. package/packages/datadog-plugin-moleculer/src/server.js +9 -5
  51. package/packages/datadog-plugin-next/src/index.js +2 -1
  52. package/packages/datadog-plugin-openai/src/tracing.js +127 -80
  53. package/packages/datadog-plugin-pino/src/index.js +2 -2
  54. package/packages/datadog-plugin-prisma/src/client.js +62 -0
  55. package/packages/datadog-plugin-prisma/src/engine.js +81 -0
  56. package/packages/datadog-plugin-prisma/src/index.js +22 -0
  57. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
  58. package/packages/datadog-plugin-redis/src/index.js +9 -3
  59. package/packages/datadog-plugin-router/src/index.js +1 -0
  60. package/packages/datadog-plugin-sharedb/src/index.js +13 -5
  61. package/packages/datadog-plugin-winston/src/index.js +2 -2
  62. package/packages/dd-trace/src/appsec/channels.js +26 -21
  63. package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +13 -20
  64. package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +0 -1
  65. package/packages/dd-trace/src/appsec/index.js +16 -1
  66. package/packages/dd-trace/src/appsec/rasp/utils.js +0 -5
  67. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +3 -3
  68. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -1
  69. package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +1 -1
  70. package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +1 -1
  71. package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
  72. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +6 -6
  73. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -3
  74. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +3 -3
  75. package/packages/dd-trace/src/config.js +286 -270
  76. package/packages/dd-trace/src/constants.js +2 -1
  77. package/packages/dd-trace/src/crashtracking/crashtracker.js +12 -14
  78. package/packages/dd-trace/src/datastreams/context.js +1 -1
  79. package/packages/dd-trace/src/datastreams/processor.js +1 -1
  80. package/packages/dd-trace/src/datastreams/writer.js +3 -3
  81. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +6 -3
  82. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  83. package/packages/dd-trace/src/debugger/devtools_client/index.js +2 -3
  84. package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -4
  85. package/packages/dd-trace/src/dogstatsd.js +3 -3
  86. package/packages/dd-trace/src/exporters/agent/index.js +10 -5
  87. package/packages/dd-trace/src/exporters/agent/writer.js +1 -1
  88. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -2
  89. package/packages/dd-trace/src/exporters/log/index.js +1 -1
  90. package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -2
  91. package/packages/dd-trace/src/guardrails/index.js +3 -1
  92. package/packages/dd-trace/src/guardrails/telemetry.js +1 -1
  93. package/packages/dd-trace/src/llmobs/index.js +11 -5
  94. package/packages/dd-trace/src/llmobs/plugins/base.js +2 -2
  95. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -1
  96. package/packages/dd-trace/src/llmobs/tagger.js +13 -13
  97. package/packages/dd-trace/src/llmobs/writers/base.js +2 -2
  98. package/packages/dd-trace/src/llmobs/writers/spans.js +2 -2
  99. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  100. package/packages/dd-trace/src/opentracing/propagation/text_map.js +4 -4
  101. package/packages/dd-trace/src/opentracing/span.js +1 -0
  102. package/packages/dd-trace/src/plugin_manager.js +3 -3
  103. package/packages/dd-trace/src/plugins/cache.js +2 -2
  104. package/packages/dd-trace/src/plugins/ci_plugin.js +11 -7
  105. package/packages/dd-trace/src/plugins/database.js +3 -1
  106. package/packages/dd-trace/src/plugins/index.js +1 -0
  107. package/packages/dd-trace/src/plugins/log_plugin.js +5 -1
  108. package/packages/dd-trace/src/plugins/outbound.js +8 -6
  109. package/packages/dd-trace/src/plugins/structured_log_plugin.js +9 -0
  110. package/packages/dd-trace/src/plugins/tracing.js +1 -1
  111. package/packages/dd-trace/src/plugins/util/ci.js +83 -30
  112. package/packages/dd-trace/src/plugins/util/git.js +1 -0
  113. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +3 -2
  114. package/packages/dd-trace/src/plugins/util/ip_extractor.js +1 -0
  115. package/packages/dd-trace/src/plugins/util/tags.js +4 -1
  116. package/packages/dd-trace/src/plugins/util/test.js +80 -10
  117. package/packages/dd-trace/src/plugins/util/web.js +1 -0
  118. package/packages/dd-trace/src/profiler.js +0 -2
  119. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -3
  120. package/packages/dd-trace/src/profiling/ssi-heuristics.js +18 -126
  121. package/packages/dd-trace/src/proxy.js +12 -27
  122. package/packages/dd-trace/src/runtime_metrics/index.js +1 -1
  123. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +14 -45
  124. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -2
  125. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +4 -0
  126. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -2
  127. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
  128. package/packages/dd-trace/src/supported-configurations.json +12 -3
  129. package/packages/dd-trace/src/telemetry/telemetry.js +5 -1
  130. package/packages/dd-trace/src/tracer.js +11 -0
  131. package/packages/dd-trace/src/tracer_metadata.js +25 -0
  132. package/packages/dd-trace/src/util.js +11 -4
  133. package/version.js +3 -1
  134. package/packages/dd-trace/src/profiling/ssi-telemetry-mock-profiler.js +0 -30
@@ -53,5 +53,6 @@ module.exports = {
53
53
  SPAN_POINTER_DIRECTION: Object.freeze({
54
54
  UPSTREAM: 'u',
55
55
  DOWNSTREAM: 'd'
56
- })
56
+ }),
57
+ INSTRUMENTED_BY_SSI: Symbol('_dd.instrumented.by.ssi')
57
58
  }
@@ -9,31 +9,29 @@ const { URL } = require('url')
9
9
  const pkg = require('../../../../package.json')
10
10
 
11
11
  class Crashtracker {
12
- constructor () {
13
- this._started = false
14
- }
12
+ #started = false
15
13
 
16
14
  configure (config) {
17
- if (!this._started) return
15
+ if (!this.#started) return
18
16
 
19
17
  try {
20
- binding.updateConfig(this._getConfig(config))
21
- binding.updateMetadata(this._getMetadata(config))
18
+ binding.updateConfig(this.#getConfig(config))
19
+ binding.updateMetadata(this.#getMetadata(config))
22
20
  } catch (e) {
23
21
  log.error('Error configuring crashtracker', e)
24
22
  }
25
23
  }
26
24
 
27
25
  start (config) {
28
- if (this._started) return this.configure(config)
26
+ if (this.#started) return this.configure(config)
29
27
 
30
- this._started = true
28
+ this.#started = true
31
29
 
32
30
  try {
33
31
  binding.init(
34
- this._getConfig(config),
35
- this._getReceiverConfig(config),
36
- this._getMetadata(config)
32
+ this.#getConfig(config),
33
+ this.#getReceiverConfig(),
34
+ this.#getMetadata(config)
37
35
  )
38
36
  } catch (e) {
39
37
  log.error('Error initialising crashtracker', e)
@@ -50,7 +48,7 @@ class Crashtracker {
50
48
  }
51
49
 
52
50
  // TODO: Send only configured values when defaults are fixed.
53
- _getConfig (config) {
51
+ #getConfig (config) {
54
52
  const { hostname = '127.0.0.1', port = 8126 } = config
55
53
  const url = config.url || new URL(`http://${hostname}:${port}`)
56
54
 
@@ -75,7 +73,7 @@ class Crashtracker {
75
73
  }
76
74
  }
77
75
 
78
- _getMetadata (config) {
76
+ #getMetadata (config) {
79
77
  const tags = Object.keys(config.tags).map(key => `${key}:${config.tags[key]}`)
80
78
 
81
79
  return {
@@ -94,7 +92,7 @@ class Crashtracker {
94
92
  }
95
93
  }
96
94
 
97
- _getReceiverConfig () {
95
+ #getReceiverConfig () {
98
96
  return {
99
97
  args: [],
100
98
  env: [],
@@ -7,7 +7,7 @@ function getDataStreamsContext () {
7
7
  }
8
8
 
9
9
  function setDataStreamsContext (dataStreamsContext) {
10
- log.debug(() => `Setting new DSM Context: ${JSON.stringify(dataStreamsContext)}.`)
10
+ log.debug('Setting new DSM Context: %j.', dataStreamsContext)
11
11
 
12
12
  if (dataStreamsContext) storage('legacy').enterWith({ ...(storage('legacy').getStore()), dataStreamsContext })
13
13
  }
@@ -204,7 +204,7 @@ class DataStreamsProcessor {
204
204
  let closestOppositeDirectionHash = ENTRY_PARENT_HASH
205
205
  let closestOppositeDirectionEdgeStart = nowNs
206
206
  if (ctx == null) {
207
- log.debug(() => 'Setting DSM Checkpoint with empty parent context.')
207
+ log.debug('Setting DSM Checkpoint with empty parent context.')
208
208
  } else {
209
209
  pathwayStartNs = ctx.pathwayStartNs
210
210
  edgeStartNs = ctx.edgeStartNs
@@ -20,7 +20,7 @@ function makeRequest (data, url, cb) {
20
20
  url
21
21
  }
22
22
 
23
- log.debug(() => `Request to the intake: ${JSON.stringify(options)}`)
23
+ log.debug('Request to the intake: %j', options)
24
24
 
25
25
  request(data, options, (err, res) => {
26
26
  cb(err, res)
@@ -39,7 +39,7 @@ class DataStreamsWriter {
39
39
 
40
40
  flush (payload) {
41
41
  if (!request.writable) {
42
- log.debug(() => `Maximum number of active requests reached. Payload discarded: ${JSON.stringify(payload)}`)
42
+ log.debug('Maximum number of active requests reached. Payload discarded: %j', payload)
43
43
  return
44
44
  }
45
45
  const encodedPayload = msgpack.encode(payload)
@@ -50,7 +50,7 @@ class DataStreamsWriter {
50
50
  return
51
51
  }
52
52
  makeRequest(compressedData, this._url, (err, res) => {
53
- log.debug(`Response from the agent: ${res}`)
53
+ log.debug('Response from the agent:', res)
54
54
  if (err) {
55
55
  log.error('Error sending datastream', err)
56
56
  }
@@ -87,7 +87,10 @@ async function addBreakpoint (probe) {
87
87
  try {
88
88
  probe.condition = probe.when?.json && compileCondition(probe.when.json)
89
89
  } catch (err) {
90
- throw new Error(`Cannot compile expression: ${probe.when.dsl}`, { cause: err })
90
+ throw new Error(
91
+ `Cannot compile expression: ${probe.when.dsl} (probe: ${probe.id}, version: ${probe.version})`,
92
+ { cause: err }
93
+ )
91
94
  }
92
95
 
93
96
  const locationKey = generateLocationKey(scriptId, lineNumber, columnNumber)
@@ -115,7 +118,7 @@ async function addBreakpoint (probe) {
115
118
  condition: probe.condition
116
119
  })
117
120
  } catch (err) {
118
- throw new Error(`Error setting breakpoint for probe ${probe.id}`, { cause: err })
121
+ throw new Error(`Error setting breakpoint for probe ${probe.id} (version: ${probe.version})`, { cause: err })
119
122
  }
120
123
  probeToLocation.set(probe.id, locationKey)
121
124
  locationToBreakpoint.set(locationKey, { id: result.breakpointId, location, locationKey })
@@ -192,7 +195,7 @@ async function updateBreakpointInternal (breakpoint, probe) {
192
195
  condition
193
196
  })
194
197
  } catch (err) {
195
- throw new Error(`Error setting breakpoint for probe ${probe.id}`, { cause: err })
198
+ throw new Error(`Error setting breakpoint for probe ${probe.id} (version: ${probe.version})`, { cause: err })
196
199
  }
197
200
  breakpointToProbes.set(result.breakpointId, probesAtLocation)
198
201
  }
@@ -278,7 +278,7 @@ function guardAgainstCoercionSideEffects (variable) {
278
278
 
279
279
  function assertString (variable) {
280
280
  return `((val) => {
281
- if (typeof val === 'string' || val instanceof String) {
281
+ if (${isString('val')}) {
282
282
  return val
283
283
  } else {
284
284
  throw new TypeError('Variable is not a string')
@@ -160,10 +160,9 @@ session.on('Debugger.paused', async ({ params }) => {
160
160
  await session.post('Debugger.resume')
161
161
  const diff = process.hrtime.bigint() - start // TODO: Recored as telemetry (DEBUG-2858)
162
162
 
163
- log.debug(
164
- '[debugger:devtools_client] Finished processing breakpoints - main thread paused for: %d ms',
163
+ log.debug(() => `[debugger:devtools_client] Finished processing breakpoints - main thread paused for: ${
165
164
  Number(diff) / 1_000_000
166
- )
165
+ } ms`)
167
166
 
168
167
  const logger = {
169
168
  // We can safely use `location.file` from the first probe in the array, since all probes hit by `hitBreakpoints`
@@ -165,9 +165,12 @@ session.on('Debugger.scriptParsed', ({ params }) => {
165
165
  loadedScripts.push(params)
166
166
  }
167
167
 
168
- clearTimeout(reEvaluateProbesTimer)
169
- reEvaluateProbesTimer = setTimeout(() => {
170
- session.emit('scriptLoadingStabilized')
171
- }, 500)
168
+ if (reEvaluateProbesTimer === null) {
169
+ reEvaluateProbesTimer = setTimeout(() => {
170
+ session.emit('scriptLoadingStabilized')
171
+ }, 500).unref()
172
+ } else {
173
+ reEvaluateProbesTimer.refresh()
174
+ }
172
175
  }
173
176
  })
@@ -63,7 +63,7 @@ class DogStatsDClient {
63
63
  flush () {
64
64
  const queue = this._enqueue()
65
65
 
66
- log.debug(`Flushing ${queue.length} metrics via ${this._httpOptions ? 'HTTP' : 'UDP'}`)
66
+ log.debug('Flushing %s metrics via', queue.length, this._httpOptions ? 'HTTP' : 'UDP')
67
67
 
68
68
  if (this._queue.length === 0) return
69
69
 
@@ -108,7 +108,7 @@ class DogStatsDClient {
108
108
  const socket = family === 6 ? this._udp6 : this._udp4
109
109
 
110
110
  queue.forEach((buffer) => {
111
- log.debug(`Sending to DogStatsD: ${buffer}`)
111
+ log.debug('Sending to DogStatsD: %s', buffer)
112
112
  socket.send(buffer, 0, buffer.length, this._port, address)
113
113
  })
114
114
  }
@@ -165,7 +165,7 @@ class DogStatsDClient {
165
165
  .filter(key => {
166
166
  // Skip runtime-id unless enabled as cardinality may be too high
167
167
  if (key !== 'runtime-id') return true
168
- return (config.experimental && config.experimental.runtimeId)
168
+ return config.runtimeMetricsRuntimeId
169
169
  })
170
170
  .forEach(key => {
171
171
  // https://docs.datadoghq.com/tagging/#defining-tags
@@ -5,6 +5,8 @@ const log = require('../../log')
5
5
  const Writer = require('./writer')
6
6
 
7
7
  class AgentExporter {
8
+ #timer
9
+
8
10
  constructor (config, prioritySampler) {
9
11
  this._config = config
10
12
  const { url, hostname, port, lookup, protocolVersion, stats = {}, apmTracingEnabled } = config
@@ -28,8 +30,9 @@ class AgentExporter {
28
30
  config
29
31
  })
30
32
 
31
- this._timer = undefined
32
- process.once('beforeExit', () => this._writer.flush())
33
+ process.once('beforeExit', () => {
34
+ this.flush()
35
+ })
33
36
  }
34
37
 
35
38
  setUrl (url) {
@@ -49,15 +52,17 @@ class AgentExporter {
49
52
 
50
53
  if (flushInterval === 0) {
51
54
  this._writer.flush()
52
- } else if (flushInterval > 0 && !this._timer) {
53
- this._timer = setTimeout(() => {
55
+ } else if (this.#timer === undefined) {
56
+ this.#timer = setTimeout(() => {
54
57
  this._writer.flush()
55
- this._timer = clearTimeout(this._timer)
58
+ this.#timer = undefined
56
59
  }, flushInterval).unref()
57
60
  }
58
61
  }
59
62
 
60
63
  flush (done = () => {}) {
64
+ clearTimeout(this.#timer)
65
+ this.#timer = undefined
61
66
  this._writer.flush(done)
62
67
  }
63
68
  }
@@ -92,7 +92,7 @@ function makeRequest (version, data, count, url, headers, lookup, needsStartupLo
92
92
  setHeader(options.headers, 'Datadog-Meta-Lang-Version', process.version)
93
93
  setHeader(options.headers, 'Datadog-Meta-Lang-Interpreter', process.jsEngine || 'v8')
94
94
 
95
- log.debug(() => `Request to the agent: ${JSON.stringify(options)}`)
95
+ log.debug('Request to the agent: %j', options)
96
96
 
97
97
  request(data, options, (err, res, status) => {
98
98
  if (needsStartupLog) {
@@ -59,10 +59,10 @@ class AgentInfoExporter {
59
59
 
60
60
  if (flushInterval === 0) {
61
61
  writer.flush()
62
- } else if (flushInterval > 0 && !this[timerKey]) {
62
+ } else if (this[timerKey] === undefined) {
63
63
  this[timerKey] = setTimeout(() => {
64
64
  writer.flush()
65
- this[timerKey] = clearTimeout(this[timerKey])
65
+ this[timerKey] = undefined
66
66
  }, flushInterval).unref()
67
67
  }
68
68
  }
@@ -9,7 +9,7 @@ const MAX_SIZE = 64 * 1024 // 64kb
9
9
 
10
10
  class LogExporter {
11
11
  export (spans) {
12
- log.debug(() => `Adding trace to queue: ${JSON.stringify(spans)}`)
12
+ log.debug('Adding trace to queue: %j', spans)
13
13
 
14
14
  let size = TRACE_FORMAT_OVERHEAD
15
15
  let queue = []
@@ -20,7 +20,7 @@ class Writer extends BaseWriter {
20
20
  done()
21
21
  return
22
22
  }
23
- log.debug(`Response from the intake: ${res}`)
23
+ log.debug('Response from the intake:', res)
24
24
  done()
25
25
  })
26
26
  }
@@ -41,7 +41,7 @@ function makeRequest (data, url, cb) {
41
41
  options.hostname = url.hostname
42
42
  options.port = url.port
43
43
 
44
- log.debug(() => `Request to the intake: ${JSON.stringify(options)}`)
44
+ log.debug('Request to the intake: %j', options)
45
45
 
46
46
  request(data, options, (err, res) => {
47
47
  cb(err, res)
@@ -47,13 +47,15 @@ function guard (fn) {
47
47
  { name: 'abort.runtime', tags: [] }
48
48
  ])
49
49
  log.info('Aborting application instrumentation due to incompatible_runtime.')
50
- log.info('Found incompatible runtime nodejs ' + version + ', Supported runtimes: nodejs ' + engines.node + '.')
50
+ log.info('Found incompatible runtime nodejs %s, Supported runtimes: nodejs %s.', version, engines.node)
51
51
  if (forced) {
52
52
  log.info('DD_INJECT_FORCE enabled, allowing unsupported runtimes and continuing.')
53
53
  }
54
54
  }
55
55
 
56
56
  if (!clobberBailout && (!initBailout || forced)) {
57
+ // Ensure the instrumentation source is set for the current process and potential
58
+ // child processes.
57
59
  var result = fn()
58
60
  telemetry('complete', ['injection_forced:' + (forced && initBailout ? 'true' : 'false')])
59
61
  log.info('Application instrumentation bootstrapping complete')
@@ -65,7 +65,7 @@ function sendTelemetry (name, tags) {
65
65
  })
66
66
  proc.on('exit', function (code) {
67
67
  if (code !== 0) {
68
- log.error('Telemetry forwarder exited with code ' + code)
68
+ log.error('Telemetry forwarder exited with code', code)
69
69
  }
70
70
  })
71
71
  proc.stdin.on('error', function () {
@@ -22,6 +22,8 @@ const LLMObsTagger = require('./tagger')
22
22
  const LLMObsSpanWriter = require('./writers/spans')
23
23
  const { setAgentStrategy } = require('./writers/util')
24
24
 
25
+ const util = require('node:util')
26
+
25
27
  /**
26
28
  * Setting writers and processor globally when LLMObs is enabled
27
29
  * We're setting these in this module instead of on the SDK.
@@ -75,6 +77,7 @@ function enable (config) {
75
77
  spanWriter?.setAgentless(useAgentless)
76
78
 
77
79
  telemetry.recordLLMObsEnabled(startTime, config)
80
+ log.debug(`[LLMObs] Enabled LLM Observability with configuration: ${util.inspect(config.llmobs)}`)
78
81
  })
79
82
  }
80
83
 
@@ -90,6 +93,8 @@ function disable () {
90
93
 
91
94
  spanWriter = null
92
95
  evalWriter = null
96
+
97
+ log.debug('[LLMObs] Disabled LLM Observability')
93
98
  }
94
99
 
95
100
  // since LLMObs traces can extend between services and be the same trace,
@@ -116,7 +121,7 @@ function handleFlush () {
116
121
  evalWriter.flush()
117
122
  } catch (e) {
118
123
  err = 'writer_flush_error'
119
- log.warn(`Failed to flush LLMObs spans and evaluation metrics: ${e.message}`)
124
+ log.warn('Failed to flush LLMObs spans and evaluation metrics:', e.message)
120
125
  }
121
126
  telemetry.recordUserFlush(err)
122
127
  }
@@ -129,10 +134,11 @@ function handleEvalMetricAppend (payload) {
129
134
  try {
130
135
  evalWriter.append(payload)
131
136
  } catch (e) {
132
- log.warn(`
133
- Failed to append evaluation metric to LLM Observability writer, likely due to an unserializable property.
134
- Evaluation metrics won't be sent to LLM Observability: ${e.message}
135
- `)
137
+ log.warn(
138
+ // eslint-disable-next-line @stylistic/max-len
139
+ 'Failed to append evaluation metric to LLM Observability writer, likely due to an unserializable property. Evaluation metrics won\'t be sent to LLM Observability:',
140
+ e.message
141
+ )
136
142
  }
137
143
  }
138
144
 
@@ -70,8 +70,8 @@ class LLMObsPlugin extends TracingPlugin {
70
70
  const span = apmStore?.span
71
71
  if (!span) {
72
72
  log.debug(
73
- `Tried to start an LLMObs span for ${this.constructor.name} without an active APM span.
74
- Not starting LLMObs span.`
73
+ 'Tried to start an LLMObs span for %s without an active APM span. Not starting LLMObs span.',
74
+ this.constructor.name
75
75
  )
76
76
  return
77
77
  }
@@ -63,7 +63,7 @@ class BaseLangChainLLMObsPlugin extends LLMObsPlugin {
63
63
  const type = ctx.type = this.constructor.lcType // langchain operation type (oneof chain,chat_model,llm,embedding)
64
64
 
65
65
  if (!Object.keys(this._handlers).includes(type)) {
66
- log.warn(`Unsupported LangChain operation type: ${type}`)
66
+ log.warn('Unsupported LangChain operation type:', type)
67
67
  return
68
68
  }
69
69
 
@@ -61,19 +61,6 @@ class LLMObsTagger {
61
61
  if (!this._config.llmobs.enabled) return
62
62
  if (!kind) return // do not register it in the map if it doesn't have an llmobs span kind
63
63
 
64
- this._register(span)
65
-
66
- if (name) this._setTag(span, NAME, name)
67
-
68
- this._setTag(span, SPAN_KIND, kind)
69
- if (modelName) this._setTag(span, MODEL_NAME, modelName)
70
- if (modelProvider) this._setTag(span, MODEL_PROVIDER, modelProvider)
71
-
72
- sessionId = sessionId || registry.get(parent)?.[SESSION_ID]
73
- if (sessionId) this._setTag(span, SESSION_ID, sessionId)
74
- if (integration) this._setTag(span, INTEGRATION, integration)
75
- if (_decorator) this._setTag(span, DECORATOR, _decorator)
76
-
77
64
  const spanMlApp =
78
65
  mlApp ||
79
66
  registry.get(parent)?.[ML_APP] ||
@@ -87,8 +74,21 @@ class LLMObsTagger {
87
74
  )
88
75
  }
89
76
 
77
+ this._register(span)
78
+
90
79
  this._setTag(span, ML_APP, spanMlApp)
91
80
 
81
+ if (name) this._setTag(span, NAME, name)
82
+
83
+ this._setTag(span, SPAN_KIND, kind)
84
+ if (modelName) this._setTag(span, MODEL_NAME, modelName)
85
+ if (modelProvider) this._setTag(span, MODEL_PROVIDER, modelProvider)
86
+
87
+ sessionId = sessionId || registry.get(parent)?.[SESSION_ID]
88
+ if (sessionId) this._setTag(span, SESSION_ID, sessionId)
89
+ if (integration) this._setTag(span, INTEGRATION, integration)
90
+ if (_decorator) this._setTag(span, DECORATOR, _decorator)
91
+
92
92
  const parentId =
93
93
  parent?.context().toSpanId() ??
94
94
  span.context()._trace.tags[PROPAGATED_PARENT_ID_KEY] ??
@@ -60,7 +60,7 @@ class BaseLLMObsWriter {
60
60
  return
61
61
  }
62
62
 
63
- this._bufferSize += byteLength || Buffer.from(JSON.stringify(event)).byteLength
63
+ this._bufferSize += byteLength || Buffer.byteLength(JSON.stringify(event))
64
64
  this._buffer.push(event)
65
65
  }
66
66
 
@@ -76,7 +76,7 @@ class BaseLLMObsWriter {
76
76
  this._bufferSize = 0
77
77
  const payload = this._encode(this.makePayload(events))
78
78
 
79
- log.debug(`Encoded LLMObs payload: ${payload}`)
79
+ log.debug('Encoded LLMObs payload: %s', payload)
80
80
 
81
81
  const options = this._getOptions()
82
82
 
@@ -26,7 +26,7 @@ class LLMObsSpanWriter extends BaseWriter {
26
26
  }
27
27
 
28
28
  append (event) {
29
- const eventSizeBytes = Buffer.from(JSON.stringify(event)).byteLength
29
+ const eventSizeBytes = Buffer.byteLength(JSON.stringify(event))
30
30
  telemetry.recordLLMObsRawSpanSize(event, eventSizeBytes)
31
31
 
32
32
  const shouldTruncate = eventSizeBytes > EVP_EVENT_SIZE_LIMIT
@@ -35,7 +35,7 @@ class LLMObsSpanWriter extends BaseWriter {
35
35
  if (shouldTruncate) {
36
36
  logger.warn(`Dropping event input/output because its size (${eventSizeBytes}) exceeds the 1MB event size limit`)
37
37
  event = this._truncateSpanEvent(event)
38
- processedEventSizeBytes = Buffer.from(JSON.stringify(event)).byteLength
38
+ processedEventSizeBytes = Buffer.byteLength(JSON.stringify(event))
39
39
  }
40
40
 
41
41
  telemetry.recordLLMObsSpanSize(event, processedEventSizeBytes, shouldTruncate)
@@ -77,7 +77,7 @@ class Tracer {
77
77
  origin
78
78
  )
79
79
  } else {
80
- log.debug(`no dd list member in tracestate from incoming request: ${ts}`)
80
+ log.debug('no dd list member in tracestate from incoming request:', ts)
81
81
  }
82
82
  }
83
83
 
@@ -141,7 +141,7 @@ class TextMapPropagator {
141
141
  for (const [key, value] of Object.entries(baggageItems)) {
142
142
  const item = `${this._encodeOtelBaggageKey(String(key).trim())}=${encodeURIComponent(String(value).trim())},`
143
143
  itemCounter += 1
144
- byteCounter += item.length
144
+ byteCounter += Buffer.byteLength(item)
145
145
  if (itemCounter > this._config.baggageMaxItems || byteCounter > this._config.baggageMaxBytes) break
146
146
  baggage += item
147
147
  }
@@ -325,7 +325,7 @@ class TextMapPropagator {
325
325
  extractedContext = this._extractB3MultiContext(carrier)
326
326
  break
327
327
  default:
328
- if (extractor !== 'baggage') log.warn(`Unknown propagation style: ${extractor}`)
328
+ if (extractor !== 'baggage') log.warn('Unknown propagation style:', extractor)
329
329
  }
330
330
 
331
331
  if (extractedContext === null) { // If the current extractor was invalid, continue to the next extractor
@@ -514,7 +514,7 @@ class TextMapPropagator {
514
514
  // If subkey is tid then do nothing because trace header tid should always be preserved
515
515
  if (subKey === 'tid') {
516
516
  if (!hex16.test(value) || spanContext._trace.tags['_dd.p.tid'] !== transformedValue) {
517
- log.error(`Invalid trace id ${value} in tracestate, skipping`)
517
+ log.error('Invalid trace id %s in tracestate, skipping', value)
518
518
  }
519
519
  continue
520
520
  }
@@ -683,7 +683,7 @@ class TextMapPropagator {
683
683
  }
684
684
  // Check if value is a valid 16 character lower-case hexadecimal encoded number as per spec
685
685
  if (key === '_dd.p.tid' && !(hex16.test(value))) {
686
- log.error(`Invalid _dd.p.tid tag ${value}, skipping`)
686
+ log.error('Invalid _dd.p.tid tag %s, skipping', value)
687
687
  continue
688
688
  }
689
689
  tags[key] = value
@@ -240,6 +240,7 @@ class DatadogSpan {
240
240
  }
241
241
 
242
242
  getIntegrationCounter('spans_finished', this._integrationName).inc()
243
+ this._spanContext._tags['_dd.integration'] = this._integrationName
243
244
 
244
245
  if (DD_TRACE_EXPERIMENTAL_SPAN_COUNTS && finishedRegistry) {
245
246
  runtimeMetrics.decrement('runtime.node.spans.unfinished')
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { channel } = require('dc-polyfill')
4
- const { isFalse } = require('./util')
4
+ const { isFalse, normalizePluginEnvName } = require('./util')
5
5
  const plugins = require('./plugins')
6
6
  const log = require('./log')
7
7
  const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
@@ -33,11 +33,11 @@ function maybeEnable (Plugin) {
33
33
  if (!Plugin || typeof Plugin !== 'function') return
34
34
  if (!pluginClasses[Plugin.id]) {
35
35
  const envName = `DD_TRACE_${Plugin.id.toUpperCase()}_ENABLED`
36
- const enabled = getEnvironmentVariable(envName.replaceAll(/[^a-z0-9_]/ig, '_'))
36
+ const enabled = getEnvironmentVariable(normalizePluginEnvName(envName))
37
37
 
38
38
  // TODO: remove the need to load the plugin class in order to disable the plugin
39
39
  if (isFalse(enabled) || disabledPlugins.has(Plugin.id)) {
40
- log.debug(`Plugin "${Plugin.id}" was disabled via configuration option.`)
40
+ log.debug('Plugin "%s" was disabled via configuration option.', Plugin.id)
41
41
 
42
42
  pluginClasses[Plugin.id] = null
43
43
  } else {
@@ -5,11 +5,11 @@ const StoragePlugin = require('./storage')
5
5
  class CachePlugin extends StoragePlugin {
6
6
  static get operation () { return 'command' }
7
7
 
8
- startSpan (options) {
8
+ startSpan (options, ctx) {
9
9
  if (!options.kind) {
10
10
  options.kind = this.constructor.kind
11
11
  }
12
- return super.startSpan(this.operationName(), options)
12
+ return super.startSpan(this.operationName(), options, ctx)
13
13
  }
14
14
  }
15
15