dd-trace 5.96.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 (114) hide show
  1. package/index.d.ts +34 -0
  2. package/package.json +9 -7
  3. package/packages/datadog-esbuild/index.js +20 -9
  4. package/packages/datadog-instrumentations/src/child_process.js +7 -17
  5. package/packages/datadog-instrumentations/src/crypto.js +1 -2
  6. package/packages/datadog-instrumentations/src/cucumber.js +4 -1
  7. package/packages/datadog-instrumentations/src/cypress-config.js +324 -0
  8. package/packages/datadog-instrumentations/src/cypress.js +86 -4
  9. package/packages/datadog-instrumentations/src/dns.js +1 -2
  10. package/packages/datadog-instrumentations/src/express.js +4 -4
  11. package/packages/datadog-instrumentations/src/fs.js +27 -29
  12. package/packages/datadog-instrumentations/src/graphql.js +1 -1
  13. package/packages/datadog-instrumentations/src/helpers/bundler-register.js +41 -13
  14. package/packages/datadog-instrumentations/src/helpers/hook.js +31 -6
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +12 -19
  16. package/packages/datadog-instrumentations/src/helpers/instrument.js +27 -13
  17. package/packages/datadog-instrumentations/src/helpers/register.js +103 -142
  18. package/packages/datadog-instrumentations/src/http/client.js +2 -3
  19. package/packages/datadog-instrumentations/src/http/server.js +2 -5
  20. package/packages/datadog-instrumentations/src/http2/client.js +1 -3
  21. package/packages/datadog-instrumentations/src/http2/server.js +1 -3
  22. package/packages/datadog-instrumentations/src/jest.js +13 -4
  23. package/packages/datadog-instrumentations/src/limitd-client.js +1 -1
  24. package/packages/datadog-instrumentations/src/mocha/utils.js +4 -1
  25. package/packages/datadog-instrumentations/src/net.js +2 -8
  26. package/packages/datadog-instrumentations/src/pino.js +1 -1
  27. package/packages/datadog-instrumentations/src/playwright.js +4 -1
  28. package/packages/datadog-instrumentations/src/prisma.js +1 -2
  29. package/packages/datadog-instrumentations/src/selenium.js +4 -1
  30. package/packages/datadog-instrumentations/src/sequelize.js +1 -1
  31. package/packages/datadog-instrumentations/src/url.js +1 -3
  32. package/packages/datadog-instrumentations/src/vitest.js +5 -1
  33. package/packages/datadog-instrumentations/src/vm.js +1 -3
  34. package/packages/datadog-plugin-aws-sdk/src/base.js +4 -3
  35. package/packages/datadog-plugin-cucumber/src/index.js +7 -3
  36. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +57 -5
  37. package/packages/datadog-plugin-graphql/src/resolve.js +1 -1
  38. package/packages/datadog-plugin-jest/src/index.js +4 -2
  39. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +31 -4
  40. package/packages/datadog-plugin-mocha/src/index.js +5 -2
  41. package/packages/datadog-plugin-next/src/index.js +2 -14
  42. package/packages/datadog-plugin-openai/src/services.js +1 -0
  43. package/packages/datadog-webpack/index.js +3 -3
  44. package/packages/dd-trace/index.js +12 -10
  45. package/packages/dd-trace/src/agent/url.js +2 -2
  46. package/packages/dd-trace/src/aiguard/sdk.js +4 -0
  47. package/packages/dd-trace/src/appsec/blocking.js +3 -0
  48. package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
  49. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
  50. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +1 -1
  51. package/packages/dd-trace/src/appsec/remote_config.js +1 -0
  52. package/packages/dd-trace/src/appsec/sdk/index.js +4 -0
  53. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +6 -1
  54. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +4 -0
  55. package/packages/dd-trace/src/config/defaults.js +316 -146
  56. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
  57. package/packages/dd-trace/src/config/helper.js +59 -10
  58. package/packages/dd-trace/src/config/index.js +569 -1505
  59. package/packages/dd-trace/src/config/parsers.js +256 -0
  60. package/packages/dd-trace/src/config/remote_config.js +59 -2
  61. package/packages/dd-trace/src/config/supported-configurations.json +350 -433
  62. package/packages/dd-trace/src/crashtracking/crashtracker.js +7 -1
  63. package/packages/dd-trace/src/crashtracking/index.js +1 -7
  64. package/packages/dd-trace/src/debugger/index.js +1 -1
  65. package/packages/dd-trace/src/dogstatsd.js +12 -9
  66. package/packages/dd-trace/src/encode/0.4.js +1 -1
  67. package/packages/dd-trace/src/exporters/agent/writer.js +7 -1
  68. package/packages/dd-trace/src/exporters/common/request.js +9 -0
  69. package/packages/dd-trace/src/exporters/common/writer.js +12 -2
  70. package/packages/dd-trace/src/heap_snapshots.js +3 -0
  71. package/packages/dd-trace/src/index.js +5 -2
  72. package/packages/dd-trace/src/lambda/runtime/ritm.js +6 -6
  73. package/packages/dd-trace/src/llmobs/index.js +4 -1
  74. package/packages/dd-trace/src/llmobs/plugins/ai/index.js +5 -1
  75. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +60 -12
  76. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +4 -2
  77. package/packages/dd-trace/src/llmobs/sdk.js +12 -8
  78. package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
  79. package/packages/dd-trace/src/llmobs/tagger.js +9 -6
  80. package/packages/dd-trace/src/llmobs/writers/base.js +2 -0
  81. package/packages/dd-trace/src/llmobs/writers/util.js +3 -0
  82. package/packages/dd-trace/src/log/index.js +26 -55
  83. package/packages/dd-trace/src/log/writer.js +7 -19
  84. package/packages/dd-trace/src/noop/proxy.js +8 -0
  85. package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
  86. package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
  87. package/packages/dd-trace/src/opentracing/propagation/text_map.js +9 -4
  88. package/packages/dd-trace/src/payload-tagging/config/index.js +6 -5
  89. package/packages/dd-trace/src/plugin_manager.js +8 -6
  90. package/packages/dd-trace/src/plugins/ci_plugin.js +4 -0
  91. package/packages/dd-trace/src/plugins/plugin.js +7 -4
  92. package/packages/dd-trace/src/process-tags/index.js +3 -0
  93. package/packages/dd-trace/src/profiler.js +27 -2
  94. package/packages/dd-trace/src/profiling/config.js +73 -241
  95. package/packages/dd-trace/src/profiling/exporter_cli.js +1 -4
  96. package/packages/dd-trace/src/profiling/exporters/event_serializer.js +6 -2
  97. package/packages/dd-trace/src/profiling/profiler.js +56 -44
  98. package/packages/dd-trace/src/profiling/profilers/events.js +2 -3
  99. package/packages/dd-trace/src/profiling/profilers/wall.js +89 -6
  100. package/packages/dd-trace/src/profiling/ssi-heuristics.js +4 -1
  101. package/packages/dd-trace/src/propagation-hash/index.js +2 -1
  102. package/packages/dd-trace/src/proxy.js +32 -3
  103. package/packages/dd-trace/src/remote_config/index.js +3 -0
  104. package/packages/dd-trace/src/require-package-json.js +8 -4
  105. package/packages/dd-trace/src/ritm.js +58 -26
  106. package/packages/dd-trace/src/runtime_metrics/index.js +3 -0
  107. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +3 -0
  108. package/packages/dd-trace/src/sampler.js +1 -1
  109. package/packages/dd-trace/src/standalone/index.js +3 -0
  110. package/packages/dd-trace/src/telemetry/index.js +2 -3
  111. package/packages/dd-trace/src/telemetry/send-data.js +5 -19
  112. package/packages/dd-trace/src/telemetry/session-propagation.js +19 -44
  113. package/packages/dd-trace/src/telemetry/telemetry.js +28 -171
  114. package/packages/dd-trace/src/util.js +0 -9
@@ -0,0 +1,256 @@
1
+ 'use strict'
2
+
3
+ const fs = require('fs')
4
+
5
+ const tagger = require('../tagger')
6
+
7
+ let warnInvalidValue
8
+ function setWarnInvalidValue (fn) {
9
+ warnInvalidValue = fn
10
+ }
11
+
12
+ const VALID_PROPAGATION_STYLES = new Set([
13
+ 'datadog', 'tracecontext', 'b3', 'b3 single header', 'b3multi', 'baggage', 'none',
14
+ ])
15
+
16
+ function toCase (value, methodName) {
17
+ if (Array.isArray(value)) {
18
+ return value.map(item => {
19
+ return transformers[methodName](item)
20
+ })
21
+ }
22
+ return value[methodName]()
23
+ }
24
+
25
+ const transformers = {
26
+ setGRPCRange (value) {
27
+ if (value == null) {
28
+ return
29
+ }
30
+ value = value.split(',')
31
+ const result = []
32
+
33
+ for (const val of value) {
34
+ const dashIndex = val.indexOf('-')
35
+ if (dashIndex === -1) {
36
+ result.push(Number(val))
37
+ } else {
38
+ const start = Number(val.slice(0, dashIndex))
39
+ const end = Number(val.slice(dashIndex + 1))
40
+ for (let i = start; i <= end; i++) {
41
+ result.push(i)
42
+ }
43
+ }
44
+ }
45
+ return result
46
+ },
47
+ toLowerCase (value) {
48
+ return toCase(value, 'toLowerCase')
49
+ },
50
+ toUpperCase (value) {
51
+ return toCase(value, 'toUpperCase')
52
+ },
53
+ toCamelCase (value) {
54
+ if (Array.isArray(value)) {
55
+ return value.map(item => {
56
+ return transformers.toCamelCase(item)
57
+ })
58
+ }
59
+ if (typeof value === 'object' && value !== null) {
60
+ const result = {}
61
+ for (const [key, innerValue] of Object.entries(value)) {
62
+ const camelCaseKey = key.replaceAll(/_(\w)/g, (_, letter) => letter.toUpperCase())
63
+ result[camelCaseKey] = transformers.toCamelCase(innerValue)
64
+ }
65
+ return result
66
+ }
67
+ return value
68
+ },
69
+ parseOtelTags (value, optionName) {
70
+ return parsers.MAP(value
71
+ ?.replace(/(^|,)deployment\.environment=/, '$1env:')
72
+ .replace(/(^|,)service\.name=/, '$1service:')
73
+ .replace(/(^|,)service\.version=/, '$1version:')
74
+ .replaceAll('=', ':'), optionName)
75
+ },
76
+ normalizeProfilingEnabled (configValue) {
77
+ if (configValue == null) {
78
+ return
79
+ }
80
+ if (configValue === 'true' || configValue === '1') {
81
+ return 'true'
82
+ }
83
+ if (configValue === 'false' || configValue === '0') {
84
+ return 'false'
85
+ }
86
+ const lowercased = String(configValue).toLowerCase()
87
+ if (lowercased !== configValue) {
88
+ return transformers.normalizeProfilingEnabled(lowercased)
89
+ }
90
+ return configValue
91
+ },
92
+ sampleRate (value, optionName, source) {
93
+ const number = Number(value)
94
+ if (Number.isNaN(number) || value === null) {
95
+ warnInvalidValue(value, optionName, source, 'Sample rate invalid')
96
+ return
97
+ }
98
+ const clamped = Math.min(Math.max(number, 0), 1)
99
+ if (clamped !== number) {
100
+ warnInvalidValue(value, optionName, source, 'Sample rate out of range between 0 and 1')
101
+ return clamped
102
+ }
103
+ return number
104
+ },
105
+ readFilePath (raw, optionName, source) {
106
+ const { stackTraceLimit } = Error
107
+ Error.stackTraceLimit = 0
108
+ try {
109
+ return fs.readFileSync(raw, 'utf8')
110
+ } catch (error) {
111
+ warnInvalidValue(raw, optionName, source, 'Error reading path', error)
112
+ } finally {
113
+ Error.stackTraceLimit = stackTraceLimit
114
+ }
115
+ },
116
+ /**
117
+ * Given a string of comma-separated paths, return the array of paths.
118
+ * If a blank path is provided a null is returned to signal that the feature is disabled.
119
+ * An empty array means the feature is enabled but that no rules need to be applied.
120
+ *
121
+ * @param {string | string[]} input
122
+ */
123
+ splitJSONPathRules (input) {
124
+ if (!input || input === '$') return
125
+ if (Array.isArray(input)) return input
126
+ if (input === 'all') return []
127
+ return input.split(',')
128
+ },
129
+ stripColonWhitespace (value) {
130
+ if (Array.isArray(value)) {
131
+ return value.map(item => {
132
+ return transformers.stripColonWhitespace(item)
133
+ })
134
+ }
135
+ return value.replaceAll(/\s*:\s*/g, ':')
136
+ },
137
+ validatePropagationStyles (value, optionName) {
138
+ value = transformers.toLowerCase(value)
139
+ for (const propagator of value) {
140
+ if (!VALID_PROPAGATION_STYLES.has(propagator)) {
141
+ warnInvalidValue(propagator, optionName, optionName, 'Invalid propagator')
142
+ return
143
+ }
144
+ }
145
+ return value
146
+ },
147
+ }
148
+
149
+ const telemetryTransformers = {
150
+ JSON (object) {
151
+ return (typeof object !== 'object' || object === null) ? object : JSON.stringify(object)
152
+ },
153
+ MAP (object) {
154
+ if (typeof object !== 'object' || object === null) {
155
+ return object
156
+ }
157
+ let result = ''
158
+ for (const [key, value] of Object.entries(object)) {
159
+ result += `${key}:${value},`
160
+ }
161
+ return result.slice(0, -1)
162
+ },
163
+ ARRAY (array) {
164
+ return Array.isArray(array) ? array.join(',') : array
165
+ },
166
+ }
167
+
168
+ const parsers = {
169
+ BOOLEAN (raw) {
170
+ if (raw === 'true' || raw === '1') {
171
+ return true
172
+ }
173
+ if (raw === 'false' || raw === '0') {
174
+ return false
175
+ }
176
+ const lowercased = raw.toLowerCase()
177
+ if (lowercased !== raw) {
178
+ return parsers.BOOLEAN(lowercased)
179
+ }
180
+ },
181
+ INT (raw) {
182
+ const parsed = Math.trunc(raw)
183
+ if (Number.isNaN(parsed)) {
184
+ return
185
+ }
186
+ return parsed
187
+ },
188
+ DECIMAL (raw) {
189
+ const parsed = Number(raw)
190
+ if (Number.isNaN(parsed)) {
191
+ return
192
+ }
193
+ return parsed
194
+ },
195
+ ARRAY (raw) {
196
+ // TODO: Make the parsing a helper that is reused everywhere.
197
+ const result = []
198
+ if (!raw) {
199
+ return result
200
+ }
201
+ let valueStart = 0
202
+ for (let i = 0; i < raw.length; i++) {
203
+ const char = raw[i]
204
+ if (char === ',') {
205
+ const value = raw.slice(valueStart, i).trim()
206
+ // Auto filter empty entries.
207
+ if (value.length > 0) {
208
+ result.push(value)
209
+ }
210
+ valueStart = i + 1
211
+ }
212
+ }
213
+ if (valueStart < raw.length) {
214
+ const value = raw.slice(valueStart).trim()
215
+ // Auto filter empty entries.
216
+ if (value.length > 0) {
217
+ result.push(value)
218
+ }
219
+ }
220
+ return result
221
+ },
222
+ MAP (raw, optionName) {
223
+ /** @type {Record<string, string>} */
224
+ const entries = {}
225
+ if (!raw) {
226
+ return entries
227
+ }
228
+ // DD_TAGS is a special case. It may be a map of key-value pairs separated by spaces.
229
+ if (optionName === 'DD_TAGS' && !raw.includes(',')) {
230
+ raw = raw.replaceAll(/\s+/g, ',')
231
+ }
232
+ tagger.add(entries, raw)
233
+ return entries
234
+ },
235
+ JSON (raw) {
236
+ const { stackTraceLimit } = Error
237
+ Error.stackTraceLimit = 0
238
+ try {
239
+ return JSON.parse(raw)
240
+ } catch {
241
+ // ignore
242
+ } finally {
243
+ Error.stackTraceLimit = stackTraceLimit
244
+ }
245
+ },
246
+ STRING (raw) {
247
+ return raw
248
+ },
249
+ }
250
+
251
+ module.exports = {
252
+ parsers,
253
+ transformers,
254
+ telemetryTransformers,
255
+ setWarnInvalidValue,
256
+ }
@@ -2,6 +2,7 @@
2
2
 
3
3
  const RemoteConfigCapabilities = require('../remote_config/capabilities')
4
4
  const log = require('../log')
5
+ const tagger = require('../tagger')
5
6
 
6
7
  module.exports = {
7
8
  enable,
@@ -194,10 +195,66 @@ function enable (rc, config, onConfigUpdated) {
194
195
  transaction.ack(item.path)
195
196
  }
196
197
 
197
- // Get merged config and apply it
198
- const mergedLibConfig = rcClientLibConfigManager.getMergedLibConfig()
198
+ /** @type {import('../config').TracerOptions|null|RemoteConfigOptions} */
199
+ let mergedLibConfig = rcClientLibConfigManager.getMergedLibConfig()
200
+
201
+ if (mergedLibConfig) {
202
+ mergedLibConfig = transformRemoteConfigToLocalOption(mergedLibConfig)
203
+ }
204
+
199
205
  config.setRemoteConfig(mergedLibConfig)
200
206
 
201
207
  onConfigUpdated()
202
208
  })
203
209
  }
210
+
211
+ /**
212
+ * @param {RemoteConfigOptions} libConfig
213
+ * @returns {import('../config').TracerOptions}
214
+ */
215
+ function transformRemoteConfigToLocalOption (libConfig) {
216
+ const normalizedConfig = {}
217
+ for (const [name, value] of Object.entries(libConfig)) {
218
+ if (value !== null) {
219
+ normalizedConfig[optionLookupTable[name] ?? name] = transformers[name]?.(value) ?? value
220
+ }
221
+ }
222
+ return normalizedConfig
223
+ }
224
+
225
+ // This is intermediate solution until remote config is reworked to handle all known entries with proper names
226
+ const optionLookupTable = {
227
+ dynamic_instrumentation_enabled: 'dynamicInstrumentation.enabled',
228
+ code_origin_enabled: 'codeOriginForSpans.enabled',
229
+ tracing_sampling_rate: 'sampleRate',
230
+ log_injection_enabled: 'logInjection',
231
+ tracing_enabled: 'tracing',
232
+ tracing_sampling_rules: 'samplingRules',
233
+ tracing_header_tags: 'headerTags',
234
+ tracing_tags: 'tags',
235
+ }
236
+
237
+ const transformers = {
238
+ tracing_sampling_rules (samplingRules) {
239
+ for (const rule of (samplingRules || [])) {
240
+ if (rule.tags) {
241
+ const reformattedTags = {}
242
+ for (const tag of rule.tags) {
243
+ reformattedTags[tag.key] = tag.value_glob
244
+ }
245
+ rule.tags = reformattedTags
246
+ }
247
+ }
248
+ return samplingRules
249
+ },
250
+ tracing_header_tags (headerTags) {
251
+ return headerTags?.map(tag => {
252
+ return tag.tag_name ? `${tag.header}:${tag.tag_name}` : tag.header
253
+ })
254
+ },
255
+ tracing_tags (tags) {
256
+ const normalizedTags = {}
257
+ tagger.add(normalizedTags, tags)
258
+ return normalizedTags
259
+ },
260
+ }