dd-trace 5.57.1 → 5.59.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 (206) hide show
  1. package/LICENSE-3rdparty.csv +3 -1
  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 +1 -6
  10. package/initialize.mjs +2 -0
  11. package/package.json +40 -9
  12. package/packages/datadog-code-origin/index.js +14 -9
  13. package/packages/datadog-instrumentations/src/apollo.js +7 -10
  14. package/packages/datadog-instrumentations/src/avsc.js +2 -0
  15. package/packages/datadog-instrumentations/src/azure-functions.js +1 -1
  16. package/packages/datadog-instrumentations/src/child_process.js +22 -43
  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/graphql.js +9 -0
  21. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  22. package/packages/datadog-instrumentations/src/helpers/register.js +2 -2
  23. package/packages/datadog-instrumentations/src/hono.js +102 -0
  24. package/packages/datadog-instrumentations/src/jest.js +1 -1
  25. package/packages/datadog-instrumentations/src/langchain.js +21 -0
  26. package/packages/datadog-instrumentations/src/mocha/common.js +2 -0
  27. package/packages/datadog-instrumentations/src/mocha.js +2 -0
  28. package/packages/datadog-instrumentations/src/mysql2.js +6 -6
  29. package/packages/datadog-instrumentations/src/next.js +3 -1
  30. package/packages/datadog-instrumentations/src/nyc.js +2 -0
  31. package/packages/datadog-instrumentations/src/oracledb.js +24 -2
  32. package/packages/datadog-instrumentations/src/orchestrion-config/index.js +32 -0
  33. package/packages/datadog-instrumentations/src/playwright.js +5 -1
  34. package/packages/datadog-instrumentations/src/protobufjs.js +2 -0
  35. package/packages/datadog-instrumentations/src/selenium.js +2 -0
  36. package/packages/datadog-instrumentations/src/tedious.js +12 -17
  37. package/packages/datadog-instrumentations/src/vitest.js +2 -0
  38. package/packages/datadog-plugin-avsc/src/index.js +2 -0
  39. package/packages/datadog-plugin-avsc/src/schema_iterator.js +2 -0
  40. package/packages/datadog-plugin-aws-sdk/src/base.js +51 -1
  41. package/packages/datadog-plugin-aws-sdk/src/services/bedrockruntime/index.js +2 -0
  42. package/packages/datadog-plugin-child_process/src/index.js +30 -10
  43. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -1
  44. package/packages/datadog-plugin-cypress/src/after-run.js +2 -0
  45. package/packages/datadog-plugin-cypress/src/after-spec.js +2 -0
  46. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +8 -3
  47. package/packages/datadog-plugin-cypress/src/index.js +2 -0
  48. package/packages/datadog-plugin-cypress/src/plugin.js +2 -0
  49. package/packages/datadog-plugin-cypress/src/support.js +21 -25
  50. package/packages/datadog-plugin-google-cloud-vertexai/src/utils.js +2 -0
  51. package/packages/datadog-plugin-graphql/src/tools/index.js +0 -2
  52. package/packages/datadog-plugin-graphql/src/tools/signature.js +0 -2
  53. package/packages/datadog-plugin-graphql/src/tools/transforms.js +0 -2
  54. package/packages/datadog-plugin-graphql/src/utils.js +2 -0
  55. package/packages/datadog-plugin-hono/src/index.js +28 -0
  56. package/packages/datadog-plugin-http/src/client.js +3 -4
  57. package/packages/datadog-plugin-http2/src/client.js +9 -8
  58. package/packages/datadog-plugin-jest/src/index.js +2 -0
  59. package/packages/datadog-plugin-jest/src/util.js +2 -0
  60. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +2 -0
  61. package/packages/datadog-plugin-langchain/src/handlers/chain.js +1 -1
  62. package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +1 -1
  63. package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +1 -1
  64. package/packages/datadog-plugin-langchain/src/tracing.js +36 -4
  65. package/packages/datadog-plugin-nyc/src/index.js +2 -0
  66. package/packages/datadog-plugin-oracledb/src/connection-parser.js +37 -0
  67. package/packages/datadog-plugin-oracledb/src/index.js +15 -17
  68. package/packages/datadog-plugin-protobufjs/src/index.js +2 -0
  69. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +2 -0
  70. package/packages/datadog-plugin-selenium/src/index.js +2 -0
  71. package/packages/datadog-plugin-tedious/src/index.js +10 -9
  72. package/packages/datadog-plugin-vitest/src/index.js +2 -0
  73. package/packages/dd-trace/src/appsec/iast/analyzers/injection-analyzer.js +6 -4
  74. package/packages/dd-trace/src/appsec/iast/analyzers/ssrf-analyzer.js +9 -0
  75. package/packages/dd-trace/src/appsec/iast/iast-context.js +5 -1
  76. package/packages/dd-trace/src/appsec/iast/index.js +2 -0
  77. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
  78. package/packages/dd-trace/src/appsec/iast/taint-tracking/operations-taint-object.js +5 -2
  79. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +0 -2
  80. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -0
  81. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-regex.js +2 -0
  82. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -0
  83. package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +2 -0
  84. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +3 -3
  85. package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +18 -11
  86. package/packages/dd-trace/src/appsec/rasp/utils.js +1 -1
  87. package/packages/dd-trace/src/appsec/recommended.json +88 -2
  88. package/packages/dd-trace/src/appsec/reporter.js +68 -14
  89. package/packages/dd-trace/src/appsec/rule_manager.js +63 -171
  90. package/packages/dd-trace/src/appsec/sdk/track_event.js +3 -5
  91. package/packages/dd-trace/src/appsec/stack_trace.js +11 -11
  92. package/packages/dd-trace/src/appsec/telemetry/common.js +2 -2
  93. package/packages/dd-trace/src/appsec/telemetry/index.js +8 -0
  94. package/packages/dd-trace/src/appsec/telemetry/waf.js +5 -3
  95. package/packages/dd-trace/src/appsec/waf/diagnostics.js +15 -0
  96. package/packages/dd-trace/src/appsec/waf/index.js +47 -6
  97. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +2 -2
  98. package/packages/dd-trace/src/appsec/waf/waf_manager.js +22 -12
  99. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +3 -3
  100. package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -0
  101. package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -1
  102. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -0
  103. package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +2 -0
  104. package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +2 -0
  105. package/packages/dd-trace/src/ci-visibility/telemetry.js +2 -0
  106. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +2 -0
  107. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +7 -3
  108. package/packages/dd-trace/src/config.js +15 -4
  109. package/packages/dd-trace/src/config_stable.js +2 -0
  110. package/packages/dd-trace/src/constants.js +1 -2
  111. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -0
  112. package/packages/dd-trace/src/datastreams/context.js +2 -0
  113. package/packages/dd-trace/src/datastreams/encoding.js +2 -0
  114. package/packages/dd-trace/src/datastreams/fnv.js +2 -0
  115. package/packages/dd-trace/src/datastreams/pathway.js +11 -9
  116. package/packages/dd-trace/src/datastreams/processor.js +8 -7
  117. package/packages/dd-trace/src/datastreams/schemas/schema.js +2 -0
  118. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +45 -36
  119. package/packages/dd-trace/src/datastreams/schemas/schema_sampler.js +2 -0
  120. package/packages/dd-trace/src/datastreams/writer.js +2 -0
  121. package/packages/dd-trace/src/debugger/devtools_client/index.js +12 -4
  122. package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +2 -0
  123. package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +8 -5
  124. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +1 -1
  125. package/packages/dd-trace/src/debugger/index.js +36 -9
  126. package/packages/dd-trace/src/encode/tags-processors.js +2 -0
  127. package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +2 -0
  128. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  129. package/packages/dd-trace/src/exporters/common/util.js +2 -0
  130. package/packages/dd-trace/src/exporters/span-stats/index.js +2 -0
  131. package/packages/dd-trace/src/exporters/span-stats/writer.js +2 -0
  132. package/packages/dd-trace/src/external-logger/src/index.js +2 -0
  133. package/packages/dd-trace/src/git_metadata_tagger.js +2 -0
  134. package/packages/dd-trace/src/git_properties.js +2 -0
  135. package/packages/dd-trace/src/guardrails/index.js +3 -4
  136. package/packages/dd-trace/src/guardrails/log.js +2 -2
  137. package/packages/dd-trace/src/guardrails/telemetry.js +16 -14
  138. package/packages/dd-trace/src/guardrails/util.js +0 -2
  139. package/packages/dd-trace/src/heap_snapshots.js +58 -0
  140. package/packages/dd-trace/src/llmobs/noop.js +1 -1
  141. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +2 -0
  142. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +5 -0
  143. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/tool.js +15 -0
  144. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +36 -0
  145. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +47 -4
  146. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  147. package/packages/dd-trace/src/llmobs/tagger.js +10 -1
  148. package/packages/dd-trace/src/log/log.js +1 -1
  149. package/packages/dd-trace/src/noop/dogstatsd.js +2 -0
  150. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -0
  151. package/packages/dd-trace/src/opentracing/span.js +1 -1
  152. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -0
  153. package/packages/dd-trace/src/payload-tagging/index.js +3 -1
  154. package/packages/dd-trace/src/payload-tagging/tagging.js +4 -2
  155. package/packages/dd-trace/src/plugins/apollo.js +2 -0
  156. package/packages/dd-trace/src/plugins/ci_plugin.js +8 -3
  157. package/packages/dd-trace/src/plugins/index.js +1 -0
  158. package/packages/dd-trace/src/plugins/outbound.js +7 -0
  159. package/packages/dd-trace/src/plugins/util/ci.js +2 -0
  160. package/packages/dd-trace/src/plugins/util/env.js +2 -0
  161. package/packages/dd-trace/src/plugins/util/git.js +40 -5
  162. package/packages/dd-trace/src/plugins/util/inferred_proxy.js +2 -0
  163. package/packages/dd-trace/src/plugins/util/llm.js +2 -0
  164. package/packages/dd-trace/src/plugins/util/serverless.js +2 -0
  165. package/packages/dd-trace/src/plugins/util/stacktrace.js +178 -50
  166. package/packages/dd-trace/src/plugins/util/tags.js +17 -1
  167. package/packages/dd-trace/src/plugins/util/test.js +9 -4
  168. package/packages/dd-trace/src/plugins/util/url.js +2 -0
  169. package/packages/dd-trace/src/plugins/util/user-provided-git.js +2 -0
  170. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +4 -0
  171. package/packages/dd-trace/src/profiling/profiler.js +89 -70
  172. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns.js +2 -0
  173. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookup.js +2 -0
  174. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_lookupservice.js +2 -0
  175. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_resolve.js +2 -0
  176. package/packages/dd-trace/src/profiling/profilers/event_plugins/dns_reverse.js +2 -0
  177. package/packages/dd-trace/src/profiling/profilers/event_plugins/event.js +2 -0
  178. package/packages/dd-trace/src/profiling/profilers/event_plugins/fs.js +2 -0
  179. package/packages/dd-trace/src/profiling/profilers/event_plugins/net.js +2 -0
  180. package/packages/dd-trace/src/profiling/profilers/events.js +2 -0
  181. package/packages/dd-trace/src/profiling/profilers/wall.js +2 -2
  182. package/packages/dd-trace/src/profiling/webspan-utils.js +2 -0
  183. package/packages/dd-trace/src/proxy.js +4 -0
  184. package/packages/dd-trace/src/remote_config/capabilities.js +3 -1
  185. package/packages/dd-trace/src/remote_config/index.js +4 -0
  186. package/packages/dd-trace/src/service-naming/index.js +2 -0
  187. package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -9
  188. package/packages/dd-trace/src/service-naming/schemas/util.js +2 -0
  189. package/packages/dd-trace/src/service-naming/schemas/v0/graphql.js +2 -0
  190. package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -0
  191. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +2 -0
  192. package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +2 -0
  193. package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +2 -0
  194. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +2 -0
  195. package/packages/dd-trace/src/service-naming/schemas/v1/graphql.js +2 -0
  196. package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -0
  197. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +2 -0
  198. package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +2 -0
  199. package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -1
  200. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +2 -0
  201. package/packages/dd-trace/src/span_stats.js +2 -0
  202. package/packages/dd-trace/src/supported-configurations.json +5 -0
  203. package/packages/dd-trace/src/telemetry/send-data.js +2 -0
  204. package/register.js +4 -0
  205. package/version.js +0 -3
  206. package/packages/dd-trace/src/payload-tagging/jsonpath-plus.js +0 -2094
@@ -1,4 +1,6 @@
1
- const LRUCache = require('lru-cache')
1
+ 'use strict'
2
+
3
+ const { LRUCache } = require('lru-cache')
2
4
  const { fnv64 } = require('../fnv')
3
5
  const { Schema } = require('./schema')
4
6
 
@@ -13,22 +15,24 @@ class SchemaBuilder {
13
15
  this.properties = 0
14
16
  }
15
17
 
18
+ // TODO: This is only used in tests. Let's refactor the code and stop exposing the cache.
16
19
  static getCache () {
17
20
  return CACHE
18
21
  }
19
22
 
20
23
  static getSchemaDefinition (schema) {
21
- const noNones = convertToJsonCompatible(schema)
22
- const definition = jsonStringify(noNones)
24
+ const definition = toJSON(schema)
23
25
  const id = fnv64(Buffer.from(definition, 'utf8')).toString()
24
26
  return new Schema(definition, id)
25
27
  }
26
28
 
27
29
  static getSchema (schemaName, iterator, builder) {
28
- if (!CACHE.has(schemaName)) {
29
- CACHE.set(schemaName, (builder ?? new SchemaBuilder(iterator)).build())
30
+ let entry = CACHE.get(schemaName)
31
+ if (!entry) {
32
+ entry = (builder ?? new SchemaBuilder(iterator)).build()
33
+ CACHE.set(schemaName, entry)
30
34
  }
31
- return CACHE.get(schemaName)
35
+ return entry
32
36
  }
33
37
 
34
38
  build () {
@@ -92,42 +96,47 @@ class OpenApiComponents {
92
96
  }
93
97
  }
94
98
 
95
- function convertToJsonCompatible (obj) {
96
- if (Array.isArray(obj)) {
97
- return obj.filter(item => item !== null).map(item => convertToJsonCompatible(item))
98
- } else if (obj && typeof obj === 'object') {
99
- const jsonObj = {}
100
- for (const [key, value] of Object.entries(obj)) {
101
- if (value !== null) {
102
- jsonObj[key] = convertToJsonCompatible(value)
99
+ // This adds a single whitespace between entries without adding newlines.
100
+ // This differs from JSON.stringify and is used to align with the output
101
+ // in other platforms.
102
+ // TODO: Add tests to verify this behavior. A couple of cases are not
103
+ // covered by the existing tests.
104
+ function toJSON (value) {
105
+ // eslint-disable-next-line eslint-rules/eslint-safe-typeof-object
106
+ if (typeof value === 'object') {
107
+ if (value === null) {
108
+ return 'null'
109
+ }
110
+ if (Array.isArray(value)) {
111
+ let result = '['
112
+ for (let i = 0; i < value.length; i++) {
113
+ if (value[i] !== null) {
114
+ if (i !== 0) {
115
+ result += ', '
116
+ }
117
+ result += value[i] === undefined ? 'null' : toJSON(value[i])
118
+ }
103
119
  }
120
+ return `${result}]`
104
121
  }
105
- return jsonObj
106
- }
107
- return obj
108
- }
109
-
110
- function convertKey (key) {
111
- if (key === 'enumValues') {
112
- return 'enum'
122
+ let result = '{'
123
+ for (const [key, objectValue] of Object.entries(value)) {
124
+ if (objectValue != null && typeof key === 'string') {
125
+ const converted = toJSON(objectValue)
126
+ if (converted !== undefined) {
127
+ if (result !== '{') {
128
+ result += ', '
129
+ }
130
+ result += `"${key}": ${converted}`
131
+ }
132
+ }
133
+ }
134
+ return `${result}}`
113
135
  }
114
- return key
115
- }
116
-
117
- function jsonStringify (obj, indent = 2) {
118
- // made to stringify json exactly similar to python / java in order for hashing to be the same
119
- const jsonString = JSON.stringify(obj, (_, value) => value, indent)
120
- return jsonString.replaceAll(/^ +/gm, ' ') // Replace leading spaces with single space
121
- .replaceAll('\n', '') // Remove newlines
122
- .replaceAll('{ ', '{') // Remove space after '{'
123
- .replaceAll(' }', '}') // Remove space before '}'
124
- .replaceAll('[ ', '[') // Remove space after '['
125
- .replaceAll(' ]', ']') // Remove space before ']'
136
+ return JSON.stringify(value)
126
137
  }
127
138
 
128
139
  module.exports = {
129
140
  SchemaBuilder,
130
141
  OpenApiSchema,
131
- convertToJsonCompatible,
132
- convertKey
133
142
  }
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const SAMPLE_INTERVAL_MILLIS = 30 * 1000
2
4
 
3
5
  class SchemaSampler {
@@ -1,3 +1,5 @@
1
+ 'use strict'
2
+
1
3
  const pkg = require('../../../../package.json')
2
4
  const log = require('../log')
3
5
  const request = require('../exporters/common/request')
@@ -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')) {
@@ -1,6 +1,6 @@
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
6
  const log = require('../../log')
@@ -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(
@@ -1,4 +1,4 @@
1
- 'use stict'
1
+ 'use strict'
2
2
 
3
3
  module.exports = {
4
4
  collectionSizeSym: Symbol('datadog.collectionSize'),
@@ -1,5 +1,6 @@
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')
@@ -23,17 +24,24 @@ function start (config, rc) {
23
24
  log.debug('[debugger] Starting Dynamic Instrumentation client...')
24
25
 
25
26
  const rcAckCallbacks = new Map()
26
- const rcChannel = new MessageChannel()
27
+ const probeChannel = new MessageChannel()
27
28
  configChannel = new MessageChannel()
28
29
 
29
30
  process[Symbol.for('datadog:node:util:types')] = types
30
31
 
31
- rc.setProductHandler('LIVE_DEBUGGING', (action, conf, id, ack) => {
32
+ readProbeFile(config.dynamicInstrumentation.probeFile, (probes) => {
33
+ const action = 'apply'
34
+ for (const probe of probes) {
35
+ probeChannel.port2.postMessage({ action, probe })
36
+ }
37
+ })
38
+
39
+ rc.setProductHandler('LIVE_DEBUGGING', (action, probe, id, ack) => {
32
40
  rcAckCallbacks.set(++ackId, ack)
33
- rcChannel.port2.postMessage({ action, conf, ackId })
41
+ probeChannel.port2.postMessage({ action, probe, ackId })
34
42
  })
35
43
 
36
- rcChannel.port2.on('message', ({ ackId, error }) => {
44
+ probeChannel.port2.on('message', ({ ackId, error }) => {
37
45
  const ack = rcAckCallbacks.get(ackId)
38
46
  if (ack === undefined) {
39
47
  // This should never happen, but just in case something changes in the future, we should guard against it
@@ -44,7 +52,7 @@ function start (config, rc) {
44
52
  ack(error)
45
53
  rcAckCallbacks.delete(ackId)
46
54
  })
47
- rcChannel.port2.on('messageerror', (err) => log.error('[debugger] received "messageerror" on RC port', err))
55
+ probeChannel.port2.on('messageerror', (err) => log.error('[debugger] received "messageerror" on probe port', err))
48
56
 
49
57
  worker = new Worker(
50
58
  join(__dirname, 'devtools_client', 'index.js'),
@@ -54,10 +62,10 @@ function start (config, rc) {
54
62
  workerData: {
55
63
  config: config.serialize(),
56
64
  parentThreadId,
57
- rcPort: rcChannel.port1,
65
+ probePort: probeChannel.port1,
58
66
  configPort: configChannel.port1
59
67
  },
60
- transferList: [rcChannel.port1, configChannel.port1]
68
+ transferList: [probeChannel.port1, configChannel.port1]
61
69
  }
62
70
  )
63
71
 
@@ -84,8 +92,8 @@ function start (config, rc) {
84
92
  })
85
93
 
86
94
  worker.unref()
87
- rcChannel.port1.unref()
88
- rcChannel.port2.unref()
95
+ probeChannel.port1.unref()
96
+ probeChannel.port2.unref()
89
97
  configChannel.port1.unref()
90
98
  configChannel.port2.unref()
91
99
  }
@@ -94,3 +102,22 @@ function configure (config) {
94
102
  if (configChannel === null) return
95
103
  configChannel.port2.postMessage(config.serialize())
96
104
  }
105
+
106
+ function readProbeFile (path, cb) {
107
+ if (!path) return
108
+
109
+ log.debug('[debugger] Reading probe file: %s', path)
110
+ readFile(path, 'utf8', (err, data) => {
111
+ if (err) {
112
+ log.error('[debugger] Failed to read probe file: %s', path, err)
113
+ return
114
+ }
115
+ try {
116
+ const parsedData = JSON.parse(data)
117
+ log.debug('[debugger] Successfully parsed probe file: %s', path)
118
+ cb(parsedData)
119
+ } catch (err) {
120
+ log.error('[debugger] Probe file (%s) is not valid JSON', path, err)
121
+ }
122
+ })
123
+ }
@@ -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')
@@ -19,7 +19,7 @@ const maxActiveRequests = 8
19
19
  let activeRequests = 0
20
20
 
21
21
  function parseUrl (urlObjOrString) {
22
- if (typeof urlObjOrString === 'object') return urlToHttpOptions(urlObjOrString)
22
+ if (urlObjOrString !== null && typeof urlObjOrString === 'object') return urlToHttpOptions(urlObjOrString)
23
23
 
24
24
  const url = urlToHttpOptions(new URL(urlObjOrString))
25
25
 
@@ -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'
@@ -0,0 +1,58 @@
1
+ 'use strict'
2
+
3
+ const { join } = require('path')
4
+ const { setImmediate, setTimeout } = require('timers/promises')
5
+ const { format } = require('util')
6
+ const { writeHeapSnapshot } = require('v8')
7
+ const { threadId } = require('worker_threads')
8
+ const log = require('./log')
9
+
10
+ async function scheduleSnapshot (config, total) {
11
+ if (total > config.heapSnapshot.count) return
12
+
13
+ await setTimeout(config.heapSnapshot.interval * 1000, null, { ref: false })
14
+ await clearMemory()
15
+ writeHeapSnapshot(getName(config.heapSnapshot.destination))
16
+ await scheduleSnapshot(config, total + 1)
17
+ }
18
+
19
+ async function clearMemory () {
20
+ if (!globalThis.gc) return
21
+ globalThis.gc()
22
+ await setImmediate()
23
+ globalThis.gc() // Run full GC a second time for anything missed in first GC.
24
+ }
25
+
26
+ function pad (value) {
27
+ return String(value).padStart(2, 0)
28
+ }
29
+
30
+ function getName (destination) {
31
+ const date = new Date()
32
+ const filename = format(
33
+ 'Heap-%s%s%s-%s%s%s-%s-%s.heapsnapshot',
34
+ date.getFullYear(),
35
+ pad(date.getMonth()),
36
+ pad(date.getDate()),
37
+ pad(date.getHours()),
38
+ pad(date.getMinutes()),
39
+ pad(date.getSeconds()),
40
+ process.pid,
41
+ threadId
42
+ )
43
+
44
+ return join(destination, filename)
45
+ }
46
+
47
+ module.exports = {
48
+ async start (config) {
49
+ const destination = config.heapSnapshot.destination
50
+
51
+ try {
52
+ await scheduleSnapshot(config, 1)
53
+ log.debug('Wrote heap snapshots to %s.', destination)
54
+ } catch (e) {
55
+ log.error('Failed to write heap snapshots to %s.', destination, e)
56
+ }
57
+ }
58
+ }
@@ -39,7 +39,7 @@ class NoopLLMObs {
39
39
  const llmobs = this
40
40
  return function (target, ctxOrPropertyKey, descriptor) {
41
41
  if (!ctxOrPropertyKey) return target
42
- if (typeof ctxOrPropertyKey === 'object') {
42
+ if (typeof ctxOrPropertyKey === 'object') { // eslint-disable-line eslint-rules/eslint-safe-typeof-object
43
43
  const ctx = ctxOrPropertyKey
44
44
  if (ctx.kind !== 'method') return target
45
45
 
@@ -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