dd-trace 5.104.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.
- package/LICENSE-3rdparty.csv +90 -102
- package/index.d.ts +82 -3
- package/package.json +15 -15
- package/packages/datadog-core/src/storage.js +1 -1
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/ai.js +8 -7
- package/packages/datadog-instrumentations/src/aws-sdk.js +13 -0
- package/packages/datadog-instrumentations/src/azure-cosmos.js +7 -0
- package/packages/datadog-instrumentations/src/azure-functions.js +3 -0
- package/packages/datadog-instrumentations/src/cucumber.js +78 -5
- package/packages/datadog-instrumentations/src/dns.js +54 -18
- package/packages/datadog-instrumentations/src/fastify.js +142 -82
- package/packages/datadog-instrumentations/src/graphql.js +188 -62
- package/packages/datadog-instrumentations/src/helpers/ai-messages.js +322 -14
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +269 -0
- package/packages/datadog-instrumentations/src/helpers/promise-instrumentor.js +42 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-cosmos.js +50 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langgraph.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +85 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +37 -236
- package/packages/datadog-instrumentations/src/hono.js +54 -3
- package/packages/datadog-instrumentations/src/http/server.js +9 -4
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +163 -0
- package/packages/datadog-instrumentations/src/jest.js +360 -150
- package/packages/datadog-instrumentations/src/kafkajs.js +120 -16
- package/packages/datadog-instrumentations/src/mocha/main.js +128 -17
- package/packages/datadog-instrumentations/src/nats.js +182 -0
- package/packages/datadog-instrumentations/src/nyc.js +38 -1
- package/packages/datadog-instrumentations/src/openai.js +33 -18
- package/packages/datadog-instrumentations/src/oracledb.js +6 -1
- package/packages/datadog-instrumentations/src/pino.js +17 -5
- package/packages/datadog-instrumentations/src/playwright.js +515 -292
- package/packages/datadog-instrumentations/src/router.js +76 -32
- package/packages/datadog-instrumentations/src/stripe.js +1 -1
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-azure-cosmos/src/index.js +144 -0
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -1
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -2
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +1 -1
- package/packages/datadog-plugin-bunyan/src/index.js +28 -0
- package/packages/datadog-plugin-cucumber/src/index.js +17 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +199 -28
- package/packages/datadog-plugin-cypress/src/support.js +69 -1
- package/packages/datadog-plugin-dns/src/lookup.js +8 -6
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +2 -0
- package/packages/datadog-plugin-graphql/src/resolve.js +64 -67
- package/packages/datadog-plugin-http/src/server.js +40 -15
- package/packages/datadog-plugin-jest/src/index.js +11 -3
- package/packages/datadog-plugin-jest/src/util.js +15 -8
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -0
- package/packages/datadog-plugin-langgraph/src/stream.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +19 -4
- package/packages/datadog-plugin-mongodb-core/src/index.js +281 -40
- package/packages/datadog-plugin-nats/src/consumer.js +43 -0
- package/packages/datadog-plugin-nats/src/index.js +20 -0
- package/packages/datadog-plugin-nats/src/producer.js +62 -0
- package/packages/datadog-plugin-nats/src/util.js +33 -0
- package/packages/datadog-plugin-next/src/index.js +5 -3
- package/packages/datadog-plugin-openai/src/tracing.js +15 -2
- package/packages/datadog-plugin-oracledb/src/index.js +13 -2
- package/packages/datadog-plugin-pino/src/index.js +42 -0
- package/packages/datadog-plugin-playwright/src/index.js +4 -4
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +33 -44
- package/packages/datadog-plugin-selenium/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +5 -13
- package/packages/datadog-plugin-winston/src/index.js +30 -0
- package/packages/datadog-shimmer/src/shimmer.js +33 -40
- package/packages/dd-trace/src/aiguard/index.js +1 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +1 -1
- package/packages/dd-trace/src/appsec/reporter.js +5 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/utils.js +1 -1
- package/packages/dd-trace/src/appsec/user_tracking.js +5 -4
- package/packages/dd-trace/src/baggage.js +7 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +0 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +25 -13
- package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +70 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +6 -2
- package/packages/dd-trace/src/config/supported-configurations.json +27 -8
- package/packages/dd-trace/src/datastreams/writer.js +2 -4
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -8
- package/packages/dd-trace/src/encode/0.4.js +124 -108
- package/packages/dd-trace/src/encode/0.5.js +114 -26
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +31 -23
- package/packages/dd-trace/src/encode/agentless-json.js +4 -2
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +32 -13
- package/packages/dd-trace/src/encode/span-stats.js +16 -16
- package/packages/dd-trace/src/encode/tags-processors.js +16 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +9 -7
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +0 -16
- package/packages/dd-trace/src/llmobs/span_processor.js +3 -3
- package/packages/dd-trace/src/llmobs/tagger.js +9 -1
- package/packages/dd-trace/src/llmobs/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/util.js +66 -3
- package/packages/dd-trace/src/log/index.js +1 -1
- package/packages/dd-trace/src/msgpack/chunk.js +394 -10
- package/packages/dd-trace/src/msgpack/index.js +96 -2
- package/packages/dd-trace/src/openfeature/encoding.js +70 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +20 -0
- package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +143 -0
- package/packages/dd-trace/src/openfeature/span-enrichment.js +149 -0
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +4 -3
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/log.js +18 -7
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +62 -67
- package/packages/dd-trace/src/opentracing/span.js +59 -19
- package/packages/dd-trace/src/opentracing/span_context.js +49 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -20
- package/packages/dd-trace/src/plugins/database.js +7 -6
- package/packages/dd-trace/src/plugins/index.js +4 -0
- package/packages/dd-trace/src/plugins/log_injection.js +56 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -48
- package/packages/dd-trace/src/plugins/outbound.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +15 -17
- package/packages/dd-trace/src/plugins/tracing.js +43 -5
- package/packages/dd-trace/src/plugins/util/test.js +236 -13
- package/packages/dd-trace/src/plugins/util/web.js +79 -65
- package/packages/dd-trace/src/priority_sampler.js +2 -2
- package/packages/dd-trace/src/profiling/profiler.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +10 -4
- package/packages/dd-trace/src/sampling_rule.js +7 -7
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +10 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/source-resolver.js +46 -0
- package/packages/dd-trace/src/span_format.js +190 -58
- package/packages/dd-trace/src/spanleak.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -3
- package/packages/dd-trace/src/tagger.js +0 -2
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +70 -39
- package/vendor/dist/@datadog/sketches-js/LICENSE +10 -36
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/packages/dd-trace/src/msgpack/encoder.js +0 -308
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +0 -9
|
@@ -6,10 +6,18 @@ const { AgentEncoder: BaseEncoder, stringifySpanEvents } = require('./0.4')
|
|
|
6
6
|
const ARRAY_OF_TWO = 0x92
|
|
7
7
|
const ARRAY_OF_TWELVE = 0x9C
|
|
8
8
|
|
|
9
|
+
// Per-span fused head: `[0x9C, service-idx, name-idx, resource-idx,
|
|
10
|
+
// trace-id, span-id, parent-id]` — three uint32 indexes (5 bytes each) +
|
|
11
|
+
// three uint64 IDs (9 bytes each) + the array marker. Replaces seven
|
|
12
|
+
// separate reserves (`writeByte` + 3 × `writeInteger` + 3 × `_encodeId`)
|
|
13
|
+
// with one block-sized reserve per span.
|
|
14
|
+
const HEAD_BLOCK_SIZE = 1 + 5 * 3 + 9 * 3
|
|
15
|
+
|
|
9
16
|
function formatSpan (span) {
|
|
10
17
|
span = normalizeSpan(span)
|
|
11
18
|
// v0.5 has no native span_events slot; always serialize as a meta tag.
|
|
12
19
|
if (span.span_events) {
|
|
20
|
+
// TODO: this is a costly operation. Consolidate this with the formatter
|
|
13
21
|
span.meta.events = stringifySpanEvents(span.span_events)
|
|
14
22
|
// `= undefined` over `delete` to keep the span's hidden class.
|
|
15
23
|
span.span_events = undefined
|
|
@@ -35,20 +43,36 @@ class AgentEncoder extends BaseEncoder {
|
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
_encode (bytes, trace) {
|
|
38
|
-
|
|
46
|
+
bytes.writeArrayPrefix(trace)
|
|
47
|
+
|
|
48
|
+
const stringMap = this._stringMap
|
|
39
49
|
|
|
40
50
|
for (let span of trace) {
|
|
41
51
|
span = formatSpan(span)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
|
|
53
|
+
// Resolve the three head string indices up front. `_cacheString`
|
|
54
|
+
// writes into `_stringBytes`, an independent chunk, so the side
|
|
55
|
+
// effect is safe to interleave with the `_traceBytes` reserve
|
|
56
|
+
// below.
|
|
57
|
+
const serviceIndex = stringMap[span.service] ?? this._cacheString(span.service)
|
|
58
|
+
const nameIndex = stringMap[span.name] ?? this._cacheString(span.name)
|
|
59
|
+
const resourceIndex = stringMap[span.resource] ?? this._cacheString(span.resource)
|
|
60
|
+
|
|
61
|
+
const blockOffset = bytes.length
|
|
62
|
+
bytes.reserve(HEAD_BLOCK_SIZE)
|
|
63
|
+
const target = bytes.buffer
|
|
64
|
+
|
|
65
|
+
target[blockOffset] = ARRAY_OF_TWELVE
|
|
66
|
+
let cursor = this.#writeIndexAt(target, blockOffset + 1, serviceIndex)
|
|
67
|
+
cursor = this.#writeIndexAt(target, cursor, nameIndex)
|
|
68
|
+
cursor = this.#writeIndexAt(target, cursor, resourceIndex)
|
|
69
|
+
cursor = this.#writeIdAt(target, cursor, span.trace_id)
|
|
70
|
+
cursor = this.#writeIdAt(target, cursor, span.span_id)
|
|
71
|
+
this.#writeIdAt(target, cursor, span.parent_id)
|
|
72
|
+
|
|
73
|
+
bytes.writeIntOrFloat(span.start || 0)
|
|
74
|
+
bytes.writeIntOrFloat(span.duration || 0)
|
|
75
|
+
bytes.writeIntOrFloat(span.error)
|
|
52
76
|
this._encodeMap(bytes, span.meta || {})
|
|
53
77
|
this._encodeMap(bytes, span.metrics || {})
|
|
54
78
|
this._encodeString(bytes, span.type)
|
|
@@ -65,18 +89,41 @@ class AgentEncoder extends BaseEncoder {
|
|
|
65
89
|
bytes.reserve(5)
|
|
66
90
|
bytes.buffer[offset] = 0xDF
|
|
67
91
|
|
|
92
|
+
const stringMap = this._stringMap
|
|
68
93
|
let count = 0
|
|
69
94
|
for (const key of Object.keys(value)) {
|
|
70
95
|
const entryValue = value[key]
|
|
96
|
+
if (typeof entryValue !== 'string' && typeof entryValue !== 'number') continue
|
|
97
|
+
|
|
98
|
+
const keyIndex = stringMap[key] ?? this._cacheString(key)
|
|
99
|
+
const writeOffset = bytes.length
|
|
100
|
+
|
|
71
101
|
if (typeof entryValue === 'string') {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this
|
|
78
|
-
|
|
102
|
+
// Both halves are uint32 indices on the v0.5 wire — known
|
|
103
|
+
// size, so the key and value pair fuses into one reserve.
|
|
104
|
+
const valueIndex = stringMap[entryValue] ?? this._cacheString(entryValue)
|
|
105
|
+
bytes.reserve(10)
|
|
106
|
+
const target = bytes.buffer
|
|
107
|
+
this.#writeIndexAt(target, writeOffset, keyIndex)
|
|
108
|
+
this.#writeIndexAt(target, writeOffset + 5, valueIndex)
|
|
109
|
+
} else {
|
|
110
|
+
// Speculate that the value is a positive fixint (0..127). The
|
|
111
|
+
// metrics map is mostly small unsigned integers (sample priority,
|
|
112
|
+
// `_dd.measured`, attribute counts), so one reserve covers the
|
|
113
|
+
// key (5 bytes) and the value (1 byte). Misses rewind the
|
|
114
|
+
// speculative value byte and route the value through the full
|
|
115
|
+
// encoder so the wire still picks the shortest valid encoding.
|
|
116
|
+
bytes.reserve(6)
|
|
117
|
+
const target = bytes.buffer
|
|
118
|
+
this.#writeIndexAt(target, writeOffset, keyIndex)
|
|
119
|
+
if (entryValue === (entryValue & 0x7F)) {
|
|
120
|
+
target[writeOffset + 5] = entryValue
|
|
121
|
+
} else {
|
|
122
|
+
bytes.length = writeOffset + 5
|
|
123
|
+
bytes.writeIntOrFloat(entryValue)
|
|
124
|
+
}
|
|
79
125
|
}
|
|
126
|
+
count++
|
|
80
127
|
}
|
|
81
128
|
|
|
82
129
|
const target = bytes.buffer
|
|
@@ -87,20 +134,18 @@ class AgentEncoder extends BaseEncoder {
|
|
|
87
134
|
}
|
|
88
135
|
|
|
89
136
|
_encodeString (bytes, value = '') {
|
|
137
|
+
const index = this._stringMap[value] ?? this._cacheString(value)
|
|
138
|
+
bytes.writeInteger(index)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
_cacheString (value) {
|
|
90
142
|
let index = this._stringMap[value]
|
|
91
143
|
if (index === undefined) {
|
|
92
144
|
index = this._stringCount++
|
|
93
145
|
this._stringMap[value] = index
|
|
94
146
|
this._stringBytes.write(value)
|
|
95
147
|
}
|
|
96
|
-
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
_cacheString (value) {
|
|
100
|
-
if (this._stringMap[value] === undefined) {
|
|
101
|
-
this._stringMap[value] = this._stringCount++
|
|
102
|
-
this._stringBytes.write(value)
|
|
103
|
-
}
|
|
148
|
+
return index
|
|
104
149
|
}
|
|
105
150
|
|
|
106
151
|
_writeStrings (buffer, offset) {
|
|
@@ -109,6 +154,49 @@ class AgentEncoder extends BaseEncoder {
|
|
|
109
154
|
|
|
110
155
|
return offset
|
|
111
156
|
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Write `[0xCE, uint32(index)]` into `target` at `offset` and return the
|
|
160
|
+
* new cursor. Caller is responsible for having reserved enough room.
|
|
161
|
+
*
|
|
162
|
+
* @param {Uint8Array} target
|
|
163
|
+
* @param {number} offset
|
|
164
|
+
* @param {number} index
|
|
165
|
+
* @returns {number}
|
|
166
|
+
*/
|
|
167
|
+
#writeIndexAt (target, offset, index) {
|
|
168
|
+
target[offset] = 0xCE
|
|
169
|
+
target[offset + 1] = index >> 24
|
|
170
|
+
target[offset + 2] = index >> 16
|
|
171
|
+
target[offset + 3] = index >> 8
|
|
172
|
+
target[offset + 4] = index
|
|
173
|
+
return offset + 5
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Write `[0xCF, uint64(id)]` into `target` at `offset` and return the
|
|
178
|
+
* new cursor. The id is truncated to the low 8 bytes, matching the
|
|
179
|
+
* inherited `_encodeId` behavior.
|
|
180
|
+
*
|
|
181
|
+
* @param {Uint8Array} target
|
|
182
|
+
* @param {number} offset
|
|
183
|
+
* @param {{ toBuffer: () => Uint8Array | number[] }} identifier
|
|
184
|
+
* @returns {number}
|
|
185
|
+
*/
|
|
186
|
+
#writeIdAt (target, offset, identifier) {
|
|
187
|
+
target[offset] = 0xCF
|
|
188
|
+
const idBuffer = identifier.toBuffer()
|
|
189
|
+
const start = idBuffer.length - 8
|
|
190
|
+
target[offset + 1] = idBuffer[start]
|
|
191
|
+
target[offset + 2] = idBuffer[start + 1]
|
|
192
|
+
target[offset + 3] = idBuffer[start + 2]
|
|
193
|
+
target[offset + 4] = idBuffer[start + 3]
|
|
194
|
+
target[offset + 5] = idBuffer[start + 4]
|
|
195
|
+
target[offset + 6] = idBuffer[start + 5]
|
|
196
|
+
target[offset + 7] = idBuffer[start + 6]
|
|
197
|
+
target[offset + 8] = idBuffer[start + 7]
|
|
198
|
+
return offset + 9
|
|
199
|
+
}
|
|
112
200
|
}
|
|
113
201
|
|
|
114
202
|
module.exports = { AgentEncoder }
|
|
@@ -9,7 +9,7 @@ const {
|
|
|
9
9
|
} = require('../ci-visibility/telemetry')
|
|
10
10
|
const { MsgpackChunk } = require('../msgpack')
|
|
11
11
|
const { AgentEncoder } = require('./0.4')
|
|
12
|
-
const {
|
|
12
|
+
const { truncateSpanTestOpt, normalizeSpan } = require('./tags-processors')
|
|
13
13
|
|
|
14
14
|
const ENCODING_VERSION = 1
|
|
15
15
|
const ALLOWED_CONTENT_TYPES = new Set(['test_session_end', 'test_module_end', 'test_suite_end', 'test'])
|
|
@@ -32,7 +32,7 @@ function formatSpan (span) {
|
|
|
32
32
|
return {
|
|
33
33
|
type: ALLOWED_CONTENT_TYPES.has(span.type) ? span.type : 'span',
|
|
34
34
|
version: encodingVersion,
|
|
35
|
-
content: normalizeSpan(
|
|
35
|
+
content: normalizeSpan(truncateSpanTestOpt(span)),
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -48,11 +48,18 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
48
48
|
this._eventCount = 0
|
|
49
49
|
|
|
50
50
|
this.metadataTags = {}
|
|
51
|
+
this.wildcardMetadataTags = {}
|
|
51
52
|
|
|
52
53
|
this.reset()
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
addMetadataTags (tags) {
|
|
57
|
+
if (tags['*']) {
|
|
58
|
+
this.wildcardMetadataTags = {
|
|
59
|
+
...this.wildcardMetadataTags,
|
|
60
|
+
...tags['*'],
|
|
61
|
+
}
|
|
62
|
+
}
|
|
56
63
|
for (const type of ALLOWED_CONTENT_TYPES) {
|
|
57
64
|
if (tags[type]) {
|
|
58
65
|
this.metadataTags[type] = {
|
|
@@ -70,7 +77,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
70
77
|
keysLength++
|
|
71
78
|
}
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
bytes.writeMapPrefix(keysLength)
|
|
74
81
|
this._encodeString(bytes, 'type')
|
|
75
82
|
this._encodeString(bytes, content.type)
|
|
76
83
|
|
|
@@ -90,7 +97,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
this._encodeString(bytes, 'error')
|
|
93
|
-
|
|
100
|
+
bytes.writeNumber(content.error)
|
|
94
101
|
this._encodeString(bytes, 'name')
|
|
95
102
|
this._encodeString(bytes, content.name)
|
|
96
103
|
this._encodeString(bytes, 'service')
|
|
@@ -98,9 +105,9 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
98
105
|
this._encodeString(bytes, 'resource')
|
|
99
106
|
this._encodeString(bytes, content.resource)
|
|
100
107
|
this._encodeString(bytes, 'start')
|
|
101
|
-
|
|
108
|
+
bytes.writeNumber(content.start)
|
|
102
109
|
this._encodeString(bytes, 'duration')
|
|
103
|
-
|
|
110
|
+
bytes.writeNumber(content.duration)
|
|
104
111
|
this._encodeString(bytes, 'meta')
|
|
105
112
|
this._encodeMap(bytes, content.meta)
|
|
106
113
|
this._encodeString(bytes, 'metrics')
|
|
@@ -108,7 +115,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
108
115
|
}
|
|
109
116
|
|
|
110
117
|
_encodeTestModule (bytes, content) {
|
|
111
|
-
|
|
118
|
+
bytes.writeMapPrefix(TEST_MODULE_KEYS_LENGTH)
|
|
112
119
|
this._encodeString(bytes, 'type')
|
|
113
120
|
this._encodeString(bytes, content.type)
|
|
114
121
|
|
|
@@ -119,7 +126,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
119
126
|
this._encodeId(bytes, content.span_id)
|
|
120
127
|
|
|
121
128
|
this._encodeString(bytes, 'error')
|
|
122
|
-
|
|
129
|
+
bytes.writeNumber(content.error)
|
|
123
130
|
this._encodeString(bytes, 'name')
|
|
124
131
|
this._encodeString(bytes, content.name)
|
|
125
132
|
this._encodeString(bytes, 'service')
|
|
@@ -127,9 +134,9 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
127
134
|
this._encodeString(bytes, 'resource')
|
|
128
135
|
this._encodeString(bytes, content.resource)
|
|
129
136
|
this._encodeString(bytes, 'start')
|
|
130
|
-
|
|
137
|
+
bytes.writeNumber(content.start)
|
|
131
138
|
this._encodeString(bytes, 'duration')
|
|
132
|
-
|
|
139
|
+
bytes.writeNumber(content.duration)
|
|
133
140
|
this._encodeString(bytes, 'meta')
|
|
134
141
|
this._encodeMap(bytes, content.meta)
|
|
135
142
|
this._encodeString(bytes, 'metrics')
|
|
@@ -137,7 +144,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
137
144
|
}
|
|
138
145
|
|
|
139
146
|
_encodeTestSession (bytes, content) {
|
|
140
|
-
|
|
147
|
+
bytes.writeMapPrefix(TEST_SESSION_KEYS_LENGTH)
|
|
141
148
|
this._encodeString(bytes, 'type')
|
|
142
149
|
this._encodeString(bytes, content.type)
|
|
143
150
|
|
|
@@ -145,7 +152,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
145
152
|
this._encodeId(bytes, content.trace_id)
|
|
146
153
|
|
|
147
154
|
this._encodeString(bytes, 'error')
|
|
148
|
-
|
|
155
|
+
bytes.writeNumber(content.error)
|
|
149
156
|
this._encodeString(bytes, 'name')
|
|
150
157
|
this._encodeString(bytes, content.name)
|
|
151
158
|
this._encodeString(bytes, 'service')
|
|
@@ -153,9 +160,9 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
153
160
|
this._encodeString(bytes, 'resource')
|
|
154
161
|
this._encodeString(bytes, content.resource)
|
|
155
162
|
this._encodeString(bytes, 'start')
|
|
156
|
-
|
|
163
|
+
bytes.writeNumber(content.start)
|
|
157
164
|
this._encodeString(bytes, 'duration')
|
|
158
|
-
|
|
165
|
+
bytes.writeNumber(content.duration)
|
|
159
166
|
this._encodeString(bytes, 'meta')
|
|
160
167
|
this._encodeMap(bytes, content.meta)
|
|
161
168
|
this._encodeString(bytes, 'metrics')
|
|
@@ -180,7 +187,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
180
187
|
if (content.type) {
|
|
181
188
|
totalKeysLength += 1
|
|
182
189
|
}
|
|
183
|
-
|
|
190
|
+
bytes.writeMapPrefix(totalKeysLength)
|
|
184
191
|
if (content.type) {
|
|
185
192
|
this._encodeString(bytes, 'type')
|
|
186
193
|
this._encodeString(bytes, content.type)
|
|
@@ -198,11 +205,11 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
198
205
|
this._encodeString(bytes, 'service')
|
|
199
206
|
this._encodeString(bytes, content.service)
|
|
200
207
|
this._encodeString(bytes, 'error')
|
|
201
|
-
|
|
208
|
+
bytes.writeNumber(content.error)
|
|
202
209
|
this._encodeString(bytes, 'start')
|
|
203
|
-
|
|
210
|
+
bytes.writeNumber(content.start)
|
|
204
211
|
this._encodeString(bytes, 'duration')
|
|
205
|
-
|
|
212
|
+
bytes.writeNumber(content.duration)
|
|
206
213
|
/**
|
|
207
214
|
* We include `test_session_id` and `test_suite_id`
|
|
208
215
|
* in the root of the event by passing them via the `meta` dict.
|
|
@@ -243,12 +250,12 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
243
250
|
}
|
|
244
251
|
|
|
245
252
|
_encodeEvent (bytes, event) {
|
|
246
|
-
|
|
253
|
+
bytes.writeMapPrefix(Object.keys(event).length)
|
|
247
254
|
this._encodeString(bytes, 'type')
|
|
248
255
|
this._encodeString(bytes, event.type)
|
|
249
256
|
|
|
250
257
|
this._encodeString(bytes, 'version')
|
|
251
|
-
|
|
258
|
+
bytes.writeNumber(event.version)
|
|
252
259
|
|
|
253
260
|
this._encodeString(bytes, 'content')
|
|
254
261
|
if (event.type === 'span' || event.type === 'test') {
|
|
@@ -318,6 +325,7 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
318
325
|
'*': {
|
|
319
326
|
language: 'javascript',
|
|
320
327
|
library_version: ddTraceVersion,
|
|
328
|
+
...this.wildcardMetadataTags,
|
|
321
329
|
},
|
|
322
330
|
...this.metadataTags,
|
|
323
331
|
},
|
|
@@ -331,11 +339,11 @@ class AgentlessCiVisibilityEncoder extends AgentEncoder {
|
|
|
331
339
|
payload.metadata['*']['runtime-id'] = this.runtimeId
|
|
332
340
|
}
|
|
333
341
|
|
|
334
|
-
|
|
342
|
+
bytes.writeMapPrefix(Object.keys(payload).length)
|
|
335
343
|
this._encodeString(bytes, 'version')
|
|
336
|
-
|
|
344
|
+
bytes.writeNumber(payload.version)
|
|
337
345
|
this._encodeString(bytes, 'metadata')
|
|
338
|
-
|
|
346
|
+
bytes.writeMapPrefix(Object.keys(payload.metadata).length)
|
|
339
347
|
this._encodeString(bytes, '*')
|
|
340
348
|
this._encodeMap(bytes, payload.metadata['*'])
|
|
341
349
|
if (payload.metadata.test) {
|
|
@@ -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 >
|
|
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
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
57
|
-
for (const
|
|
58
|
-
|
|
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.
|
|
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
|
-
|
|
97
|
+
bytes.writeMapPrefix(COVERAGE_KEYS_LENGTH)
|
|
79
98
|
this._encodeString(bytes, 'version')
|
|
80
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
54
|
+
bytes.writeLong(stat.Hits)
|
|
55
55
|
|
|
56
56
|
this._encodeString(bytes, 'Errors')
|
|
57
|
-
|
|
57
|
+
bytes.writeLong(stat.Errors)
|
|
58
58
|
|
|
59
59
|
this._encodeString(bytes, 'Duration')
|
|
60
|
-
|
|
60
|
+
bytes.writeLong(stat.Duration)
|
|
61
61
|
|
|
62
62
|
this._encodeString(bytes, 'OkSummary')
|
|
63
|
-
|
|
63
|
+
bytes.writeBin(stat.OkSummary)
|
|
64
64
|
|
|
65
65
|
this._encodeString(bytes, 'ErrorSummary')
|
|
66
|
-
|
|
66
|
+
bytes.writeBin(stat.ErrorSummary)
|
|
67
67
|
|
|
68
68
|
this._encodeString(bytes, 'Synthetics')
|
|
69
|
-
|
|
69
|
+
bytes.writeBoolean(stat.Synthetics)
|
|
70
70
|
|
|
71
71
|
this._encodeString(bytes, 'TopLevelHits')
|
|
72
|
-
|
|
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
|
-
|
|
85
|
+
bytes.writeMapPrefix(3)
|
|
86
86
|
|
|
87
87
|
this._encodeString(bytes, 'Start')
|
|
88
|
-
|
|
88
|
+
bytes.writeLong(bucket.Start)
|
|
89
89
|
|
|
90
90
|
this._encodeString(bytes, 'Duration')
|
|
91
|
-
|
|
91
|
+
bytes.writeLong(bucket.Duration)
|
|
92
92
|
|
|
93
93
|
this._encodeString(bytes, 'Stats')
|
|
94
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
@@ -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().
|
|
44
|
+
return /** @type {SpanTags} */ (ctx.attributes ?? span?.context().getTags() ?? {})
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|