dd-trace 5.102.0 → 5.104.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 (201) hide show
  1. package/ext/exporters.js +1 -0
  2. package/index.d.ts +25 -3
  3. package/package.json +15 -13
  4. package/packages/datadog-esbuild/src/utils.js +2 -2
  5. package/packages/datadog-instrumentations/src/ai.js +1 -1
  6. package/packages/datadog-instrumentations/src/aws-sdk.js +2 -2
  7. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -2
  8. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +32 -15
  9. package/packages/datadog-instrumentations/src/couchbase.js +69 -220
  10. package/packages/datadog-instrumentations/src/cucumber.js +104 -31
  11. package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
  12. package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
  13. package/packages/datadog-instrumentations/src/electron.js +240 -0
  14. package/packages/datadog-instrumentations/src/fetch.js +5 -5
  15. package/packages/datadog-instrumentations/src/graphql.js +13 -17
  16. package/packages/datadog-instrumentations/src/grpc/client.js +48 -32
  17. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +2 -2
  18. package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
  19. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  20. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
  21. package/packages/datadog-instrumentations/src/helpers/kafka.js +58 -0
  22. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +3 -2
  23. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +19 -5
  24. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +14 -13
  25. package/packages/datadog-instrumentations/src/http/client.js +2 -2
  26. package/packages/datadog-instrumentations/src/ioredis.js +18 -14
  27. package/packages/datadog-instrumentations/src/jest.js +382 -84
  28. package/packages/datadog-instrumentations/src/kafkajs.js +184 -174
  29. package/packages/datadog-instrumentations/src/mariadb.js +1 -1
  30. package/packages/datadog-instrumentations/src/memcached.js +2 -1
  31. package/packages/datadog-instrumentations/src/mocha/main.js +309 -56
  32. package/packages/datadog-instrumentations/src/mocha/utils.js +48 -8
  33. package/packages/datadog-instrumentations/src/mongodb-core.js +34 -9
  34. package/packages/datadog-instrumentations/src/mongoose.js +10 -12
  35. package/packages/datadog-instrumentations/src/mysql.js +2 -2
  36. package/packages/datadog-instrumentations/src/mysql2.js +1 -1
  37. package/packages/datadog-instrumentations/src/pg.js +25 -11
  38. package/packages/datadog-instrumentations/src/playwright.js +449 -60
  39. package/packages/datadog-instrumentations/src/redis.js +19 -10
  40. package/packages/datadog-instrumentations/src/router.js +4 -2
  41. package/packages/datadog-instrumentations/src/vitest.js +246 -149
  42. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
  43. package/packages/datadog-plugin-aws-sdk/src/base.js +18 -24
  44. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  45. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -1
  46. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -1
  47. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +1 -1
  48. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  49. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
  50. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +2 -2
  51. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -1
  52. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +1 -1
  53. package/packages/datadog-plugin-couchbase/src/index.js +58 -52
  54. package/packages/datadog-plugin-cucumber/src/index.js +1 -0
  55. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +239 -40
  56. package/packages/datadog-plugin-cypress/src/support.js +13 -1
  57. package/packages/datadog-plugin-elasticsearch/src/index.js +28 -8
  58. package/packages/datadog-plugin-electron/src/index.js +17 -0
  59. package/packages/datadog-plugin-electron/src/ipc.js +143 -0
  60. package/packages/datadog-plugin-electron/src/net.js +82 -0
  61. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
  62. package/packages/datadog-plugin-graphql/src/execute.js +6 -28
  63. package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
  64. package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
  65. package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
  66. package/packages/datadog-plugin-graphql/src/utils.js +33 -1
  67. package/packages/datadog-plugin-grpc/src/client.js +6 -7
  68. package/packages/datadog-plugin-grpc/src/util.js +57 -22
  69. package/packages/datadog-plugin-http/src/client.js +2 -2
  70. package/packages/datadog-plugin-jest/src/index.js +92 -50
  71. package/packages/datadog-plugin-kafkajs/src/producer.js +32 -0
  72. package/packages/datadog-plugin-mocha/src/index.js +1 -0
  73. package/packages/datadog-plugin-mongodb-core/src/index.js +70 -69
  74. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  75. package/packages/datadog-plugin-openai/src/services.js +2 -1
  76. package/packages/datadog-plugin-pg/src/index.js +3 -3
  77. package/packages/datadog-plugin-playwright/src/index.js +4 -0
  78. package/packages/datadog-plugin-redis/src/index.js +54 -24
  79. package/packages/datadog-plugin-undici/src/index.js +19 -0
  80. package/packages/datadog-plugin-vitest/src/index.js +19 -7
  81. package/packages/datadog-shimmer/src/shimmer.js +35 -0
  82. package/packages/dd-trace/src/aiguard/index.js +3 -1
  83. package/packages/dd-trace/src/aiguard/sdk.js +36 -30
  84. package/packages/dd-trace/src/aiguard/tags.js +20 -11
  85. package/packages/dd-trace/src/appsec/blocking.js +2 -2
  86. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +2 -2
  87. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
  88. package/packages/dd-trace/src/appsec/index.js +10 -3
  89. package/packages/dd-trace/src/appsec/reporter.js +19 -5
  90. package/packages/dd-trace/src/azure_metadata.js +17 -6
  91. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
  92. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
  93. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
  94. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
  95. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -1
  96. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +5 -3
  97. package/packages/dd-trace/src/config/defaults.js +3 -14
  98. package/packages/dd-trace/src/config/generated-config-types.d.ts +4 -1
  99. package/packages/dd-trace/src/config/helper.js +4 -0
  100. package/packages/dd-trace/src/config/index.js +2 -2
  101. package/packages/dd-trace/src/config/major-overrides.js +98 -0
  102. package/packages/dd-trace/src/config/parsers.js +7 -1
  103. package/packages/dd-trace/src/config/supported-configurations.json +60 -38
  104. package/packages/dd-trace/src/crashtracking/crashtracker.js +15 -3
  105. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  106. package/packages/dd-trace/src/datastreams/context.js +4 -2
  107. package/packages/dd-trace/src/datastreams/manager.js +1 -1
  108. package/packages/dd-trace/src/datastreams/processor.js +2 -2
  109. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
  110. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  111. package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
  112. package/packages/dd-trace/src/debugger/index.js +7 -7
  113. package/packages/dd-trace/src/dogstatsd.js +2 -2
  114. package/packages/dd-trace/src/encode/0.4.js +45 -54
  115. package/packages/dd-trace/src/encode/0.5.js +34 -3
  116. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +26 -19
  117. package/packages/dd-trace/src/encode/agentless-json.js +1 -1
  118. package/packages/dd-trace/src/exporter.js +2 -0
  119. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  120. package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
  121. package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
  122. package/packages/dd-trace/src/exporters/common/agents.js +3 -1
  123. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
  124. package/packages/dd-trace/src/exporters/common/request.js +4 -2
  125. package/packages/dd-trace/src/exporters/electron/index.js +49 -0
  126. package/packages/dd-trace/src/external-logger/src/index.js +2 -1
  127. package/packages/dd-trace/src/git_metadata.js +10 -8
  128. package/packages/dd-trace/src/id.js +17 -4
  129. package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
  130. package/packages/dd-trace/src/lambda/handler.js +2 -4
  131. package/packages/dd-trace/src/lambda/index.js +62 -14
  132. package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
  133. package/packages/dd-trace/src/llmobs/index.js +13 -2
  134. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
  135. package/packages/dd-trace/src/llmobs/sdk.js +10 -0
  136. package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
  137. package/packages/dd-trace/src/log/writer.js +3 -1
  138. package/packages/dd-trace/src/noop/span.js +3 -1
  139. package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
  140. package/packages/dd-trace/src/openfeature/writers/exposures.js +51 -20
  141. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +3 -2
  142. package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
  143. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
  144. package/packages/dd-trace/src/plugins/apollo.js +3 -1
  145. package/packages/dd-trace/src/plugins/ci_plugin.js +52 -17
  146. package/packages/dd-trace/src/plugins/database.js +54 -12
  147. package/packages/dd-trace/src/plugins/index.js +1 -0
  148. package/packages/dd-trace/src/plugins/log_plugin.js +3 -1
  149. package/packages/dd-trace/src/plugins/plugin.js +2 -4
  150. package/packages/dd-trace/src/plugins/tracing.js +5 -3
  151. package/packages/dd-trace/src/plugins/util/ci.js +8 -8
  152. package/packages/dd-trace/src/plugins/util/git-cache.js +20 -18
  153. package/packages/dd-trace/src/plugins/util/git.js +3 -1
  154. package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
  155. package/packages/dd-trace/src/plugins/util/test.js +119 -5
  156. package/packages/dd-trace/src/plugins/util/user-provided-git.js +17 -15
  157. package/packages/dd-trace/src/plugins/util/web.js +11 -0
  158. package/packages/dd-trace/src/priority_sampler.js +1 -1
  159. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  160. package/packages/dd-trace/src/profiling/profilers/wall.js +1 -1
  161. package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
  162. package/packages/dd-trace/src/rate_limiter.js +1 -1
  163. package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
  164. package/packages/dd-trace/src/ritm.js +2 -1
  165. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
  166. package/packages/dd-trace/src/scope.js +7 -5
  167. package/packages/dd-trace/src/serverless.js +5 -2
  168. package/packages/dd-trace/src/service-naming/extra-services.js +14 -0
  169. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +20 -0
  170. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  171. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +20 -0
  172. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  173. package/packages/dd-trace/src/span_stats.js +1 -1
  174. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  175. package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
  176. package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
  177. package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
  178. package/vendor/dist/opentracing/LICENSE +0 -201
  179. package/vendor/dist/opentracing/binary_carrier.d.ts +0 -11
  180. package/vendor/dist/opentracing/constants.d.ts +0 -61
  181. package/vendor/dist/opentracing/examples/demo/demo.d.ts +0 -2
  182. package/vendor/dist/opentracing/ext/tags.d.ts +0 -90
  183. package/vendor/dist/opentracing/functions.d.ts +0 -20
  184. package/vendor/dist/opentracing/global_tracer.d.ts +0 -14
  185. package/vendor/dist/opentracing/index.d.ts +0 -12
  186. package/vendor/dist/opentracing/index.js +0 -1
  187. package/vendor/dist/opentracing/mock_tracer/index.d.ts +0 -5
  188. package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +0 -13
  189. package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +0 -16
  190. package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +0 -50
  191. package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +0 -26
  192. package/vendor/dist/opentracing/noop.d.ts +0 -8
  193. package/vendor/dist/opentracing/reference.d.ts +0 -33
  194. package/vendor/dist/opentracing/span.d.ts +0 -147
  195. package/vendor/dist/opentracing/span_context.d.ts +0 -26
  196. package/vendor/dist/opentracing/test/api_compatibility.d.ts +0 -16
  197. package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +0 -3
  198. package/vendor/dist/opentracing/test/noop_implementation.d.ts +0 -4
  199. package/vendor/dist/opentracing/test/opentracing_api.d.ts +0 -3
  200. package/vendor/dist/opentracing/test/unittest.d.ts +0 -2
  201. package/vendor/dist/opentracing/tracer.d.ts +0 -127
package/ext/exporters.js CHANGED
@@ -10,4 +10,5 @@ module.exports = {
10
10
  MOCHA_WORKER: 'mocha_worker',
11
11
  PLAYWRIGHT_WORKER: 'playwright_worker',
12
12
  VITEST_WORKER: 'vitest_worker',
13
+ ELECTRON: 'electron',
13
14
  }
package/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { ClientRequest, IncomingMessage, OutgoingMessage, ServerResponse } from "http";
2
2
  import { LookupFunction } from 'net';
3
- import * as opentracing from "./vendor/dist/opentracing";
3
+ import * as opentracing from "opentracing";
4
4
  import * as otel from "@opentelemetry/api";
5
5
 
6
6
  /**
@@ -2849,13 +2849,13 @@ declare namespace tracer {
2849
2849
  * [mocha](https://mochajs.org/) module.
2850
2850
  */
2851
2851
  interface mocha extends Integration {}
2852
-
2852
+
2853
2853
  /**
2854
2854
  * This plugin automatically instruments the
2855
2855
  * [modelcontextprotocol-sdk](https://github.com/npmjs/package/@modelcontextprotocol/sdk) library.
2856
2856
  */
2857
2857
  interface modelcontextprotocol_sdk extends Instrumentation {}
2858
-
2858
+
2859
2859
  /**
2860
2860
  * This plugin automatically instruments the
2861
2861
  * [moleculer](https://moleculer.services/) module.
@@ -2887,6 +2887,24 @@ declare namespace tracer {
2887
2887
  */
2888
2888
  heartbeatEnabled?: boolean;
2889
2889
 
2890
+ /**
2891
+ * How to mask primitive query values in the `mongodb.query` tag and the
2892
+ * resource name (when `queryInResourceName` is also enabled). Keys,
2893
+ * operator names, and array / pipeline shape are preserved so the masked
2894
+ * query is still a usable query signature.
2895
+ *
2896
+ * - `'types'`: replace each primitive leaf with its `typeof` name
2897
+ * (`'string'`, `'number'`, `'boolean'`, `'bigint'`, `'object'`,
2898
+ * `'null'`). Keeps the same redaction guarantee as `'redact'` but
2899
+ * preserves the value types so the rendered query can still be used
2900
+ * to design indexes.
2901
+ * - `'redact'`: replace each primitive leaf with `'?'`. Strictest masking.
2902
+ * - `'none'`: do not mask. Values land verbatim on the span.
2903
+ *
2904
+ * @default 'none'
2905
+ */
2906
+ obfuscateQuery?: 'none' | 'types' | 'redact';
2907
+
2890
2908
  /**
2891
2909
  * Whether to include the query contents in the resource name.
2892
2910
  */
@@ -3584,11 +3602,15 @@ declare namespace tracer {
3584
3602
 
3585
3603
  /**
3586
3604
  * Enable LLM Observability tracing.
3605
+ *
3606
+ * @deprecated Enabling LLM Observability via `llmobs.enable()` is deprecated and will be removed in dd-trace@7.0.0. Please instantiate LLM Observability via DD_LLMOBS_ENABLED or `tracer.init({ llmobs: ...options })`.
3587
3607
  */
3588
3608
  enable (options: LLMObsEnableOptions): void,
3589
3609
 
3590
3610
  /**
3591
3611
  * Disable LLM Observability tracing.
3612
+ *
3613
+ * @deprecated Disabling LLM Observability via `llmobs.disable()` is deprecated and will be removed in dd-trace@7.0.0. Set DD_LLMOBS_ENABLED=false to disable LLM Observability.
3592
3614
  */
3593
3615
  disable (): void,
3594
3616
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dd-trace",
3
- "version": "5.102.0",
3
+ "version": "5.104.0",
4
4
  "description": "Datadog APM tracing client for JavaScript",
5
5
  "main": "index.js",
6
6
  "typings": "index.d.ts",
@@ -72,6 +72,7 @@
72
72
  "test:integration:aiguard:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/aiguard/*.spec.js\"",
73
73
  "test:integration:appsec": "mocha --timeout 60000 \"integration-tests/appsec/*.spec.js\"",
74
74
  "test:integration:appsec:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/appsec/*.spec.js\"",
75
+ "test:integration:crashtracking": "mocha --timeout 60000 \"integration-tests/crashtracking/*.spec.js\"",
75
76
  "test:integration:bun": "mocha --timeout 60000 \"integration-tests/bun/*.spec.js\"",
76
77
  "test:integration:cucumber": "mocha --timeout 60000 \"integration-tests/cucumber/*.spec.js\"",
77
78
  "test:integration:cucumber:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/cucumber/*.spec.js\"",
@@ -79,6 +80,7 @@
79
80
  "test:integration:cypress:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/cypress/${SPEC:-cypress-*}.spec.js\"",
80
81
  "test:integration:debugger": "mocha --timeout 60000 \"integration-tests/debugger/*.spec.js\"",
81
82
  "test:integration:debugger:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/debugger/*.spec.js\"",
83
+ "test:integration:electron": "mocha \"integration-tests/electron/*.spec.js\"",
82
84
  "test:integration:esbuild": "mocha --timeout 60000 \"integration-tests/esbuild/*.spec.js\"",
83
85
  "test:integration:esbuild:coverage": "node ./integration-tests/coverage/run-suite.js --timeout 60000 \"integration-tests/esbuild/*.spec.js\"",
84
86
  "test:integration:webpack": "mocha --timeout 60000 \"integration-tests/webpack/*.spec.js\"",
@@ -159,20 +161,21 @@
159
161
  "version.js"
160
162
  ],
161
163
  "dependencies": {
162
- "dc-polyfill": "^0.1.10",
163
- "import-in-the-middle": "^3.0.1"
164
+ "dc-polyfill": "^0.1.11",
165
+ "import-in-the-middle": "^3.0.1",
166
+ "opentracing": ">=0.14.7"
164
167
  },
165
168
  "optionalDependencies": {
166
169
  "@datadog/libdatadog": "0.9.3",
167
170
  "@datadog/native-appsec": "11.0.1",
168
171
  "@datadog/native-iast-taint-tracking": "4.1.0",
169
- "@datadog/native-metrics": "3.1.1",
170
- "@datadog/openfeature-node-server": "^1.1.2",
172
+ "@datadog/native-metrics": "3.1.2",
173
+ "@datadog/openfeature-node-server": "1.1.2",
171
174
  "@datadog/pprof": "5.14.1",
172
175
  "@datadog/wasm-js-rewriter": "5.0.1",
173
176
  "@opentelemetry/api": ">=1.0.0 <1.10.0",
174
177
  "@opentelemetry/api-logs": "<1.0.0",
175
- "oxc-parser": "^0.128.0"
178
+ "oxc-parser": "^0.129.0"
176
179
  },
177
180
  "devDependencies": {
178
181
  "@actions/core": "^3.0.1",
@@ -187,17 +190,17 @@
187
190
  "@types/mocha": "^10.0.10",
188
191
  "@types/node": "^18.19.106",
189
192
  "@types/sinon": "^21.0.1",
190
- "axios": "^1.15.2",
193
+ "axios": "^1.16.0",
191
194
  "benchmark": "^2.1.4",
192
195
  "body-parser": "^2.2.2",
193
196
  "bun": "1.3.13",
194
197
  "codeowners-audit": "^2.9.0",
195
198
  "eslint": "^9.39.2",
196
- "eslint-plugin-cypress": "^6.4.0",
199
+ "eslint-plugin-cypress": "^6.4.1",
197
200
  "eslint-plugin-import": "^2.32.0",
198
201
  "eslint-plugin-jsdoc": "^62.9.0",
199
202
  "eslint-plugin-mocha": "^11.2.0",
200
- "eslint-plugin-n": "^17.23.2",
203
+ "eslint-plugin-n": "^18.0.1",
201
204
  "eslint-plugin-promise": "^7.3.0",
202
205
  "eslint-plugin-sonarjs": "^4.0.3",
203
206
  "eslint-plugin-unicorn": "^64.0.0",
@@ -213,21 +216,20 @@
213
216
  "mocha-junit-reporter": "^2.2.1",
214
217
  "mocha-multi-reporters": "^1.5.1",
215
218
  "multer": "^2.1.1",
216
- "nock": "^13.5.6",
219
+ "nock": "^14.0.15",
217
220
  "node-preload": "^0.2.1",
218
221
  "nyc": "^18.0.0",
219
222
  "octokit": "^5.0.3",
220
- "opentracing": ">=0.14.7",
221
223
  "p-limit": "^7.2.0",
222
224
  "proxyquire": "^2.1.3",
223
225
  "retry": "^0.13.1",
224
226
  "semifies": "^1.0.0",
225
227
  "semver": "^7.7.2",
226
- "sinon": "^21.1.2",
228
+ "sinon": "^22.0.0",
227
229
  "tiktoken": "^1.0.21",
228
230
  "typescript": "^6.0.3",
229
231
  "workerpool": "^10.0.2",
230
- "yaml": "^2.8.3",
232
+ "yaml": "^2.8.4",
231
233
  "yarn-deduplicate": "^6.0.2"
232
234
  }
233
235
  }
@@ -83,9 +83,9 @@ function getSource (url, { format }) {
83
83
  *
84
84
  * @param {object} moduleData
85
85
  * @param {string} moduleData.path
86
- * @param {boolean} [moduleData.internal = false]
86
+ * @param {boolean} [moduleData.internal]
87
87
  * @param {object} moduleData.context
88
- * @param {boolean} [moduleData.excludeDefault = false]
88
+ * @param {boolean} [moduleData.excludeDefault]
89
89
  * @returns {Promise<Map>}
90
90
  */
91
91
  async function processModule ({ path, internal = false, context, excludeDefault = false }) {
@@ -20,7 +20,7 @@ const wrappedModels = new WeakSet()
20
20
  */
21
21
  function publishToAIGuard (messages) {
22
22
  return new Promise((resolve, reject) => {
23
- aiguardChannel.publish({ messages, resolve, reject })
23
+ aiguardChannel.publish({ messages, integration: 'ai', resolve, reject })
24
24
  })
25
25
  }
26
26
 
@@ -198,7 +198,7 @@ function wrapSmithySend (send) {
198
198
  })
199
199
 
200
200
  if (typeof cb === 'function') {
201
- args[args.length - 1] = shimmer.wrapFunction(cb, cb => function (err, result) {
201
+ args[args.length - 1] = shimmer.wrapCallback(cb, cb => function (err, result) {
202
202
  addResponse(ctx, err, result)
203
203
 
204
204
  handleCompletion(result, ctx, channels)
@@ -270,7 +270,7 @@ function handleCompletion (result, ctx, channels) {
270
270
 
271
271
  function wrapCb (cb, channels, ctx) {
272
272
  // eslint-disable-next-line n/handle-callback-err
273
- return shimmer.wrapFunction(cb, cb => function wrappedCb (err, response) {
273
+ return shimmer.wrapCallback(cb, cb => function wrappedCb (err, response) {
274
274
  ctx = { request: ctx.request, response }
275
275
  return channels.responseStart.runStores(ctx, () => {
276
276
  try {
@@ -29,9 +29,12 @@ addHook({ name: 'cassandra-driver', versions: ['>=3.0.0'] }, cassandra => {
29
29
 
30
30
  try {
31
31
  const res = batch.apply(this, arguments)
32
- if (typeof res === 'function' || !res) {
32
+ if (typeof res === 'function') {
33
33
  return wrapCallback(finishCh, errorCh, startCtx, res)
34
34
  }
35
+ if (!res) {
36
+ return res
37
+ }
35
38
  return res.then(
36
39
  () => finish(finishCh, errorCh, startCtx),
37
40
  err => finish(finishCh, errorCh, startCtx, err)
@@ -162,7 +165,7 @@ function finish (finishCh, errorCh, ctx, error) {
162
165
  }
163
166
 
164
167
  function wrapCallback (finishCh, errorCh, ctx, callback) {
165
- return shimmer.wrapFunction(callback, callback => function (err) {
168
+ return shimmer.wrapCallback(callback, callback => function (err) {
166
169
  if (err) {
167
170
  ctx.error = err
168
171
  errorCh.publish(ctx)
@@ -7,6 +7,7 @@ const {
7
7
  addHook,
8
8
  channel,
9
9
  } = require('./helpers/instrument')
10
+ const { cloneMessages } = require('./helpers/kafka')
10
11
 
11
12
  // Create channels for Confluent Kafka JavaScript
12
13
  const channels = {
@@ -211,46 +212,62 @@ function instrumentKafkaJS (kafkaJS) {
211
212
  return send.apply(this, arguments)
212
213
  }
213
214
 
215
+ const disableHeaderInjection = disabledHeaderWeakSet.has(producer)
216
+
217
+ // Hand the underlying client a shallow clone so neither
218
+ // injection nor the client's auto-fields (it sets
219
+ // `headers: null` on messages without headers) ever
220
+ // touch caller-owned objects. With injection disabled the
221
+ // clone must not seed `headers: {}` either: brokers that
222
+ // reject any header field cannot recover otherwise.
223
+ let outgoingPayload = payload
224
+ if (payload && Array.isArray(payload.messages)) {
225
+ outgoingPayload = {
226
+ ...payload,
227
+ messages: cloneMessages(payload.messages, !disableHeaderInjection),
228
+ }
229
+ }
230
+
214
231
  const ctx = {
215
- topic: payload?.topic,
216
- messages: payload?.messages || [],
232
+ topic: outgoingPayload?.topic,
233
+ messages: outgoingPayload?.messages || [],
217
234
  bootstrapServers: kafka._ddBrokers,
218
- disableHeaderInjection: disabledHeaderWeakSet.has(producer),
235
+ disableHeaderInjection,
219
236
  }
220
237
 
221
238
  return channels.producerStart.runStores(ctx, () => {
222
239
  try {
223
- const result = send.apply(this, arguments)
240
+ const result = send.call(this, outgoingPayload)
224
241
 
225
242
  result.then((res) => {
226
243
  ctx.result = res
227
244
  channels.producerCommit.publish(ctx)
228
245
  channels.producerFinish.publish(ctx)
229
- }, (err) => {
230
- if (err) {
231
- // Fixes bug where we would inject message headers for kafka brokers
232
- // that don't support headers (version <0.11). On the error, we disable
233
- // header injection. Tnfortunately the error name / type is not more specific.
234
- // This approach is implemented by other tracers as well.
235
- if (err.name === 'KafkaJSError' && err.type === 'ERR_UNKNOWN') {
246
+ }, (error) => {
247
+ if (error) {
248
+ // KafkaJS-compat reports `ERR_UNKNOWN` for brokers
249
+ // <0.11 that cannot parse headers. Stop injecting
250
+ // for this producer; subsequent sends to the same
251
+ // broker succeed.
252
+ if (error.name === 'KafkaJSError' && error.type === 'ERR_UNKNOWN') {
236
253
  disabledHeaderWeakSet.add(producer)
237
254
  log.error(
238
255
  // eslint-disable-next-line @stylistic/max-len
239
256
  'Kafka Broker responded with UNKNOWN_SERVER_ERROR (-1). Please look at broker logs for more information. Tracer message header injection for Kafka is disabled.'
240
257
  )
241
258
  }
242
- ctx.error = err
259
+ ctx.error = error
243
260
  channels.producerError.publish(ctx)
244
261
  }
245
262
  channels.producerFinish.publish(ctx)
246
263
  })
247
264
 
248
265
  return result
249
- } catch (e) {
250
- ctx.error = e
266
+ } catch (error) {
267
+ ctx.error = error
251
268
  channels.producerError.publish(ctx)
252
269
  channels.producerFinish.publish(ctx)
253
- throw e
270
+ throw error
254
271
  }
255
272
  })
256
273
  }
@@ -1,12 +1,27 @@
1
1
  'use strict'
2
2
 
3
- const { errorMonitor } = require('events')
3
+ const { tracingChannel } = require('dc-polyfill')
4
+
4
5
  const shimmer = require('../../datadog-shimmer')
5
6
  const {
6
- channel,
7
7
  addHook,
8
8
  } = require('./helpers/instrument')
9
9
 
10
+ // One TracingChannel per traced operation, looked up at module init so the
11
+ // hot path only does property reads on a stable handle.
12
+ const queryCh = tracingChannel('apm:couchbase:query')
13
+ const upsertCh = tracingChannel('apm:couchbase:upsert')
14
+ const insertCh = tracingChannel('apm:couchbase:insert')
15
+ const replaceCh = tracingChannel('apm:couchbase:replace')
16
+
17
+ /** @type {Map<string, ReturnType<typeof tracingChannel>>} */
18
+ const opChannelByName = new Map([
19
+ ['query', queryCh],
20
+ ['upsert', upsertCh],
21
+ ['insert', insertCh],
22
+ ['replace', replaceCh],
23
+ ])
24
+
10
25
  function findCallbackIndex (args, lowerbound = 2) {
11
26
  for (let i = args.length - 1; i >= lowerbound; i--) {
12
27
  if (typeof args[i] === 'function') return i
@@ -19,244 +34,78 @@ function getQueryResource (q) {
19
34
  return q && (typeof q === 'string' ? q : q.statement)
20
35
  }
21
36
 
22
- function wrapAllNames (names, action) {
23
- for (const name of names) {
24
- action(name)
37
+ // Hand-rolled instead of `tracingChannel.tracePromise`: synchronous
38
+ // `res.then(...)` dodges the `Promise.resolve(thenable)` microtask race on
39
+ // SDK v3.2.x / v4.0-v4.4 (lazy listener attachment), and external `.on()`
40
+ // is forbidden on v4.5.0+ (JSCBC-1301 depromisify). See commit body.
41
+ /**
42
+ * @param {import('node:diagnostics_channel').TracingChannel} ch
43
+ * Pinned per-op channel.
44
+ * @param {(...callArgs: unknown[]) => unknown} fn The SDK method being traced.
45
+ * @param {object} ctx Mutated to record `result` / `error`.
46
+ * @param {object} thisArg
47
+ * @param {unknown[]} args Forwarded to `fn` verbatim.
48
+ */
49
+ function traceV3 (ch, fn, ctx, thisArg, args) {
50
+ if (!ch.start.hasSubscribers) return fn.apply(thisArg, args)
51
+ const cbIndex = findCallbackIndex(args, 1)
52
+ if (cbIndex >= 0) {
53
+ return ch.traceCallback(fn, cbIndex, ctx, thisArg, ...args)
25
54
  }
26
- }
27
-
28
- function wrapCallback (callback, ctx, channelPrefix) {
29
- const callbackStartCh = channel(`${channelPrefix}:callback:start`)
30
- const callbackFinishCh = channel(`${channelPrefix}:callback:finish`)
31
-
32
- const wrapped = callbackStartCh.runStores(ctx, () => {
33
- return function (...args) {
34
- return callbackFinishCh.runStores(ctx, () => {
35
- return callback.apply(this, args)
36
- })
37
- }
38
- })
39
- Object.defineProperty(wrapped, '_dd_wrapped', { value: true })
40
- return wrapped
41
- }
42
-
43
- function wrapQuery (query) {
44
- return function (q, params, callback) {
45
- const cb = arguments[arguments.length - 1]
46
- if (typeof cb === 'function') {
47
- const ctx = {}
48
- arguments[arguments.length - 1] = wrapCallback(cb, ctx, 'apm:couchbase:query')
49
- }
50
-
51
- return query.apply(this, arguments)
52
- }
53
- }
54
-
55
- function wrapCallbackFinish (callback, thisArg, _args, errorCh, finishCh, ctx, channelPrefix) {
56
- const callbackStartCh = channel(`${channelPrefix}:callback:start`)
57
- const callbackFinishCh = channel(`${channelPrefix}:callback:finish`)
58
-
59
- const wrapped = callbackStartCh.runStores(ctx, () => {
60
- return function finish (error, result) {
61
- return callbackFinishCh.runStores(ctx, () => {
62
- if (error) {
63
- ctx.error = error
64
- errorCh.publish(ctx)
65
- }
66
- finishCh.publish(ctx)
67
- return callback.apply(thisArg, [error, result])
68
- })
69
- }
70
- })
71
- Object.defineProperty(wrapped, '_dd_wrapped', { value: true })
72
- return wrapped
73
- }
74
-
75
- function wrap (prefix, fn) {
76
- const startCh = channel(prefix + ':start')
77
- const finishCh = channel(prefix + ':finish')
78
- const errorCh = channel(prefix + ':error')
79
-
80
- return function (...args) {
81
- if (!startCh.hasSubscribers) {
82
- return fn.apply(this, args)
83
- }
84
-
85
- const callbackIndex = findCallbackIndex(args, 1)
86
-
87
- if (callbackIndex < 0) return fn.apply(this, args)
88
-
89
- const ctx = { bucket: { name: this.name || this._name }, seedNodes: this._dd_hosts }
90
- return startCh.runStores(ctx, () => {
91
- const cb = args[callbackIndex]
92
-
93
- args[callbackIndex] = shimmer.wrapFunction(cb, (cb) => {
94
- return wrapCallbackFinish(cb, this, args, errorCh, finishCh, ctx, prefix)
95
- })
96
-
97
- try {
98
- return fn.apply(this, args)
99
- } catch (error) {
100
- ctx.error = error
101
- void error.stack // trigger getting the stack at the original throwing point
102
- errorCh.publish(ctx)
103
-
104
- throw error
105
- }
106
- })
107
- }
108
- }
109
-
110
- // semver >=2 <3
111
- function wrapMaybeInvoke (_maybeInvoke, channelPrefix) {
112
- return function (fn, args) {
113
- if (!Array.isArray(args)) return _maybeInvoke.apply(this, arguments)
114
-
115
- const callbackIndex = findCallbackIndex(args, 0)
116
-
117
- if (callbackIndex === -1) return _maybeInvoke.apply(this, arguments)
118
-
119
- const callback = args[callbackIndex]
120
-
121
- if (typeof callback === 'function' && !callback._dd_wrapped) {
122
- const ctx = {}
123
- args[callbackIndex] = wrapCallback(callback, ctx, channelPrefix)
124
- }
125
-
126
- return _maybeInvoke.apply(this, arguments)
127
- }
128
- }
129
-
130
- // semver >=3
131
-
132
- function wrapCBandPromise (fn, name, startData, thisArg, args) {
133
- const startCh = channel(`apm:couchbase:${name}:start`)
134
- const finishCh = channel(`apm:couchbase:${name}:finish`)
135
- const errorCh = channel(`apm:couchbase:${name}:error`)
136
-
137
- if (!startCh.hasSubscribers) return fn.apply(thisArg, args)
138
-
139
- const ctx = startData
140
- return startCh.runStores(ctx, () => {
55
+ return ch.start.runStores(ctx, () => {
141
56
  try {
142
- const cbIndex = findCallbackIndex(args, 1)
143
- if (cbIndex >= 0) {
144
- // v3 offers callback or promises event handling
145
- // NOTE: this does not work with v3.2.0-3.2.1 cluster.query, as there is a bug in the couchbase source code
146
- args[cbIndex] = shimmer.wrapFunction(args[cbIndex], (cb) => {
147
- return wrapCallbackFinish(cb, thisArg, args, errorCh, finishCh, ctx, `apm:couchbase:${name}`)
148
- })
149
- }
150
57
  const res = fn.apply(thisArg, args)
151
-
152
- // semver >=3 will always return promise by default
153
58
  res.then(
154
59
  (result) => {
155
60
  ctx.result = result
156
- finishCh.publish(ctx)
61
+ ch.asyncStart.publish(ctx)
62
+ ch.asyncEnd.publish(ctx)
157
63
  },
158
- (err) => {
159
- ctx.error = err
160
- errorCh.publish(ctx)
161
- finishCh.publish(ctx)
64
+ (error) => {
65
+ ctx.error = error
66
+ ch.error.publish(ctx)
67
+ ch.asyncStart.publish(ctx)
68
+ ch.asyncEnd.publish(ctx)
162
69
  }
163
70
  )
164
71
  return res
165
- } catch (e) {
166
- void e.stack
167
- ctx.error = e
168
- errorCh.publish(ctx)
169
- throw e
72
+ } catch (error) {
73
+ ctx.error = error
74
+ ch.error.publish(ctx)
75
+ throw error
76
+ } finally {
77
+ ch.end.publish(ctx)
170
78
  }
171
79
  })
172
80
  }
173
81
 
174
- function wrapWithName (name) {
82
+ /**
83
+ * @param {string} name Operation name (`upsert`, `insert`, `replace`).
84
+ */
85
+ function wrapV3WithName (name) {
86
+ const ch = opChannelByName.get(name)
175
87
  return function (operation) {
176
- return function (...args) { // no arguments used by us
177
- return wrapCBandPromise(operation, name, {
88
+ return function (...args) {
89
+ const ctx = {
178
90
  collection: { name: this._name || '_default' },
179
91
  bucket: { name: this._scope._bucket._name },
180
92
  seedNodes: this._dd_connStr,
181
- }, this, args)
93
+ }
94
+ return traceV3(ch, operation, ctx, this, args)
182
95
  }
183
96
  }
184
97
  }
185
98
 
99
+ /**
100
+ * @param {(...args: unknown[]) => unknown} query Original `Cluster.prototype.query`.
101
+ */
186
102
  function wrapV3Query (query) {
187
- return function (q) {
188
- const resource = getQueryResource(q)
189
- return wrapCBandPromise(query, 'query', { resource, seedNodes: this._connStr }, this, arguments)
103
+ return function (...args) {
104
+ const ctx = { resource: getQueryResource(args[0]), seedNodes: this._connStr }
105
+ return traceV3(queryCh, query, ctx, this, args)
190
106
  }
191
107
  }
192
108
 
193
- // semver >=2 <3
194
- addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.12'] }, Bucket => {
195
- shimmer.wrap(Bucket.prototype, '_maybeInvoke', maybeInvoke => {
196
- return wrapMaybeInvoke(maybeInvoke, 'apm:couchbase:bucket:maybeInvoke')
197
- })
198
-
199
- const startCh = channel('apm:couchbase:query:start')
200
- const finishCh = channel('apm:couchbase:query:finish')
201
- const errorCh = channel('apm:couchbase:query:error')
202
-
203
- shimmer.wrap(Bucket.prototype, 'query', query => wrapQuery(query))
204
-
205
- shimmer.wrap(Bucket.prototype, '_n1qlReq', _n1qlReq => function (host, q, adhoc, emitter) {
206
- if (!startCh.hasSubscribers) {
207
- return _n1qlReq.apply(this, arguments)
208
- }
209
-
210
- if (!emitter || !emitter.once) return _n1qlReq.apply(this, arguments)
211
-
212
- const n1qlQuery = getQueryResource(q)
213
-
214
- const ctx = { resource: n1qlQuery, bucket: { name: this.name || this._name }, seedNodes: this._dd_hosts }
215
- return startCh.runStores(ctx, () => {
216
- emitter.once('rows', () => {
217
- finishCh.publish(ctx)
218
- })
219
-
220
- emitter.once(errorMonitor, (error) => {
221
- if (!error) return
222
- ctx.error = error
223
- errorCh.publish(ctx)
224
- finishCh.publish(ctx)
225
- })
226
-
227
- try {
228
- return _n1qlReq.apply(this, arguments)
229
- } catch (err) {
230
- void err.stack // trigger getting the stack at the original throwing point
231
- ctx.error = err
232
- errorCh.publish(ctx)
233
-
234
- throw err
235
- }
236
- })
237
- })
238
-
239
- wrapAllNames(['upsert', 'insert', 'replace', 'append', 'prepend'], name => {
240
- shimmer.wrap(Bucket.prototype, name, fn => wrap(`apm:couchbase:${name}`, fn))
241
- })
242
- })
243
-
244
- addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.12'] }, Cluster => {
245
- shimmer.wrap(Cluster.prototype, '_maybeInvoke', maybeInvoke => {
246
- return wrapMaybeInvoke(maybeInvoke, 'apm:couchbase:cluster:maybeInvoke')
247
- })
248
-
249
- shimmer.wrap(Cluster.prototype, 'query', query => wrapQuery(query))
250
- shimmer.wrap(Cluster.prototype, 'openBucket', openBucket => {
251
- return function (...args) {
252
- const bucket = openBucket.apply(this, args)
253
- const hosts = this.dsnObj.hosts
254
- bucket._dd_hosts = hosts.map(hostAndPort => hostAndPort.join(':')).join(',')
255
- return bucket
256
- }
257
- })
258
- })
259
-
260
109
  // semver >=3 <3.2.0
261
110
 
262
111
  addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^3.0.7', '^3.1.3'] }, Bucket => {
@@ -271,9 +120,9 @@ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^3.0.7', '^3.1.3
271
120
  })
272
121
 
273
122
  addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['^3.0.7', '^3.1.3'] }, Collection => {
274
- wrapAllNames(['upsert', 'insert', 'replace'], name => {
275
- shimmer.wrap(Collection.prototype, name, wrapWithName(name))
276
- })
123
+ for (const name of ['upsert', 'insert', 'replace']) {
124
+ shimmer.wrap(Collection.prototype, name, wrapV3WithName(name))
125
+ }
277
126
  })
278
127
 
279
128
  addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^3.0.7', '^3.1.3'] }, Cluster => {
@@ -286,9 +135,9 @@ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^3.0.7', '^3.1.
286
135
  addHook({ name: 'couchbase', file: 'dist/collection.js', versions: ['>=3.2.2'] }, collection => {
287
136
  const Collection = collection.Collection
288
137
 
289
- wrapAllNames(['upsert', 'insert', 'replace'], name => {
290
- shimmer.wrap(Collection.prototype, name, wrapWithName(name))
291
- })
138
+ for (const name of ['upsert', 'insert', 'replace']) {
139
+ shimmer.wrap(Collection.prototype, name, wrapV3WithName(name))
140
+ }
292
141
  })
293
142
 
294
143
  addHook({ name: 'couchbase', file: 'dist/bucket.js', versions: ['>=3.2.2'] }, bucket => {