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
@@ -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
@@ -7,7 +7,10 @@ function extractErrorIntoSpanEvent (config, span, exc) {
7
7
  attributes.type = exc.name
8
8
  }
9
9
 
10
- if (exc.stack) {
10
+ // graphql-js validation errors carry a lazy `.stack` accessor; reading it
11
+ // here is the only consumer in the pipeline and pays full V8 symbolisation.
12
+ const isValidationOnly = exc.locations && !exc.path && !exc.originalError?.stack
13
+ if (!isValidationOnly && exc.stack) {
11
14
  attributes.stacktrace = exc.stack
12
15
  }
13
16
 
@@ -44,6 +47,35 @@ function extractErrorIntoSpanEvent (config, span, exc) {
44
47
  span.addEvent('dd.graphql.query.error', attributes, Date.now())
45
48
  }
46
49
 
50
+ let tools
51
+
52
+ function getSignature (document, operationName, operationType, calculate) {
53
+ if (calculate !== false && tools !== false) {
54
+ try {
55
+ try {
56
+ tools ||= require('./tools')
57
+ } catch (e) {
58
+ tools = false
59
+ throw e
60
+ }
61
+
62
+ return tools.defaultEngineReportingSignature(document, operationName)
63
+ } catch {
64
+ // safety net
65
+ }
66
+ }
67
+
68
+ if (operationType) {
69
+ if (operationName) {
70
+ return `${operationType} ${operationName}`
71
+ }
72
+ return operationType
73
+ }
74
+
75
+ return operationName ?? ''
76
+ }
77
+
47
78
  module.exports = {
48
79
  extractErrorIntoSpanEvent,
80
+ getSignature,
49
81
  }
@@ -86,12 +86,11 @@ class GrpcClientPlugin extends ClientPlugin {
86
86
  // The only scheme we want to support here is ipv[46]:port, although
87
87
  // more are supported by the library
88
88
  // https://github.com/grpc/grpc/blob/v1.60.0/doc/naming.md
89
- const parts = peer.split(':')
90
- if (/^\d+/.test(parts.at(-1))) {
91
- const port = parts.at(-1)
92
- const ip = parts.slice(0, -1).join(':')
93
- span.setTag('network.destination.ip', ip)
94
- span.setTag('network.destination.port', port)
89
+ const colonIndex = peer.lastIndexOf(':')
90
+ const tail = colonIndex === -1 ? '' : peer.slice(colonIndex + 1)
91
+ if (tail && /^\d+$/.test(tail)) {
92
+ span.setTag('network.destination.ip', peer.slice(0, colonIndex))
93
+ span.setTag('network.destination.port', tail)
95
94
  } else {
96
95
  span.setTag('network.destination.ip', peer)
97
96
  }
@@ -121,7 +120,7 @@ function inject (tracer, span, metadata) {
121
120
 
122
121
  tracer.inject(span, TEXT_MAP, carrier)
123
122
 
124
- for (const key in carrier) {
123
+ for (const key of Object.keys(carrier)) {
125
124
  metadata.set(key, carrier[key])
126
125
  }
127
126
  }
@@ -3,46 +3,81 @@
3
3
  const pick = require('../../datadog-core/src/utils/src/pick')
4
4
  const log = require('../../dd-trace/src/log')
5
5
 
6
+ /**
7
+ * @typedef {object} ParsedMethodPath
8
+ * @property {string} name
9
+ * @property {string} service
10
+ * @property {string} package
11
+ */
12
+
13
+ // Sentinel returned by `getFilter` when the user has not configured a metadata
14
+ // filter. `addMetadataTags` short-circuits on this identity to skip the
15
+ // `metadata.getMap()` clone in the default no-filter case.
6
16
  function getEmptyObject () {
7
17
  return {}
8
18
  }
9
19
 
10
- module.exports = {
11
- getMethodMetadata (path, kind) {
12
- const tags = {
13
- path,
14
- kind,
15
- name: '',
16
- service: '',
17
- package: '',
20
+ /**
21
+ * gRPC method paths are stable per service definition (e.g.
22
+ * `/pkg.Service/Method`); a service typically only has a small finite set.
23
+ * Cache the parsed `{name, service, package}` triple by path so we skip the
24
+ * `path.split('/')` + `serviceParts.split('.')` + `serviceParts.pop()` work
25
+ * on every call.
26
+ *
27
+ * @type {Map<string, ParsedMethodPath>}
28
+ */
29
+ const methodPathCache = new Map()
30
+
31
+ /**
32
+ * @param {string} path
33
+ * @returns {ParsedMethodPath}
34
+ */
35
+ function parseMethodPath (path) {
36
+ const methodParts = path.split('/')
37
+
38
+ if (methodParts.length > 2) {
39
+ const serviceParts = methodParts[1].split('.')
40
+ return {
41
+ name: methodParts[2],
42
+ service: serviceParts.pop(),
43
+ package: serviceParts.join('.'),
18
44
  }
45
+ }
19
46
 
20
- if (typeof path !== 'string') return tags
47
+ return { name: methodParts.at(-1), service: '', package: '' }
48
+ }
21
49
 
22
- const methodParts = path.split('/')
50
+ module.exports = {
51
+ getEmptyObject,
23
52
 
24
- if (methodParts.length > 2) {
25
- const serviceParts = methodParts[1].split('.')
26
- const name = methodParts[2]
27
- const service = serviceParts.pop()
28
- const pkg = serviceParts.join('.')
53
+ getMethodMetadata (path, kind) {
54
+ if (typeof path !== 'string') {
55
+ return { path, kind, name: '', service: '', package: '' }
56
+ }
29
57
 
30
- tags.name = name
31
- tags.service = service
32
- tags.package = pkg
33
- } else {
34
- tags.name = methodParts.at(-1)
58
+ let parsed = methodPathCache.get(path)
59
+ if (parsed === undefined) {
60
+ parsed = parseMethodPath(path)
61
+ methodPathCache.set(path, parsed)
35
62
  }
36
63
 
37
- return tags
64
+ return {
65
+ path,
66
+ kind,
67
+ name: parsed.name,
68
+ service: parsed.service,
69
+ package: parsed.package,
70
+ }
38
71
  },
39
72
 
40
73
  addMetadataTags (span, metadata, filter, type) {
41
74
  if (!metadata || typeof metadata.getMap !== 'function') return
75
+ // Default no-op filter: skip the full metadata clone via `getMap()`.
76
+ if (filter === getEmptyObject) return
42
77
 
43
78
  const values = filter(metadata.getMap())
44
79
 
45
- for (const key in values) {
80
+ for (const key of Object.keys(values)) {
46
81
  span.setTag(`grpc.${type}.metadata.${key}`, values[key])
47
82
  }
48
83
  },
@@ -39,10 +39,10 @@ class HttpClientPlugin extends ClientPlugin {
39
39
  // TODO delegate to super.startspan
40
40
  const span = this.startSpan(this.operationName(), {
41
41
  childOf,
42
- integrationName: this.constructor.id,
42
+ integrationName: this.component,
43
43
  service: this.serviceName({ pluginConfig: this.config, sessionDetails: extractSessionDetails(options) }),
44
44
  meta: {
45
- [COMPONENT]: this.constructor.id,
45
+ [COMPONENT]: this.component,
46
46
  'span.kind': 'client',
47
47
  'resource.name': method,
48
48
  'span.type': 'http',
@@ -21,6 +21,7 @@ const {
21
21
  TEST_SOURCE_START,
22
22
  TEST_ITR_UNSKIPPABLE,
23
23
  TEST_ITR_FORCED_RUN,
24
+ TEST_ITR_SKIPPING_ENABLED,
24
25
  TEST_CODE_OWNERS,
25
26
  ITR_CORRELATION_ID,
26
27
  TEST_SOURCE_FILE,
@@ -107,6 +108,7 @@ class JestPlugin extends CiPlugin {
107
108
  process.on('message', handler)
108
109
  }
109
110
  this.testSuiteSpanPerTestSuiteAbsolutePath = new Map()
111
+ this.pendingTestSuiteFinishes = new Set()
110
112
 
111
113
  this.addSub('ci:jest:session:finish', ({
112
114
  status,
@@ -123,58 +125,66 @@ class JestPlugin extends CiPlugin {
123
125
  isTestManagementTestsEnabled,
124
126
  onDone,
125
127
  }) => {
126
- this.testSessionSpan.setTag(TEST_STATUS, status)
127
- this.testModuleSpan.setTag(TEST_STATUS, status)
128
+ const finishSession = () => {
129
+ this.testSessionSpan.setTag(TEST_STATUS, status)
130
+ this.testModuleSpan.setTag(TEST_STATUS, status)
128
131
 
129
- if (error) {
130
- this.testSessionSpan.setTag('error', error)
131
- this.testModuleSpan.setTag('error', error)
132
- }
133
-
134
- addIntelligentTestRunnerSpanTags(
135
- this.testSessionSpan,
136
- this.testModuleSpan,
137
- {
138
- isSuitesSkipped,
139
- isSuitesSkippingEnabled,
140
- isCodeCoverageEnabled,
141
- testCodeCoverageLinesTotal,
142
- skippingType: 'suite',
143
- skippingCount: numSkippedSuites,
144
- hasUnskippableSuites,
145
- hasForcedToRunSuites,
132
+ if (error) {
133
+ this.testSessionSpan.setTag('error', error)
134
+ this.testModuleSpan.setTag('error', error)
146
135
  }
147
- )
148
136
 
149
- if (isEarlyFlakeDetectionEnabled) {
150
- this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
151
- }
152
- if (isEarlyFlakeDetectionFaulty) {
153
- this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'faulty')
154
- }
155
- if (isTestManagementTestsEnabled) {
156
- this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
157
- }
137
+ addIntelligentTestRunnerSpanTags(
138
+ this.testSessionSpan,
139
+ this.testModuleSpan,
140
+ {
141
+ isSuitesSkipped,
142
+ isSuitesSkippingEnabled,
143
+ isCodeCoverageEnabled,
144
+ testCodeCoverageLinesTotal,
145
+ skippingType: 'suite',
146
+ skippingCount: numSkippedSuites,
147
+ hasUnskippableSuites,
148
+ hasForcedToRunSuites,
149
+ }
150
+ )
158
151
 
159
- this.testModuleSpan.finish()
160
- this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
161
- this.testSessionSpan.finish()
162
- this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session', {
163
- hasFailedTestReplay: this.libraryConfig?.isDiEnabled || undefined,
164
- })
165
- finishAllTraceSpans(this.testSessionSpan)
152
+ if (isEarlyFlakeDetectionEnabled) {
153
+ this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ENABLED, 'true')
154
+ }
155
+ if (isEarlyFlakeDetectionFaulty) {
156
+ this.testSessionSpan.setTag(TEST_EARLY_FLAKE_ABORT_REASON, 'faulty')
157
+ }
158
+ if (isTestManagementTestsEnabled) {
159
+ this.testSessionSpan.setTag(TEST_MANAGEMENT_ENABLED, 'true')
160
+ }
166
161
 
167
- this.telemetry.count(TELEMETRY_TEST_SESSION, {
168
- provider: this.ciProviderName,
169
- autoInjected: !!this._tracerConfig.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
170
- })
162
+ this.testModuleSpan.finish()
163
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'module')
164
+ this.testSessionSpan.finish()
165
+ this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'session', {
166
+ hasFailedTestReplay: this.libraryConfig?.isDiEnabled || undefined,
167
+ })
168
+ finishAllTraceSpans(this.testSessionSpan)
169
+
170
+ this.telemetry.count(TELEMETRY_TEST_SESSION, {
171
+ provider: this.ciProviderName,
172
+ autoInjected: !!this._tracerConfig.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
173
+ })
174
+
175
+ appClosingTelemetry()
176
+ this.tracer._exporter.flush(() => {
177
+ if (onDone) {
178
+ onDone()
179
+ }
180
+ })
181
+ }
171
182
 
172
- appClosingTelemetry()
173
- this.tracer._exporter.flush(() => {
174
- if (onDone) {
175
- onDone()
176
- }
177
- })
183
+ if (this.pendingTestSuiteFinishes.size > 0) {
184
+ Promise.all(this.pendingTestSuiteFinishes).then(finishSession)
185
+ } else {
186
+ finishSession()
187
+ }
178
188
  })
179
189
 
180
190
  // Test suites can be run in a different process from jest's main one.
@@ -197,6 +207,7 @@ class JestPlugin extends CiPlugin {
197
207
  config._ddIsDiEnabled = this.libraryConfig?.isDiEnabled ?? false
198
208
  config._ddIsKnownTestsEnabled = this.libraryConfig?.isKnownTestsEnabled ?? false
199
209
  config._ddIsImpactedTestsEnabled = this.libraryConfig?.isImpactedTestsEnabled ?? false
210
+ config._ddItrSkippingEnabledTags = this.getSessionItrSkippingEnabledTags()
200
211
  }
201
212
  })
202
213
 
@@ -217,6 +228,7 @@ class JestPlugin extends CiPlugin {
217
228
  _ddForcedToRun,
218
229
  _ddUnskippable,
219
230
  _ddTestCodeCoverageEnabled,
231
+ _ddItrSkippingEnabledTags: itrSkippingEnabledTags,
220
232
  } = testEnvironmentOptions
221
233
 
222
234
  const testSessionSpanContext = this.tracer.extract('text_map', {
@@ -228,6 +240,7 @@ class JestPlugin extends CiPlugin {
228
240
  ...getTestSuiteCommonTags(testCommand, frameworkVersion, testSuite, 'jest'),
229
241
  // requestErrorTags from test env options may be undefined
230
242
  ...(requestErrorTags !== undefined && requestErrorTags !== null ? requestErrorTags : {}),
243
+ ...(itrSkippingEnabledTags !== undefined && itrSkippingEnabledTags !== null ? itrSkippingEnabledTags : {}),
231
244
  }
232
245
 
233
246
  if (_ddUnskippable) {
@@ -305,10 +318,18 @@ class JestPlugin extends CiPlugin {
305
318
  }
306
319
  })
307
320
 
308
- this.addSub('ci:jest:test-suite:finish', ({ status, errorMessage, error, testSuiteAbsolutePath }) => {
321
+ this.addSub('ci:jest:test-suite:finish', ({
322
+ status,
323
+ errorMessage,
324
+ error,
325
+ testSuiteAbsolutePath,
326
+ waitForFinish,
327
+ onDone,
328
+ }) => {
309
329
  const testSuiteSpan = this.testSuiteSpanPerTestSuiteAbsolutePath.get(testSuiteAbsolutePath)
310
330
  if (!testSuiteSpan) {
311
331
  log.warn('"ci:jest:test-suite:finish": no span found for test suite absolute path %s', testSuiteAbsolutePath)
332
+ onDone?.()
312
333
  return
313
334
  }
314
335
  testSuiteSpan.setTag(TEST_STATUS, status)
@@ -319,8 +340,13 @@ class JestPlugin extends CiPlugin {
319
340
  testSuiteSpan.setTag('error', new Error(errorMessage))
320
341
  testSuiteSpan.setTag(TEST_STATUS, 'fail')
321
342
  }
322
- // We need to give the potential error in 'ci:jest:test-suite:error' time to be published
323
- process.nextTick(() => {
343
+ let resolvePendingFinish
344
+ const pendingFinish = new Promise(resolve => {
345
+ resolvePendingFinish = resolve
346
+ })
347
+ this.pendingTestSuiteFinishes.add(pendingFinish)
348
+
349
+ const finish = () => {
324
350
  testSuiteSpan.finish()
325
351
  this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'suite')
326
352
  // Suites potentially run in a different process than the session,
@@ -334,7 +360,19 @@ class JestPlugin extends CiPlugin {
334
360
  }
335
361
  this.removeAllDiProbes()
336
362
  this.testSuiteSpanPerTestSuiteAbsolutePath.delete(testSuiteAbsolutePath)
337
- })
363
+ this.pendingTestSuiteFinishes.delete(pendingFinish)
364
+ resolvePendingFinish()
365
+ if (onDone) {
366
+ onDone()
367
+ }
368
+ }
369
+
370
+ if (waitForFinish) {
371
+ // Give late async work time to run before Jest restarts a worker because of workerIdleMemoryLimit.
372
+ realSetTimeout(finish)
373
+ } else {
374
+ process.nextTick(finish)
375
+ }
338
376
  })
339
377
 
340
378
  this.addSub('ci:jest:test-suite:error', ({ error, errorMessage, testSuiteAbsolutePath }) => {
@@ -558,6 +596,10 @@ class JestPlugin extends CiPlugin {
558
596
  extraTags[TEST_HAS_DYNAMIC_NAME] = 'true'
559
597
  }
560
598
  const testSuiteSpan = this.testSuiteSpanPerTestSuiteAbsolutePath.get(testSuiteAbsolutePath) || this.testSuiteSpan
599
+ const skippingEnabled = testSuiteSpan?.context()._tags?.[TEST_ITR_SKIPPING_ENABLED]
600
+ if (skippingEnabled !== undefined) {
601
+ extraTags[TEST_ITR_SKIPPING_ENABLED] = skippingEnabled
602
+ }
561
603
 
562
604
  return super.startTestSpan(name, suite, testSuiteSpan, extraTags)
563
605
  }