dd-trace 5.80.0 → 5.81.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 (213) hide show
  1. package/LICENSE-3rdparty.csv +79 -88
  2. package/ext/tags.d.ts +1 -0
  3. package/ext/tags.js +1 -0
  4. package/index.d.ts +35 -35
  5. package/loader-hook.mjs +10 -3
  6. package/package.json +22 -40
  7. package/packages/datadog-esbuild/index.js +36 -19
  8. package/packages/datadog-instrumentations/index.js +1 -0
  9. package/packages/datadog-instrumentations/src/anthropic.js +12 -0
  10. package/packages/datadog-instrumentations/src/aws-sdk.js +5 -1
  11. package/packages/datadog-instrumentations/src/cucumber.js +2 -2
  12. package/packages/datadog-instrumentations/src/find-my-way.js +6 -5
  13. package/packages/datadog-instrumentations/src/google-genai.js +120 -0
  14. package/packages/datadog-instrumentations/src/graphql.js +20 -0
  15. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  16. package/packages/datadog-instrumentations/src/helpers/instrument.js +10 -0
  17. package/packages/datadog-instrumentations/src/helpers/register.js +6 -1
  18. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +27 -0
  19. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +152 -0
  20. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +5 -0
  21. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langchain.js +237 -0
  22. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.js +9 -0
  23. package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +11 -0
  24. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +139 -0
  25. package/packages/datadog-instrumentations/src/langchain.js +3 -109
  26. package/packages/datadog-instrumentations/src/mocha/main.js +1 -1
  27. package/packages/datadog-instrumentations/src/mysql2.js +1 -1
  28. package/packages/datadog-instrumentations/src/playwright.js +45 -16
  29. package/packages/datadog-instrumentations/src/router.js +1 -1
  30. package/packages/datadog-instrumentations/src/selenium.js +3 -1
  31. package/packages/datadog-instrumentations/src/ws.js +35 -17
  32. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -1
  33. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +23 -2
  34. package/packages/datadog-plugin-cypress/src/plugin.js +1 -1
  35. package/packages/datadog-plugin-cypress/src/support.js +73 -31
  36. package/packages/datadog-plugin-google-genai/src/index.js +17 -0
  37. package/packages/datadog-plugin-google-genai/src/tracing.js +41 -0
  38. package/packages/datadog-plugin-graphql/src/tools/transforms.js +5 -4
  39. package/packages/datadog-plugin-jest/src/util.js +1 -1
  40. package/packages/datadog-plugin-langchain/src/tracing.js +7 -3
  41. package/packages/datadog-plugin-next/src/index.js +11 -3
  42. package/packages/dd-trace/src/aiguard/sdk.js +18 -10
  43. package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
  44. package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
  45. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -1
  46. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +1 -2
  47. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
  48. package/packages/dd-trace/src/appsec/reporter.js +0 -4
  49. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +4 -8
  50. package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
  51. package/packages/dd-trace/src/config.js +81 -7
  52. package/packages/dd-trace/src/config_defaults.js +14 -2
  53. package/packages/dd-trace/src/datastreams/encoding.js +23 -6
  54. package/packages/dd-trace/src/datastreams/pathway.js +40 -1
  55. package/packages/dd-trace/src/datastreams/processor.js +1 -1
  56. package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -1
  57. package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +15 -5
  58. package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
  59. package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
  60. package/packages/dd-trace/src/debugger/devtools_client/index.js +30 -15
  61. package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +2 -0
  62. package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +24 -18
  63. package/packages/dd-trace/src/debugger/devtools_client/send.js +18 -8
  64. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +103 -15
  65. package/packages/dd-trace/src/debugger/devtools_client/snapshot/constants.js +25 -0
  66. package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +56 -25
  67. package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +64 -23
  68. package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +3 -1
  69. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +404 -0
  70. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  71. package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -2
  72. package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
  73. package/packages/dd-trace/src/debugger/index.js +1 -1
  74. package/packages/dd-trace/src/encode/span-stats.js +7 -1
  75. package/packages/dd-trace/src/histogram.js +1 -1
  76. package/packages/dd-trace/src/id.js +60 -0
  77. package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
  78. package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
  79. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +104 -0
  80. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +486 -0
  81. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +2 -2
  82. package/packages/dd-trace/src/llmobs/plugins/{openai.js → openai/index.js} +48 -6
  83. package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +114 -0
  84. package/packages/dd-trace/src/llmobs/sdk.js +5 -0
  85. package/packages/dd-trace/src/llmobs/span_processor.js +6 -1
  86. package/packages/dd-trace/src/llmobs/tagger.js +4 -0
  87. package/packages/dd-trace/src/opentelemetry/logs/index.js +2 -2
  88. package/packages/dd-trace/src/opentelemetry/logs/logger.js +3 -2
  89. package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +5 -3
  90. package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +8 -8
  91. package/packages/dd-trace/src/opentelemetry/metrics/constants.js +34 -0
  92. package/packages/dd-trace/src/opentelemetry/metrics/index.js +81 -0
  93. package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +225 -0
  94. package/packages/dd-trace/src/opentelemetry/metrics/meter.js +171 -0
  95. package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +54 -0
  96. package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +62 -0
  97. package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +251 -0
  98. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +532 -0
  99. package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +10 -18
  100. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +36 -22
  101. package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +1 -1
  102. package/packages/dd-trace/src/opentelemetry/span.js +1 -1
  103. package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
  104. package/packages/dd-trace/src/opentelemetry/tracer_provider.js +1 -1
  105. package/packages/dd-trace/src/payload-tagging/index.js +2 -2
  106. package/packages/dd-trace/src/plugin_manager.js +4 -2
  107. package/packages/dd-trace/src/plugins/index.js +1 -0
  108. package/packages/dd-trace/src/plugins/util/test.js +3 -3
  109. package/packages/dd-trace/src/plugins/util/url.js +119 -1
  110. package/packages/dd-trace/src/plugins/util/web.js +10 -41
  111. package/packages/dd-trace/src/process-tags/index.js +81 -0
  112. package/packages/dd-trace/src/profiling/config.js +1 -1
  113. package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
  114. package/packages/dd-trace/src/profiling/profilers/events.js +10 -1
  115. package/packages/dd-trace/src/proxy.js +5 -0
  116. package/packages/dd-trace/src/rate_limiter.js +1 -1
  117. package/packages/dd-trace/src/remote_config/manager.js +1 -1
  118. package/packages/dd-trace/src/ritm.js +1 -1
  119. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  120. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  121. package/packages/dd-trace/src/span_format.js +9 -4
  122. package/packages/dd-trace/src/span_processor.js +8 -3
  123. package/packages/dd-trace/src/span_stats.js +15 -4
  124. package/packages/dd-trace/src/spanleak.js +1 -1
  125. package/packages/dd-trace/src/supported-configurations.json +13 -0
  126. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  127. package/packages/dd-trace/src/telemetry/telemetry.js +11 -2
  128. package/vendor/dist/@datadog/sketches-js/LICENSE +39 -0
  129. package/vendor/dist/@datadog/sketches-js/index.js +1 -0
  130. package/vendor/dist/@datadog/source-map/LICENSE +28 -0
  131. package/vendor/dist/@datadog/source-map/index.js +1 -0
  132. package/vendor/dist/@isaacs/ttlcache/LICENSE +55 -0
  133. package/vendor/dist/@isaacs/ttlcache/index.js +1 -0
  134. package/vendor/dist/@opentelemetry/core/LICENSE +201 -0
  135. package/vendor/dist/@opentelemetry/core/index.js +1 -0
  136. package/vendor/dist/@opentelemetry/resources/LICENSE +201 -0
  137. package/vendor/dist/@opentelemetry/resources/index.js +1 -0
  138. package/vendor/dist/astring/LICENSE +19 -0
  139. package/vendor/dist/astring/index.js +1 -0
  140. package/vendor/dist/crypto-randomuuid/index.js +1 -0
  141. package/vendor/dist/escape-string-regexp/LICENSE +9 -0
  142. package/vendor/dist/escape-string-regexp/index.js +1 -0
  143. package/vendor/dist/esquery/LICENSE +24 -0
  144. package/vendor/dist/esquery/index.js +1 -0
  145. package/vendor/dist/ignore/LICENSE +21 -0
  146. package/vendor/dist/ignore/index.js +1 -0
  147. package/vendor/dist/istanbul-lib-coverage/LICENSE +24 -0
  148. package/vendor/dist/istanbul-lib-coverage/index.js +1 -0
  149. package/vendor/dist/jest-docblock/LICENSE +21 -0
  150. package/vendor/dist/jest-docblock/index.js +1 -0
  151. package/vendor/dist/jsonpath-plus/LICENSE +22 -0
  152. package/vendor/dist/jsonpath-plus/index.js +1 -0
  153. package/vendor/dist/limiter/LICENSE +19 -0
  154. package/vendor/dist/limiter/index.js +1 -0
  155. package/vendor/dist/lodash.sortby/LICENSE +47 -0
  156. package/vendor/dist/lodash.sortby/index.js +1 -0
  157. package/vendor/dist/lru-cache/LICENSE +15 -0
  158. package/vendor/dist/lru-cache/index.js +1 -0
  159. package/vendor/dist/meriyah/LICENSE +7 -0
  160. package/vendor/dist/meriyah/index.js +1 -0
  161. package/vendor/dist/module-details-from-path/LICENSE +21 -0
  162. package/vendor/dist/module-details-from-path/index.js +1 -0
  163. package/vendor/dist/mutexify/promise/LICENSE +21 -0
  164. package/vendor/dist/mutexify/promise/index.js +1 -0
  165. package/vendor/dist/opentracing/LICENSE +201 -0
  166. package/vendor/dist/opentracing/binary_carrier.d.ts +11 -0
  167. package/vendor/dist/opentracing/constants.d.ts +61 -0
  168. package/vendor/dist/opentracing/examples/demo/demo.d.ts +2 -0
  169. package/vendor/dist/opentracing/ext/tags.d.ts +90 -0
  170. package/vendor/dist/opentracing/functions.d.ts +20 -0
  171. package/vendor/dist/opentracing/global_tracer.d.ts +14 -0
  172. package/vendor/dist/opentracing/index.d.ts +12 -0
  173. package/vendor/dist/opentracing/index.js +1 -0
  174. package/vendor/dist/opentracing/mock_tracer/index.d.ts +5 -0
  175. package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +13 -0
  176. package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +16 -0
  177. package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +50 -0
  178. package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +26 -0
  179. package/vendor/dist/opentracing/noop.d.ts +8 -0
  180. package/vendor/dist/opentracing/reference.d.ts +33 -0
  181. package/vendor/dist/opentracing/span.d.ts +147 -0
  182. package/vendor/dist/opentracing/span_context.d.ts +26 -0
  183. package/vendor/dist/opentracing/test/api_compatibility.d.ts +16 -0
  184. package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +3 -0
  185. package/vendor/dist/opentracing/test/noop_implementation.d.ts +4 -0
  186. package/vendor/dist/opentracing/test/opentracing_api.d.ts +3 -0
  187. package/vendor/dist/opentracing/test/unittest.d.ts +2 -0
  188. package/vendor/dist/opentracing/tracer.d.ts +127 -0
  189. package/vendor/dist/path-to-regexp/LICENSE +21 -0
  190. package/vendor/dist/path-to-regexp/index.js +1 -0
  191. package/vendor/dist/pprof-format/LICENSE +8 -0
  192. package/vendor/dist/pprof-format/index.js +1 -0
  193. package/vendor/dist/protobufjs/LICENSE +39 -0
  194. package/vendor/dist/protobufjs/index.js +1 -0
  195. package/vendor/dist/protobufjs/minimal/LICENSE +39 -0
  196. package/vendor/dist/protobufjs/minimal/index.js +1 -0
  197. package/vendor/dist/retry/LICENSE +21 -0
  198. package/vendor/dist/retry/index.js +1 -0
  199. package/vendor/dist/rfdc/LICENSE +15 -0
  200. package/vendor/dist/rfdc/index.js +1 -0
  201. package/vendor/dist/semifies/LICENSE +201 -0
  202. package/vendor/dist/semifies/index.js +1 -0
  203. package/vendor/dist/shell-quote/LICENSE +24 -0
  204. package/vendor/dist/shell-quote/index.js +1 -0
  205. package/vendor/dist/source-map/LICENSE +28 -0
  206. package/vendor/dist/source-map/index.js +1 -0
  207. package/vendor/dist/source-map/lib/util/LICENSE +28 -0
  208. package/vendor/dist/source-map/lib/util/index.js +1 -0
  209. package/vendor/dist/source-map/mappings.wasm +0 -0
  210. package/vendor/dist/tlhunter-sorted-set/LICENSE +21 -0
  211. package/vendor/dist/tlhunter-sorted-set/index.js +1 -0
  212. package/vendor/dist/ttl-set/LICENSE +21 -0
  213. package/vendor/dist/ttl-set/index.js +1 -0
@@ -25,7 +25,7 @@ class OtlpTransformerBase {
25
25
  * @param {string} signalType - Signal type for warning messages (e.g., 'logs', 'metrics')
26
26
  */
27
27
  constructor (resourceAttributes, protocol, signalType) {
28
- this.#resourceAttributes = this._transformAttributes(resourceAttributes)
28
+ this.#resourceAttributes = this.transformAttributes(resourceAttributes)
29
29
  if (protocol === 'grpc') {
30
30
  log.warn(`OTLP gRPC protocol is not supported for ${signalType}. ` +
31
31
  'Defaulting to http/protobuf. gRPC protobuf support may be added in a future release.')
@@ -40,12 +40,12 @@ class OtlpTransformerBase {
40
40
  * @returns {Map<string, Array>} Map of instrumentation scope key to items
41
41
  * @protected
42
42
  */
43
- _groupByInstrumentationScope (items) {
43
+ groupByInstrumentationScope (items) {
44
44
  const grouped = new Map()
45
45
 
46
46
  for (const item of items) {
47
47
  const instrumentationScope = item.instrumentationScope || { name: '', version: '', schemaUrl: '', attributes: {} }
48
- const attrsKey = JSON.stringify(instrumentationScope.attributes || {})
48
+ const attrsKey = stableStringify(instrumentationScope.attributes || {})
49
49
  const key = `${instrumentationScope.name}@${instrumentationScope.version}@` +
50
50
  `${instrumentationScope.schemaUrl}@${attrsKey}`
51
51
 
@@ -64,7 +64,7 @@ class OtlpTransformerBase {
64
64
  * @returns {Object} OTLP resource object
65
65
  * @protected
66
66
  */
67
- _transformResource () {
67
+ transformResource () {
68
68
  return {
69
69
  attributes: this.#resourceAttributes,
70
70
  droppedAttributesCount: 0
@@ -77,12 +77,10 @@ class OtlpTransformerBase {
77
77
  * @returns {Object[]} Array of OTLP KeyValue objects
78
78
  * @protected
79
79
  */
80
- _transformAttributes (attributes) {
81
- if (!attributes) return []
82
-
80
+ transformAttributes (attributes) {
83
81
  return Object.entries(attributes).map(([key, value]) => ({
84
82
  key,
85
- value: this._transformAnyValue(value)
83
+ value: this.transformAnyValue(value)
86
84
  }))
87
85
  }
88
86
 
@@ -92,7 +90,7 @@ class OtlpTransformerBase {
92
90
  * @returns {Object[]} Array of OTLP KeyValue objects with string values
93
91
  * @protected
94
92
  */
95
- _attributesToJson (attributes) {
93
+ attributesToJson (attributes) {
96
94
  if (!attributes) return []
97
95
 
98
96
  return Object.entries(attributes).map(([key, value]) => ({
@@ -103,11 +101,13 @@ class OtlpTransformerBase {
103
101
 
104
102
  /**
105
103
  * Transforms any value to OTLP AnyValue format.
104
+ * Supports: strings, numbers (int/double), booleans, arrays.
105
+ * Objects are filtered out by sanitizeAttributes before reaching this method.
106
106
  * @param {any} value - Value to transform
107
107
  * @returns {Object} OTLP AnyValue object
108
108
  * @protected
109
109
  */
110
- _transformAnyValue (value) {
110
+ transformAnyValue (value) {
111
111
  if (typeof value === 'string') {
112
112
  return { stringValue: value }
113
113
  } else if (typeof value === 'number') {
@@ -120,19 +120,11 @@ class OtlpTransformerBase {
120
120
  } else if (Array.isArray(value)) {
121
121
  return {
122
122
  arrayValue: {
123
- values: value.map(v => this._transformAnyValue(v))
124
- }
125
- }
126
- } else if (value && typeof value === 'object') {
127
- return {
128
- kvlistValue: {
129
- values: Object.entries(value).map(([k, v]) => ({
130
- key: k,
131
- value: this._transformAnyValue(v)
132
- }))
123
+ values: value.map(v => this.transformAnyValue(v))
133
124
  }
134
125
  }
135
126
  }
127
+ // Fallback for any unexpected types
136
128
  return { stringValue: String(value) }
137
129
  }
138
130
 
@@ -143,7 +135,7 @@ class OtlpTransformerBase {
143
135
  * @returns {Buffer} Protobuf-encoded data
144
136
  * @protected
145
137
  */
146
- _serializeToProtobuf (protoType, data) {
138
+ serializeToProtobuf (protoType, data) {
147
139
  const message = protoType.create(data)
148
140
  const buffer = protoType.encode(message).finish()
149
141
  return buffer
@@ -155,9 +147,31 @@ class OtlpTransformerBase {
155
147
  * @returns {Buffer} JSON-encoded data
156
148
  * @protected
157
149
  */
158
- _serializeToJson (data) {
150
+ serializeToJson (data) {
159
151
  return Buffer.from(JSON.stringify(data))
160
152
  }
161
153
  }
162
154
 
155
+ /**
156
+ * Stable stringification of OpenTelemetry Attributes.
157
+ * Ensures consistent serialization regardless of key order by sorting keys.
158
+ * Supports string keys with primitive values or arrays of primitives.
159
+ *
160
+ * @param {Attributes} attributes - Attributes object to stringify
161
+ * @returns {string} Stable string representation
162
+ */
163
+ function stableStringify (attributes) {
164
+ if (attributes == null) {
165
+ return JSON.stringify(attributes)
166
+ }
167
+ // Attributes are sorted by key to ensure consistent serialization regardless of key order.
168
+ // Keys are always strings and values are always strings, numbers, booleans,
169
+ // or arrays of strings, numbers, or booleans.
170
+ return Object.keys(attributes)
171
+ .sort()
172
+ .map(key => `${key}:${JSON.stringify(attributes[key])}`)
173
+ .join(',')
174
+ }
175
+
163
176
  module.exports = OtlpTransformerBase
177
+ module.exports.stableStringify = stableStringify
@@ -14,7 +14,7 @@
14
14
  * - https://github.com/open-telemetry/opentelemetry-proto (v1.7.0)
15
15
  */
16
16
 
17
- const protobuf = require('protobufjs')
17
+ const protobuf = require('../../../../../vendor/dist/protobufjs')
18
18
  const path = require('path')
19
19
 
20
20
  let _root = null
@@ -5,7 +5,7 @@ const api = require('@opentelemetry/api')
5
5
  const { performance } = require('perf_hooks')
6
6
  const { timeOrigin } = performance
7
7
 
8
- const { timeInputToHrTime } = require('@opentelemetry/core')
8
+ const { timeInputToHrTime } = require('../../../../vendor/dist/@opentelemetry/core')
9
9
 
10
10
  const tracer = require('../../')
11
11
  const DatadogSpan = require('../opentracing/span')
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const api = require('@opentelemetry/api')
4
- const { sanitizeAttributes } = require('@opentelemetry/core')
4
+ const { sanitizeAttributes } = require('../../../../vendor/dist/@opentelemetry/core')
5
5
 
6
6
  const Sampler = require('./sampler')
7
7
  const Span = require('./span')
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { trace, context, propagation } = require('@opentelemetry/api')
4
- const { W3CTraceContextPropagator } = require('@opentelemetry/core')
4
+ const { W3CTraceContextPropagator } = require('../../../../vendor/dist/@opentelemetry/core')
5
5
 
6
6
  const tracer = require('../../')
7
7
 
@@ -1,13 +1,13 @@
1
1
  'use strict'
2
2
 
3
- const rfdc = require('rfdc')({ proto: false, circles: false })
3
+ const rfdc = require('../../../../vendor/dist/rfdc')({ proto: false, circles: false })
4
4
 
5
5
  const {
6
6
  PAYLOAD_TAG_REQUEST_PREFIX,
7
7
  PAYLOAD_TAG_RESPONSE_PREFIX
8
8
  } = require('../constants')
9
9
 
10
- const jsonpath = require('jsonpath-plus').JSONPath
10
+ const jsonpath = require('../../../../vendor/dist/jsonpath-plus').JSONPath
11
11
 
12
12
  const { tagsFromObject } = require('./tagging')
13
13
 
@@ -165,7 +165,8 @@ module.exports = class PluginManager {
165
165
  traceWebsocketMessagesEnabled,
166
166
  traceWebsocketMessagesInheritSampling,
167
167
  traceWebsocketMessagesSeparateTraces,
168
- experimental
168
+ experimental,
169
+ resourceRenamingEnabled
169
170
  } = this._tracerConfig
170
171
 
171
172
  const sharedConfig = {
@@ -184,7 +185,8 @@ module.exports = class PluginManager {
184
185
  traceWebsocketMessagesEnabled,
185
186
  traceWebsocketMessagesInheritSampling,
186
187
  traceWebsocketMessagesSeparateTraces,
187
- experimental
188
+ experimental,
189
+ resourceRenamingEnabled
188
190
  }
189
191
 
190
192
  if (logInjection !== undefined) {
@@ -13,6 +13,7 @@ module.exports = {
13
13
  get '@elastic/transport' () { return require('../../../datadog-plugin-elasticsearch/src') },
14
14
  get '@google-cloud/pubsub' () { return require('../../../datadog-plugin-google-cloud-pubsub/src') },
15
15
  get '@google-cloud/vertexai' () { return require('../../../datadog-plugin-google-cloud-vertexai/src') },
16
+ get '@google/genai' () { return require('../../../datadog-plugin-google-genai/src') },
16
17
  get '@grpc/grpc-js' () { return require('../../../datadog-plugin-grpc/src') },
17
18
  get '@hapi/hapi' () { return require('../../../datadog-plugin-hapi/src') },
18
19
  get '@happy-dom/jest-environment' () { return require('../../../datadog-plugin-jest/src') },
@@ -5,10 +5,10 @@ const fs = require('fs')
5
5
  const { URL } = require('url')
6
6
  const log = require('../../log')
7
7
  const { getEnvironmentVariable } = require('../../config-helper')
8
- const satisfies = require('semifies')
8
+ const satisfies = require('../../../../../vendor/dist/semifies')
9
9
 
10
- const istanbul = require('istanbul-lib-coverage')
11
- const ignore = require('ignore')
10
+ const istanbul = require('../../../../../vendor/dist/istanbul-lib-coverage')
11
+ const ignore = require('../../../../../vendor/dist/ignore')
12
12
 
13
13
  const {
14
14
  getGitMetadata,
@@ -2,6 +2,118 @@
2
2
 
3
3
  const { URL } = require('url')
4
4
 
5
+ const HTTP2_HEADER_AUTHORITY = ':authority'
6
+ const HTTP2_HEADER_SCHEME = ':scheme'
7
+ const HTTP2_HEADER_PATH = ':path'
8
+
9
+ const PATH_REGEX = /^(?:[a-z]+:\/\/(?:[^?/]+))?(?<path>\/[^?]*)(?:(\?).*)?$/
10
+
11
+ const INT_SEGMENT = /^[1-9][0-9]+$/ // Integer of size at least 2 (>=10)
12
+ const INT_ID_SEGMENT = /^(?=.*[0-9].*)[0-9._-]{3,}$/ // Mixed string with digits and delimiters
13
+ const HEX_SEGMENT = /^(?=.*[0-9].*)[A-Fa-f0-9]{6,}$/ // Hexadecimal digits of size at least 6 with at least one decimal digit
14
+ const HEX_ID_SEGMENT = /^(?=.*[0-9].*)[A-Fa-f0-9._-]{6,}$/ // Mixed string with hex digits and delimiters
15
+ const STRING_SEGMENT = /^.{20,}|.*[%&'()*+,:=@].*$/ // Long string or a string containing special characters
16
+
17
+ /**
18
+ * Extract full URL from HTTP request
19
+ * @param {import('http').IncomingMessage} req
20
+ * @returns {string} Full URL
21
+ */
22
+ function extractURL (req) {
23
+ const headers = req.headers
24
+
25
+ if (req.stream) {
26
+ return `${headers[HTTP2_HEADER_SCHEME]}://${headers[HTTP2_HEADER_AUTHORITY]}${headers[HTTP2_HEADER_PATH]}`
27
+ }
28
+
29
+ const protocol = getProtocol(req)
30
+ return `${protocol}://${req.headers.host}${req.originalUrl || req.url}`
31
+ }
32
+
33
+ function getProtocol (req) {
34
+ return (req.socket?.encrypted || req.connection?.encrypted) ? 'https' : 'http'
35
+ }
36
+
37
+ /**
38
+ * Obfuscate query string
39
+ *
40
+ * @param {object} config
41
+ * @param {string} url
42
+ * @returns {string} obfuscated URL
43
+ */
44
+ function obfuscateQs (config, url) {
45
+ const { queryStringObfuscation } = config
46
+
47
+ if (queryStringObfuscation === false) return url
48
+
49
+ const i = url.indexOf('?')
50
+ if (i === -1) return url
51
+
52
+ const path = url.slice(0, i)
53
+ if (queryStringObfuscation === true) return path
54
+
55
+ let qs = url.slice(i + 1)
56
+
57
+ qs = qs.replace(queryStringObfuscation, '<redacted>')
58
+
59
+ return `${path}?${qs}`
60
+ }
61
+
62
+ /**
63
+ * Extract URL path from URL using regex pattern instead of Node.js URL API because:
64
+ *
65
+ * - Handles edge cases like malformed URLs
66
+ * - Works with relative paths
67
+ * - Cross tracers compatibility
68
+ *
69
+ * @param {string} url
70
+ * @returns {string} Url path
71
+ */
72
+ function extractPathFromUrl (url) {
73
+ if (!url) return '/'
74
+ const match = url.match(PATH_REGEX)
75
+
76
+ return match?.groups?.path || '/'
77
+ }
78
+
79
+ /**
80
+ * Calculate http.endpoint from URL path
81
+ *
82
+ * @param {string} url
83
+ * @returns {string} The normalized endpoint
84
+ */
85
+ function calculateHttpEndpoint (url) {
86
+ const path = extractPathFromUrl(url)
87
+
88
+ // Split path by '/' and filter empty elements
89
+ const elements = path.split('/').filter(Boolean)
90
+
91
+ // Keep only first 8 non-empty elements
92
+ const limitedElements = elements.slice(0, 8)
93
+
94
+ // Apply regex replacements to each element respecting this order
95
+ const normalizedElements = limitedElements.map(element => {
96
+ if (INT_SEGMENT.test(element)) return '{param:int}'
97
+
98
+ if (INT_ID_SEGMENT.test(element)) return '{param:int_id}'
99
+
100
+ if (HEX_SEGMENT.test(element)) return '{param:hex}'
101
+
102
+ if (HEX_ID_SEGMENT.test(element)) return '{param:hex_id}'
103
+
104
+ if (STRING_SEGMENT.test(element)) return '{param:str}'
105
+
106
+ // No match
107
+ return element
108
+ })
109
+
110
+ const endpoint = normalizedElements.length > 0
111
+ ? '/' + normalizedElements.join('/')
112
+ : '/'
113
+
114
+ return endpoint
115
+ }
116
+
5
117
  function filterSensitiveInfoFromRepository (repositoryUrl) {
6
118
  if (!repositoryUrl) {
7
119
  return ''
@@ -25,4 +137,10 @@ function filterSensitiveInfoFromRepository (repositoryUrl) {
25
137
  }
26
138
  }
27
139
 
28
- module.exports = { filterSensitiveInfoFromRepository }
140
+ module.exports = {
141
+ extractURL,
142
+ obfuscateQs,
143
+ calculateHttpEndpoint,
144
+ filterSensitiveInfoFromRepository,
145
+ extractPathFromUrl // test only
146
+ }
@@ -11,6 +11,7 @@ const urlFilter = require('./urlfilter')
11
11
  const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../constants')
12
12
  const { createInferredProxySpan, finishInferredProxySpan } = require('./inferred_proxy')
13
13
  const TracingPlugin = require('../tracing')
14
+ const { extractURL, obfuscateQs, calculateHttpEndpoint } = require('./url')
14
15
 
15
16
  let extractIp
16
17
 
@@ -25,16 +26,13 @@ const HTTP_METHOD = tags.HTTP_METHOD
25
26
  const HTTP_URL = tags.HTTP_URL
26
27
  const HTTP_STATUS_CODE = tags.HTTP_STATUS_CODE
27
28
  const HTTP_ROUTE = tags.HTTP_ROUTE
29
+ const HTTP_ENDPOINT = tags.HTTP_ENDPOINT
28
30
  const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
29
31
  const HTTP_RESPONSE_HEADERS = tags.HTTP_RESPONSE_HEADERS
30
32
  const HTTP_USERAGENT = tags.HTTP_USERAGENT
31
33
  const HTTP_CLIENT_IP = tags.HTTP_CLIENT_IP
32
34
  const MANUAL_DROP = tags.MANUAL_DROP
33
35
 
34
- const HTTP2_HEADER_AUTHORITY = ':authority'
35
- const HTTP2_HEADER_SCHEME = ':scheme'
36
- const HTTP2_HEADER_PATH = ':path'
37
-
38
36
  const contexts = new WeakMap()
39
37
  const ends = new WeakMap()
40
38
 
@@ -363,24 +361,6 @@ const web = {
363
361
  finishInferredProxySpan(context)
364
362
  },
365
363
 
366
- obfuscateQs (config, url) {
367
- const { queryStringObfuscation } = config
368
-
369
- if (queryStringObfuscation === false) return url
370
-
371
- const i = url.indexOf('?')
372
- if (i === -1) return url
373
-
374
- const path = url.slice(0, i)
375
- if (queryStringObfuscation === true) return path
376
-
377
- let qs = url.slice(i + 1)
378
-
379
- qs = qs.replace(queryStringObfuscation, '<redacted>')
380
-
381
- return `${path}?${qs}`
382
- },
383
-
384
364
  wrapWriteHead (context) {
385
365
  const { req, res } = context
386
366
  const writeHead = res.writeHead
@@ -475,7 +455,7 @@ function addRequestTags (context, spanType) {
475
455
  const url = extractURL(req)
476
456
 
477
457
  span.addTags({
478
- [HTTP_URL]: web.obfuscateQs(config, url),
458
+ [HTTP_URL]: obfuscateQs(config, url),
479
459
  [HTTP_METHOD]: req.method,
480
460
  [SPAN_KIND]: SERVER,
481
461
  [SPAN_TYPE]: spanType,
@@ -496,11 +476,17 @@ function addRequestTags (context, spanType) {
496
476
  }
497
477
 
498
478
  function addResponseTags (context) {
499
- const { req, res, paths, span, inferredProxySpan } = context
479
+ const { req, res, paths, span, inferredProxySpan, config } = context
500
480
 
501
481
  const route = paths.join('')
502
482
  if (route) {
483
+ // Use http.route from trusted framework instrumentation
503
484
  span.setTag(HTTP_ROUTE, route)
485
+ } else if (config.resourceRenamingEnabled) {
486
+ // Route is unavailable, compute http.endpoint instead
487
+ const url = span.context()._tags[HTTP_URL]
488
+ const endpoint = url ? calculateHttpEndpoint(url) : '/'
489
+ span.setTag(HTTP_ENDPOINT, endpoint)
504
490
  }
505
491
 
506
492
  span.addTags({
@@ -545,23 +531,6 @@ function addHeaders (context) {
545
531
  })
546
532
  }
547
533
 
548
- function extractURL (req) {
549
- const headers = req.headers
550
-
551
- if (req.stream) {
552
- return `${headers[HTTP2_HEADER_SCHEME]}://${headers[HTTP2_HEADER_AUTHORITY]}${headers[HTTP2_HEADER_PATH]}`
553
- }
554
- const protocol = getProtocol(req)
555
- return `${protocol}://${req.headers.host}${req.originalUrl || req.url}`
556
- }
557
-
558
- function getProtocol (req) {
559
- if (req.socket && req.socket.encrypted) return 'https'
560
- if (req.connection && req.connection.encrypted) return 'https'
561
-
562
- return 'http'
563
- }
564
-
565
534
  function getHeadersToRecord (config) {
566
535
  if (Array.isArray(config.headers)) {
567
536
  try {
@@ -0,0 +1,81 @@
1
+ 'use strict'
2
+
3
+ const path = require('node:path')
4
+ const pkg = require('../pkg')
5
+
6
+ const CURRENT_WORKING_DIRECTORY = process.cwd()
7
+ const ENTRYPOINT_PATH = require.main?.filename || ''
8
+
9
+ const TRACING_FIELD_NAME = '_dd.tags.process'
10
+ const DSM_FIELD_NAME = 'ProcessTags'
11
+ const PROFILING_FIELD_NAME = 'process_tags'
12
+
13
+ module.exports.TRACING_FIELD_NAME = TRACING_FIELD_NAME
14
+ module.exports.DSM_FIELD_NAME = DSM_FIELD_NAME
15
+ module.exports.PROFILING_FIELD_NAME = PROFILING_FIELD_NAME
16
+
17
+ // TODO CRASH_TRACKING_FIELD_NAME /process_tags /application/process_tags
18
+ // TODO: TELEMETRY_FIELD_NAME /application/process_tags
19
+ // TODO: DYNAMIC_INSTRUMENTATION_FIELD_NAME process_tags
20
+ // TODO: CLIENT_TRACE_STATISTICS_FIELD_NAME process_tags
21
+ // TODO: REMOTE_CONFIG_FIELD_NAME process_tags
22
+
23
+ // $ cd /foo/bar && node baz/banana.js
24
+ // entrypoint.workdir = bar
25
+ // entrypoint.name = banana
26
+ // entrypoint.type = script
27
+ // entrypoint.basedir = baz
28
+ // package.json.name = <from package.json>
29
+
30
+ module.exports = function getProcessTags () {
31
+ // this list is sorted alphabetically for consistent serialization
32
+ const tags = [
33
+ // the parent directory name of the entrypoint script, e.g. /foo/bar/baz/banana.js -> baz
34
+ ['entrypoint.basedir', ENTRYPOINT_PATH === '' ? undefined : path.basename(path.dirname(ENTRYPOINT_PATH))],
35
+
36
+ // the entrypoint script filename without the extension, e.g. /foo/bar/baz/banana.js -> banana
37
+ ['entrypoint.name', path.basename(ENTRYPOINT_PATH, path.extname(ENTRYPOINT_PATH)) || undefined],
38
+
39
+ // always script for JavaScript applications
40
+ ['entrypoint.type', 'script'],
41
+
42
+ // last segment of the current working directory, e.g. /foo/bar/baz/ -> baz
43
+ ['entrypoint.workdir', path.basename(CURRENT_WORKING_DIRECTORY) || undefined],
44
+
45
+ // the .name field from the application's package.json
46
+ ['package.json.name', pkg.name || undefined]
47
+ ]
48
+
49
+ const serialized = serialize(tags)
50
+
51
+ return {
52
+ tags,
53
+ serialized
54
+ }
55
+ }
56
+
57
+ function serialize (tags) {
58
+ const intermediary = []
59
+ for (const [name, value] of tags) {
60
+ // if we don't have a value we should send nothing at all
61
+ if (value === undefined) continue
62
+ intermediary.push(`${name}:${sanitize(value)}`)
63
+ }
64
+ return intermediary.join(',')
65
+ }
66
+
67
+ module.exports.serialize = serialize
68
+
69
+ /**
70
+ * Sanitize a process tag value
71
+ *
72
+ * @param {string} value
73
+ * @returns {string}
74
+ */
75
+ function sanitize (value) {
76
+ return String(value)
77
+ .toLowerCase()
78
+ .replaceAll(/[^a-zA-Z0-9/_.-]+/g, '_')
79
+ }
80
+
81
+ module.exports.sanitize = sanitize
@@ -3,7 +3,7 @@
3
3
  const os = require('os')
4
4
  const path = require('path')
5
5
  const { URL, format, pathToFileURL } = require('url')
6
- const satisfies = require('semifies')
6
+ const satisfies = require('../../../../vendor/dist/semifies')
7
7
  const { AgentExporter } = require('./exporters/agent')
8
8
  const { FileExporter } = require('./exporters/file')
9
9
  const { ConsoleLogger } = require('./loggers/console')
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const retry = require('retry')
3
+ const retry = require('../../../../../vendor/dist/retry')
4
4
  const { request: httpRequest } = require('http')
5
5
  const { request: httpsRequest } = require('https')
6
6
  const { EventSerializer } = require('./event_serializer')
@@ -2,7 +2,16 @@
2
2
 
3
3
  const { performance, constants, PerformanceObserver } = require('perf_hooks')
4
4
  const { END_TIMESTAMP_LABEL, SPAN_ID_LABEL, LOCAL_ROOT_SPAN_ID_LABEL, encodeProfileAsync } = require('./shared')
5
- const { Function, Label, Line, Location, Profile, Sample, StringTable, ValueType } = require('pprof-format')
5
+ const {
6
+ Function,
7
+ Label,
8
+ Line,
9
+ Location,
10
+ Profile,
11
+ Sample,
12
+ StringTable,
13
+ ValueType
14
+ } = require('../../../../../vendor/dist/pprof-format')
6
15
  const PoissonProcessSamplingFilter = require('./poisson')
7
16
  const { availableParallelism, effectiveLibuvThreadCount } = require('../libuv-size')
8
17
  // perf_hooks uses millis, with fractional part representing nanos. We emit nanos into the pprof file.
@@ -219,6 +219,11 @@ class Tracer extends NoopProxy {
219
219
  initializeOpenTelemetryLogs(config)
220
220
  }
221
221
 
222
+ if (config.otelMetricsEnabled) {
223
+ const { initializeOpenTelemetryMetrics } = require('./opentelemetry/metrics')
224
+ initializeOpenTelemetryMetrics(config)
225
+ }
226
+
222
227
  if (config.isTestDynamicInstrumentationEnabled) {
223
228
  const getDynamicInstrumentationClient = require('./ci-visibility/dynamic-instrumentation')
224
229
  // We instantiate the client but do not start the Worker here. The worker is started lazily
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- const limiter = require('limiter')
3
+ const limiter = require('../../../vendor/dist/limiter')
4
4
 
5
5
  class RateLimiter {
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { URL, format } = require('url')
4
- const uuid = require('crypto-randomuuid')
4
+ const uuid = require('../../../../vendor/dist/crypto-randomuuid')
5
5
  const { EventEmitter } = require('events')
6
6
  const tracerVersion = require('../../../../package.json').version
7
7
  const request = require('../exporters/common/request')
@@ -2,7 +2,7 @@
2
2
 
3
3
  const path = require('path')
4
4
  const Module = require('module')
5
- const parse = require('module-details-from-path')
5
+ const parse = require('../../../vendor/dist/module-details-from-path')
6
6
  const dc = require('dc-polyfill')
7
7
  const { getEnvironmentVariable } = require('../../dd-trace/src/config-helper')
8
8
 
@@ -24,6 +24,10 @@ const web = {
24
24
  opName: () => 'http.request',
25
25
  serviceName: httpPluginClientService
26
26
  },
27
+ genai: {
28
+ opName: () => 'google_genai.request',
29
+ serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
30
+ },
27
31
  aws: {
28
32
  opName: () => 'aws.request',
29
33
  serviceName: awsServiceV0
@@ -16,6 +16,10 @@ const web = {
16
16
  opName: () => 'http.client.request',
17
17
  serviceName: httpPluginClientService
18
18
  },
19
+ genai: {
20
+ opName: () => 'google_genai.request',
21
+ serviceName: ({ pluginConfig, tracerService }) => pluginConfig.service || tracerService
22
+ },
19
23
  fetch: {
20
24
  opName: () => 'http.client.request',
21
25
  serviceName: httpPluginClientService