dd-trace 5.101.0 → 5.103.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 (235) hide show
  1. package/ext/exporters.js +1 -0
  2. package/package.json +20 -17
  3. package/packages/datadog-esbuild/src/utils.js +2 -2
  4. package/packages/datadog-instrumentations/src/aerospike.js +2 -2
  5. package/packages/datadog-instrumentations/src/ai.js +9 -9
  6. package/packages/datadog-instrumentations/src/amqplib.js +6 -7
  7. package/packages/datadog-instrumentations/src/anthropic.js +10 -10
  8. package/packages/datadog-instrumentations/src/apollo-server-core.js +3 -3
  9. package/packages/datadog-instrumentations/src/apollo-server.js +5 -5
  10. package/packages/datadog-instrumentations/src/avsc.js +6 -6
  11. package/packages/datadog-instrumentations/src/aws-sdk.js +151 -67
  12. package/packages/datadog-instrumentations/src/azure-durable-functions.js +8 -8
  13. package/packages/datadog-instrumentations/src/bluebird.js +2 -2
  14. package/packages/datadog-instrumentations/src/body-parser.js +2 -2
  15. package/packages/datadog-instrumentations/src/cassandra-driver.js +7 -7
  16. package/packages/datadog-instrumentations/src/child_process.js +12 -12
  17. package/packages/datadog-instrumentations/src/confluentinc-kafka-javascript.js +41 -24
  18. package/packages/datadog-instrumentations/src/connect.js +7 -7
  19. package/packages/datadog-instrumentations/src/cookie-parser.js +4 -4
  20. package/packages/datadog-instrumentations/src/cookie.js +2 -2
  21. package/packages/datadog-instrumentations/src/couchbase.js +73 -238
  22. package/packages/datadog-instrumentations/src/crypto.js +4 -4
  23. package/packages/datadog-instrumentations/src/cucumber.js +78 -17
  24. package/packages/datadog-instrumentations/src/dns.js +0 -3
  25. package/packages/datadog-instrumentations/src/elasticsearch.js +8 -11
  26. package/packages/datadog-instrumentations/src/electron/preload.js +42 -0
  27. package/packages/datadog-instrumentations/src/electron.js +240 -0
  28. package/packages/datadog-instrumentations/src/express-mongo-sanitize.js +6 -6
  29. package/packages/datadog-instrumentations/src/express-session.js +4 -4
  30. package/packages/datadog-instrumentations/src/express.js +10 -11
  31. package/packages/datadog-instrumentations/src/fastify.js +2 -2
  32. package/packages/datadog-instrumentations/src/fetch.js +5 -5
  33. package/packages/datadog-instrumentations/src/fs.js +14 -14
  34. package/packages/datadog-instrumentations/src/google-cloud-pubsub.js +5 -7
  35. package/packages/datadog-instrumentations/src/google-genai.js +4 -4
  36. package/packages/datadog-instrumentations/src/graphql.js +13 -12
  37. package/packages/datadog-instrumentations/src/grpc/server.js +2 -2
  38. package/packages/datadog-instrumentations/src/hapi.js +2 -2
  39. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +9 -9
  40. package/packages/datadog-instrumentations/src/helpers/hook.js +4 -1
  41. package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
  42. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -2
  43. package/packages/datadog-instrumentations/src/helpers/kafka.js +41 -0
  44. package/packages/datadog-instrumentations/src/helpers/promise.js +2 -2
  45. package/packages/datadog-instrumentations/src/hono.js +2 -2
  46. package/packages/datadog-instrumentations/src/http/client.js +6 -6
  47. package/packages/datadog-instrumentations/src/http/server.js +9 -9
  48. package/packages/datadog-instrumentations/src/ioredis.js +16 -12
  49. package/packages/datadog-instrumentations/src/jest.js +382 -81
  50. package/packages/datadog-instrumentations/src/kafkajs.js +165 -174
  51. package/packages/datadog-instrumentations/src/knex.js +17 -17
  52. package/packages/datadog-instrumentations/src/koa.js +12 -12
  53. package/packages/datadog-instrumentations/src/ldapjs.js +5 -5
  54. package/packages/datadog-instrumentations/src/light-my-request.js +2 -2
  55. package/packages/datadog-instrumentations/src/limitd-client.js +4 -4
  56. package/packages/datadog-instrumentations/src/lodash.js +4 -4
  57. package/packages/datadog-instrumentations/src/mariadb.js +13 -13
  58. package/packages/datadog-instrumentations/src/memcached.js +2 -2
  59. package/packages/datadog-instrumentations/src/microgateway-core.js +2 -2
  60. package/packages/datadog-instrumentations/src/mocha/common.js +3 -3
  61. package/packages/datadog-instrumentations/src/mocha/main.js +85 -11
  62. package/packages/datadog-instrumentations/src/mocha/utils.js +133 -16
  63. package/packages/datadog-instrumentations/src/mocha/worker.js +7 -5
  64. package/packages/datadog-instrumentations/src/mongodb-core.js +42 -30
  65. package/packages/datadog-instrumentations/src/mongodb.js +5 -5
  66. package/packages/datadog-instrumentations/src/mongoose.js +21 -21
  67. package/packages/datadog-instrumentations/src/mquery.js +5 -5
  68. package/packages/datadog-instrumentations/src/multer.js +4 -4
  69. package/packages/datadog-instrumentations/src/mysql.js +16 -16
  70. package/packages/datadog-instrumentations/src/mysql2.js +4 -4
  71. package/packages/datadog-instrumentations/src/net.js +14 -8
  72. package/packages/datadog-instrumentations/src/nyc.js +5 -5
  73. package/packages/datadog-instrumentations/src/openai.js +19 -19
  74. package/packages/datadog-instrumentations/src/oracledb.js +6 -6
  75. package/packages/datadog-instrumentations/src/passport-utils.js +5 -5
  76. package/packages/datadog-instrumentations/src/pg.js +39 -25
  77. package/packages/datadog-instrumentations/src/pino.js +6 -10
  78. package/packages/datadog-instrumentations/src/playwright.js +445 -68
  79. package/packages/datadog-instrumentations/src/protobufjs.js +16 -16
  80. package/packages/datadog-instrumentations/src/redis.js +20 -12
  81. package/packages/datadog-instrumentations/src/restify.js +2 -2
  82. package/packages/datadog-instrumentations/src/router.js +12 -12
  83. package/packages/datadog-instrumentations/src/stripe.js +12 -12
  84. package/packages/datadog-instrumentations/src/vitest.js +107 -26
  85. package/packages/datadog-instrumentations/src/winston.js +4 -4
  86. package/packages/datadog-instrumentations/src/ws.js +7 -7
  87. package/packages/datadog-plugin-apollo/src/gateway/request.js +1 -21
  88. package/packages/datadog-plugin-aws-sdk/src/base.js +70 -28
  89. package/packages/datadog-plugin-aws-sdk/src/services/cloudwatchlogs.js +1 -1
  90. package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +20 -13
  91. package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +46 -36
  92. package/packages/datadog-plugin-aws-sdk/src/services/lambda.js +34 -23
  93. package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -1
  94. package/packages/datadog-plugin-aws-sdk/src/services/s3.js +1 -1
  95. package/packages/datadog-plugin-aws-sdk/src/services/sns.js +14 -15
  96. package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +74 -55
  97. package/packages/datadog-plugin-aws-sdk/src/services/stepfunctions.js +20 -18
  98. package/packages/datadog-plugin-aws-sdk/src/util.js +22 -0
  99. package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +6 -6
  100. package/packages/datadog-plugin-couchbase/src/index.js +58 -52
  101. package/packages/datadog-plugin-cucumber/src/index.js +5 -0
  102. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +215 -26
  103. package/packages/datadog-plugin-cypress/src/support.js +13 -1
  104. package/packages/datadog-plugin-electron/src/index.js +17 -0
  105. package/packages/datadog-plugin-electron/src/ipc.js +143 -0
  106. package/packages/datadog-plugin-electron/src/net.js +82 -0
  107. package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -5
  108. package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +27 -18
  109. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +3 -1
  110. package/packages/datadog-plugin-graphql/src/execute.js +6 -28
  111. package/packages/datadog-plugin-graphql/src/resolve.js +30 -35
  112. package/packages/datadog-plugin-graphql/src/tools/signature.js +32 -7
  113. package/packages/datadog-plugin-graphql/src/tools/transforms.js +118 -100
  114. package/packages/datadog-plugin-graphql/src/utils.js +29 -0
  115. package/packages/datadog-plugin-grpc/src/client.js +6 -7
  116. package/packages/datadog-plugin-grpc/src/util.js +57 -22
  117. package/packages/datadog-plugin-http/src/client.js +3 -7
  118. package/packages/datadog-plugin-jest/src/index.js +92 -50
  119. package/packages/datadog-plugin-jest/src/util.js +1 -2
  120. package/packages/datadog-plugin-mocha/src/index.js +5 -0
  121. package/packages/datadog-plugin-mongodb-core/src/index.js +36 -69
  122. package/packages/datadog-plugin-mysql/src/index.js +1 -1
  123. package/packages/datadog-plugin-openai/src/services.js +2 -1
  124. package/packages/datadog-plugin-openai/src/tracing.js +12 -23
  125. package/packages/datadog-plugin-pg/src/index.js +3 -3
  126. package/packages/datadog-plugin-playwright/src/index.js +5 -1
  127. package/packages/datadog-plugin-redis/src/index.js +18 -23
  128. package/packages/datadog-plugin-vitest/src/index.js +8 -1
  129. package/packages/datadog-shimmer/src/shimmer.js +7 -1
  130. package/packages/dd-trace/src/aiguard/index.js +3 -1
  131. package/packages/dd-trace/src/aiguard/sdk.js +36 -30
  132. package/packages/dd-trace/src/aiguard/tags.js +20 -11
  133. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-password-rules.js +1 -1
  134. package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-rules.js +81 -81
  135. package/packages/dd-trace/src/appsec/iast/security-controls/index.js +2 -2
  136. package/packages/dd-trace/src/appsec/iast/taint-tracking/plugins/kafka.js +2 -2
  137. package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +4 -4
  138. package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +2 -2
  139. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +2 -0
  140. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +1 -3
  141. package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/utils.js +83 -48
  142. package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
  143. package/packages/dd-trace/src/appsec/index.js +21 -24
  144. package/packages/dd-trace/src/appsec/reporter.js +3 -1
  145. package/packages/dd-trace/src/appsec/rule_manager.js +4 -2
  146. package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +31 -16
  147. package/packages/dd-trace/src/azure_metadata.js +17 -6
  148. package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +4 -4
  149. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -2
  150. package/packages/dd-trace/src/ci-visibility/exporters/test-worker/index.js +6 -4
  151. package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +1 -1
  152. package/packages/dd-trace/src/config/defaults.js +3 -14
  153. package/packages/dd-trace/src/config/generated-config-types.d.ts +3 -1
  154. package/packages/dd-trace/src/config/git_properties.js +2 -2
  155. package/packages/dd-trace/src/config/helper.js +4 -0
  156. package/packages/dd-trace/src/config/index.js +2 -2
  157. package/packages/dd-trace/src/config/major-overrides.js +98 -0
  158. package/packages/dd-trace/src/config/parsers.js +7 -1
  159. package/packages/dd-trace/src/config/supported-configurations.json +51 -38
  160. package/packages/dd-trace/src/datastreams/checkpointer.js +2 -2
  161. package/packages/dd-trace/src/datastreams/index.js +2 -1
  162. package/packages/dd-trace/src/datastreams/manager.js +1 -1
  163. package/packages/dd-trace/src/datastreams/processor.js +3 -4
  164. package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +2 -2
  165. package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +1 -0
  166. package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
  167. package/packages/dd-trace/src/debugger/devtools_client/state.js +2 -1
  168. package/packages/dd-trace/src/debugger/index.js +7 -7
  169. package/packages/dd-trace/src/dogstatsd.js +2 -2
  170. package/packages/dd-trace/src/encode/0.4.js +748 -232
  171. package/packages/dd-trace/src/encode/0.5.js +47 -10
  172. package/packages/dd-trace/src/encode/agentless-json.js +1 -1
  173. package/packages/dd-trace/src/exporter.js +2 -0
  174. package/packages/dd-trace/src/exporters/agent/index.js +2 -1
  175. package/packages/dd-trace/src/exporters/agentless/index.js +3 -2
  176. package/packages/dd-trace/src/exporters/agentless/writer.js +2 -2
  177. package/packages/dd-trace/src/exporters/common/buffering-exporter.js +2 -1
  178. package/packages/dd-trace/src/exporters/common/request.js +1 -1
  179. package/packages/dd-trace/src/exporters/electron/index.js +49 -0
  180. package/packages/dd-trace/src/external-logger/src/index.js +2 -1
  181. package/packages/dd-trace/src/git_metadata.js +10 -8
  182. package/packages/dd-trace/src/lambda/handler-paths.js +52 -0
  183. package/packages/dd-trace/src/lambda/index.js +62 -14
  184. package/packages/dd-trace/src/lambda/runtime/patch.js +21 -46
  185. package/packages/dd-trace/src/llmobs/index.js +13 -2
  186. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -2
  187. package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +45 -15
  188. package/packages/dd-trace/src/llmobs/plugins/genai/util.js +6 -3
  189. package/packages/dd-trace/src/llmobs/sdk.js +24 -26
  190. package/packages/dd-trace/src/llmobs/span_processor.js +25 -5
  191. package/packages/dd-trace/src/llmobs/util.js +1 -0
  192. package/packages/dd-trace/src/llmobs/writers/base.js +2 -1
  193. package/packages/dd-trace/src/msgpack/chunk.js +6 -3
  194. package/packages/dd-trace/src/openfeature/noop.js +40 -36
  195. package/packages/dd-trace/src/openfeature/writers/base.js +2 -1
  196. package/packages/dd-trace/src/openfeature/writers/exposures.js +33 -52
  197. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +2 -1
  198. package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +1 -2
  199. package/packages/dd-trace/src/opentelemetry/tracer.js +0 -22
  200. package/packages/dd-trace/src/opentracing/propagation/text_map.js +20 -9
  201. package/packages/dd-trace/src/opentracing/propagation/text_map_dsm.js +2 -11
  202. package/packages/dd-trace/src/payload-tagging/config/index.js +2 -2
  203. package/packages/dd-trace/src/plugins/ci_plugin.js +49 -4
  204. package/packages/dd-trace/src/plugins/database.js +54 -12
  205. package/packages/dd-trace/src/plugins/index.js +1 -0
  206. package/packages/dd-trace/src/plugins/plugin.js +2 -4
  207. package/packages/dd-trace/src/plugins/util/ci.js +9 -9
  208. package/packages/dd-trace/src/plugins/util/git-cache.js +23 -23
  209. package/packages/dd-trace/src/plugins/util/stacktrace.js +2 -2
  210. package/packages/dd-trace/src/plugins/util/test.js +56 -12
  211. package/packages/dd-trace/src/plugins/util/url.js +1 -3
  212. package/packages/dd-trace/src/plugins/util/user-provided-git.js +18 -16
  213. package/packages/dd-trace/src/plugins/util/web.js +5 -7
  214. package/packages/dd-trace/src/priority_sampler.js +1 -1
  215. package/packages/dd-trace/src/profiling/profiler.js +1 -1
  216. package/packages/dd-trace/src/profiling/profilers/events.js +3 -23
  217. package/packages/dd-trace/src/profiling/profilers/wall.js +5 -6
  218. package/packages/dd-trace/src/profiling/ssi-heuristics.js +1 -1
  219. package/packages/dd-trace/src/rate_limiter.js +1 -1
  220. package/packages/dd-trace/src/remote_config/scheduler.js +1 -1
  221. package/packages/dd-trace/src/ritm.js +2 -1
  222. package/packages/dd-trace/src/runtime_metrics/index.js +2 -2
  223. package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +5 -8
  224. package/packages/dd-trace/src/scope.js +3 -10
  225. package/packages/dd-trace/src/serverless.js +6 -6
  226. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +27 -1
  227. package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
  228. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +24 -0
  229. package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
  230. package/packages/dd-trace/src/span_stats.js +1 -1
  231. package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
  232. package/packages/dd-trace/src/telemetry/endpoints.js +1 -1
  233. package/packages/dd-trace/src/telemetry/telemetry.js +2 -2
  234. package/packages/dd-trace/src/tracer.js +7 -7
  235. package/packages/dd-trace/src/lambda/runtime/ritm.js +0 -133
@@ -0,0 +1,82 @@
1
+ 'use strict'
2
+
3
+ const HttpClientPlugin = require('../../datadog-plugin-http/src/client')
4
+ const CompositePlugin = require('../../dd-trace/src/plugins/composite')
5
+
6
+ class ElectronNetPlugin extends CompositePlugin {
7
+ static id = 'electron:net'
8
+ static get plugins () {
9
+ return {
10
+ request: ElectronRequestPlugin,
11
+ }
12
+ }
13
+ }
14
+
15
+ class ElectronRequestPlugin extends HttpClientPlugin {
16
+ static id = 'electron:net:request'
17
+ static component = 'electron'
18
+ static operation = 'request'
19
+ static prefix = 'tracing:apm:electron:net:request'
20
+
21
+ bindStart (ctx) {
22
+ const args = ctx.args
23
+
24
+ let options = args[0]
25
+
26
+ if (typeof options === 'string') {
27
+ options = args[0] = { url: options }
28
+ } else if (!options) {
29
+ options = args[0] = {}
30
+ }
31
+
32
+ const headers = options.headers || {}
33
+
34
+ try {
35
+ if (typeof options === 'string') {
36
+ options = new URL(options)
37
+ } else if (options.url) {
38
+ options = new URL(options.url)
39
+ }
40
+ } catch {
41
+ // leave options as-is
42
+ }
43
+
44
+ options.headers = headers
45
+ ctx.args = { options }
46
+
47
+ const store = super.bindStart(ctx)
48
+
49
+ ctx.args = args
50
+
51
+ for (const name in options.headers) {
52
+ if (!headers[name]) {
53
+ args[0].headers ??= {}
54
+ args[0].headers[name] = options.headers[name]
55
+ }
56
+ }
57
+
58
+ return store
59
+ }
60
+
61
+ asyncStart (ctx) {
62
+ const reqHeaders = {}
63
+ const resHeaders = {}
64
+ const responseHead = ctx.res?._responseHead
65
+ const { statusCode } = responseHead || {}
66
+
67
+ for (const header in ctx.req._urlLoaderOptions?.headers || {}) {
68
+ reqHeaders[header.name] = header.value
69
+ }
70
+
71
+ for (const header in responseHead?.rawHeaders || {}) {
72
+ resHeaders[header.name] = header.value
73
+ }
74
+
75
+ ctx.req = { headers: reqHeaders }
76
+ ctx.res = { headers: resHeaders, statusCode }
77
+
78
+ this.finish(ctx)
79
+ }
80
+ }
81
+
82
+ module.exports = ElectronNetPlugin
@@ -122,8 +122,6 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
122
122
 
123
123
  const topicName = topic?.slice(topic.lastIndexOf('/') + 1) ??
124
124
  subscription.name.slice(subscription.name.lastIndexOf('/') + 1)
125
- const baseService = this.tracer._service || 'unknown'
126
- const serviceName = this.config.service || { name: `${baseService}-pubsub`, source: baseService }
127
125
 
128
126
  const meta = {
129
127
  'gcloud.project_id': subscription.pubsub.projectId,
@@ -133,8 +131,6 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
133
131
  'pubsub.subscription': subscription.name,
134
132
  'pubsub.subscription_type': 'pull',
135
133
  'messaging.operation': 'receive',
136
- base_service: baseService,
137
- service_override_type: 'custom',
138
134
  }
139
135
 
140
136
  if (batchRequestTraceId && batchRequestSpanId) {
@@ -168,7 +164,7 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
168
164
  childOf,
169
165
  resource: `Message from ${topicName}`,
170
166
  type: 'worker',
171
- service: serviceName,
167
+ service: this.config.service || this.serviceName(),
172
168
  meta,
173
169
  metrics,
174
170
  }, ctx)
@@ -54,9 +54,13 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
54
54
  * - Inject batch span context + metadata into all message attributes for downstream
55
55
  * consumers to reconstruct the trace and understand batch relationships
56
56
  */
57
- const spanLinkData = hasTraceContext
58
- ? messages.slice(1).map(msg => this.#extractSpanLink(msg.attributes)).filter(Boolean)
59
- : []
57
+ const spanLinkData = []
58
+ if (hasTraceContext) {
59
+ for (let i = 1; i < messageCount; i++) {
60
+ const link = this.#extractSpanLink(messages[i].attributes)
61
+ if (link) spanLinkData.push(link)
62
+ }
63
+ }
60
64
 
61
65
  const firstAttrs = messages[0]?.attributes
62
66
  const parentData = firstAttrs?.['x-datadog-trace-id'] && firstAttrs['x-datadog-parent-id']
@@ -107,35 +111,40 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
107
111
  ))
108
112
  }
109
113
 
110
- for (let i = 0; i < messages.length; i++) {
114
+ const messageCountStr = String(messageCount)
115
+ const startTimeStr = String(Math.floor(batchSpan._startTime))
116
+ const dsmEnabled = this.config.dsmEnabled
117
+
118
+ for (let i = 0; i < messageCount; i++) {
111
119
  const msg = messages[i]
112
- msg.attributes ??= {}
120
+ const attributes = msg.attributes ??= {}
113
121
 
114
122
  if (!hasTraceContext) {
115
- this.tracer.inject(batchSpan, 'text_map', msg.attributes)
123
+ this.tracer.inject(batchSpan, 'text_map', attributes)
116
124
  }
117
125
 
118
- Object.assign(msg.attributes, {
119
- '_dd.pubsub_request.trace_id': batchTraceIdHex,
120
- '_dd.pubsub_request.span_id': batchSpanIdHex,
121
- '_dd.batch.size': String(messageCount),
122
- '_dd.batch.index': String(i),
123
- 'gcloud.project_id': projectId,
124
- 'pubsub.topic': topic,
125
- 'x-dd-publish-start-time': String(Math.floor(batchSpan._startTime)),
126
- })
126
+ // Assign keys one-by-one rather than via `Object.assign({...})` so V8
127
+ // keeps the attributes object on its existing hidden class instead of
128
+ // allocating a fresh literal per message.
129
+ attributes['_dd.pubsub_request.trace_id'] = batchTraceIdHex
130
+ attributes['_dd.pubsub_request.span_id'] = batchSpanIdHex
131
+ attributes['_dd.batch.size'] = messageCountStr
132
+ attributes['_dd.batch.index'] = String(i)
133
+ attributes['gcloud.project_id'] = projectId
134
+ attributes['pubsub.topic'] = topic
135
+ attributes['x-dd-publish-start-time'] = startTimeStr
127
136
 
128
137
  if (batchTraceIdUpper) {
129
- msg.attributes['_dd.pubsub_request.p.tid'] = batchTraceIdUpper
138
+ attributes['_dd.pubsub_request.p.tid'] = batchTraceIdUpper
130
139
  }
131
140
 
132
- if (this.config.dsmEnabled) {
141
+ if (dsmEnabled) {
133
142
  const dataStreamsContext = this.tracer.setCheckpoint(
134
143
  ['direction:out', `topic:${topic}`, 'type:google-pubsub'],
135
144
  batchSpan,
136
145
  getHeadersSize(msg)
137
146
  )
138
- DsmPathwayCodec.encode(dataStreamsContext, msg.attributes)
147
+ DsmPathwayCodec.encode(dataStreamsContext, attributes)
139
148
  }
140
149
  }
141
150
 
@@ -10,6 +10,8 @@ const pushReceiveSpans = new WeakMap()
10
10
 
11
11
  class GoogleCloudPubsubPushSubscriptionPlugin extends TracingPlugin {
12
12
  static get id () { return 'google-cloud-pubsub-push-subscription' }
13
+ static type = 'messaging'
14
+ static kind = 'consumer'
13
15
 
14
16
  constructor (...args) {
15
17
  super(...args)
@@ -150,7 +152,7 @@ class GoogleCloudPubsubPushSubscriptionPlugin extends TracingPlugin {
150
152
  childOf: parentContext,
151
153
  startTime,
152
154
  kind: 'consumer',
153
- service: this.config.service || { name: `${this.tracer._service}-pubsub`, source: this.tracer._service },
155
+ service: this.config.service || this.serviceName(),
154
156
  meta: {
155
157
  component: 'google-cloud-pubsub',
156
158
  'pubsub.method': 'receive',
@@ -1,9 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
4
- const { extractErrorIntoSpanEvent } = require('./utils')
5
-
6
- let tools
4
+ const { extractErrorIntoSpanEvent, getSignature } = require('./utils')
7
5
 
8
6
  class GraphQLExecutePlugin extends TracingPlugin {
9
7
  static id = 'graphql'
@@ -54,35 +52,15 @@ class GraphQLExecutePlugin extends TracingPlugin {
54
52
  // span-related
55
53
 
56
54
  function addVariableTags (config, span, variableValues) {
57
- const tags = {}
55
+ if (!variableValues || !config.variables) return
58
56
 
59
- if (variableValues && config.variables) {
60
- const variables = config.variables(variableValues)
61
- for (const [param, value] of Object.entries(variables)) {
62
- tags[`graphql.variables.${param}`] = value
63
- }
57
+ const tags = {}
58
+ const variables = config.variables(variableValues)
59
+ for (const [param, value] of Object.entries(variables)) {
60
+ tags[`graphql.variables.${param}`] = value
64
61
  }
65
62
 
66
63
  span.addTags(tags)
67
64
  }
68
65
 
69
- function getSignature (document, operationName, operationType, calculate) {
70
- if (calculate !== false && tools !== false) {
71
- try {
72
- try {
73
- tools = tools || require('./tools')
74
- } catch (e) {
75
- tools = false
76
- throw e
77
- }
78
-
79
- return tools.defaultEngineReportingSignature(document, operationName)
80
- } catch {
81
- // safety net
82
- }
83
- }
84
-
85
- return [operationType, operationName].filter(Boolean).join(' ')
86
- }
87
-
88
66
  module.exports = GraphQLExecutePlugin
@@ -12,8 +12,6 @@ class GraphQLResolvePlugin extends TracingPlugin {
12
12
  start (fieldCtx) {
13
13
  const { info, rootCtx, args, path: pathAsArray, pathString } = fieldCtx
14
14
 
15
- const path = getPath(this.config, pathAsArray)
16
-
17
15
  // we need to get the parent span to the field if it exists for correct span parenting
18
16
  // of nested fields
19
17
  const parentField = getParentField(rootCtx, pathString)
@@ -21,8 +19,10 @@ class GraphQLResolvePlugin extends TracingPlugin {
21
19
 
22
20
  fieldCtx.parent = parentField
23
21
 
24
- if (!shouldInstrument(this.config, path)) return
25
- const computedPathString = path.join('.')
22
+ if (!shouldInstrument(this.config, pathAsArray)) return
23
+ const computedPathString = this.config.collapse
24
+ ? buildCollapsedPathString(pathAsArray)
25
+ : pathString
26
26
 
27
27
  if (this.config.collapse) {
28
28
  if (rootCtx.fields[computedPathString]) return
@@ -37,7 +37,7 @@ class GraphQLResolvePlugin extends TracingPlugin {
37
37
  }
38
38
 
39
39
  const document = rootCtx.source
40
- const fieldNode = info.fieldNodes.find(fieldNode => fieldNode.kind === 'Field')
40
+ const fieldNode = info.fieldNodes[0]
41
41
  const loc = this.config.source && document && fieldNode && fieldNode.loc
42
42
  const source = loc && document.slice(loc.start, loc.end)
43
43
 
@@ -78,9 +78,7 @@ class GraphQLResolvePlugin extends TracingPlugin {
78
78
  this.addTraceSub('updateField', (ctx) => {
79
79
  const { field, error, path: pathAsArray } = ctx
80
80
 
81
- const path = getPath(this.config, pathAsArray)
82
-
83
- if (!shouldInstrument(this.config, path)) return
81
+ if (!shouldInstrument(this.config, pathAsArray)) return
84
82
 
85
83
  const span = ctx?.currentStore?.span || this.activeSpan
86
84
  field.finishTime = span._getTime ? span._getTime() : 0
@@ -107,56 +105,53 @@ class GraphQLResolvePlugin extends TracingPlugin {
107
105
 
108
106
  // helpers
109
107
 
110
- function shouldInstrument (config, path) {
108
+ function shouldInstrument (config, pathAsArray) {
109
+ if (config.depth < 0) return true
110
+
111
111
  let depth = 0
112
- for (const item of path) {
113
- if (typeof item === 'string') {
114
- depth += 1
112
+ if (config.collapse) {
113
+ depth = pathAsArray.length
114
+ } else {
115
+ for (const segment of pathAsArray) {
116
+ if (typeof segment === 'string') depth += 1
115
117
  }
116
118
  }
117
119
 
118
- return config.depth < 0 || config.depth >= depth
119
- }
120
-
121
- function getPath (config, pathAsArray) {
122
- return config.collapse
123
- ? withCollapse(pathAsArray)
124
- : pathAsArray
120
+ return config.depth >= depth
125
121
  }
126
122
 
127
- function withCollapse (pathAsArray) {
128
- return pathAsArray.map(segment => typeof segment === 'number' ? '*' : segment)
123
+ function buildCollapsedPathString (pathAsArray) {
124
+ let result = ''
125
+ for (const segment of pathAsArray) {
126
+ if (result.length > 0) result += '.'
127
+ result += typeof segment === 'number' ? '*' : segment
128
+ }
129
+ return result
129
130
  }
130
131
 
131
132
  function getResolverInfo (info, args) {
132
- let resolverInfo = null
133
- const resolverVars = {}
133
+ let resolverVars
134
134
 
135
- if (args) {
136
- Object.assign(resolverVars, args)
135
+ if (args && Object.keys(args).length > 0) {
136
+ resolverVars = { ...args }
137
137
  }
138
138
 
139
- let hasResolvers = false
140
139
  const directives = info.fieldNodes?.[0]?.directives
141
140
  if (Array.isArray(directives)) {
142
141
  for (const directive of directives) {
142
+ if (directive.arguments.length === 0) continue
143
+
143
144
  const argList = {}
144
145
  for (const argument of directive.arguments) {
145
146
  argList[argument.name.value] = argument.value.value
146
147
  }
147
148
 
148
- if (directive.arguments.length > 0) {
149
- hasResolvers = true
150
- resolverVars[directive.name.value] = argList
151
- }
149
+ resolverVars ??= {}
150
+ resolverVars[directive.name.value] = argList
152
151
  }
153
152
  }
154
153
 
155
- if (hasResolvers || args && Object.keys(resolverVars).length) {
156
- resolverInfo = { [info.fieldName]: resolverVars }
157
- }
158
-
159
- return resolverInfo
154
+ return resolverVars === undefined ? null : { [info.fieldName]: resolverVars }
160
155
  }
161
156
 
162
157
  function getParentField (parentCtx, pathToString) {
@@ -1,9 +1,34 @@
1
- // file mostly untouched from apollo-graphql
1
+ 'use strict'
2
2
 
3
- "use strict";
4
- Object.defineProperty(exports, "__esModule", { value: true });
5
- const transforms_1 = require("./transforms");
6
- function defaultEngineReportingSignature(ast, operationName) {
7
- return transforms_1.printWithReducedWhitespace(transforms_1.sortAST(transforms_1.removeAliases(transforms_1.hideLiterals(transforms_1.dropUnusedDefinitions(ast, operationName)))));
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+ const transforms = require('./transforms')
5
+
6
+ // Apollo Server / Yoga / Mercurius hand back the same parsed `DocumentNode`
7
+ // from their own document caches per execute, so memoizing the signature on
8
+ // the document keeps the visit/print pipeline off the hot path. The inner
9
+ // Map keys on operationName since `separateOperations` picks a different
10
+ // sub-document for each operation.
11
+ const cache = new WeakMap()
12
+
13
+ function defaultEngineReportingSignature (ast, operationName) {
14
+ const key = operationName == null ? '' : operationName
15
+ let inner = cache.get(ast)
16
+ if (inner !== undefined) {
17
+ const cached = inner.get(key)
18
+ if (cached !== undefined) {
19
+ return cached
20
+ }
21
+ }
22
+ const signature = transforms.printWithReducedWhitespace(
23
+ transforms.transformForSignature(
24
+ transforms.dropUnusedDefinitions(ast, operationName)
25
+ )
26
+ )
27
+ if (inner === undefined) {
28
+ inner = new Map()
29
+ cache.set(ast, inner)
30
+ }
31
+ inner.set(key, signature)
32
+ return signature
8
33
  }
9
- exports.defaultEngineReportingSignature = defaultEngineReportingSignature;
34
+ exports.defaultEngineReportingSignature = defaultEngineReportingSignature
@@ -1,108 +1,126 @@
1
- // file mostly untouched from apollo-graphql
1
+ 'use strict'
2
2
 
3
- "use strict";
4
- var __importDefault = (this && this.__importDefault) || function (mod) {
5
- return (mod && mod.__esModule) ? mod : { "default": mod };
6
- };
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- const ddGlobal = globalThis[Symbol.for('dd-trace')];
9
- const visitor_1 = ddGlobal.graphql_visitor;
10
- const printer_1 = ddGlobal.graphql_printer;
11
- const utilities_1 = ddGlobal.graphql_utilities;
12
- const lodash_sortby_1 = __importDefault(require("../../../../vendor/dist/lodash.sortby"));
13
- function hideLiterals(ast) {
14
- return visitor_1.visit(ast, {
15
- IntValue(node) {
16
- return Object.assign({}, node, { value: "0" });
17
- },
18
- FloatValue(node) {
19
- return Object.assign({}, node, { value: "0" });
20
- },
21
- StringValue(node) {
22
- return Object.assign({}, node, { value: "", block: false });
23
- },
24
- ListValue(node) {
25
- return Object.assign({}, node, { values: [] });
26
- },
27
- ObjectValue(node) {
28
- return Object.assign({}, node, { fields: [] });
29
- }
30
- });
3
+ Object.defineProperty(exports, '__esModule', { value: true })
4
+
5
+ const ddGlobal = globalThis[Symbol.for('dd-trace')]
6
+ const visitor = ddGlobal.graphql_visitor
7
+ const printer = ddGlobal.graphql_printer
8
+ const utilities = ddGlobal.graphql_utilities
9
+
10
+ function dropUnusedDefinitions (ast, operationName) {
11
+ const separated = utilities.separateOperations(ast)[operationName]
12
+ if (!separated) {
13
+ return ast
14
+ }
15
+ return separated
31
16
  }
32
- exports.hideLiterals = hideLiterals;
33
- function hideStringAndNumericLiterals(ast) {
34
- return visitor_1.visit(ast, {
35
- IntValue(node) {
36
- return Object.assign({}, node, { value: "0" });
37
- },
38
- FloatValue(node) {
39
- return Object.assign({}, node, { value: "0" });
40
- },
41
- StringValue(node) {
42
- return Object.assign({}, node, { value: "", block: false });
43
- }
44
- });
17
+
18
+ // One walk replaces Apollo's `hideLiterals` + `removeAliases` + `sortAST` +
19
+ // the `StringValue` pre-pass that used to live in `printWithReducedWhitespace`.
20
+ // The byte output is unchanged: hideLiterals had already collapsed every
21
+ // `StringValue.value` to '', so the original hex round-trip degenerated to
22
+ // hex('') === '' anyway.
23
+ function transformForSignature (ast) {
24
+ return visitor.visit(ast, {
25
+ IntValue (node) {
26
+ return { ...node, value: '0' }
27
+ },
28
+ FloatValue (node) {
29
+ return { ...node, value: '0' }
30
+ },
31
+ StringValue (node) {
32
+ return { ...node, value: '', block: false }
33
+ },
34
+ ListValue (node) {
35
+ return { ...node, values: [] }
36
+ },
37
+ ObjectValue (node) {
38
+ return { ...node, fields: [] }
39
+ },
40
+ Field (node) {
41
+ return {
42
+ ...node,
43
+ alias: undefined,
44
+ arguments: sortByName(node.arguments),
45
+ }
46
+ },
47
+ OperationDefinition (node) {
48
+ return {
49
+ ...node,
50
+ variableDefinitions: sortByVariableName(node.variableDefinitions),
51
+ }
52
+ },
53
+ SelectionSet (node) {
54
+ return { ...node, selections: sortByKindThenName(node.selections) }
55
+ },
56
+ FragmentSpread (node) {
57
+ return { ...node, directives: sortByName(node.directives) }
58
+ },
59
+ InlineFragment (node) {
60
+ return { ...node, directives: sortByName(node.directives) }
61
+ },
62
+ FragmentDefinition (node) {
63
+ return {
64
+ ...node,
65
+ directives: sortByName(node.directives),
66
+ variableDefinitions: sortByVariableName(node.variableDefinitions),
67
+ }
68
+ },
69
+ Directive (node) {
70
+ return { ...node, arguments: sortByName(node.arguments) }
71
+ },
72
+ })
45
73
  }
46
- exports.hideStringAndNumericLiterals = hideStringAndNumericLiterals;
47
- function dropUnusedDefinitions(ast, operationName) {
48
- const separated = utilities_1.separateOperations(ast)[operationName];
49
- if (!separated) {
50
- return ast;
51
- }
52
- return separated;
74
+
75
+ function printWithReducedWhitespace (ast) {
76
+ return printer.print(ast)
77
+ .replaceAll(/\s+/g, ' ')
78
+ .replaceAll(/ (?=[^_a-zA-Z0-9])|(?<=[^_a-zA-Z0-9]) /g, '')
53
79
  }
54
- exports.dropUnusedDefinitions = dropUnusedDefinitions;
55
- function sorted(items) {
56
- if (items) {
57
- return lodash_sortby_1.default.apply(null, arguments);
58
- }
59
- return undefined;
80
+
81
+ function sortByName (items) {
82
+ if (!items) return
83
+ return [...items].sort(byName)
60
84
  }
61
- function sortAST(ast) {
62
- return visitor_1.visit(ast, {
63
- OperationDefinition(node) {
64
- return Object.assign({}, node, { variableDefinitions: sorted(node.variableDefinitions, "variable.name.value") });
65
- },
66
- SelectionSet(node) {
67
- return Object.assign({}, node, { selections: lodash_sortby_1.default(node.selections, "kind", "name.value") });
68
- },
69
- Field(node) {
70
- return Object.assign({}, node, { arguments: sorted(node.arguments, "name.value") });
71
- },
72
- FragmentSpread(node) {
73
- return Object.assign({}, node, { directives: sorted(node.directives, "name.value") });
74
- },
75
- InlineFragment(node) {
76
- return Object.assign({}, node, { directives: sorted(node.directives, "name.value") });
77
- },
78
- FragmentDefinition(node) {
79
- return Object.assign({}, node, { directives: sorted(node.directives, "name.value"), variableDefinitions: sorted(node.variableDefinitions, "variable.name.value") });
80
- },
81
- Directive(node) {
82
- return Object.assign({}, node, { arguments: sorted(node.arguments, "name.value") });
83
- }
84
- });
85
+
86
+ function byName (a, b) {
87
+ const left = a.name.value
88
+ const right = b.name.value
89
+ if (left < right) return -1
90
+ if (left > right) return 1
91
+ return 0
85
92
  }
86
- exports.sortAST = sortAST;
87
- function removeAliases(ast) {
88
- return visitor_1.visit(ast, {
89
- Field(node) {
90
- return Object.assign({}, node, { alias: undefined });
91
- }
92
- });
93
+
94
+ function sortByVariableName (items) {
95
+ if (!items) return
96
+ return [...items].sort(byVariableName)
93
97
  }
94
- exports.removeAliases = removeAliases;
95
- function printWithReducedWhitespace(ast) {
96
- const sanitizedAST = visitor_1.visit(ast, {
97
- StringValue(node) {
98
- return Object.assign({}, node, { value: Buffer.from(node.value, "utf8").toString("hex"), block: false });
99
- }
100
- });
101
- const withWhitespace = printer_1.print(sanitizedAST);
102
- const minimizedButStillHex = withWhitespace
103
- .replace(/\s+/g, " ")
104
- .replace(/([^_a-zA-Z0-9]) /g, (_, c) => c)
105
- .replace(/ ([^_a-zA-Z0-9])/g, (_, c) => c);
106
- return minimizedButStillHex.replace(/"([a-f0-9]+)"/g, (_, hex) => JSON.stringify(Buffer.from(hex, "hex").toString("utf8")));
98
+
99
+ function byVariableName (a, b) {
100
+ const left = a.variable.name.value
101
+ const right = b.variable.name.value
102
+ if (left < right) return -1
103
+ if (left > right) return 1
104
+ return 0
105
+ }
106
+
107
+ // SelectionSet children include InlineFragment, which has no `name`, so the
108
+ // secondary key falls back to undefined and stable sort keeps sibling order.
109
+ function sortByKindThenName (items) {
110
+ return [...items].sort(byKindThenName)
107
111
  }
108
- exports.printWithReducedWhitespace = printWithReducedWhitespace;
112
+
113
+ function byKindThenName (a, b) {
114
+ if (a.kind < b.kind) return -1
115
+ if (a.kind > b.kind) return 1
116
+ const left = a.name?.value
117
+ const right = b.name?.value
118
+ if (left === right) return 0
119
+ if (left === undefined) return 1
120
+ if (right === undefined) return -1
121
+ return left < right ? -1 : 1
122
+ }
123
+
124
+ exports.dropUnusedDefinitions = dropUnusedDefinitions
125
+ exports.transformForSignature = transformForSignature
126
+ exports.printWithReducedWhitespace = printWithReducedWhitespace