dd-trace 5.103.0 → 5.105.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (213) hide show
  1. package/LICENSE-3rdparty.csv +90 -102
  2. package/index.d.ts +107 -6
  3. package/package.json +18 -17
  4. package/packages/datadog-core/src/storage.js +1 -1
  5. package/packages/datadog-instrumentations/src/aerospike.js +1 -1
  6. package/packages/datadog-instrumentations/src/ai.js +8 -7
  7. package/packages/datadog-instrumentations/src/aws-sdk.js +15 -2
  8. package/packages/datadog-instrumentations/src/azure-cosmos.js +7 -0
  9. package/packages/datadog-instrumentations/src/azure-functions.js +3 -0
  10. package/packages/datadog-instrumentations/src/cassandra-driver.js +5 -2
  11. package/packages/datadog-instrumentations/src/cucumber.js +181 -35
  12. package/packages/datadog-instrumentations/src/dns.js +54 -18
  13. package/packages/datadog-instrumentations/src/elasticsearch.js +4 -4
  14. package/packages/datadog-instrumentations/src/fastify.js +142 -82
  15. package/packages/datadog-instrumentations/src/graphql.js +188 -67
  16. package/packages/datadog-instrumentations/src/grpc/client.js +48 -32
  17. package/packages/datadog-instrumentations/src/helpers/ai-messages.js +322 -14
  18. package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +1 -1
  19. package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
  20. package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -1
  21. package/packages/datadog-instrumentations/src/helpers/kafka.js +17 -0
  22. package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +269 -0
  23. package/packages/datadog-instrumentations/src/helpers/promise-instrumentor.js +42 -0
  24. package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
  25. package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +3 -2
  26. package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +19 -6
  27. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-cosmos.js +50 -0
  28. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
  29. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langgraph.js +4 -2
  30. package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +85 -0
  31. package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +31 -229
  32. package/packages/datadog-instrumentations/src/hono.js +54 -3
  33. package/packages/datadog-instrumentations/src/http/client.js +2 -2
  34. package/packages/datadog-instrumentations/src/http/server.js +9 -4
  35. package/packages/datadog-instrumentations/src/ioredis.js +3 -3
  36. package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +163 -0
  37. package/packages/datadog-instrumentations/src/jest.js +390 -183
  38. package/packages/datadog-instrumentations/src/kafkajs.js +140 -17
  39. package/packages/datadog-instrumentations/src/mariadb.js +1 -1
  40. package/packages/datadog-instrumentations/src/memcached.js +2 -1
  41. package/packages/datadog-instrumentations/src/mocha/main.js +399 -107
  42. package/packages/datadog-instrumentations/src/mocha/utils.js +48 -8
  43. package/packages/datadog-instrumentations/src/mongodb-core.js +1 -1
  44. package/packages/datadog-instrumentations/src/mongoose.js +10 -12
  45. package/packages/datadog-instrumentations/src/mysql.js +2 -2
  46. package/packages/datadog-instrumentations/src/mysql2.js +1 -1
  47. package/packages/datadog-instrumentations/src/nats.js +182 -0
  48. package/packages/datadog-instrumentations/src/nyc.js +38 -1
  49. package/packages/datadog-instrumentations/src/openai.js +33 -18
  50. package/packages/datadog-instrumentations/src/oracledb.js +6 -1
  51. package/packages/datadog-instrumentations/src/pg.js +1 -1
  52. package/packages/datadog-instrumentations/src/pino.js +17 -5
  53. package/packages/datadog-instrumentations/src/playwright.js +537 -297
  54. package/packages/datadog-instrumentations/src/router.js +80 -34
  55. package/packages/datadog-instrumentations/src/stripe.js +1 -1
  56. package/packages/datadog-instrumentations/src/vitest.js +246 -149
  57. package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
  58. package/packages/datadog-plugin-azure-cosmos/src/index.js +144 -0
  59. package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -1
  60. package/packages/datadog-plugin-azure-functions/src/index.js +5 -2
  61. package/packages/datadog-plugin-azure-service-bus/src/producer.js +1 -1
  62. package/packages/datadog-plugin-bunyan/src/index.js +28 -0
  63. package/packages/datadog-plugin-cucumber/src/index.js +17 -3
  64. package/packages/datadog-plugin-cypress/src/cypress-plugin.js +223 -45
  65. package/packages/datadog-plugin-cypress/src/support.js +69 -1
  66. package/packages/datadog-plugin-dns/src/lookup.js +8 -6
  67. package/packages/datadog-plugin-elasticsearch/src/index.js +28 -8
  68. package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +1 -1
  69. package/packages/datadog-plugin-graphql/src/execute.js +2 -0
  70. package/packages/datadog-plugin-graphql/src/resolve.js +64 -67
  71. package/packages/datadog-plugin-graphql/src/utils.js +4 -1
  72. package/packages/datadog-plugin-http/src/server.js +40 -15
  73. package/packages/datadog-plugin-jest/src/index.js +11 -3
  74. package/packages/datadog-plugin-jest/src/util.js +15 -8
  75. package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
  76. package/packages/datadog-plugin-kafkajs/src/producer.js +35 -0
  77. package/packages/datadog-plugin-langgraph/src/stream.js +1 -1
  78. package/packages/datadog-plugin-mocha/src/index.js +19 -4
  79. package/packages/datadog-plugin-mongodb-core/src/index.js +311 -35
  80. package/packages/datadog-plugin-nats/src/consumer.js +43 -0
  81. package/packages/datadog-plugin-nats/src/index.js +20 -0
  82. package/packages/datadog-plugin-nats/src/producer.js +62 -0
  83. package/packages/datadog-plugin-nats/src/util.js +33 -0
  84. package/packages/datadog-plugin-next/src/index.js +5 -3
  85. package/packages/datadog-plugin-openai/src/tracing.js +15 -2
  86. package/packages/datadog-plugin-oracledb/src/index.js +13 -2
  87. package/packages/datadog-plugin-pino/src/index.js +42 -0
  88. package/packages/datadog-plugin-playwright/src/index.js +4 -4
  89. package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
  90. package/packages/datadog-plugin-redis/src/index.js +37 -2
  91. package/packages/datadog-plugin-rhea/src/producer.js +1 -1
  92. package/packages/datadog-plugin-router/src/index.js +33 -44
  93. package/packages/datadog-plugin-selenium/src/index.js +1 -1
  94. package/packages/datadog-plugin-undici/src/index.js +19 -0
  95. package/packages/datadog-plugin-vitest/src/index.js +24 -20
  96. package/packages/datadog-plugin-winston/src/index.js +30 -0
  97. package/packages/datadog-shimmer/src/shimmer.js +49 -21
  98. package/packages/dd-trace/src/aiguard/index.js +1 -1
  99. package/packages/dd-trace/src/aiguard/sdk.js +1 -1
  100. package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
  101. package/packages/dd-trace/src/appsec/blocking.js +2 -2
  102. package/packages/dd-trace/src/appsec/index.js +11 -4
  103. package/packages/dd-trace/src/appsec/reporter.js +24 -11
  104. package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
  105. package/packages/dd-trace/src/appsec/sdk/utils.js +1 -1
  106. package/packages/dd-trace/src/appsec/user_tracking.js +5 -4
  107. package/packages/dd-trace/src/baggage.js +7 -1
  108. package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +0 -1
  109. package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +25 -13
  110. package/packages/dd-trace/src/ci-visibility/requests/request.js +3 -1
  111. package/packages/dd-trace/src/ci-visibility/test-api-manual/test-api-manual-plugin.js +5 -3
  112. package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +70 -6
  113. package/packages/dd-trace/src/config/generated-config-types.d.ts +7 -2
  114. package/packages/dd-trace/src/config/supported-configurations.json +36 -8
  115. package/packages/dd-trace/src/crashtracking/crashtracker.js +15 -3
  116. package/packages/dd-trace/src/datastreams/context.js +4 -2
  117. package/packages/dd-trace/src/datastreams/writer.js +2 -4
  118. package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -8
  119. package/packages/dd-trace/src/encode/0.4.js +124 -108
  120. package/packages/dd-trace/src/encode/0.5.js +114 -26
  121. package/packages/dd-trace/src/encode/agentless-ci-visibility.js +57 -42
  122. package/packages/dd-trace/src/encode/agentless-json.js +4 -2
  123. package/packages/dd-trace/src/encode/coverage-ci-visibility.js +32 -13
  124. package/packages/dd-trace/src/encode/span-stats.js +16 -16
  125. package/packages/dd-trace/src/encode/tags-processors.js +16 -0
  126. package/packages/dd-trace/src/exporters/common/agents.js +3 -1
  127. package/packages/dd-trace/src/exporters/common/request.js +3 -1
  128. package/packages/dd-trace/src/id.js +17 -4
  129. package/packages/dd-trace/src/lambda/handler.js +2 -4
  130. package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
  131. package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
  132. package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
  133. package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +9 -7
  134. package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
  135. package/packages/dd-trace/src/llmobs/plugins/openai/index.js +1 -1
  136. package/packages/dd-trace/src/llmobs/sdk.js +10 -16
  137. package/packages/dd-trace/src/llmobs/span_processor.js +3 -3
  138. package/packages/dd-trace/src/llmobs/tagger.js +9 -1
  139. package/packages/dd-trace/src/llmobs/telemetry.js +1 -1
  140. package/packages/dd-trace/src/llmobs/util.js +66 -3
  141. package/packages/dd-trace/src/log/index.js +1 -1
  142. package/packages/dd-trace/src/log/writer.js +3 -1
  143. package/packages/dd-trace/src/msgpack/chunk.js +394 -10
  144. package/packages/dd-trace/src/msgpack/index.js +96 -2
  145. package/packages/dd-trace/src/noop/span.js +3 -1
  146. package/packages/dd-trace/src/openfeature/encoding.js +70 -0
  147. package/packages/dd-trace/src/openfeature/flagging_provider.js +20 -0
  148. package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +143 -0
  149. package/packages/dd-trace/src/openfeature/span-enrichment.js +149 -0
  150. package/packages/dd-trace/src/openfeature/writers/exposures.js +51 -20
  151. package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +1 -1
  152. package/packages/dd-trace/src/opentelemetry/span-helpers.js +4 -3
  153. package/packages/dd-trace/src/opentelemetry/span.js +1 -1
  154. package/packages/dd-trace/src/opentracing/propagation/log.js +18 -7
  155. package/packages/dd-trace/src/opentracing/propagation/text_map.js +62 -67
  156. package/packages/dd-trace/src/opentracing/span.js +59 -19
  157. package/packages/dd-trace/src/opentracing/span_context.js +49 -0
  158. package/packages/dd-trace/src/plugins/apollo.js +3 -1
  159. package/packages/dd-trace/src/plugins/ci_plugin.js +23 -33
  160. package/packages/dd-trace/src/plugins/database.js +7 -6
  161. package/packages/dd-trace/src/plugins/index.js +4 -0
  162. package/packages/dd-trace/src/plugins/log_injection.js +56 -0
  163. package/packages/dd-trace/src/plugins/log_plugin.js +3 -46
  164. package/packages/dd-trace/src/plugins/outbound.js +1 -1
  165. package/packages/dd-trace/src/plugins/plugin.js +15 -17
  166. package/packages/dd-trace/src/plugins/tracing.js +48 -8
  167. package/packages/dd-trace/src/plugins/util/git.js +3 -1
  168. package/packages/dd-trace/src/plugins/util/test.js +318 -13
  169. package/packages/dd-trace/src/plugins/util/web.js +89 -64
  170. package/packages/dd-trace/src/priority_sampler.js +2 -2
  171. package/packages/dd-trace/src/profiling/profiler.js +2 -2
  172. package/packages/dd-trace/src/profiling/profilers/wall.js +10 -4
  173. package/packages/dd-trace/src/sampling_rule.js +7 -7
  174. package/packages/dd-trace/src/scope.js +7 -5
  175. package/packages/dd-trace/src/service-naming/extra-services.js +14 -0
  176. package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +10 -0
  177. package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
  178. package/packages/dd-trace/src/service-naming/source-resolver.js +46 -0
  179. package/packages/dd-trace/src/span_format.js +190 -58
  180. package/packages/dd-trace/src/spanleak.js +1 -1
  181. package/packages/dd-trace/src/standalone/index.js +3 -3
  182. package/packages/dd-trace/src/tagger.js +0 -2
  183. package/vendor/dist/@apm-js-collab/code-transformer/index.js +70 -39
  184. package/vendor/dist/@datadog/sketches-js/LICENSE +10 -36
  185. package/vendor/dist/@datadog/sketches-js/index.js +1 -1
  186. package/vendor/dist/protobufjs/index.js +1 -1
  187. package/vendor/dist/protobufjs/minimal/index.js +1 -1
  188. package/packages/dd-trace/src/msgpack/encoder.js +0 -308
  189. package/packages/dd-trace/src/plugins/structured_log_plugin.js +0 -9
  190. package/vendor/dist/opentracing/LICENSE +0 -201
  191. package/vendor/dist/opentracing/binary_carrier.d.ts +0 -11
  192. package/vendor/dist/opentracing/constants.d.ts +0 -61
  193. package/vendor/dist/opentracing/examples/demo/demo.d.ts +0 -2
  194. package/vendor/dist/opentracing/ext/tags.d.ts +0 -90
  195. package/vendor/dist/opentracing/functions.d.ts +0 -20
  196. package/vendor/dist/opentracing/global_tracer.d.ts +0 -14
  197. package/vendor/dist/opentracing/index.d.ts +0 -12
  198. package/vendor/dist/opentracing/index.js +0 -1
  199. package/vendor/dist/opentracing/mock_tracer/index.d.ts +0 -5
  200. package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +0 -13
  201. package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +0 -16
  202. package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +0 -50
  203. package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +0 -26
  204. package/vendor/dist/opentracing/noop.d.ts +0 -8
  205. package/vendor/dist/opentracing/reference.d.ts +0 -33
  206. package/vendor/dist/opentracing/span.d.ts +0 -147
  207. package/vendor/dist/opentracing/span_context.d.ts +0 -26
  208. package/vendor/dist/opentracing/test/api_compatibility.d.ts +0 -16
  209. package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +0 -3
  210. package/vendor/dist/opentracing/test/noop_implementation.d.ts +0 -4
  211. package/vendor/dist/opentracing/test/opentracing_api.d.ts +0 -3
  212. package/vendor/dist/opentracing/test/unittest.d.ts +0 -2
  213. package/vendor/dist/opentracing/tracer.d.ts +0 -127
@@ -7,8 +7,9 @@ const {
7
7
  TELEMETRY_ENDPOINT_PAYLOAD_SERIALIZATION_MS,
8
8
  TELEMETRY_ENDPOINT_PAYLOAD_EVENTS_COUNT,
9
9
  } = require('../ci-visibility/telemetry')
10
+ const { MsgpackChunk } = require('../msgpack')
10
11
  const { AgentEncoder } = require('./0.4')
11
- const { truncateSpan, normalizeSpan } = require('./tags-processors')
12
+ const { truncateSpanTestOpt, normalizeSpan } = require('./tags-processors')
12
13
 
13
14
  const ENCODING_VERSION = 1
14
15
  const ALLOWED_CONTENT_TYPES = new Set(['test_session_end', 'test_module_end', 'test_suite_end', 'test'])
@@ -20,6 +21,9 @@ const TEST_AND_SPAN_KEYS_LENGTH = 11
20
21
 
21
22
  const INTAKE_SOFT_LIMIT = 2 * 1024 * 1024 // 2MB
22
23
 
24
+ // Prefix is ~1 KB in practice; `MsgpackChunk` resizes on overflow.
25
+ const PREFIX_CHUNK_INITIAL_SIZE = 2048
26
+
23
27
  function formatSpan (span) {
24
28
  let encodingVersion = ENCODING_VERSION
25
29
  if (span.type === 'test' && span.meta && span.meta.test_session_id) {
@@ -28,7 +32,7 @@ function formatSpan (span) {
28
32
  return {
29
33
  type: ALLOWED_CONTENT_TYPES.has(span.type) ? span.type : 'span',
30
34
  version: encodingVersion,
31
- content: normalizeSpan(truncateSpan(span)),
35
+ content: normalizeSpan(truncateSpanTestOpt(span)),
32
36
  }
33
37
  }
34
38
 
@@ -44,11 +48,18 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
44
48
  this._eventCount = 0
45
49
 
46
50
  this.metadataTags = {}
51
+ this.wildcardMetadataTags = {}
47
52
 
48
53
  this.reset()
49
54
  }
50
55
 
51
56
  addMetadataTags (tags) {
57
+ if (tags['*']) {
58
+ this.wildcardMetadataTags = {
59
+ ...this.wildcardMetadataTags,
60
+ ...tags['*'],
61
+ }
62
+ }
52
63
  for (const type of ALLOWED_CONTENT_TYPES) {
53
64
  if (tags[type]) {
54
65
  this.metadataTags[type] = {
@@ -66,7 +77,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
66
77
  keysLength++
67
78
  }
68
79
 
69
- this._encodeMapPrefix(bytes, keysLength)
80
+ bytes.writeMapPrefix(keysLength)
70
81
  this._encodeString(bytes, 'type')
71
82
  this._encodeString(bytes, content.type)
72
83
 
@@ -86,7 +97,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
86
97
  }
87
98
 
88
99
  this._encodeString(bytes, 'error')
89
- this._encodeNumber(bytes, content.error)
100
+ bytes.writeNumber(content.error)
90
101
  this._encodeString(bytes, 'name')
91
102
  this._encodeString(bytes, content.name)
92
103
  this._encodeString(bytes, 'service')
@@ -94,9 +105,9 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
94
105
  this._encodeString(bytes, 'resource')
95
106
  this._encodeString(bytes, content.resource)
96
107
  this._encodeString(bytes, 'start')
97
- this._encodeNumber(bytes, content.start)
108
+ bytes.writeNumber(content.start)
98
109
  this._encodeString(bytes, 'duration')
99
- this._encodeNumber(bytes, content.duration)
110
+ bytes.writeNumber(content.duration)
100
111
  this._encodeString(bytes, 'meta')
101
112
  this._encodeMap(bytes, content.meta)
102
113
  this._encodeString(bytes, 'metrics')
@@ -104,7 +115,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
104
115
  }
105
116
 
106
117
  _encodeTestModule (bytes, content) {
107
- this._encodeMapPrefix(bytes, TEST_MODULE_KEYS_LENGTH)
118
+ bytes.writeMapPrefix(TEST_MODULE_KEYS_LENGTH)
108
119
  this._encodeString(bytes, 'type')
109
120
  this._encodeString(bytes, content.type)
110
121
 
@@ -115,7 +126,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
115
126
  this._encodeId(bytes, content.span_id)
116
127
 
117
128
  this._encodeString(bytes, 'error')
118
- this._encodeNumber(bytes, content.error)
129
+ bytes.writeNumber(content.error)
119
130
  this._encodeString(bytes, 'name')
120
131
  this._encodeString(bytes, content.name)
121
132
  this._encodeString(bytes, 'service')
@@ -123,9 +134,9 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
123
134
  this._encodeString(bytes, 'resource')
124
135
  this._encodeString(bytes, content.resource)
125
136
  this._encodeString(bytes, 'start')
126
- this._encodeNumber(bytes, content.start)
137
+ bytes.writeNumber(content.start)
127
138
  this._encodeString(bytes, 'duration')
128
- this._encodeNumber(bytes, content.duration)
139
+ bytes.writeNumber(content.duration)
129
140
  this._encodeString(bytes, 'meta')
130
141
  this._encodeMap(bytes, content.meta)
131
142
  this._encodeString(bytes, 'metrics')
@@ -133,7 +144,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
133
144
  }
134
145
 
135
146
  _encodeTestSession (bytes, content) {
136
- this._encodeMapPrefix(bytes, TEST_SESSION_KEYS_LENGTH)
147
+ bytes.writeMapPrefix(TEST_SESSION_KEYS_LENGTH)
137
148
  this._encodeString(bytes, 'type')
138
149
  this._encodeString(bytes, content.type)
139
150
 
@@ -141,7 +152,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
141
152
  this._encodeId(bytes, content.trace_id)
142
153
 
143
154
  this._encodeString(bytes, 'error')
144
- this._encodeNumber(bytes, content.error)
155
+ bytes.writeNumber(content.error)
145
156
  this._encodeString(bytes, 'name')
146
157
  this._encodeString(bytes, content.name)
147
158
  this._encodeString(bytes, 'service')
@@ -149,9 +160,9 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
149
160
  this._encodeString(bytes, 'resource')
150
161
  this._encodeString(bytes, content.resource)
151
162
  this._encodeString(bytes, 'start')
152
- this._encodeNumber(bytes, content.start)
163
+ bytes.writeNumber(content.start)
153
164
  this._encodeString(bytes, 'duration')
154
- this._encodeNumber(bytes, content.duration)
165
+ bytes.writeNumber(content.duration)
155
166
  this._encodeString(bytes, 'meta')
156
167
  this._encodeMap(bytes, content.meta)
157
168
  this._encodeString(bytes, 'metrics')
@@ -176,7 +187,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
176
187
  if (content.type) {
177
188
  totalKeysLength += 1
178
189
  }
179
- this._encodeMapPrefix(bytes, totalKeysLength)
190
+ bytes.writeMapPrefix(totalKeysLength)
180
191
  if (content.type) {
181
192
  this._encodeString(bytes, 'type')
182
193
  this._encodeString(bytes, content.type)
@@ -194,11 +205,11 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
194
205
  this._encodeString(bytes, 'service')
195
206
  this._encodeString(bytes, content.service)
196
207
  this._encodeString(bytes, 'error')
197
- this._encodeNumber(bytes, content.error)
208
+ bytes.writeNumber(content.error)
198
209
  this._encodeString(bytes, 'start')
199
- this._encodeNumber(bytes, content.start)
210
+ bytes.writeNumber(content.start)
200
211
  this._encodeString(bytes, 'duration')
201
- this._encodeNumber(bytes, content.duration)
212
+ bytes.writeNumber(content.duration)
202
213
  /**
203
214
  * We include `test_session_id` and `test_suite_id`
204
215
  * in the root of the event by passing them via the `meta` dict.
@@ -239,12 +250,12 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
239
250
  }
240
251
 
241
252
  _encodeEvent (bytes, event) {
242
- this._encodeMapPrefix(bytes, Object.keys(event).length)
253
+ bytes.writeMapPrefix(Object.keys(event).length)
243
254
  this._encodeString(bytes, 'type')
244
255
  this._encodeString(bytes, event.type)
245
256
 
246
257
  this._encodeString(bytes, 'version')
247
- this._encodeNumber(bytes, event.version)
258
+ bytes.writeNumber(event.version)
248
259
 
249
260
  this._encodeString(bytes, 'content')
250
261
  if (event.type === 'span' || event.type === 'test') {
@@ -259,10 +270,6 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
259
270
  }
260
271
 
261
272
  _encode (bytes, trace) {
262
- if (this._isReset) {
263
- this._encodePayloadStart(bytes)
264
- this._isReset = false
265
- }
266
273
  const startTime = Date.now()
267
274
 
268
275
  const events = trace.map(formatSpan)
@@ -281,20 +288,28 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
281
288
 
282
289
  makePayload () {
283
290
  distributionMetric(TELEMETRY_ENDPOINT_PAYLOAD_EVENTS_COUNT, { endpoint: 'test_cycle' }, this._eventCount)
284
- const bytes = this._traceBytes
285
- const eventsOffset = this._eventsOffset
286
- const eventsCount = this._eventCount
287
-
288
- bytes.buffer[eventsOffset] = 0xDD
289
- bytes.buffer[eventsOffset + 1] = eventsCount >> 24
290
- bytes.buffer[eventsOffset + 2] = eventsCount >> 16
291
- bytes.buffer[eventsOffset + 3] = eventsCount >> 8
292
- bytes.buffer[eventsOffset + 4] = eventsCount
293
291
 
294
- const traceSize = bytes.length
295
- const buffer = Buffer.allocUnsafe(traceSize)
292
+ // Encode the payload prefix (version + metadata + events-array header) at flush time,
293
+ // not on the first `_encode`. The CI Visibility flow adds metadata across multiple
294
+ // diagnostic channels (`session:start` adds `test_session.name`, the async
295
+ // `library-configuration` callback adds capability tags). Any span finished between
296
+ // those calls would otherwise freeze the prefix with stale metadata.
297
+ const prefixBytes = new MsgpackChunk(PREFIX_CHUNK_INITIAL_SIZE)
298
+ this._encodePayloadStart(prefixBytes)
296
299
 
297
- bytes.buffer.copy(buffer, 0, 0, traceSize)
300
+ const eventsOffset = this._eventsOffset
301
+ const eventsCount = this._eventCount
302
+ prefixBytes.buffer[eventsOffset] = 0xDD
303
+ prefixBytes.buffer[eventsOffset + 1] = eventsCount >> 24
304
+ prefixBytes.buffer[eventsOffset + 2] = eventsCount >> 16
305
+ prefixBytes.buffer[eventsOffset + 3] = eventsCount >> 8
306
+ prefixBytes.buffer[eventsOffset + 4] = eventsCount
307
+
308
+ const eventsBytes = this._traceBytes
309
+ const totalSize = prefixBytes.length + eventsBytes.length
310
+ const buffer = Buffer.allocUnsafe(totalSize)
311
+ prefixBytes.buffer.copy(buffer, 0, 0, prefixBytes.length)
312
+ eventsBytes.buffer.copy(buffer, prefixBytes.length, 0, eventsBytes.length)
298
313
 
299
314
  this.reset()
300
315
 
@@ -302,13 +317,15 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
302
317
  }
303
318
 
304
319
  _encodePayloadStart (bytes) {
305
- // encodes the payload up to `events`. `events` will be encoded via _encode
320
+ // Encodes the payload up to (and including) the `events` array prefix. The 5 reserved
321
+ // bytes for the array length are patched in `makePayload`.
306
322
  const payload = {
307
323
  version: ENCODING_VERSION,
308
324
  metadata: {
309
325
  '*': {
310
326
  language: 'javascript',
311
327
  library_version: ddTraceVersion,
328
+ ...this.wildcardMetadataTags,
312
329
  },
313
330
  ...this.metadataTags,
314
331
  },
@@ -322,11 +339,11 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
322
339
  payload.metadata['*']['runtime-id'] = this.runtimeId
323
340
  }
324
341
 
325
- this._encodeMapPrefix(bytes, Object.keys(payload).length)
342
+ bytes.writeMapPrefix(Object.keys(payload).length)
326
343
  this._encodeString(bytes, 'version')
327
- this._encodeNumber(bytes, payload.version)
344
+ bytes.writeNumber(payload.version)
328
345
  this._encodeString(bytes, 'metadata')
329
- this._encodeMapPrefix(bytes, Object.keys(payload.metadata).length)
346
+ bytes.writeMapPrefix(Object.keys(payload.metadata).length)
330
347
  this._encodeString(bytes, '*')
331
348
  this._encodeMap(bytes, payload.metadata['*'])
332
349
  if (payload.metadata.test) {
@@ -346,7 +363,6 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
346
363
  this._encodeMap(bytes, payload.metadata.test_session_end)
347
364
  }
348
365
  this._encodeString(bytes, 'events')
349
- // Get offset of the events list to update the length of the array when calling `makePayload`
350
366
  this._eventsOffset = bytes.length
351
367
  bytes.reserve(5)
352
368
  }
@@ -354,7 +370,6 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
354
370
  reset () {
355
371
  this._reset()
356
372
  this._eventCount = 0
357
- this._isReset = true
358
373
  }
359
374
  }
360
375
 
@@ -86,10 +86,12 @@ class AgentlessJSONEncoder {
86
86
  /**
87
87
  * @param {object} writer - Writer instance with a flush() method, called when the buffer exceeds the soft limit
88
88
  * @param {object} [metadata] - Shared metadata spread into each trace object (hostname, env, tracerVersion, etc.)
89
+ * @param {number} [softLimit] - Estimated payload-size threshold that triggers an early flush. Defaults to 8 MiB.
89
90
  */
90
- constructor (writer, metadata = {}) {
91
+ constructor (writer, metadata = {}, softLimit = SOFT_LIMIT) {
91
92
  this._writer = writer
92
93
  this._metadata = metadata
94
+ this._softLimit = softLimit
93
95
  this._reset()
94
96
  }
95
97
 
@@ -134,7 +136,7 @@ class AgentlessJSONEncoder {
134
136
  log.error('All %d span(s) in trace failed to encode. Entire trace dropped.', trace.length)
135
137
  }
136
138
 
137
- if (this._estimatedSize > SOFT_LIMIT) {
139
+ if (this._estimatedSize > this._softLimit) {
138
140
  log.debug('Buffer went over soft limit, flushing')
139
141
  try {
140
142
  this._writer.flush()
@@ -12,6 +12,17 @@ const { AgentEncoder } = require('./0.4')
12
12
  const COVERAGE_PAYLOAD_VERSION = 2
13
13
  const COVERAGE_KEYS_LENGTH = 2
14
14
 
15
+ function getBitmapBuffer (bitmap) {
16
+ if (!bitmap) return
17
+ if (Buffer.isBuffer(bitmap)) return bitmap
18
+ if (ArrayBuffer.isView(bitmap)) {
19
+ return Buffer.from(bitmap.buffer, bitmap.byteOffset, bitmap.byteLength)
20
+ }
21
+ if (bitmap.type === 'Buffer' && Array.isArray(bitmap.data)) {
22
+ return Buffer.from(bitmap.data)
23
+ }
24
+ }
25
+
15
26
  class CoverageCIVisibilityEncoder extends AgentEncoder {
16
27
  constructor () {
17
28
  super(...arguments)
@@ -39,32 +50,40 @@ class CoverageCIVisibilityEncoder extends AgentEncoder {
39
50
  }
40
51
 
41
52
  encodeCodeCoverage (bytes, coverage) {
42
- if (coverage.testId) {
43
- this._encodeMapPrefix(bytes, 4)
44
- } else {
45
- this._encodeMapPrefix(bytes, 3)
46
- }
53
+ let keysLength = 2
54
+ if (coverage.suiteId) keysLength++
55
+ if (coverage.testId) keysLength++
56
+
57
+ bytes.writeMapPrefix(keysLength)
47
58
  this._encodeString(bytes, 'test_session_id')
48
59
  this._encodeId(bytes, coverage.sessionId)
49
- this._encodeString(bytes, 'test_suite_id')
50
- this._encodeId(bytes, coverage.suiteId)
60
+ if (coverage.suiteId) {
61
+ this._encodeString(bytes, 'test_suite_id')
62
+ this._encodeId(bytes, coverage.suiteId)
63
+ }
51
64
  if (coverage.testId) {
52
65
  this._encodeString(bytes, 'span_id')
53
66
  this._encodeId(bytes, coverage.testId)
54
67
  }
55
68
  this._encodeString(bytes, 'files')
56
- this._encodeArrayPrefix(bytes, coverage.files)
57
- for (const filename of coverage.files) {
58
- this._encodeMapPrefix(bytes, 1)
69
+ bytes.writeArrayPrefix(coverage.files)
70
+ for (const file of coverage.files) {
71
+ const filename = typeof file === 'string' ? file : file.filename
72
+ const bitmap = getBitmapBuffer(file.bitmap)
73
+ bytes.writeMapPrefix(bitmap ? 2 : 1)
59
74
  this._encodeString(bytes, 'filename')
60
75
  this._encodeString(bytes, filename)
76
+ if (bitmap) {
77
+ this._encodeString(bytes, 'bitmap')
78
+ bytes.writeBin(bitmap)
79
+ }
61
80
  }
62
81
  }
63
82
 
64
83
  reset () {
65
84
  this._reset()
66
85
  if (this._coverageBytes) {
67
- this._coverageBytes.length = 0
86
+ this._coverageBytes.reset()
68
87
  }
69
88
  this._coveragesCount = 0
70
89
  this._encodePayloadStart(this._coverageBytes)
@@ -75,9 +94,9 @@ class CoverageCIVisibilityEncoder extends AgentEncoder {
75
94
  version: COVERAGE_PAYLOAD_VERSION,
76
95
  coverages: [],
77
96
  }
78
- this._encodeMapPrefix(bytes, COVERAGE_KEYS_LENGTH)
97
+ bytes.writeMapPrefix(COVERAGE_KEYS_LENGTH)
79
98
  this._encodeString(bytes, 'version')
80
- this._encodeInteger(bytes, payload.version)
99
+ bytes.writeInteger(payload.version)
81
100
  this._encodeString(bytes, 'coverages')
82
101
  // Get offset of the coverages list to update the length of the array when calling `makePayload`
83
102
  this._coveragesOffset = bytes.length
@@ -31,7 +31,7 @@ class SpanStatsEncoder extends AgentEncoder {
31
31
  }
32
32
 
33
33
  _encodeStat (bytes, stat) {
34
- this._encodeMapPrefix(bytes, 15)
34
+ bytes.writeMapPrefix(15)
35
35
 
36
36
  this._encodeString(bytes, 'Service')
37
37
  const service = stat.Service || DEFAULT_SERVICE_NAME
@@ -45,31 +45,31 @@ class SpanStatsEncoder extends AgentEncoder {
45
45
  this._encodeString(bytes, truncate(stat.Resource, MAX_RESOURCE_NAME_LENGTH, '...'))
46
46
 
47
47
  this._encodeString(bytes, 'HTTPStatusCode')
48
- this._encodeInteger(bytes, stat.HTTPStatusCode)
48
+ bytes.writeInteger(stat.HTTPStatusCode)
49
49
 
50
50
  this._encodeString(bytes, 'Type')
51
51
  this._encodeString(bytes, truncate(stat.Type, MAX_TYPE_LENGTH))
52
52
 
53
53
  this._encodeString(bytes, 'Hits')
54
- this._encodeLong(bytes, stat.Hits)
54
+ bytes.writeLong(stat.Hits)
55
55
 
56
56
  this._encodeString(bytes, 'Errors')
57
- this._encodeLong(bytes, stat.Errors)
57
+ bytes.writeLong(stat.Errors)
58
58
 
59
59
  this._encodeString(bytes, 'Duration')
60
- this._encodeLong(bytes, stat.Duration)
60
+ bytes.writeLong(stat.Duration)
61
61
 
62
62
  this._encodeString(bytes, 'OkSummary')
63
- this._encodeBuffer(bytes, stat.OkSummary)
63
+ bytes.writeBin(stat.OkSummary)
64
64
 
65
65
  this._encodeString(bytes, 'ErrorSummary')
66
- this._encodeBuffer(bytes, stat.ErrorSummary)
66
+ bytes.writeBin(stat.ErrorSummary)
67
67
 
68
68
  this._encodeString(bytes, 'Synthetics')
69
- this._encodeBool(bytes, stat.Synthetics)
69
+ bytes.writeBoolean(stat.Synthetics)
70
70
 
71
71
  this._encodeString(bytes, 'TopLevelHits')
72
- this._encodeLong(bytes, stat.TopLevelHits)
72
+ bytes.writeLong(stat.TopLevelHits)
73
73
 
74
74
  this._encodeString(bytes, 'HTTPMethod')
75
75
  this._encodeString(bytes, stat.HTTPMethod)
@@ -82,23 +82,23 @@ class SpanStatsEncoder extends AgentEncoder {
82
82
  }
83
83
 
84
84
  _encodeBucket (bytes, bucket) {
85
- this._encodeMapPrefix(bytes, 3)
85
+ bytes.writeMapPrefix(3)
86
86
 
87
87
  this._encodeString(bytes, 'Start')
88
- this._encodeLong(bytes, bucket.Start)
88
+ bytes.writeLong(bucket.Start)
89
89
 
90
90
  this._encodeString(bytes, 'Duration')
91
- this._encodeLong(bytes, bucket.Duration)
91
+ bytes.writeLong(bucket.Duration)
92
92
 
93
93
  this._encodeString(bytes, 'Stats')
94
- this._encodeArrayPrefix(bytes, bucket.Stats)
94
+ bytes.writeArrayPrefix(bucket.Stats)
95
95
  for (const stat of bucket.Stats) {
96
96
  this._encodeStat(bytes, stat)
97
97
  }
98
98
  }
99
99
 
100
100
  _encode (bytes, stats) {
101
- this._encodeMapPrefix(bytes, stats.ProcessTags ? 9 : 8)
101
+ bytes.writeMapPrefix(stats.ProcessTags ? 9 : 8)
102
102
 
103
103
  this._encodeString(bytes, 'Hostname')
104
104
  this._encodeString(bytes, stats.Hostname)
@@ -110,7 +110,7 @@ class SpanStatsEncoder extends AgentEncoder {
110
110
  this._encodeString(bytes, stats.Version)
111
111
 
112
112
  this._encodeString(bytes, 'Stats')
113
- this._encodeArrayPrefix(bytes, stats.Stats)
113
+ bytes.writeArrayPrefix(stats.Stats)
114
114
  for (const bucket of stats.Stats) {
115
115
  this._encodeBucket(bytes, bucket)
116
116
  }
@@ -125,7 +125,7 @@ class SpanStatsEncoder extends AgentEncoder {
125
125
  this._encodeString(bytes, stats.RuntimeID)
126
126
 
127
127
  this._encodeString(bytes, 'Sequence')
128
- this._encodeLong(bytes, stats.Sequence)
128
+ bytes.writeLong(stats.Sequence)
129
129
 
130
130
  if (stats.ProcessTags) {
131
131
  this._encodeString(bytes, 'ProcessTags')
@@ -9,6 +9,8 @@ const MAX_RESOURCE_NAME_LENGTH = 5000
9
9
  const MAX_META_KEY_LENGTH = 200
10
10
  // MAX_META_VALUE_LENGTH the maximum length of metadata value
11
11
  const MAX_META_VALUE_LENGTH = 25_000
12
+ // MAX_META_VALUE_LENGTH_TEST_OPTIMIZATION the maximum length of metadata value for Test Optimization
13
+ const MAX_META_VALUE_LENGTH_TEST_OPTIMIZATION = 5000
12
14
  // MAX_METRIC_KEY_LENGTH the maximum length of a metric name key
13
15
  const MAX_METRIC_KEY_LENGTH = MAX_META_KEY_LENGTH
14
16
 
@@ -32,6 +34,18 @@ function truncateSpan (span) {
32
34
  return span
33
35
  }
34
36
 
37
+ function truncateSpanTestOpt (span) {
38
+ truncateSpan(span)
39
+ if (span.meta) {
40
+ for (const key of Object.keys(span.meta)) {
41
+ if (span.meta[key].length > MAX_META_VALUE_LENGTH_TEST_OPTIMIZATION) {
42
+ span.meta[key] = `${span.meta[key].slice(0, MAX_META_VALUE_LENGTH_TEST_OPTIMIZATION)}...`
43
+ }
44
+ }
45
+ }
46
+ return span
47
+ }
48
+
35
49
  function normalizeSpan (span) {
36
50
  span.service = span.service || DEFAULT_SERVICE_NAME
37
51
  if (span.service.length > MAX_SERVICE_LENGTH) {
@@ -53,9 +67,11 @@ function normalizeSpan (span) {
53
67
 
54
68
  module.exports = {
55
69
  truncateSpan,
70
+ truncateSpanTestOpt,
56
71
  normalizeSpan,
57
72
  MAX_META_KEY_LENGTH,
58
73
  MAX_META_VALUE_LENGTH,
74
+ MAX_META_VALUE_LENGTH_TEST_OPTIMIZATION,
59
75
  MAX_METRIC_KEY_LENGTH,
60
76
  MAX_NAME_LENGTH,
61
77
  MAX_SERVICE_LENGTH,
@@ -4,6 +4,8 @@ const http = require('http')
4
4
  const https = require('https')
5
5
  const { storage } = require('../../../../datadog-core')
6
6
 
7
+ const legacyStorage = storage('legacy')
8
+
7
9
  const keepAlive = true
8
10
  const maxSockets = 1
9
11
 
@@ -26,7 +28,7 @@ function createAgentClass (BaseAgent) {
26
28
  }
27
29
 
28
30
  _noop (callback) {
29
- return storage('legacy').run({ noop: true }, callback)
31
+ return legacyStorage.run({ noop: true }, callback)
30
32
  }
31
33
  }
32
34
 
@@ -20,6 +20,8 @@ const {
20
20
  markEndpointReached,
21
21
  } = require('./retry')
22
22
 
23
+ const legacyStorage = storage('legacy')
24
+
23
25
  const maxActiveBufferSize = 1024 * 1024 * 64
24
26
 
25
27
  let activeBufferSize = 0
@@ -161,7 +163,7 @@ function request (data, options, callback) {
161
163
 
162
164
  activeBufferSize += options.headers['Content-Length'] ?? 0
163
165
 
164
- storage('legacy').run({ noop: true }, () => {
166
+ legacyStorage.run({ noop: true }, () => {
165
167
  let finished = false
166
168
  const finalize = () => {
167
169
  if (finished) return
@@ -13,6 +13,12 @@ let batch = 0
13
13
  class Identifier {
14
14
  /** @type {number[] | Uint8Array} */
15
15
  #buffer
16
+ /** @type {bigint | undefined} */
17
+ #bigInt
18
+ /** @type {string | undefined} */
19
+ #stringHex
20
+ /** @type {string | undefined} */
21
+ #stringDecimal
16
22
 
17
23
  /**
18
24
  * @param {string} value
@@ -29,16 +35,23 @@ class Identifier {
29
35
  * @returns {string}
30
36
  */
31
37
  toString (radix = 16) {
32
- return radix === 16
33
- ? Buffer.from(this.#buffer).toString('hex')
34
- : toNumberString(this.#buffer, radix)
38
+ if (radix === 16) {
39
+ this.#stringHex ??= Buffer.from(this.#buffer).toString('hex')
40
+ return this.#stringHex
41
+ }
42
+ if (radix === 10) {
43
+ this.#stringDecimal ??= toNumberString(this.#buffer, 10)
44
+ return this.#stringDecimal
45
+ }
46
+ return toNumberString(this.#buffer, radix)
35
47
  }
36
48
 
37
49
  /**
38
50
  * @returns {bigint}
39
51
  */
40
52
  toBigInt () {
41
- return Buffer.from(this.#buffer).readBigUInt64BE(0)
53
+ this.#bigInt ??= Buffer.from(this.#buffer).readBigUInt64BE(0)
54
+ return this.#bigInt
42
55
  }
43
56
 
44
57
  /**
@@ -6,8 +6,6 @@ const { ERROR_MESSAGE, ERROR_TYPE } = require('../constants')
6
6
  const { ImpendingTimeout } = require('./runtime/errors')
7
7
  const { extractContext } = require('./context')
8
8
 
9
- const globalTracer = global._ddtrace
10
- const tracer = globalTracer._tracer
11
9
  const timeoutChannel = channel('apm:aws:lambda:timeout')
12
10
  // Always crash the flushes when a message is received
13
11
  // from this channel.
@@ -25,8 +23,7 @@ let __lambdaTimeout
25
23
  */
26
24
  function checkTimeout (context) {
27
25
  const remainingTimeInMillis = context.getRemainingTimeInMillis()
28
-
29
- const apmFlushDeadline = tracer._config.DD_APM_FLUSH_DEADLINE_MILLISECONDS
26
+ const apmFlushDeadline = global._ddtrace._tracer._config.DD_APM_FLUSH_DEADLINE_MILLISECONDS
30
27
 
31
28
  __lambdaTimeout = setTimeout(() => {
32
29
  timeoutChannel.publish()
@@ -42,6 +39,7 @@ function checkTimeout (context) {
42
39
  * Once that is done, it finishes the last span.
43
40
  */
44
41
  function crashFlush () {
42
+ const tracer = global._ddtrace._tracer
45
43
  const activeSpan = tracer.scope().active()
46
44
  if (activeSpan === null) {
47
45
  log.debug('An impending timeout was reached, but no root span was found. No error will be tagged.')
@@ -41,7 +41,7 @@ const VERCEL_AI_GENERATION_METADATA_PREFIX = 'ai.settings.'
41
41
  */
42
42
  function getSpanTags (ctx) {
43
43
  const span = ctx.currentStore?.span
44
- return /** @type {SpanTags} */ (ctx.attributes ?? span?.context()._tags ?? {})
44
+ return /** @type {SpanTags} */ (ctx.attributes ?? span?.context().getTags() ?? {})
45
45
  }
46
46
 
47
47
  /**
@@ -55,7 +55,7 @@ class GenAiLLMObsPlugin extends LLMObsPlugin {
55
55
 
56
56
  const inputs = args[0]
57
57
  const response = ctx.result
58
- const error = !!span.context()._tags.error
58
+ const error = !!span.context().getTag('error')
59
59
 
60
60
  const operation = getOperation(methodName)
61
61
 
@@ -7,7 +7,7 @@ class LangChainLLMObsHandler {
7
7
  }
8
8
 
9
9
  getName ({ span }) {
10
- return span?.context()._tags?.['resource.name']
10
+ return span?.context()?.getTag('resource.name')
11
11
  }
12
12
 
13
13
  setMetaTags () {}