dd-trace 5.80.0 → 5.81.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 +79 -88
- package/ext/tags.d.ts +1 -0
- package/ext/tags.js +1 -0
- package/index.d.ts +35 -35
- package/loader-hook.mjs +10 -3
- package/package.json +22 -40
- package/packages/datadog-esbuild/index.js +36 -19
- package/packages/datadog-instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/anthropic.js +12 -0
- package/packages/datadog-instrumentations/src/aws-sdk.js +5 -1
- package/packages/datadog-instrumentations/src/cucumber.js +2 -2
- package/packages/datadog-instrumentations/src/find-my-way.js +6 -5
- package/packages/datadog-instrumentations/src/google-genai.js +120 -0
- package/packages/datadog-instrumentations/src/graphql.js +20 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +10 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +6 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +27 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +152 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +5 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langchain.js +237 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.js +9 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/loader.mjs +11 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +139 -0
- package/packages/datadog-instrumentations/src/langchain.js +3 -109
- package/packages/datadog-instrumentations/src/mocha/main.js +1 -1
- package/packages/datadog-instrumentations/src/mysql2.js +1 -1
- package/packages/datadog-instrumentations/src/playwright.js +45 -16
- package/packages/datadog-instrumentations/src/router.js +1 -1
- package/packages/datadog-instrumentations/src/selenium.js +3 -1
- package/packages/datadog-instrumentations/src/ws.js +35 -17
- package/packages/datadog-plugin-child_process/src/scrub-cmd-params.js +1 -1
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +23 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +1 -1
- package/packages/datadog-plugin-cypress/src/support.js +73 -31
- package/packages/datadog-plugin-google-genai/src/index.js +17 -0
- package/packages/datadog-plugin-google-genai/src/tracing.js +41 -0
- package/packages/datadog-plugin-graphql/src/tools/transforms.js +5 -4
- package/packages/datadog-plugin-jest/src/util.js +1 -1
- package/packages/datadog-plugin-langchain/src/tracing.js +7 -3
- package/packages/datadog-plugin-next/src/index.js +11 -3
- package/packages/dd-trace/src/aiguard/sdk.js +18 -10
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/iast/overhead-controller.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-esm.mjs +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +1 -2
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
- package/packages/dd-trace/src/appsec/reporter.js +0 -4
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +4 -8
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +4 -2
- package/packages/dd-trace/src/config.js +81 -7
- package/packages/dd-trace/src/config_defaults.js +14 -2
- package/packages/dd-trace/src/datastreams/encoding.js +23 -6
- package/packages/dd-trace/src/datastreams/pathway.js +40 -1
- package/packages/dd-trace/src/datastreams/processor.js +1 -1
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/breakpoints.js +15 -5
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +30 -15
- package/packages/dd-trace/src/debugger/devtools_client/inspector_promises_polyfill.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +24 -18
- package/packages/dd-trace/src/debugger/devtools_client/send.js +18 -8
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +103 -15
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/constants.js +25 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +56 -25
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +64 -23
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +3 -1
- package/packages/dd-trace/src/debugger/devtools_client/snapshot-pruner.js +404 -0
- package/packages/dd-trace/src/debugger/devtools_client/source-maps.js +1 -1
- package/packages/dd-trace/src/debugger/devtools_client/state.js +7 -2
- package/packages/dd-trace/src/debugger/devtools_client/status.js +1 -1
- package/packages/dd-trace/src/debugger/index.js +1 -1
- package/packages/dd-trace/src/encode/span-stats.js +7 -1
- package/packages/dd-trace/src/histogram.js +1 -1
- package/packages/dd-trace/src/id.js +60 -0
- package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
- package/packages/dd-trace/src/llmobs/constants/tags.js +1 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +104 -0
- package/packages/dd-trace/src/llmobs/plugins/genai/util.js +486 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +2 -2
- package/packages/dd-trace/src/llmobs/plugins/{openai.js → openai/index.js} +48 -6
- package/packages/dd-trace/src/llmobs/plugins/openai/utils.js +114 -0
- package/packages/dd-trace/src/llmobs/sdk.js +5 -0
- package/packages/dd-trace/src/llmobs/span_processor.js +6 -1
- package/packages/dd-trace/src/llmobs/tagger.js +4 -0
- package/packages/dd-trace/src/opentelemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/opentelemetry/logs/logger.js +3 -2
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +5 -3
- package/packages/dd-trace/src/opentelemetry/logs/otlp_transformer.js +8 -8
- package/packages/dd-trace/src/opentelemetry/metrics/constants.js +34 -0
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +81 -0
- package/packages/dd-trace/src/opentelemetry/metrics/instruments.js +225 -0
- package/packages/dd-trace/src/opentelemetry/metrics/meter.js +171 -0
- package/packages/dd-trace/src/opentelemetry/metrics/meter_provider.js +54 -0
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +62 -0
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_transformer.js +251 -0
- package/packages/dd-trace/src/opentelemetry/metrics/periodic_metric_reader.js +532 -0
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +10 -18
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_transformer_base.js +36 -22
- package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +1 -1
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -1
- package/packages/dd-trace/src/opentelemetry/tracer_provider.js +1 -1
- package/packages/dd-trace/src/payload-tagging/index.js +2 -2
- package/packages/dd-trace/src/plugin_manager.js +4 -2
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/test.js +3 -3
- package/packages/dd-trace/src/plugins/util/url.js +119 -1
- package/packages/dd-trace/src/plugins/util/web.js +10 -41
- package/packages/dd-trace/src/process-tags/index.js +81 -0
- package/packages/dd-trace/src/profiling/config.js +1 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/events.js +10 -1
- package/packages/dd-trace/src/proxy.js +5 -0
- package/packages/dd-trace/src/rate_limiter.js +1 -1
- package/packages/dd-trace/src/remote_config/manager.js +1 -1
- package/packages/dd-trace/src/ritm.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +4 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +4 -0
- package/packages/dd-trace/src/span_format.js +9 -4
- package/packages/dd-trace/src/span_processor.js +8 -3
- package/packages/dd-trace/src/span_stats.js +15 -4
- package/packages/dd-trace/src/spanleak.js +1 -1
- package/packages/dd-trace/src/supported-configurations.json +13 -0
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/telemetry.js +11 -2
- package/vendor/dist/@datadog/sketches-js/LICENSE +39 -0
- package/vendor/dist/@datadog/sketches-js/index.js +1 -0
- package/vendor/dist/@datadog/source-map/LICENSE +28 -0
- package/vendor/dist/@datadog/source-map/index.js +1 -0
- package/vendor/dist/@isaacs/ttlcache/LICENSE +55 -0
- package/vendor/dist/@isaacs/ttlcache/index.js +1 -0
- package/vendor/dist/@opentelemetry/core/LICENSE +201 -0
- package/vendor/dist/@opentelemetry/core/index.js +1 -0
- package/vendor/dist/@opentelemetry/resources/LICENSE +201 -0
- package/vendor/dist/@opentelemetry/resources/index.js +1 -0
- package/vendor/dist/astring/LICENSE +19 -0
- package/vendor/dist/astring/index.js +1 -0
- package/vendor/dist/crypto-randomuuid/index.js +1 -0
- package/vendor/dist/escape-string-regexp/LICENSE +9 -0
- package/vendor/dist/escape-string-regexp/index.js +1 -0
- package/vendor/dist/esquery/LICENSE +24 -0
- package/vendor/dist/esquery/index.js +1 -0
- package/vendor/dist/ignore/LICENSE +21 -0
- package/vendor/dist/ignore/index.js +1 -0
- package/vendor/dist/istanbul-lib-coverage/LICENSE +24 -0
- package/vendor/dist/istanbul-lib-coverage/index.js +1 -0
- package/vendor/dist/jest-docblock/LICENSE +21 -0
- package/vendor/dist/jest-docblock/index.js +1 -0
- package/vendor/dist/jsonpath-plus/LICENSE +22 -0
- package/vendor/dist/jsonpath-plus/index.js +1 -0
- package/vendor/dist/limiter/LICENSE +19 -0
- package/vendor/dist/limiter/index.js +1 -0
- package/vendor/dist/lodash.sortby/LICENSE +47 -0
- package/vendor/dist/lodash.sortby/index.js +1 -0
- package/vendor/dist/lru-cache/LICENSE +15 -0
- package/vendor/dist/lru-cache/index.js +1 -0
- package/vendor/dist/meriyah/LICENSE +7 -0
- package/vendor/dist/meriyah/index.js +1 -0
- package/vendor/dist/module-details-from-path/LICENSE +21 -0
- package/vendor/dist/module-details-from-path/index.js +1 -0
- package/vendor/dist/mutexify/promise/LICENSE +21 -0
- package/vendor/dist/mutexify/promise/index.js +1 -0
- package/vendor/dist/opentracing/LICENSE +201 -0
- package/vendor/dist/opentracing/binary_carrier.d.ts +11 -0
- package/vendor/dist/opentracing/constants.d.ts +61 -0
- package/vendor/dist/opentracing/examples/demo/demo.d.ts +2 -0
- package/vendor/dist/opentracing/ext/tags.d.ts +90 -0
- package/vendor/dist/opentracing/functions.d.ts +20 -0
- package/vendor/dist/opentracing/global_tracer.d.ts +14 -0
- package/vendor/dist/opentracing/index.d.ts +12 -0
- package/vendor/dist/opentracing/index.js +1 -0
- package/vendor/dist/opentracing/mock_tracer/index.d.ts +5 -0
- package/vendor/dist/opentracing/mock_tracer/mock_context.d.ts +13 -0
- package/vendor/dist/opentracing/mock_tracer/mock_report.d.ts +16 -0
- package/vendor/dist/opentracing/mock_tracer/mock_span.d.ts +50 -0
- package/vendor/dist/opentracing/mock_tracer/mock_tracer.d.ts +26 -0
- package/vendor/dist/opentracing/noop.d.ts +8 -0
- package/vendor/dist/opentracing/reference.d.ts +33 -0
- package/vendor/dist/opentracing/span.d.ts +147 -0
- package/vendor/dist/opentracing/span_context.d.ts +26 -0
- package/vendor/dist/opentracing/test/api_compatibility.d.ts +16 -0
- package/vendor/dist/opentracing/test/mocktracer_implemenation.d.ts +3 -0
- package/vendor/dist/opentracing/test/noop_implementation.d.ts +4 -0
- package/vendor/dist/opentracing/test/opentracing_api.d.ts +3 -0
- package/vendor/dist/opentracing/test/unittest.d.ts +2 -0
- package/vendor/dist/opentracing/tracer.d.ts +127 -0
- package/vendor/dist/path-to-regexp/LICENSE +21 -0
- package/vendor/dist/path-to-regexp/index.js +1 -0
- package/vendor/dist/pprof-format/LICENSE +8 -0
- package/vendor/dist/pprof-format/index.js +1 -0
- package/vendor/dist/protobufjs/LICENSE +39 -0
- package/vendor/dist/protobufjs/index.js +1 -0
- package/vendor/dist/protobufjs/minimal/LICENSE +39 -0
- package/vendor/dist/protobufjs/minimal/index.js +1 -0
- package/vendor/dist/retry/LICENSE +21 -0
- package/vendor/dist/retry/index.js +1 -0
- package/vendor/dist/rfdc/LICENSE +15 -0
- package/vendor/dist/rfdc/index.js +1 -0
- package/vendor/dist/semifies/LICENSE +201 -0
- package/vendor/dist/semifies/index.js +1 -0
- package/vendor/dist/shell-quote/LICENSE +24 -0
- package/vendor/dist/shell-quote/index.js +1 -0
- package/vendor/dist/source-map/LICENSE +28 -0
- package/vendor/dist/source-map/index.js +1 -0
- package/vendor/dist/source-map/lib/util/LICENSE +28 -0
- package/vendor/dist/source-map/lib/util/index.js +1 -0
- package/vendor/dist/source-map/mappings.wasm +0 -0
- package/vendor/dist/tlhunter-sorted-set/LICENSE +21 -0
- package/vendor/dist/tlhunter-sorted-set/index.js +1 -0
- package/vendor/dist/ttl-set/LICENSE +21 -0
- package/vendor/dist/ttl-set/index.js +1 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* This module provides functionality to intelligently prune oversized JSON snapshots by selectively removing the
|
|
5
|
+
* largest and deepest leaf nodes while preserving the schema structure.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// The RFC specifies that we should prune nodes at level 5 or deeper, but the Node.js implementation has an extra level
|
|
9
|
+
// of depth because it doesn't use the compound key `debugger.snapshot`, but individual `debugger` and `snapshot` keys,
|
|
10
|
+
// so we prune at level 6 or deeper. This level contains the `locals` key.
|
|
11
|
+
const MIN_PRUNE_LEVEL = 6
|
|
12
|
+
const PRUNED_JSON = '{"pruned":true}'
|
|
13
|
+
const PRUNED_JSON_BYTES = Buffer.byteLength(PRUNED_JSON)
|
|
14
|
+
|
|
15
|
+
module.exports = { pruneSnapshot }
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Tree node representing a JSON object in the parsed structure
|
|
19
|
+
*/
|
|
20
|
+
class TreeNode {
|
|
21
|
+
/** @type {number} End position in JSON string (set when object closes) */
|
|
22
|
+
end = -1
|
|
23
|
+
/** @type {TreeNode[]} Child nodes */
|
|
24
|
+
children = []
|
|
25
|
+
/** @type {boolean} Has notCapturedReason: "depth" */
|
|
26
|
+
notCapturedDepth = false
|
|
27
|
+
/** @type {boolean} Has any notCapturedReason */
|
|
28
|
+
notCaptured = false
|
|
29
|
+
/** @type {number} Cached byte size */
|
|
30
|
+
#sizeCache = -1
|
|
31
|
+
/** @type {[number, number, number, number]|null} Cached priority key */
|
|
32
|
+
#priorityKeyCache = null
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {number} start - Start position in JSON string
|
|
36
|
+
* @param {number} level - Depth in tree (root = 0)
|
|
37
|
+
* @param {string} json - Reference to original JSON string
|
|
38
|
+
* @param {TreeNode|null} [parent] - Parent node reference
|
|
39
|
+
*/
|
|
40
|
+
constructor (start, level, json, parent = null) {
|
|
41
|
+
/** @type {number} Start position in JSON string */
|
|
42
|
+
this.start = start
|
|
43
|
+
/** @type {number} Depth in tree (root = 0) */
|
|
44
|
+
this.level = level
|
|
45
|
+
/** @type {string} Reference to original JSON string */
|
|
46
|
+
this.json = json
|
|
47
|
+
/** @type {TreeNode|null} Parent node reference */
|
|
48
|
+
this.parent = parent
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
get size () {
|
|
52
|
+
if (this.#sizeCache === -1) {
|
|
53
|
+
if (this.end === -1) {
|
|
54
|
+
throw new Error('Cannot get size: node.end has not been set yet')
|
|
55
|
+
}
|
|
56
|
+
this.#sizeCache = Buffer.byteLength(this.json.slice(this.start, this.end + 1))
|
|
57
|
+
}
|
|
58
|
+
return this.#sizeCache
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get isLeaf () {
|
|
62
|
+
return this.children.length === 0
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Priority key for sorting in queue (higher values = higher priority for pruning).
|
|
67
|
+
* Cached to avoid repeated computation during heap operations.
|
|
68
|
+
*
|
|
69
|
+
* @returns {[number, number, number, number]} Priority key tuple: [not_captured_depth, level, not_captured, size]
|
|
70
|
+
*/
|
|
71
|
+
get priorityKey () {
|
|
72
|
+
if (this.#priorityKeyCache === null) {
|
|
73
|
+
this.#priorityKeyCache = [
|
|
74
|
+
this.notCapturedDepth ? 1 : 0,
|
|
75
|
+
this.level,
|
|
76
|
+
this.notCaptured ? 1 : 0,
|
|
77
|
+
this.size
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
return this.#priorityKeyCache
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Priority queue implementation using a binary heap.
|
|
86
|
+
* Items with higher priority (by priorityKey) are popped first.
|
|
87
|
+
*/
|
|
88
|
+
class PriorityQueue {
|
|
89
|
+
/** @type {TreeNode[]} Binary heap of nodes */
|
|
90
|
+
#heap = []
|
|
91
|
+
|
|
92
|
+
push (node) {
|
|
93
|
+
this.#heap.push(node)
|
|
94
|
+
this.#bubbleUp(this.#heap.length - 1)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
pop () {
|
|
98
|
+
if (this.#heap.length === 0) return
|
|
99
|
+
if (this.#heap.length === 1) return /** @type {TreeNode} */ (this.#heap.pop())
|
|
100
|
+
|
|
101
|
+
const top = this.#heap[0]
|
|
102
|
+
this.#heap[0] = /** @type {TreeNode} */ (this.#heap.pop())
|
|
103
|
+
this.#bubbleDown(0)
|
|
104
|
+
return top
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
get size () {
|
|
108
|
+
return this.#heap.length
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#bubbleUp (index) {
|
|
112
|
+
while (index > 0) {
|
|
113
|
+
const parentIndex = Math.floor((index - 1) / 2)
|
|
114
|
+
if (this.#compare(this.#heap[index], this.#heap[parentIndex]) <= 0) break
|
|
115
|
+
|
|
116
|
+
[this.#heap[index], this.#heap[parentIndex]] = [this.#heap[parentIndex], this.#heap[index]]
|
|
117
|
+
index = parentIndex
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
#bubbleDown (index) {
|
|
122
|
+
while (true) {
|
|
123
|
+
let largest = index
|
|
124
|
+
const leftChild = 2 * index + 1
|
|
125
|
+
const rightChild = 2 * index + 2
|
|
126
|
+
|
|
127
|
+
if (leftChild < this.#heap.length && this.#compare(this.#heap[leftChild], this.#heap[largest]) > 0) {
|
|
128
|
+
largest = leftChild
|
|
129
|
+
}
|
|
130
|
+
if (rightChild < this.#heap.length && this.#compare(this.#heap[rightChild], this.#heap[largest]) > 0) {
|
|
131
|
+
largest = rightChild
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (largest === index) break
|
|
135
|
+
|
|
136
|
+
[this.#heap[index], this.#heap[largest]] = [this.#heap[largest], this.#heap[index]]
|
|
137
|
+
index = largest
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Compare two nodes by their priority keys.
|
|
143
|
+
*
|
|
144
|
+
* @param {TreeNode} a - First node to compare
|
|
145
|
+
* @param {TreeNode} b - Second node to compare
|
|
146
|
+
* @returns {number} - > 0 if a has higher priority, < 0 if b has higher priority, 0 if equal
|
|
147
|
+
*/
|
|
148
|
+
#compare (a, b) {
|
|
149
|
+
const keyA = a.priorityKey
|
|
150
|
+
const keyB = b.priorityKey
|
|
151
|
+
for (let i = 0; i < 4; i++) {
|
|
152
|
+
if (keyA[i] !== keyB[i]) {
|
|
153
|
+
return keyA[i] - keyB[i]
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return 0
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Parse JSON string and build a tree of objects with position tracking.
|
|
162
|
+
* Also detects notCapturedReason properties to set node flags.
|
|
163
|
+
*
|
|
164
|
+
* @param {string} json - The JSON string to parse
|
|
165
|
+
* @returns {TreeNode|null} The root node of the tree, or null if parsing fails
|
|
166
|
+
*/
|
|
167
|
+
function parseJsonToTree (json) {
|
|
168
|
+
/** @type {TreeNode[]} Stack of nodes */
|
|
169
|
+
const stack = []
|
|
170
|
+
/** @type {TreeNode|null} The root node of the tree, or null if parsing fails */
|
|
171
|
+
let root = null
|
|
172
|
+
let depth = 0
|
|
173
|
+
|
|
174
|
+
for (let index = 0; index < json.length; index++) {
|
|
175
|
+
switch (json.charCodeAt(index)) {
|
|
176
|
+
case 34: { // 34: double quote
|
|
177
|
+
const stringStart = index + 1
|
|
178
|
+
index = skipString(json, index)
|
|
179
|
+
const stringLength = index - stringStart
|
|
180
|
+
|
|
181
|
+
// Check if this is "notCapturedReason" property (check length first for performance)
|
|
182
|
+
if (stringLength === 17 && json.startsWith('notCapturedReason', stringStart)) {
|
|
183
|
+
// Look ahead for colon and value
|
|
184
|
+
let ahead = index + 1
|
|
185
|
+
|
|
186
|
+
// Skip whitespace and colon
|
|
187
|
+
while (ahead < json.length) {
|
|
188
|
+
const code = json.charCodeAt(ahead)
|
|
189
|
+
// 32: space, 9: tab, 10: newline, 13: carriage return, 58: colon
|
|
190
|
+
if (code === 32 || code === 9 || code === 10 || code === 13 || code === 58) {
|
|
191
|
+
ahead++
|
|
192
|
+
} else {
|
|
193
|
+
break
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Check if value is a string (34: double quote)
|
|
198
|
+
if (ahead < json.length && json.charCodeAt(ahead) === 34) {
|
|
199
|
+
const valueStart = ahead + 1
|
|
200
|
+
ahead = skipString(json, ahead)
|
|
201
|
+
const reason = json.slice(valueStart, ahead)
|
|
202
|
+
|
|
203
|
+
const currentNode = /** @type {TreeNode} */ (stack.at(-1))
|
|
204
|
+
currentNode.notCaptured = true
|
|
205
|
+
if (reason === 'depth') {
|
|
206
|
+
currentNode.notCapturedDepth = true
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
break
|
|
211
|
+
}
|
|
212
|
+
case 123: { // 123: opening brace
|
|
213
|
+
const parentNode = stack.at(-1)
|
|
214
|
+
const level = depth
|
|
215
|
+
const node = new TreeNode(index, level, json, parentNode)
|
|
216
|
+
|
|
217
|
+
if (parentNode) {
|
|
218
|
+
parentNode.children.push(node)
|
|
219
|
+
} else {
|
|
220
|
+
root = node
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
stack.push(node)
|
|
224
|
+
depth++
|
|
225
|
+
break
|
|
226
|
+
}
|
|
227
|
+
case 125: { // 125: closing brace
|
|
228
|
+
const node = stack.pop()
|
|
229
|
+
if (node === undefined) throw new SyntaxError('Invalid JSON: unexpected closing brace')
|
|
230
|
+
node.end = index
|
|
231
|
+
depth--
|
|
232
|
+
break
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return root
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Skip to the end of a JSON string, properly handling escape sequences.
|
|
242
|
+
*
|
|
243
|
+
* @param {string} json - The JSON string to skip
|
|
244
|
+
* @param {number} startIndex - The index to start skipping from
|
|
245
|
+
* @returns {number} The index of the closing quote
|
|
246
|
+
*/
|
|
247
|
+
function skipString (json, startIndex) {
|
|
248
|
+
let index = startIndex + 1 // Skip opening quote
|
|
249
|
+
|
|
250
|
+
while (index < json.length) {
|
|
251
|
+
const code = json.charCodeAt(index)
|
|
252
|
+
|
|
253
|
+
if (code === 92) { // 92: backslash
|
|
254
|
+
// Skip the backslash and the next character (whatever it is)
|
|
255
|
+
index += 2
|
|
256
|
+
continue
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (code === 34) { // 34: double quote
|
|
260
|
+
// Found unescaped closing quote
|
|
261
|
+
return index
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
index++
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return index
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Collect all leaf nodes at MIN_PRUNE_LEVEL or deeper.
|
|
272
|
+
*
|
|
273
|
+
* @param {TreeNode} root - The root node of the tree
|
|
274
|
+
* @returns {TreeNode[]} The array of leaf nodes
|
|
275
|
+
*/
|
|
276
|
+
function collectPrunableLeaves (root) {
|
|
277
|
+
const leaves = []
|
|
278
|
+
|
|
279
|
+
function traverse (node) {
|
|
280
|
+
if (!node) return
|
|
281
|
+
|
|
282
|
+
if (node.isLeaf && node.level >= MIN_PRUNE_LEVEL) {
|
|
283
|
+
leaves.push(node)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
for (const child of node.children) {
|
|
287
|
+
traverse(child)
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
traverse(root)
|
|
292
|
+
return leaves
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Select nodes to prune using the priority queue algorithm.
|
|
297
|
+
*
|
|
298
|
+
* @param {TreeNode} root - The root node of the tree
|
|
299
|
+
* @param {number} bytesToRemove - The number of bytes to remove
|
|
300
|
+
* @returns {Set<TreeNode>} The set of nodes marked for pruning
|
|
301
|
+
*/
|
|
302
|
+
function selectNodesToPrune (root, bytesToRemove) {
|
|
303
|
+
const queue = new PriorityQueue()
|
|
304
|
+
const prunedNodes = new Set()
|
|
305
|
+
const promotedParents = new Set()
|
|
306
|
+
|
|
307
|
+
// Collect initial leaf nodes
|
|
308
|
+
const leaves = collectPrunableLeaves(root)
|
|
309
|
+
for (const leaf of leaves) {
|
|
310
|
+
queue.push(leaf)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
let bytesRemoved = 0
|
|
314
|
+
|
|
315
|
+
while (queue.size > 0 && bytesRemoved < bytesToRemove) {
|
|
316
|
+
const node = /** @type {TreeNode} */ (queue.pop())
|
|
317
|
+
|
|
318
|
+
if (prunedNodes.has(node)) continue
|
|
319
|
+
prunedNodes.add(node)
|
|
320
|
+
|
|
321
|
+
bytesRemoved += node.size - PRUNED_JSON_BYTES
|
|
322
|
+
|
|
323
|
+
// Check if parent should be promoted to leaf
|
|
324
|
+
const parent = node.parent
|
|
325
|
+
if (parent && parent.level >= MIN_PRUNE_LEVEL && !promotedParents.has(parent)) {
|
|
326
|
+
// Check if all children are now pruned
|
|
327
|
+
const allChildrenPruned = parent.children.every(child => prunedNodes.has(child))
|
|
328
|
+
|
|
329
|
+
if (allChildrenPruned) {
|
|
330
|
+
// Unmark all children as pruned (parent will represent them)
|
|
331
|
+
for (const child of parent.children) {
|
|
332
|
+
prunedNodes.delete(child)
|
|
333
|
+
bytesRemoved -= child.size - PRUNED_JSON_BYTES
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Promote parent to leaf by marking it with notCapturedDepth flag
|
|
337
|
+
parent.notCaptured = true
|
|
338
|
+
parent.notCapturedDepth = true
|
|
339
|
+
promotedParents.add(parent)
|
|
340
|
+
|
|
341
|
+
// Add parent to queue for potential pruning
|
|
342
|
+
queue.push(parent)
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return prunedNodes
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Rebuild JSON string with pruned nodes replaced by {"pruned":true}
|
|
352
|
+
*
|
|
353
|
+
* @param {string} json - The JSON string to rebuild
|
|
354
|
+
* @param {Set<TreeNode>} prunedNodes - The set of nodes to replace with {"pruned":true}
|
|
355
|
+
* @returns {string} The rebuilt JSON string
|
|
356
|
+
*/
|
|
357
|
+
function rebuildJson (json, prunedNodes) {
|
|
358
|
+
// Convert set to array and sort by start position (descending)
|
|
359
|
+
const sortedNodes = [...prunedNodes].sort((a, b) => b.start - a.start)
|
|
360
|
+
|
|
361
|
+
// Replace from end to start to maintain position indices
|
|
362
|
+
for (const node of sortedNodes) {
|
|
363
|
+
const before = json.slice(0, node.start)
|
|
364
|
+
const after = json.slice(node.end + 1)
|
|
365
|
+
json = before + PRUNED_JSON + after
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return json
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Main pruning function
|
|
373
|
+
*
|
|
374
|
+
* @param {string} json - The JSON string to prune
|
|
375
|
+
* @param {number} originalSize - Size of the original JSON string in bytes
|
|
376
|
+
* @param {number} maxSize - Maximum allowed size in bytes
|
|
377
|
+
* @returns {string|undefined} - Pruned JSON string, or undefined if pruning fails
|
|
378
|
+
*/
|
|
379
|
+
function pruneSnapshot (json, originalSize, maxSize) {
|
|
380
|
+
const bytesToRemove = originalSize - maxSize
|
|
381
|
+
|
|
382
|
+
if (bytesToRemove <= 0) return json // No pruning needed
|
|
383
|
+
|
|
384
|
+
let prunedSize = originalSize
|
|
385
|
+
let attempts = 0
|
|
386
|
+
const maxAttempts = 6
|
|
387
|
+
|
|
388
|
+
while (prunedSize > maxSize && attempts < maxAttempts) {
|
|
389
|
+
attempts++
|
|
390
|
+
|
|
391
|
+
const root = parseJsonToTree(json)
|
|
392
|
+
if (!root) break
|
|
393
|
+
|
|
394
|
+
const targetBytesToRemove = prunedSize - maxSize
|
|
395
|
+
const prunedNodes = selectNodesToPrune(root, targetBytesToRemove)
|
|
396
|
+
if (prunedNodes.size === 0) break
|
|
397
|
+
|
|
398
|
+
json = rebuildJson(json, prunedNodes)
|
|
399
|
+
prunedSize = Buffer.byteLength(json)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// If pruning didn't help, return undefined
|
|
403
|
+
return prunedSize >= originalSize ? undefined : json
|
|
404
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const { join, dirname } = require('path')
|
|
4
4
|
const { readFileSync } = require('fs')
|
|
5
5
|
const { readFile } = require('fs/promises')
|
|
6
|
-
const { SourceMapConsumer } = require('source-map')
|
|
6
|
+
const { SourceMapConsumer } = require('../../../../../vendor/dist/source-map')
|
|
7
7
|
|
|
8
8
|
const cache = new Map()
|
|
9
9
|
let cacheTimer = null
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { join, dirname } = require('path')
|
|
4
|
-
const { normalize } = require('source-map/lib/util')
|
|
4
|
+
const { normalize } = require('../../../../../vendor/dist/source-map/lib/util')
|
|
5
5
|
const { loadSourceMapSync } = require('./source-maps')
|
|
6
6
|
const session = require('./session')
|
|
7
7
|
const log = require('./log')
|
|
@@ -81,9 +81,14 @@ module.exports = {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
// If we found a valid match and it's better than our previous best
|
|
84
|
+
// Note: bestMatch.url cannot be null when comparing lengths because:
|
|
85
|
+
// - The first time we enter this block, lastBoundaryPos > maxMatchLength is always true
|
|
86
|
+
// - We set bestMatch.url before we could evaluate the second condition
|
|
87
|
+
// - Subsequent evaluations have bestMatch.url already set
|
|
84
88
|
if (atBoundary && (
|
|
85
89
|
lastBoundaryPos > maxMatchLength ||
|
|
86
|
-
(lastBoundaryPos === maxMatchLength &&
|
|
90
|
+
(lastBoundaryPos === maxMatchLength &&
|
|
91
|
+
url.length < /** @type {string} */ (/** @type {unknown} */ (bestMatch.url)).length) // Prefer shorter paths
|
|
87
92
|
)) {
|
|
88
93
|
maxMatchLength = lastBoundaryPos
|
|
89
94
|
bestMatch.url = sourceUrl || url
|
|
@@ -89,7 +89,7 @@ function start (config, rc) {
|
|
|
89
89
|
|
|
90
90
|
log.error('[debugger] worker thread exited unexpectedly', error)
|
|
91
91
|
|
|
92
|
-
// Be nice, clean up now that the worker thread
|
|
92
|
+
// Be nice, clean up now that the worker thread encountered an issue and we can't continue
|
|
93
93
|
rc.removeProductHandler('LIVE_DEBUGGING')
|
|
94
94
|
worker.removeAllListeners()
|
|
95
95
|
configChannel = null
|
|
@@ -31,7 +31,7 @@ class SpanStatsEncoder extends AgentEncoder {
|
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
_encodeStat (bytes, stat) {
|
|
34
|
-
this._encodeMapPrefix(bytes,
|
|
34
|
+
this._encodeMapPrefix(bytes, 14)
|
|
35
35
|
|
|
36
36
|
this._encodeString(bytes, 'Service')
|
|
37
37
|
const service = stat.Service || DEFAULT_SERVICE_NAME
|
|
@@ -70,6 +70,12 @@ class SpanStatsEncoder extends AgentEncoder {
|
|
|
70
70
|
|
|
71
71
|
this._encodeString(bytes, 'TopLevelHits')
|
|
72
72
|
this._encodeLong(bytes, stat.TopLevelHits)
|
|
73
|
+
|
|
74
|
+
this._encodeString(bytes, 'HTTPMethod')
|
|
75
|
+
this._encodeString(bytes, stat.HTTPMethod)
|
|
76
|
+
|
|
77
|
+
this._encodeString(bytes, 'HTTPEndpoint')
|
|
78
|
+
this._encodeString(bytes, stat.HTTPEndpoint)
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
_encodeBucket (bytes, bucket) {
|
|
@@ -14,26 +14,43 @@ let batch = 0
|
|
|
14
14
|
|
|
15
15
|
// Internal representation of a trace or span ID.
|
|
16
16
|
class Identifier {
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} value
|
|
19
|
+
* @param {number} [radix]
|
|
20
|
+
*/
|
|
17
21
|
constructor (value, radix = 16) {
|
|
18
22
|
this._buffer = radix === 16
|
|
19
23
|
? createBuffer(value)
|
|
20
24
|
: fromString(value, radix)
|
|
21
25
|
}
|
|
22
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @param {number} [radix]
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
23
31
|
toString (radix = 16) {
|
|
24
32
|
return radix === 16
|
|
25
33
|
? toHexString(this._buffer)
|
|
26
34
|
: toNumberString(this._buffer, radix)
|
|
27
35
|
}
|
|
28
36
|
|
|
37
|
+
/**
|
|
38
|
+
* @returns {bigint}
|
|
39
|
+
*/
|
|
29
40
|
toBigInt () {
|
|
30
41
|
return Buffer.from(this._buffer).readBigUInt64BE(0)
|
|
31
42
|
}
|
|
32
43
|
|
|
44
|
+
/**
|
|
45
|
+
* @returns {number[] | Uint8Array}
|
|
46
|
+
*/
|
|
33
47
|
toBuffer () {
|
|
34
48
|
return this._buffer
|
|
35
49
|
}
|
|
36
50
|
|
|
51
|
+
/**
|
|
52
|
+
* @returns {number[] | Uint8Array}
|
|
53
|
+
*/
|
|
37
54
|
toArray () {
|
|
38
55
|
if (this._buffer.length === 8) {
|
|
39
56
|
return this._buffer
|
|
@@ -41,10 +58,17 @@ class Identifier {
|
|
|
41
58
|
return this._buffer.slice(-8)
|
|
42
59
|
}
|
|
43
60
|
|
|
61
|
+
/**
|
|
62
|
+
* @returns {string}
|
|
63
|
+
*/
|
|
44
64
|
toJSON () {
|
|
45
65
|
return this.toString()
|
|
46
66
|
}
|
|
47
67
|
|
|
68
|
+
/**
|
|
69
|
+
* @param {Identifier} other
|
|
70
|
+
* @returns {boolean}
|
|
71
|
+
*/
|
|
48
72
|
equals (other) {
|
|
49
73
|
const length = this._buffer.length
|
|
50
74
|
const otherLength = other._buffer.length
|
|
@@ -59,6 +83,10 @@ class Identifier {
|
|
|
59
83
|
}
|
|
60
84
|
|
|
61
85
|
// Create a buffer, using an optional hexadecimal value if provided.
|
|
86
|
+
/**
|
|
87
|
+
* @param {string} value
|
|
88
|
+
* @returns {number[] | Uint8Array}
|
|
89
|
+
*/
|
|
62
90
|
function createBuffer (value) {
|
|
63
91
|
if (value === '0') return zeroId
|
|
64
92
|
if (!value) return pseudoRandom()
|
|
@@ -77,6 +105,11 @@ function createBuffer (value) {
|
|
|
77
105
|
}
|
|
78
106
|
|
|
79
107
|
// Convert a numerical string to a buffer using the specified radix.
|
|
108
|
+
/**
|
|
109
|
+
* @param {string} str
|
|
110
|
+
* @param {number} raddix
|
|
111
|
+
* @returns {number[]}
|
|
112
|
+
*/
|
|
80
113
|
function fromString (str, raddix) {
|
|
81
114
|
const buffer = new Array(8)
|
|
82
115
|
const len = str.length
|
|
@@ -116,6 +149,11 @@ function fromString (str, raddix) {
|
|
|
116
149
|
}
|
|
117
150
|
|
|
118
151
|
// Convert a buffer to a numerical string.
|
|
152
|
+
/**
|
|
153
|
+
* @param {number[] | Uint8Array} buffer
|
|
154
|
+
* @param {number} [radix]
|
|
155
|
+
* @returns {string}
|
|
156
|
+
*/
|
|
119
157
|
function toNumberString (buffer, radix) {
|
|
120
158
|
let high = readInt32(buffer, buffer.length - 8)
|
|
121
159
|
let low = readInt32(buffer, buffer.length - 4)
|
|
@@ -137,11 +175,18 @@ function toNumberString (buffer, radix) {
|
|
|
137
175
|
}
|
|
138
176
|
|
|
139
177
|
// Convert a buffer to a hexadecimal string.
|
|
178
|
+
/**
|
|
179
|
+
* @param {number[] | Uint8Array} buffer
|
|
180
|
+
* @returns {string}
|
|
181
|
+
*/
|
|
140
182
|
function toHexString (buffer) {
|
|
141
183
|
return map.call(buffer, pad).join('')
|
|
142
184
|
}
|
|
143
185
|
|
|
144
186
|
// Simple pseudo-random 64-bit ID generator.
|
|
187
|
+
/**
|
|
188
|
+
* @returns {number[] | Uint8Array}
|
|
189
|
+
*/
|
|
145
190
|
function pseudoRandom () {
|
|
146
191
|
if (batch === 0) {
|
|
147
192
|
randomFillSync(data)
|
|
@@ -164,6 +209,11 @@ function pseudoRandom () {
|
|
|
164
209
|
}
|
|
165
210
|
|
|
166
211
|
// Read a buffer to unsigned integer bytes.
|
|
212
|
+
/**
|
|
213
|
+
* @param {number[] | Uint8Array} buffer
|
|
214
|
+
* @param {number} offset
|
|
215
|
+
* @returns {number}
|
|
216
|
+
*/
|
|
167
217
|
function readInt32 (buffer, offset) {
|
|
168
218
|
return (buffer[offset + 0] * 16_777_216) +
|
|
169
219
|
(buffer[offset + 1] << 16) +
|
|
@@ -172,6 +222,11 @@ function readInt32 (buffer, offset) {
|
|
|
172
222
|
}
|
|
173
223
|
|
|
174
224
|
// Write unsigned integer bytes to a buffer.
|
|
225
|
+
/**
|
|
226
|
+
* @param {number[] | Uint8Array} buffer
|
|
227
|
+
* @param {number} value
|
|
228
|
+
* @param {number} offset
|
|
229
|
+
*/
|
|
175
230
|
function writeUInt32BE (buffer, value, offset) {
|
|
176
231
|
buffer[3 + offset] = value & 255
|
|
177
232
|
value >>= 8
|
|
@@ -182,6 +237,11 @@ function writeUInt32BE (buffer, value, offset) {
|
|
|
182
237
|
buffer[0 + offset] = value & 255
|
|
183
238
|
}
|
|
184
239
|
|
|
240
|
+
/**
|
|
241
|
+
* @param {string} value
|
|
242
|
+
* @param {number} [radix]
|
|
243
|
+
* @returns {Identifier}
|
|
244
|
+
*/
|
|
185
245
|
module.exports = function createIdentifier (value, radix) {
|
|
186
246
|
return new Identifier(value, radix)
|
|
187
247
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Modifications copyright 2022 Datadog, Inc.
|
|
4
4
|
*
|
|
5
5
|
* Some functions are part of aws-lambda-nodejs-runtime-interface-client
|
|
6
|
-
* https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/blob/
|
|
6
|
+
* https://github.com/aws/aws-lambda-nodejs-runtime-interface-client/blob/v2.1.0/src/utils/UserFunction.ts
|
|
7
7
|
*/
|
|
8
8
|
'use strict'
|
|
9
9
|
|
|
@@ -34,6 +34,7 @@ module.exports = {
|
|
|
34
34
|
TOTAL_TOKENS_METRIC_KEY: 'total_tokens',
|
|
35
35
|
CACHE_READ_INPUT_TOKENS_METRIC_KEY: 'cache_read_input_tokens',
|
|
36
36
|
CACHE_WRITE_INPUT_TOKENS_METRIC_KEY: 'cache_write_input_tokens',
|
|
37
|
+
REASONING_OUTPUT_TOKENS_METRIC_KEY: 'reasoning_output_tokens',
|
|
37
38
|
|
|
38
39
|
DROPPED_IO_COLLECTION_ERROR: 'dropped_io'
|
|
39
40
|
}
|