dd-trace 5.95.0 → 5.97.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 (124) hide show
  1. package/index.d.ts +43 -0
  2. package/package.json +10 -8
  3. package/packages/datadog-esbuild/index.js +20 -9
  4. package/packages/datadog-instrumentations/src/ai.js +112 -0
  5. package/packages/datadog-instrumentations/src/child_process.js +7 -17
  6. package/packages/datadog-instrumentations/src/crypto.js +1 -2
  7. package/packages/datadog-instrumentations/src/cucumber.js +4 -1
  8. package/packages/datadog-instrumentations/src/cypress-config.js +324 -0
  9. package/packages/datadog-instrumentations/src/cypress.js +86 -4
  10. package/packages/datadog-instrumentations/src/dns.js +1 -2
  11. package/packages/datadog-instrumentations/src/express.js +4 -4
  12. package/packages/datadog-instrumentations/src/fs.js +27 -29
  13. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  14. package/packages/datadog-instrumentations/src/helpers/ai-messages.js +182 -0
  15. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
  16. package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
  17. package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
  18. package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
  19. package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
  20. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/ai.js +25 -0
  21. package/packages/datadog-instrumentations/src/http/client.js +2 -3
  22. package/packages/datadog-instrumentations/src/http/server.js +2 -5
  23. package/packages/datadog-instrumentations/src/http2/client.js +1 -3
  24. package/packages/datadog-instrumentations/src/http2/server.js +1 -3
  25. package/packages/datadog-instrumentations/src/jest.js +13 -4
  26. package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
  27. package/packages/datadog-instrumentations/src/mocha/utils.js +14 -1
  28. package/packages/datadog-instrumentations/src/net.js +2 -8
  29. package/packages/datadog-instrumentations/src/pino.js +1 -1
  30. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  31. package/packages/datadog-instrumentations/src/prisma.js +1 -2
  32. package/packages/datadog-instrumentations/src/selenium.js +4 -1
  33. package/packages/datadog-instrumentations/src/sequelize.js +1 -1
  34. package/packages/datadog-instrumentations/src/url.js +1 -3
  35. package/packages/datadog-instrumentations/src/vitest.js +5 -1
  36. package/packages/datadog-instrumentations/src/vm.js +1 -3
  37. package/packages/datadog-plugin-aws-sdk/src/base.js +4 -3
  38. package/packages/datadog-plugin-cucumber/src/index.js +7 -3
  39. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +57 -5
  40. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  41. package/packages/datadog-plugin-jest/src/index.js +4 -2
  42. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
  43. package/packages/datadog-plugin-mocha/src/index.js +5 -2
  44. package/packages/datadog-plugin-next/src/index.js +2 -14
  45. package/packages/datadog-plugin-openai/src/services.js +1 -0
  46. package/packages/datadog-webpack/index.js +3 -3
  47. package/packages/dd-trace/index.js +12 -10
  48. package/packages/dd-trace/src/agent/url.js +2 -2
  49. package/packages/dd-trace/src/aiguard/index.js +64 -0
  50. package/packages/dd-trace/src/aiguard/sdk.js +4 -0
  51. package/packages/dd-trace/src/appsec/blocking.js +3 -0
  52. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
  53. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
  54. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  55. package/packages/dd-trace/src/appsec/remote_config.js +1 -0
  56. package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
  57. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
  58. package/packages/dd-trace/src/ci-visibility/lage.js +39 -0
  59. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
  60. package/packages/dd-trace/src/config/defaults.js +316 -146
  61. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
  62. package/packages/dd-trace/src/config/helper.js +59 -10
  63. package/packages/dd-trace/src/config/index.js +570 -1503
  64. package/packages/dd-trace/src/config/parsers.js +256 -0
  65. package/packages/dd-trace/src/config/remote_config.js +59 -2
  66. package/packages/dd-trace/src/config/supported-configurations.json +367 -433
  67. package/packages/dd-trace/src/constants.js +1 -0
  68. package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
  69. package/packages/dd-trace/src/crashtracking/index.js +1 -7
  70. package/packages/dd-trace/src/debugger/index.js +1 -1
  71. package/packages/dd-trace/src/dogstatsd.js +12 -9
  72. package/packages/dd-trace/src/encode/0.4.js +1 -1
  73. package/packages/dd-trace/src/exporter.js +5 -2
  74. package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
  75. package/packages/dd-trace/src/exporters/common/request.js +9 -0
  76. package/packages/dd-trace/src/exporters/common/writer.js +12 -2
  77. package/packages/dd-trace/src/heap_snapshots.js +3 -0
  78. package/packages/dd-trace/src/index.js +5 -2
  79. package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
  80. package/packages/dd-trace/src/llmobs/constants/text.js +3 -0
  81. package/packages/dd-trace/src/llmobs/index.js +13 -5
  82. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
  83. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
  84. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
  85. package/packages/dd-trace/src/llmobs/sdk.js +12 -8
  86. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  87. package/packages/dd-trace/src/llmobs/tagger.js +9 -6
  88. package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
  89. package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
  90. package/packages/dd-trace/src/log/index.js +26 -55
  91. package/packages/dd-trace/src/log/writer.js +7 -19
  92. package/packages/dd-trace/src/noop/proxy.js +8 -0
  93. package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
  94. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  95. package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
  96. package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
  97. package/packages/dd-trace/src/plugin_manager.js +8 -6
  98. package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
  99. package/packages/dd-trace/src/plugins/plugin.js +7 -4
  100. package/packages/dd-trace/src/plugins/util/test.js +5 -0
  101. package/packages/dd-trace/src/process-tags/index.js +3 -0
  102. package/packages/dd-trace/src/profiler.js +27 -2
  103. package/packages/dd-trace/src/profiling/config.js +73 -241
  104. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
  105. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
  106. package/packages/dd-trace/src/profiling/profiler.js +56 -44
  107. package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
  108. package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
  109. package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
  110. package/packages/dd-trace/src/propagation-hash/index.js +2 -1
  111. package/packages/dd-trace/src/proxy.js +36 -3
  112. package/packages/dd-trace/src/remote_config/index.js +3 -0
  113. package/packages/dd-trace/src/require-package-json.js +8 -4
  114. package/packages/dd-trace/src/ritm.js +58 -26
  115. package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
  116. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -0
  117. package/packages/dd-trace/src/sampler.js +1 -1
  118. package/packages/dd-trace/src/standalone/index.js +3 -0
  119. package/packages/dd-trace/src/startup-log.js +9 -0
  120. package/packages/dd-trace/src/telemetry/index.js +2 -3
  121. package/packages/dd-trace/src/telemetry/send-data.js +5 -19
  122. package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
  123. package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
  124. package/packages/dd-trace/src/util.js +0 -9
@@ -0,0 +1,182 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Converts a LanguageModelV2FilePart with an image mediaType to an AI guard style image_url content part.
5
+ *
6
+ * @param {{type: 'file', data: URL|string|Uint8Array, mediaType: string}} part
7
+ * @returns {{type: 'image_url', image_url: {url: string}}|undefined}
8
+ */
9
+ function convertFilePartToImageUrl (part) {
10
+ const { data, mediaType } = part
11
+
12
+ if (data instanceof URL) {
13
+ return { type: 'image_url', image_url: { url: data.toString() } }
14
+ }
15
+
16
+ if (typeof data === 'string') {
17
+ if (data.startsWith('http') || data.startsWith('data:')) {
18
+ return { type: 'image_url', image_url: { url: data } }
19
+ }
20
+ return { type: 'image_url', image_url: { url: `data:${mediaType};base64,${data}` } }
21
+ }
22
+
23
+ if (data instanceof Uint8Array) {
24
+ return { type: 'image_url', image_url: { url: `data:${mediaType};base64,${Buffer.from(data).toString('base64')}` } }
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Converts a LanguageModelV2Prompt to the AI guard style message format.
30
+ *
31
+ * Vercel AI v2 prompt entries use content arrays with typed parts (e.g. { type: 'text', text },
32
+ * { type: 'file', data, mediaType }). This function converts them to AI guard style messages.
33
+ * When file parts with image media types are present, the content is an array of text and
34
+ * image_url parts; otherwise it is a plain string.
35
+ *
36
+ * @param {Array<{role: string, content: string|Array<{type: string}>}>} prompt
37
+ * @returns {Array<{role: string, content?: string|Array<{type: string}>, tool_calls?: Array, tool_call_id?: string}>}
38
+ */
39
+ function convertVercelPromptToMessages (prompt) {
40
+ if (!Array.isArray(prompt)) return []
41
+
42
+ const messages = []
43
+ for (const msg of prompt) {
44
+ switch (msg.role) {
45
+ case 'system':
46
+ messages.push({ role: 'system', content: typeof msg.content === 'string' ? msg.content : '' })
47
+ break
48
+
49
+ case 'user': {
50
+ if (!Array.isArray(msg.content)) break
51
+
52
+ const contentParts = []
53
+ for (const part of msg.content) {
54
+ if (part.type === 'text') {
55
+ contentParts.push({ type: 'text', text: part.text })
56
+ } else if (part.type === 'file' && part.mediaType?.startsWith('image/')) {
57
+ const converted = convertFilePartToImageUrl(part)
58
+ if (converted) contentParts.push(converted)
59
+ }
60
+ }
61
+
62
+ if (contentParts.length === 0) break
63
+
64
+ const hasImages = contentParts.some(p => p.type === 'image_url')
65
+ if (hasImages) {
66
+ messages.push({ role: 'user', content: contentParts })
67
+ } else {
68
+ messages.push({ role: 'user', content: contentParts.map(p => p.text).join('\n') })
69
+ }
70
+ break
71
+ }
72
+
73
+ case 'assistant': {
74
+ const textParts = []
75
+ const toolCalls = []
76
+ if (!Array.isArray(msg.content)) break
77
+
78
+ for (const part of msg.content) {
79
+ if (part.type === 'text') {
80
+ textParts.push(part.text)
81
+ } else if (part.type === 'tool-call') {
82
+ const args = part.args ?? part.input
83
+ toolCalls.push({
84
+ id: part.toolCallId,
85
+ function: {
86
+ name: part.toolName,
87
+ arguments: typeof args === 'string' ? args : JSON.stringify(args),
88
+ },
89
+ })
90
+ }
91
+ }
92
+
93
+ if (toolCalls.length > 0) {
94
+ messages.push({ role: 'assistant', tool_calls: toolCalls })
95
+ } else if (textParts.length > 0) {
96
+ messages.push({ role: 'assistant', content: textParts.join('\n') })
97
+ }
98
+ break
99
+ }
100
+
101
+ case 'tool': {
102
+ if (!Array.isArray(msg.content)) break
103
+
104
+ for (const part of msg.content) {
105
+ if (part.type === 'tool-result') {
106
+ const result = part.result ?? part.output
107
+ messages.push({
108
+ role: 'tool',
109
+ tool_call_id: part.toolCallId,
110
+ content: typeof result === 'string' ? result : JSON.stringify(result),
111
+ })
112
+ }
113
+ }
114
+ break
115
+ }
116
+ }
117
+ }
118
+ return messages
119
+ }
120
+
121
+ /**
122
+ * Converts LLM output tool calls to AI guard style message format.
123
+ *
124
+ * @param {Array<object>} inputMessages - The input messages already in AI guard style format
125
+ * @param {Array<{toolCallId: string, toolName: string, args?: unknown, input?: unknown}>} toolCalls
126
+ * @returns {Array<object>}
127
+ */
128
+ function buildToolCallOutputMessages (inputMessages, toolCalls) {
129
+ return [
130
+ ...inputMessages,
131
+ {
132
+ role: 'assistant',
133
+ tool_calls: toolCalls.map(tc => {
134
+ const args = tc.args ?? tc.input
135
+ return {
136
+ id: tc.toolCallId,
137
+ function: {
138
+ name: tc.toolName,
139
+ arguments: typeof args === 'string' ? args : JSON.stringify(args),
140
+ },
141
+ }
142
+ }),
143
+ },
144
+ ]
145
+ }
146
+
147
+ /**
148
+ * Builds OpenAI-style output messages for the assistant's text response.
149
+ *
150
+ * @param {Array<object>} inputMessages - The input messages already in AI guard style format
151
+ * @param {string} text - The assistant's text response
152
+ * @returns {Array<object>}
153
+ */
154
+ function buildTextOutputMessages (inputMessages, text) {
155
+ return [
156
+ ...inputMessages,
157
+ { role: 'assistant', content: text },
158
+ ]
159
+ }
160
+
161
+ /**
162
+ * Parses a Vercel AI content array and dispatches to the appropriate output message builder.
163
+ *
164
+ * @param {Array<object>} inputMessages - The input messages already in AI guard style format
165
+ * @param {Array<{type: string}>} content - Vercel AI content array from doGenerate/doStream result
166
+ * @returns {Array<object>}
167
+ */
168
+ function buildOutputMessages (inputMessages, content) {
169
+ const toolCalls = content.filter(c => c.type === 'tool-call')
170
+ const text = content.filter(c => c.type === 'text').map(c => c.text).join('\n')
171
+ if (toolCalls.length) return buildToolCallOutputMessages(inputMessages, toolCalls)
172
+ if (text) return buildTextOutputMessages(inputMessages, text)
173
+ return inputMessages
174
+ }
175
+
176
+ module.exports = {
177
+ convertVercelPromptToMessages,
178
+ convertFilePartToImageUrl,
179
+ buildToolCallOutputMessages,
180
+ buildTextOutputMessages,
181
+ buildOutputMessages,
182
+ }
@@ -45,45 +45,73 @@ if (!dc.unsubscribe) {
45
45
  dc.unsubscribe = (channel, cb) => {
46
46
  if (dc.channel(channel).hasSubscribers) {
47
47
  dc.channel(channel).unsubscribe(cb)
48
+ return true
48
49
  }
50
+ return false
49
51
  }
50
52
  }
51
53
 
52
- function doHook (payload) {
53
- const hook = hooks[payload.package]
54
+ /**
55
+ * @param {string} name
56
+ */
57
+ function doHook (name) {
58
+ const hook = hooks[name] ?? hooks[`node:${name}`]
54
59
  if (!hook) {
55
- log.error('esbuild-wrapped %s missing in list of hooks', payload.package)
60
+ log.error('esbuild-wrapped %s missing in list of hooks', name)
56
61
  return
57
62
  }
58
63
 
59
64
  const hookFn = hook.fn ?? hook
60
65
  if (typeof hookFn !== 'function') {
61
- log.error('esbuild-wrapped hook %s is not a function', payload.package)
66
+ log.error('esbuild-wrapped hook %s is not a function', name)
62
67
  return
63
68
  }
64
69
 
65
70
  try {
66
71
  hookFn()
67
72
  } catch {
68
- log.error('esbuild-wrapped %s hook failed', payload.package)
73
+ log.error('esbuild-wrapped %s hook failed', name)
69
74
  }
70
75
  }
71
76
 
72
- dc.subscribe(CHANNEL, (payload) => {
73
- doHook(payload)
77
+ /** @type {Set<string>} */
78
+ const instrumentedNodeModules = new Set()
74
79
 
75
- if (!instrumentations[payload.package]) {
76
- log.error('esbuild-wrapped %s missing in list of instrumentations', payload.package)
80
+ /** @typedef {{ package: string, module: unknown, version: string, path: string }} Payload */
81
+ dc.subscribe(CHANNEL, (message) => {
82
+ const payload = /** @type {Payload} */ (message)
83
+ const name = payload.package
84
+
85
+ const isPrefixedWithNode = name.startsWith('node:')
86
+
87
+ const isNodeModule = isPrefixedWithNode || !hooks[name]
88
+
89
+ if (isNodeModule) {
90
+ const nodeName = isPrefixedWithNode ? name.slice(5) : name
91
+ // Used for node: prefixed modules to prevent double instrumentation.
92
+ if (instrumentedNodeModules.has(nodeName)) {
93
+ return
94
+ }
95
+ instrumentedNodeModules.add(nodeName)
96
+ }
97
+
98
+ doHook(name)
99
+
100
+ const instrumentation = instrumentations[name] ?? instrumentations[`node:${name}`]
101
+
102
+ if (!instrumentation) {
103
+ log.error('esbuild-wrapped %s missing in list of instrumentations', name)
77
104
  return
78
105
  }
79
106
 
80
- for (const { name, file, versions, hook } of instrumentations[payload.package]) {
81
- if (payload.path !== filename(name, file)) continue
82
- if (!matchVersion(payload.version, versions)) continue
107
+ for (const { file, versions, hook } of instrumentation) {
108
+ if (payload.path !== filename(name, file) || !matchVersion(payload.version, versions)) {
109
+ continue
110
+ }
83
111
 
84
112
  try {
85
113
  loadChannel.publish({ name, version: payload.version, file })
86
- payload.module = hook(payload.module, payload.version)
114
+ payload.module = hook(payload.module, payload.version) ?? payload.module
87
115
  } catch (e) {
88
116
  log.error('Error executing bundler hook', e)
89
117
  }
@@ -1,17 +1,41 @@
1
1
  'use strict'
2
+
2
3
  const path = require('path')
4
+
3
5
  const iitm = require('../../../dd-trace/src/iitm')
4
6
  const ritm = require('../../../dd-trace/src/ritm')
7
+ const log = require('../../../dd-trace/src/log')
8
+ const requirePackageJson = require('../../../dd-trace/src/require-package-json')
9
+
10
+ /**
11
+ * @param {string} moduleBaseDir
12
+ * @returns {string|undefined}
13
+ */
14
+ function getVersion (moduleBaseDir) {
15
+ if (moduleBaseDir) {
16
+ return requirePackageJson(moduleBaseDir, /** @type {import('module').Module} */ (module)).version
17
+ }
18
+
19
+ return process.version
20
+ }
5
21
 
6
22
  /**
7
23
  * This is called for every package/internal-module that dd-trace supports instrumentation for
8
24
  * In practice, `modules` is always an array with a single entry.
9
25
  *
26
+ * @overload
27
+ * @param {string[]} modules list of modules to hook into
28
+ * @param {object} hookOptions hook options
29
+ * @param {Function} onrequire callback to be executed upon encountering module
30
+ */
31
+ /**
32
+ * @overload
10
33
  * @param {string[]} modules list of modules to hook into
11
34
  * @param {object} hookOptions hook options
12
35
  * @param {Function} onrequire callback to be executed upon encountering module
13
36
  */
14
37
  function Hook (modules, hookOptions, onrequire) {
38
+ // TODO: Rewrite this to use class syntax. The same should be done for ritm.
15
39
  if (!(this instanceof Hook)) return new Hook(modules, hookOptions, onrequire)
16
40
 
17
41
  if (typeof hookOptions === 'function') {
@@ -42,6 +66,13 @@ function Hook (modules, hookOptions, onrequire) {
42
66
  return result
43
67
  }
44
68
 
69
+ try {
70
+ moduleVersion ||= getVersion(moduleBaseDir)
71
+ } catch (error) {
72
+ log.error('Error getting version for "%s": %s', moduleName, error.message, error)
73
+ return
74
+ }
75
+
45
76
  if (
46
77
  isIitm &&
47
78
  moduleExports.default &&
@@ -66,10 +97,4 @@ function Hook (modules, hookOptions, onrequire) {
66
97
  })
67
98
  }
68
99
 
69
- Hook.prototype.unhook = function () {
70
- this._ritmHook.unhook()
71
- this._iitmHook.unhook()
72
- this._patched = Object.create(null)
73
- }
74
-
75
100
  module.exports = Hook
@@ -1,6 +1,18 @@
1
1
  'use strict'
2
2
 
3
3
  module.exports = {
4
+ // Only list unprefixed node modules. They will automatically be instrumented as prefixed and unprefixed.
5
+ child_process: () => require('../child_process'),
6
+ crypto: () => require('../crypto'),
7
+ dns: () => require('../dns'),
8
+ fs: { serverless: false, fn: () => require('../fs') },
9
+ http: () => require('../http'),
10
+ http2: () => require('../http2'),
11
+ https: () => require('../http'),
12
+ net: () => require('../net'),
13
+ url: () => require('../url'),
14
+ vm: () => require('../vm'),
15
+ // Non Node.js modules
4
16
  '@anthropic-ai/sdk': { esmFirst: true, fn: () => require('../anthropic') },
5
17
  '@apollo/server': () => require('../apollo-server'),
6
18
  '@apollo/gateway': () => require('../apollo'),
@@ -47,31 +59,24 @@ module.exports = {
47
59
  bullmq: () => require('../bullmq'),
48
60
  bunyan: () => require('../bunyan'),
49
61
  'cassandra-driver': () => require('../cassandra-driver'),
50
- child_process: () => require('../child_process'),
51
62
  connect: () => require('../connect'),
52
63
  cookie: () => require('../cookie'),
53
64
  'cookie-parser': () => require('../cookie-parser'),
54
65
  couchbase: () => require('../couchbase'),
55
- crypto: () => require('../crypto'),
56
66
  cypress: () => require('../cypress'),
57
67
  'dd-trace-api': () => require('../dd-trace-api'),
58
- dns: () => require('../dns'),
59
68
  elasticsearch: () => require('../elasticsearch'),
60
69
  express: () => require('../express'),
61
70
  'express-mongo-sanitize': () => require('../express-mongo-sanitize'),
62
71
  'express-session': () => require('../express-session'),
63
72
  fastify: () => require('../fastify'),
64
73
  'find-my-way': () => require('../find-my-way'),
65
- fs: { serverless: false, fn: () => require('../fs') },
66
74
  'generic-pool': () => require('../generic-pool'),
67
75
  graphql: () => require('../graphql'),
68
76
  grpc: () => require('../grpc'),
69
77
  handlebars: () => require('../handlebars'),
70
78
  hapi: () => require('../hapi'),
71
79
  hono: { esmFirst: true, fn: () => require('../hono') },
72
- http: () => require('../http'),
73
- http2: () => require('../http2'),
74
- https: () => require('../http'),
75
80
  ioredis: () => require('../ioredis'),
76
81
  iovalkey: () => require('../iovalkey'),
77
82
  'jest-circus': () => require('../jest'),
@@ -103,18 +108,8 @@ module.exports = {
103
108
  multer: () => require('../multer'),
104
109
  mysql: () => require('../mysql'),
105
110
  mysql2: () => require('../mysql2'),
106
- net: () => require('../net'),
107
111
  next: () => require('../next'),
108
112
  'node-serialize': () => require('../node-serialize'),
109
- 'node:child_process': () => require('../child_process'),
110
- 'node:crypto': () => require('../crypto'),
111
- 'node:dns': () => require('../dns'),
112
- 'node:http': () => require('../http'),
113
- 'node:http2': () => require('../http2'),
114
- 'node:https': () => require('../http'),
115
- 'node:net': () => require('../net'),
116
- 'node:url': () => require('../url'),
117
- 'node:vm': () => require('../vm'),
118
113
  nyc: () => require('../nyc'),
119
114
  oracledb: () => require('../oracledb'),
120
115
  openai: { esmFirst: true, fn: () => require('../openai') },
@@ -142,9 +137,7 @@ module.exports = {
142
137
  tedious: () => require('../tedious'),
143
138
  tinypool: { esmFirst: true, fn: () => require('../vitest') },
144
139
  undici: () => require('../undici'),
145
- url: () => require('../url'),
146
140
  vitest: { esmFirst: true, fn: () => require('../vitest') },
147
- vm: () => require('../vm'),
148
141
  when: () => require('../when'),
149
142
  winston: () => require('../winston'),
150
143
  workerpool: () => require('../mocha'),
@@ -1,11 +1,23 @@
1
1
  'use strict'
2
2
 
3
3
  const { AsyncResource } = require('async_hooks')
4
- const dc = require('dc-polyfill')
4
+ const dc = /** @type {typeof import('node:diagnostics_channel')} */ (require('dc-polyfill'))
5
5
  const instrumentations = require('./instrumentations')
6
6
  const rewriterInstrumentations = require('./rewriter/instrumentations')
7
7
 
8
+ /**
9
+ * @typedef {import('node:diagnostics_channel').Channel} Channel
10
+ * @typedef {import('node:diagnostics_channel').TracingChannel} TracingChannel
11
+ */
12
+
13
+ /**
14
+ * @type {Record<string, Channel>}
15
+ */
8
16
  const channelMap = {}
17
+ /**
18
+ * @param {string} name
19
+ * @returns {Channel}
20
+ */
9
21
  exports.channel = function (name) {
10
22
  const maybe = channelMap[name]
11
23
  if (maybe) return maybe
@@ -14,7 +26,14 @@ exports.channel = function (name) {
14
26
  return ch
15
27
  }
16
28
 
29
+ /**
30
+ * @type {Record<string, TracingChannel>}
31
+ */
17
32
  const tracingChannelMap = {}
33
+ /**
34
+ * @param {string} name
35
+ * @returns {TracingChannel}
36
+ */
18
37
  exports.tracingChannel = function (name) {
19
38
  const maybe = tracingChannelMap[name]
20
39
  if (maybe) return maybe
@@ -34,24 +53,19 @@ exports.getHooks = function getHooks (names) {
34
53
 
35
54
  /**
36
55
  * @param {object} args
37
- * @param {string|string[]} args.name module name
38
- * @param {string[]} args.versions array of semver range strings
56
+ * @param {string} args.name module name
57
+ * @param {string[]} [args.versions] array of semver range strings
39
58
  * @param {string} [args.file='index.js'] path to file within package to instrument
40
59
  * @param {string} [args.filePattern] pattern to match files within package to instrument
41
- * @param {boolean} [args.patchDefault] whether to patch the default export
42
- * @param {(moduleExports: unknown, version: string) => unknown} hook
60
+ * @param {boolean} [args.patchDefault=true] whether to patch the default export
61
+ * @param {(moduleExports: unknown, version: string, isIitm?: boolean) => unknown} [hook] Patches module exports
43
62
  */
44
63
  exports.addHook = function addHook ({ name, versions, file, filePattern, patchDefault }, hook) {
45
- if (typeof name === 'string') {
46
- name = [name]
64
+ if (!instrumentations[name]) {
65
+ instrumentations[name] = []
47
66
  }
48
67
 
49
- for (const val of name) {
50
- if (!instrumentations[val]) {
51
- instrumentations[val] = []
52
- }
53
- instrumentations[val].push({ name: val, versions, file, filePattern, hook, patchDefault })
54
- }
68
+ instrumentations[name].push({ versions, file, filePattern, hook, patchDefault })
55
69
  }
56
70
 
57
71
  exports.AsyncResource = AsyncResource