dd-trace 5.58.0 → 5.60.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 (179) hide show
  1. package/LICENSE-3rdparty.csv +1 -0
  2. package/ci/cypress/after-run.js +2 -0
  3. package/ci/cypress/after-spec.js +2 -0
  4. package/ci/cypress/plugin.js +2 -0
  5. package/ci/cypress/polyfills.js +2 -0
  6. package/ci/cypress/support.js +2 -0
  7. package/ci/init.js +2 -0
  8. package/index.d.ts +7 -0
  9. package/init.js +0 -2
  10. package/initialize.mjs +2 -0
  11. package/package.json +40 -8
  12. package/packages/datadog-code-origin/index.js +14 -9
  13. package/packages/datadog-instrumentations/src/apollo-server.js +14 -3
  14. package/packages/datadog-instrumentations/src/apollo.js +7 -10
  15. package/packages/datadog-instrumentations/src/avsc.js +2 -0
  16. package/packages/datadog-instrumentations/src/child_process.js +21 -42
  17. package/packages/datadog-instrumentations/src/cucumber.js +10 -8
  18. package/packages/datadog-instrumentations/src/cypress.js +2 -0
  19. package/packages/datadog-instrumentations/src/fastify.js +19 -1
  20. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  21. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  22. package/packages/datadog-instrumentations/src/hono.js +102 -0
  23. package/packages/datadog-instrumentations/src/langchain.js +21 -0
  24. package/packages/datadog-instrumentations/src/mocha/common.js +2 -0
  25. package/packages/datadog-instrumentations/src/mocha.js +2 -0
  26. package/packages/datadog-instrumentations/src/nyc.js +2 -0
  27. package/packages/datadog-instrumentations/src/openai.js +13 -114
  28. package/packages/datadog-instrumentations/src/orchestrion-config/index.js +32 -0
  29. package/packages/datadog-instrumentations/src/playwright.js +5 -1
  30. package/packages/datadog-instrumentations/src/protobufjs.js +2 -0
  31. package/packages/datadog-instrumentations/src/selenium.js +2 -0
  32. package/packages/datadog-instrumentations/src/vitest.js +2 -0
  33. package/packages/datadog-plugin-avsc/src/index.js +2 -0
  34. package/packages/datadog-plugin-avsc/src/schema_iterator.js +2 -0
  35. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +2 -0
  36. package/packages/datadog-plugin-child_process/src/index.js +30 -10
  37. package/packages/datadog-plugin-cypress/src/after-run.js +2 -0
  38. package/packages/datadog-plugin-cypress/src/after-spec.js +2 -0
  39. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +8 -3
  40. package/packages/datadog-plugin-cypress/src/index.js +2 -0
  41. package/packages/datadog-plugin-cypress/src/plugin.js +2 -0
  42. package/packages/datadog-plugin-cypress/src/support.js +4 -2
  43. package/packages/datadog-plugin-google-cloud-vertexai/src/tracing.js +3 -155
  44. package/packages/datadog-plugin-google-cloud-vertexai/src/utils.js +2 -0
  45. package/packages/datadog-plugin-graphql/src/utils.js +2 -0
  46. package/packages/datadog-plugin-hono/src/index.js +28 -0
  47. package/packages/datadog-plugin-jest/src/index.js +2 -0
  48. package/packages/datadog-plugin-jest/src/util.js +2 -0
  49. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -0
  50. package/packages/datadog-plugin-langchain/src/tracing.js +36 -4
  51. package/packages/datadog-plugin-nyc/src/index.js +2 -0
  52. package/packages/datadog-plugin-openai/src/stream-helpers.js +114 -0
  53. package/packages/datadog-plugin-openai/src/tracing.js +38 -0
  54. package/packages/datadog-plugin-oracledb/src/connection-parser.js +2 -0
  55. package/packages/datadog-plugin-protobufjs/src/index.js +2 -0
  56. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +2 -0
  57. package/packages/datadog-plugin-selenium/src/index.js +2 -0
  58. package/packages/datadog-plugin-vitest/src/index.js +2 -0
  59. package/packages/dd-trace/src/appsec/iast/iast-context.js +5 -1
  60. package/packages/dd-trace/src/appsec/iast/index.js +2 -0
  61. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
  62. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +0 -2
  63. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -0
  64. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +2 -0
  65. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +2 -0
  66. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +3 -3
  67. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +18 -11
  68. package/packages/dd-trace/src/appsec/rasp/utils.js +1 -1
  69. package/packages/dd-trace/src/appsec/recommended.json +88 -2
  70. package/packages/dd-trace/src/appsec/reporter.js +7 -19
  71. package/packages/dd-trace/src/appsec/stack_trace.js +11 -11
  72. package/packages/dd-trace/src/appsec/telemetry/common.js +1 -1
  73. package/packages/dd-trace/src/appsec/waf/index.js +20 -1
  74. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +2 -2
  75. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +5 -4
  76. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -0
  77. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -1
  78. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -0
  79. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +2 -0
  80. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -0
  81. package/packages/dd-trace/src/ci-visibility/telemetry.js +2 -0
  82. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +2 -0
  83. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +7 -3
  84. package/packages/dd-trace/src/config.js +4 -16
  85. package/packages/dd-trace/src/config_stable.js +2 -0
  86. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -0
  87. package/packages/dd-trace/src/datastreams/context.js +2 -0
  88. package/packages/dd-trace/src/datastreams/encoding.js +2 -0
  89. package/packages/dd-trace/src/datastreams/fnv.js +2 -0
  90. package/packages/dd-trace/src/datastreams/pathway.js +11 -9
  91. package/packages/dd-trace/src/datastreams/processor.js +8 -7
  92. package/packages/dd-trace/src/datastreams/schemas/schema.js +2 -0
  93. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +45 -36
  94. package/packages/dd-trace/src/datastreams/schemas/schema_sampler.js +2 -0
  95. package/packages/dd-trace/src/datastreams/writer.js +2 -0
  96. package/packages/dd-trace/src/debugger/config.js +16 -0
  97. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +1 -1
  98. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -6
  99. package/packages/dd-trace/src/debugger/devtools_client/index.js +13 -5
  100. package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +2 -0
  101. package/packages/dd-trace/src/debugger/devtools_client/log.js +19 -0
  102. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +9 -6
  103. package/packages/dd-trace/src/debugger/devtools_client/send.js +1 -1
  104. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +1 -1
  105. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +1 -1
  106. package/packages/dd-trace/src/debugger/devtools_client/state.js +1 -1
  107. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  108. package/packages/dd-trace/src/debugger/index.js +48 -11
  109. package/packages/dd-trace/src/encode/tags-processors.js +2 -0
  110. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -0
  111. package/packages/dd-trace/src/exporters/common/util.js +2 -0
  112. package/packages/dd-trace/src/exporters/span-stats/index.js +2 -0
  113. package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -0
  114. package/packages/dd-trace/src/external-logger/src/index.js +2 -0
  115. package/packages/dd-trace/src/git_metadata_tagger.js +2 -0
  116. package/packages/dd-trace/src/git_properties.js +2 -0
  117. package/packages/dd-trace/src/guardrails/index.js +3 -4
  118. package/packages/dd-trace/src/guardrails/log.js +2 -2
  119. package/packages/dd-trace/src/guardrails/telemetry.js +16 -14
  120. package/packages/dd-trace/src/guardrails/util.js +0 -2
  121. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +2 -0
  122. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +5 -0
  123. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/tool.js +15 -0
  124. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +36 -0
  125. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +47 -4
  126. package/packages/dd-trace/src/llmobs/tagger.js +10 -1
  127. package/packages/dd-trace/src/noop/dogstatsd.js +2 -0
  128. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -0
  129. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -0
  130. package/packages/dd-trace/src/payload-tagging/index.js +2 -0
  131. package/packages/dd-trace/src/payload-tagging/tagging.js +2 -0
  132. package/packages/dd-trace/src/plugins/apollo.js +2 -0
  133. package/packages/dd-trace/src/plugins/ci_plugin.js +8 -3
  134. package/packages/dd-trace/src/plugins/index.js +1 -0
  135. package/packages/dd-trace/src/plugins/util/ci.js +17 -7
  136. package/packages/dd-trace/src/plugins/util/env.js +2 -0
  137. package/packages/dd-trace/src/plugins/util/git.js +40 -5
  138. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +2 -0
  139. package/packages/dd-trace/src/plugins/util/llm.js +2 -0
  140. package/packages/dd-trace/src/plugins/util/serverless.js +2 -0
  141. package/packages/dd-trace/src/plugins/util/stacktrace.js +178 -50
  142. package/packages/dd-trace/src/plugins/util/tags.js +19 -1
  143. package/packages/dd-trace/src/plugins/util/test.js +9 -4
  144. package/packages/dd-trace/src/plugins/util/url.js +2 -0
  145. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -0
  146. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +4 -0
  147. package/packages/dd-trace/src/profiling/profiler.js +89 -70
  148. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -0
  149. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +2 -0
  150. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +2 -0
  151. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +2 -0
  152. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +2 -0
  153. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +2 -0
  154. package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +2 -0
  155. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +2 -0
  156. package/packages/dd-trace/src/profiling/profilers/events.js +2 -0
  157. package/packages/dd-trace/src/profiling/webspan-utils.js +2 -0
  158. package/packages/dd-trace/src/remote_config/capabilities.js +4 -1
  159. package/packages/dd-trace/src/remote_config/index.js +6 -0
  160. package/packages/dd-trace/src/service-naming/index.js +2 -0
  161. package/packages/dd-trace/src/service-naming/schemas/definition.js +2 -0
  162. package/packages/dd-trace/src/service-naming/schemas/util.js +2 -0
  163. package/packages/dd-trace/src/service-naming/schemas/v0/graphql.js +2 -0
  164. package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -0
  165. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -0
  166. package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +2 -0
  167. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +2 -0
  168. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +2 -0
  169. package/packages/dd-trace/src/service-naming/schemas/v1/graphql.js +2 -0
  170. package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -0
  171. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -0
  172. package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +2 -0
  173. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +2 -0
  174. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +2 -0
  175. package/packages/dd-trace/src/span_stats.js +2 -0
  176. package/packages/dd-trace/src/supported-configurations.json +2 -0
  177. package/packages/dd-trace/src/telemetry/send-data.js +2 -0
  178. package/register.js +4 -0
  179. package/version.js +0 -3
@@ -2,14 +2,10 @@
2
2
 
3
3
  const { workerData: { config: parentConfig, parentThreadId, configPort } } = require('node:worker_threads')
4
4
  const { format } = require('node:url')
5
- const log = require('../../log')
5
+ const log = require('./log')
6
6
 
7
7
  const config = module.exports = {
8
- dynamicInstrumentation: parentConfig.dynamicInstrumentation,
9
- runtimeId: parentConfig.tags['runtime-id'],
10
- service: parentConfig.service,
11
- commitSHA: parentConfig.commitSHA,
12
- repositoryUrl: parentConfig.repositoryUrl,
8
+ ...parentConfig,
13
9
  parentThreadId,
14
10
  maxTotalPayloadSize: 5 * 1024 * 1024 // 5MB
15
11
  }
@@ -9,7 +9,7 @@ const { getStackFromCallFrames } = require('./state')
9
9
  const { ackEmitting } = require('./status')
10
10
  const { parentThreadId } = require('./config')
11
11
  const { MAX_SNAPSHOTS_PER_SECOND_GLOBALLY } = require('./defaults')
12
- const log = require('../../log')
12
+ const log = require('./log')
13
13
  const { version } = require('../../../../../package.json')
14
14
  const { NODE_MAJOR } = require('../../../../../version')
15
15
 
@@ -40,11 +40,19 @@ const SUPPORT_ARRAY_BUFFER_RESIZE = NODE_MAJOR >= 20
40
40
  const oneSecondNs = 1_000_000_000n
41
41
  let globalSnapshotSamplingRateWindowStart = 0n
42
42
  let snapshotsSampledWithinTheLastSecond = 0
43
- // TODO: Is a limit of 256 snapshots ever going to be a problem?
44
- const snapshotProbeIndexBuffer = new ArrayBuffer(1, { maxByteLength: 256 })
45
- // TODO: Is a limit of 256 probes ever going to be a problem?
43
+
46
44
  // TODO: Change to const once we drop support for Node.js 18
47
- let snapshotProbeIndex = new Uint8Array(snapshotProbeIndexBuffer)
45
+ let snapshotProbeIndexBuffer, snapshotProbeIndex
46
+
47
+ if (SUPPORT_ARRAY_BUFFER_RESIZE) {
48
+ // TODO: Is a limit of 256 snapshots ever going to be a problem?
49
+ // eslint-disable-next-line n/no-unsupported-features/es-syntax
50
+ snapshotProbeIndexBuffer = new ArrayBuffer(1, { maxByteLength: 256 })
51
+ // TODO: Is a limit of 256 probes ever going to be a problem?
52
+ snapshotProbeIndex = new Uint8Array(snapshotProbeIndexBuffer)
53
+ } else {
54
+ snapshotProbeIndex = new Uint8Array(1)
55
+ }
48
56
 
49
57
  // WARNING: The code above the line `await session.post('Debugger.resume')` is highly optimized. Please edit with care!
50
58
  session.on('Debugger.paused', async ({ params }) => {
@@ -1,5 +1,7 @@
1
1
  'use strict'
2
2
 
3
+ /* eslint n/no-unsupported-features/node-builtins: ['error', { ignores: ['inspector/promises'] }] */
4
+
3
5
  const { builtinModules } = require('node:module')
4
6
 
5
7
  if (builtinModules.includes('inspector/promises')) {
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ const { workerData } = require('node:worker_threads')
4
+
5
+ // For testing purposes, we allow `workerData` to be undefined and fallback to a default config
6
+ const { config: { debug, logLevel }, logPort } = workerData ?? { config: { debug: false } }
7
+
8
+ const LEVELS = ['error', 'warn', 'info', 'debug']
9
+ const on = (level, ...args) => {
10
+ if (typeof args[0] === 'function') {
11
+ args = [args[0]()]
12
+ }
13
+ logPort.postMessage({ level, args })
14
+ }
15
+ const off = () => {}
16
+
17
+ for (const level of LEVELS) {
18
+ module.exports[level] = debug && LEVELS.indexOf(logLevel) >= LEVELS.indexOf(level) ? on.bind(null, level) : off
19
+ }
@@ -1,9 +1,9 @@
1
1
  'use strict'
2
2
 
3
- const { workerData: { rcPort } } = require('node:worker_threads')
3
+ const { workerData: { probePort } } = require('node:worker_threads')
4
4
  const { addBreakpoint, removeBreakpoint, modifyBreakpoint } = require('./breakpoints')
5
5
  const { ackReceived, ackInstalled, ackError } = require('./status')
6
- const log = require('../../log')
6
+ const log = require('./log')
7
7
 
8
8
  // Example log line probe (simplified):
9
9
  // {
@@ -32,16 +32,19 @@ const log = require('../../log')
32
32
  // sampling: { snapshotsPerSecond: 5000 },
33
33
  // evaluateAt: 'EXIT' // only used for method probes
34
34
  // }
35
- rcPort.on('message', async ({ action, conf: probe, ackId }) => {
35
+ probePort.on('message', async ({ action, probe, ackId }) => {
36
36
  try {
37
37
  await processMsg(action, probe)
38
- rcPort.postMessage({ ackId })
38
+ probePort.postMessage({ ackId })
39
39
  } catch (err) {
40
- rcPort.postMessage({ ackId, error: err })
40
+ probePort.postMessage({ ackId, error: err })
41
41
  ackError(err, probe)
42
42
  }
43
43
  })
44
- rcPort.on('messageerror', (err) => log.error('[debugger:devtools_client] received "messageerror" on RC port', err))
44
+ probePort.on(
45
+ 'messageerror',
46
+ (err) => log.error('[debugger:devtools_client] received "messageerror" on probe port', err)
47
+ )
45
48
 
46
49
  async function processMsg (action, probe) {
47
50
  log.debug(
@@ -7,7 +7,7 @@ const config = require('./config')
7
7
  const JSONBuffer = require('./json-buffer')
8
8
  const request = require('../../exporters/common/request')
9
9
  const { GIT_COMMIT_SHA, GIT_REPOSITORY_URL } = require('../../plugins/util/tags')
10
- const log = require('../../log')
10
+ const log = require('./log')
11
11
  const { version } = require('../../../../../package.json')
12
12
  const { getEnvironmentVariable } = require('../../config-helper')
13
13
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { getRuntimeObject } = require('./collector')
4
4
  const { processRawState } = require('./processor')
5
- const log = require('../../../log')
5
+ const log = require('../log')
6
6
 
7
7
  const DEFAULT_MAX_REFERENCE_DEPTH = 3
8
8
  const DEFAULT_MAX_COLLECTION_SIZE = 100
@@ -1,4 +1,4 @@
1
- 'use stict'
1
+ 'use strict'
2
2
 
3
3
  module.exports = {
4
4
  collectionSizeSym: Symbol('datadog.collectionSize'),
@@ -4,7 +4,7 @@ const { join, dirname } = require('path')
4
4
  const { normalize } = require('source-map/lib/util')
5
5
  const { loadSourceMapSync } = require('./source-maps')
6
6
  const session = require('./session')
7
- const log = require('../../log')
7
+ const log = require('./log')
8
8
 
9
9
  const WINDOWS_DRIVE_LETTER_REGEX = /[a-zA-Z]/
10
10
 
@@ -5,7 +5,7 @@ const config = require('./config')
5
5
  const JSONBuffer = require('./json-buffer')
6
6
  const request = require('../../exporters/common/request')
7
7
  const FormData = require('../../exporters/common/form-data')
8
- const log = require('../../log')
8
+ const log = require('./log')
9
9
 
10
10
  module.exports = {
11
11
  ackReceived,
@@ -1,8 +1,10 @@
1
1
  'use strict'
2
2
 
3
+ const { readFile } = require('fs')
3
4
  const { types } = require('util')
4
5
  const { join } = require('path')
5
6
  const { Worker, MessageChannel, threadId: parentThreadId } = require('worker_threads')
7
+ const getDebuggerConfig = require('./config')
6
8
  const log = require('../log')
7
9
 
8
10
  let worker = null
@@ -23,17 +25,25 @@ function start (config, rc) {
23
25
  log.debug('[debugger] Starting Dynamic Instrumentation client...')
24
26
 
25
27
  const rcAckCallbacks = new Map()
26
- const rcChannel = new MessageChannel()
28
+ const probeChannel = new MessageChannel()
29
+ const logChannel = new MessageChannel()
27
30
  configChannel = new MessageChannel()
28
31
 
29
32
  process[Symbol.for('datadog:node:util:types')] = types
30
33
 
31
- rc.setProductHandler('LIVE_DEBUGGING', (action, conf, id, ack) => {
34
+ readProbeFile(config.dynamicInstrumentation.probeFile, (probes) => {
35
+ const action = 'apply'
36
+ for (const probe of probes) {
37
+ probeChannel.port2.postMessage({ action, probe })
38
+ }
39
+ })
40
+
41
+ rc.setProductHandler('LIVE_DEBUGGING', (action, probe, id, ack) => {
32
42
  rcAckCallbacks.set(++ackId, ack)
33
- rcChannel.port2.postMessage({ action, conf, ackId })
43
+ probeChannel.port2.postMessage({ action, probe, ackId })
34
44
  })
35
45
 
36
- rcChannel.port2.on('message', ({ ackId, error }) => {
46
+ probeChannel.port2.on('message', ({ ackId, error }) => {
37
47
  const ack = rcAckCallbacks.get(ackId)
38
48
  if (ack === undefined) {
39
49
  // This should never happen, but just in case something changes in the future, we should guard against it
@@ -44,7 +54,12 @@ function start (config, rc) {
44
54
  ack(error)
45
55
  rcAckCallbacks.delete(ackId)
46
56
  })
47
- rcChannel.port2.on('messageerror', (err) => log.error('[debugger] received "messageerror" on RC port', err))
57
+ probeChannel.port2.on('messageerror', (err) => log.error('[debugger] received "messageerror" on probe port', err))
58
+
59
+ logChannel.port2.on('message', ({ level, args }) => {
60
+ log[level](...args)
61
+ })
62
+ logChannel.port2.on('messageerror', (err) => log.error('[debugger] received "messageerror" on log port', err))
48
63
 
49
64
  worker = new Worker(
50
65
  join(__dirname, 'devtools_client', 'index.js'),
@@ -52,12 +67,13 @@ function start (config, rc) {
52
67
  execArgv: [], // Avoid worker thread inheriting the `-r` command line argument
53
68
  env, // Avoid worker thread inheriting the `NODE_OPTIONS` environment variable (in case it contains `-r`)
54
69
  workerData: {
55
- config: config.serialize(),
70
+ config: getDebuggerConfig(config),
56
71
  parentThreadId,
57
- rcPort: rcChannel.port1,
72
+ probePort: probeChannel.port1,
73
+ logPort: logChannel.port1,
58
74
  configPort: configChannel.port1
59
75
  },
60
- transferList: [rcChannel.port1, configChannel.port1]
76
+ transferList: [probeChannel.port1, logChannel.port1, configChannel.port1]
61
77
  }
62
78
  )
63
79
 
@@ -84,13 +100,34 @@ function start (config, rc) {
84
100
  })
85
101
 
86
102
  worker.unref()
87
- rcChannel.port1.unref()
88
- rcChannel.port2.unref()
103
+ probeChannel.port1.unref()
104
+ probeChannel.port2.unref()
105
+ logChannel.port1.unref()
106
+ logChannel.port2.unref()
89
107
  configChannel.port1.unref()
90
108
  configChannel.port2.unref()
91
109
  }
92
110
 
93
111
  function configure (config) {
94
112
  if (configChannel === null) return
95
- configChannel.port2.postMessage(config.serialize())
113
+ configChannel.port2.postMessage(getDebuggerConfig(config))
114
+ }
115
+
116
+ function readProbeFile (path, cb) {
117
+ if (!path) return
118
+
119
+ log.debug('[debugger] Reading probe file: %s', path)
120
+ readFile(path, 'utf8', (err, data) => {
121
+ if (err) {
122
+ log.error('[debugger] Failed to read probe file: %s', path, err)
123
+ return
124
+ }
125
+ try {
126
+ const parsedData = JSON.parse(data)
127
+ log.debug('[debugger] Successfully parsed probe file: %s', path)
128
+ cb(parsedData)
129
+ } catch (err) {
130
+ log.error('[debugger] Probe file (%s) is not valid JSON', path, err)
131
+ }
132
+ })
96
133
  }
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  // From agent truncators: https://github.com/DataDog/datadog-agent/blob/main/pkg/trace/agent/truncator.go
2
4
 
3
5
  // Values from: https://github.com/DataDog/datadog-agent/blob/main/pkg/trace/traceutil/truncate.go#L22-L27
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { URL, format } = require('url')
2
4
 
3
5
  const request = require('./request')
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { getEnvironmentVariable } = require('../../config-helper')
2
4
 
3
5
  function safeJSONStringify (value) {
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { URL, format } = require('url')
2
4
 
3
5
  const { Writer } = require('./writer')
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { SpanStatsEncoder } = require('../../encode/span-stats')
2
4
 
3
5
  const pkg = require('../../../../../package.json')
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const tracerLogger = require('../../log')// path to require tracer logger
2
4
 
3
5
  const https = require('https')
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const { SCI_COMMIT_SHA, SCI_REPOSITORY_URL } = require('./constants')
2
4
 
3
5
  class GitMetadataTagger {
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const commitSHARegex = /git\.commit\.sha=([a-f\d]{40})/
2
4
  const repositoryUrlRegex = /git\.repository_url=([\w\d:@/.-]+)/
3
5
 
@@ -1,7 +1,5 @@
1
1
  'use strict'
2
2
 
3
- /* eslint-disable no-var */
4
-
5
3
  var path = require('path')
6
4
  var Module = require('module')
7
5
  var isTrue = require('./util').isTrue
@@ -26,9 +24,11 @@ function guard (fn) {
26
24
  var resolvedInApp
27
25
  var entrypoint = process.argv[1]
28
26
  try {
27
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
29
28
  resolvedInApp = Module.createRequire(entrypoint).resolve('dd-trace')
30
29
  } catch (e) {
31
30
  // Ignore. If we can't resolve the module, we assume it's not in the app.
31
+ // TODO: There's also the possibility that this version of Node.js doesn't have Module.createRequire (pre v12.2.0)
32
32
  }
33
33
  if (resolvedInApp) {
34
34
  var ourselves = path.normalize(path.join(__dirname, '..', '..', '..', '..', 'index.js'))
@@ -54,8 +54,7 @@ function guard (fn) {
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
+ // Ensure the instrumentation source is set for the current process and potential child processes.
59
58
  var result = fn()
60
59
  telemetry('complete', ['injection_forced:' + (forced && initBailout ? 'true' : 'false')])
61
60
  log.info('Application instrumentation bootstrapping complete')
@@ -1,6 +1,5 @@
1
1
  'use strict'
2
2
 
3
- /* eslint-disable no-var */
4
3
  /* eslint-disable no-console */
5
4
 
6
5
  var isTrue = require('./util').isTrue
@@ -23,7 +22,8 @@ var logLevel = isTrue(DD_TRACE_DEBUG)
23
22
  : logLevels.off
24
23
 
25
24
  var log = {
26
- debug: logLevel <= 20 ? console.debug.bind(console) : function () {},
25
+ /* eslint n/no-unsupported-features/node-builtins: ['error', { ignores: ['console.debug'] }] */
26
+ debug: logLevel <= 20 ? (console.debug || console.log).bind(console) : function () {},
27
27
  info: logLevel <= 30 ? console.info.bind(console) : function () {},
28
28
  warn: logLevel <= 40 ? console.warn.bind(console) : function () {},
29
29
  error: logLevel <= 50 ? console.error.bind(console) : function () {}
@@ -1,8 +1,5 @@
1
1
  'use strict'
2
2
 
3
- /* eslint-disable no-var */
4
- /* eslint-disable object-shorthand */
5
-
6
3
  var fs = require('fs')
7
4
  var spawn = require('child_process').spawn
8
5
  var tracerVersion = require('../../../../package.json').version
@@ -11,12 +8,12 @@ var log = require('./log')
11
8
  module.exports = sendTelemetry
12
9
 
13
10
  if (!process.env.DD_INJECTION_ENABLED) {
14
- module.exports = function () {}
11
+ module.exports = function noop () {}
15
12
  }
16
13
 
17
14
  var telemetryForwarderPath = process.env.DD_TELEMETRY_FORWARDER_PATH
18
15
  if (typeof telemetryForwarderPath !== 'string' || !fs.existsSync(telemetryForwarderPath)) {
19
- module.exports = function () {}
16
+ module.exports = function noop () {}
20
17
  }
21
18
 
22
19
  var metadata = {
@@ -28,18 +25,23 @@ var metadata = {
28
25
  pid: process.pid
29
26
  }
30
27
 
31
- var seen = []
32
- function hasSeen (point) {
28
+ var seen = {}
29
+ function shouldSend (point) {
33
30
  if (point.name === 'abort') {
34
31
  // This one can only be sent once, regardless of tags
35
- return seen.includes('abort')
36
- }
37
- if (point.name === 'abort.integration') {
32
+ if (seen.abort) {
33
+ return false
34
+ }
35
+ seen.abort = true
36
+ } else if (point.name === 'abort.integration') {
38
37
  // For now, this is the only other one we want to dedupe
39
38
  var compiledPoint = point.name + point.tags.join('')
40
- return seen.includes(compiledPoint)
39
+ if (seen[compiledPoint]) {
40
+ return false
41
+ }
42
+ seen[compiledPoint] = true
41
43
  }
42
- return false
44
+ return true
43
45
  }
44
46
 
45
47
  function sendTelemetry (name, tags) {
@@ -48,9 +50,9 @@ function sendTelemetry (name, tags) {
48
50
  points = [{ name: name, tags: tags || [] }]
49
51
  }
50
52
  if (['1', 'true', 'True'].indexOf(process.env.DD_INJECT_FORCE) !== -1) {
51
- points = points.filter(function (p) { return ['error', 'complete'].includes(p.name) })
53
+ points = points.filter(function (p) { return ['error', 'complete'].indexOf(p.name) !== -1 })
52
54
  }
53
- points = points.filter(function (p) { return !hasSeen(p) })
55
+ points = points.filter(function (p) { return shouldSend(p) })
54
56
  for (var i = 0; i < points.length; i++) {
55
57
  points[i].name = 'library_entrypoint.' + points[i].name
56
58
  }
@@ -1,7 +1,5 @@
1
1
  'use strict'
2
2
 
3
- /* eslint-disable object-shorthand */
4
-
5
3
  function isTrue (str) {
6
4
  str = String(str).toLowerCase()
7
5
  return str === 'true' || str === '1'
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const BaseLLMObsPlugin = require('./base')
2
4
  const { storage } = require('../../../../datadog-core')
3
5
  const llmobsStore = storage('llmobs')
@@ -8,9 +8,14 @@ const ROLE_MAPPINGS = {
8
8
 
9
9
  class LangChainLLMObsHandler {
10
10
  constructor (tagger) {
11
+ /** @type {import('../../../tagger')} */
11
12
  this._tagger = tagger
12
13
  }
13
14
 
15
+ getName ({ span }) {
16
+ return span?.context()._tags?.['resource.name']
17
+ }
18
+
14
19
  setMetaTags () {}
15
20
 
16
21
  formatIO (messages) {
@@ -0,0 +1,15 @@
1
+ 'use strict'
2
+
3
+ const LangChainLLMObsHandler = require('.')
4
+
5
+ class LangChainLLMObsToolHandler extends LangChainLLMObsHandler {
6
+ getName ({ instance }) {
7
+ return instance.name
8
+ }
9
+
10
+ setMetaTags ({ span, inputs, results }) {
11
+ this._tagger.tagTextIO(span, inputs, results)
12
+ }
13
+ }
14
+
15
+ module.exports = LangChainLLMObsToolHandler
@@ -0,0 +1,36 @@
1
+ 'use strict'
2
+
3
+ const LangChainLLMObsHandler = require('.')
4
+ const { spanHasError } = require('../../../util')
5
+
6
+ class LangChainLLMObsVectorStoreHandler extends LangChainLLMObsHandler {
7
+ setMetaTags ({ span, inputs, results }) {
8
+ const input = this.formatIO(inputs)
9
+ if (spanHasError(span)) {
10
+ this._tagger.tagRetrievalIO(span, input)
11
+ return
12
+ }
13
+
14
+ const documents = []
15
+ for (const documentResult of results) {
16
+ let document, score
17
+ if (Array.isArray(documentResult)) {
18
+ document = documentResult[0]
19
+ score = documentResult[1]
20
+ } else {
21
+ document = documentResult
22
+ }
23
+
24
+ documents.push({
25
+ text: document.pageContent,
26
+ id: document.id,
27
+ name: document.metadata?.source,
28
+ score
29
+ })
30
+ }
31
+
32
+ this._tagger.tagRetrievalIO(span, input, documents)
33
+ }
34
+ }
35
+
36
+ module.exports = LangChainLLMObsVectorStoreHandler
@@ -14,11 +14,15 @@ const LLM_SPAN_TYPES = new Set(['llm', 'chat_model', 'embedding'])
14
14
  const LLM = 'llm'
15
15
  const WORKFLOW = 'workflow'
16
16
  const EMBEDDING = 'embedding'
17
+ const TOOL = 'tool'
18
+ const RETRIEVAL = 'retrieval'
17
19
 
18
20
  const ChainHandler = require('./handlers/chain')
19
21
  const ChatModelHandler = require('./handlers/chat_model')
20
22
  const LlmHandler = require('./handlers/llm')
21
23
  const EmbeddingHandler = require('./handlers/embedding')
24
+ const ToolHandler = require('./handlers/tool')
25
+ const VectorStoreHandler = require('./handlers/vectorstore')
22
26
 
23
27
  class BaseLangChainLLMObsPlugin extends LLMObsPlugin {
24
28
  static get integration () { return 'langchain' }
@@ -34,7 +38,9 @@ class BaseLangChainLLMObsPlugin extends LLMObsPlugin {
34
38
  chain: new ChainHandler(this._tagger),
35
39
  chat_model: new ChatModelHandler(this._tagger),
36
40
  llm: new LlmHandler(this._tagger),
37
- embedding: new EmbeddingHandler(this._tagger)
41
+ embedding: new EmbeddingHandler(this._tagger),
42
+ tool: new ToolHandler(this._tagger),
43
+ similarity_search: new VectorStoreHandler(this._tagger)
38
44
  }
39
45
  }
40
46
 
@@ -45,7 +51,10 @@ class BaseLangChainLLMObsPlugin extends LLMObsPlugin {
45
51
  const modelProvider = tags['langchain.request.provider'] // could be undefined
46
52
  const modelName = tags['langchain.request.model'] // could be undefined
47
53
  const kind = this.getKind(ctx.type, modelProvider)
48
- const name = tags['resource.name']
54
+
55
+ const instance = ctx.instance || ctx.self
56
+ const handler = this._handlers[ctx.type]
57
+ const name = handler?.getName({ span, instance })
49
58
 
50
59
  return {
51
60
  modelProvider,
@@ -113,7 +122,14 @@ class BaseLangChainLLMObsPlugin extends LLMObsPlugin {
113
122
  }
114
123
  }
115
124
 
116
- return WORKFLOW
125
+ switch (type) {
126
+ case 'tool':
127
+ return TOOL
128
+ case 'similarity_search':
129
+ return RETRIEVAL
130
+ default:
131
+ return WORKFLOW
132
+ }
117
133
  }
118
134
 
119
135
  getIntegrationName (type, provider = 'custom') {
@@ -181,11 +197,38 @@ class EmbeddingsEmbedDocumentsPlugin extends BaseLangChainLLMObsPlugin {
181
197
  }
182
198
  }
183
199
 
200
+ class ToolInvokePlugin extends BaseLangChainLLMObsPlugin {
201
+ static get id () { return 'llmobs_langchain_tool_invoke' }
202
+ static get lcType () { return 'tool' }
203
+ static get prefix () {
204
+ return 'tracing:orchestrion:@langchain/core:Tool_invoke'
205
+ }
206
+ }
207
+
208
+ class VectorStoreSimilaritySearchPlugin extends BaseLangChainLLMObsPlugin {
209
+ static get id () { return 'llmobs_langchain_vectorstore_similarity_search' }
210
+ static get lcType () { return 'similarity_search' }
211
+ static get prefix () {
212
+ return 'tracing:orchestrion:@langchain/core:VectorStore_similaritySearch'
213
+ }
214
+ }
215
+
216
+ class VectorStoreSimilaritySearchWithScorePlugin extends BaseLangChainLLMObsPlugin {
217
+ static get id () { return 'llmobs_langchain_vectorstore_similarity_search_with_score' }
218
+ static get lcType () { return 'similarity_search' }
219
+ static get prefix () {
220
+ return 'tracing:orchestrion:@langchain/core:VectorStore_similaritySearchWithScore'
221
+ }
222
+ }
223
+
184
224
  module.exports = [
185
225
  RunnableSequenceInvokePlugin,
186
226
  RunnableSequenceBatchPlugin,
187
227
  BaseChatModelGeneratePlugin,
188
228
  BaseLLMGeneratePlugin,
189
229
  EmbeddingsEmbedQueryPlugin,
190
- EmbeddingsEmbedDocumentsPlugin
230
+ EmbeddingsEmbedDocumentsPlugin,
231
+ ToolInvokePlugin,
232
+ VectorStoreSimilaritySearchPlugin,
233
+ VectorStoreSimilaritySearchWithScorePlugin
191
234
  ]
@@ -281,6 +281,7 @@ class LLMObsTagger {
281
281
 
282
282
  const { content = '', role } = message
283
283
  const toolCalls = message.toolCalls
284
+ const toolId = message.toolId
284
285
  const messageObj = { content }
285
286
 
286
287
  const valid = typeof content === 'string'
@@ -288,7 +289,7 @@ class LLMObsTagger {
288
289
  this.#handleFailure('Message content must be a string.', 'invalid_io_messages')
289
290
  }
290
291
 
291
- const condition = this.#tagConditionalString(role, 'Message role', messageObj, 'role')
292
+ let condition = this.#tagConditionalString(role, 'Message role', messageObj, 'role')
292
293
 
293
294
  if (toolCalls) {
294
295
  const filteredToolCalls = this.#filterToolCalls(toolCalls)
@@ -298,6 +299,14 @@ class LLMObsTagger {
298
299
  }
299
300
  }
300
301
 
302
+ if (toolId) {
303
+ if (role === 'tool') {
304
+ condition = this.#tagConditionalString(toolId, 'Tool ID', messageObj, 'tool_id')
305
+ } else {
306
+ log.warn(`Tool ID for tool message not associated with a "tool" role, instead got "${role}"`)
307
+ }
308
+ }
309
+
301
310
  if (valid && condition) {
302
311
  messages.push(messageObj)
303
312
  }