dd-trace 5.30.0 → 5.31.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/package.json +3 -3
- package/packages/datadog-core/src/storage.js +11 -2
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/manager.js +11 -1
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -1
- package/packages/dd-trace/src/debugger/devtools_client/index.js +4 -3
- package/packages/dd-trace/src/debugger/devtools_client/json-buffer.js +36 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +33 -10
- package/packages/dd-trace/src/debugger/devtools_client/status.js +9 -2
- package/packages/dd-trace/src/llmobs/sdk.js +90 -26
- package/packages/dd-trace/src/log/index.js +8 -9
- package/packages/dd-trace/src/noop/proxy.js +2 -2
- package/packages/dd-trace/src/noop/span.js +1 -1
- package/packages/dd-trace/src/opentracing/span.js +11 -1
- package/packages/dd-trace/src/opentracing/span_context.js +12 -0
- package/packages/dd-trace/src/priority_sampler.js +4 -2
- package/packages/dd-trace/src/scope.js +1 -1
- package/packages/dd-trace/src/telemetry/index.js +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.31.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@datadog/libdatadog": "^0.3.0",
|
|
85
|
-
"@datadog/native-appsec": "8.
|
|
85
|
+
"@datadog/native-appsec": "8.4.0",
|
|
86
86
|
"@datadog/native-iast-rewriter": "2.6.1",
|
|
87
87
|
"@datadog/native-iast-taint-tracking": "3.2.0",
|
|
88
88
|
"@datadog/native-metrics": "^3.1.0",
|
|
@@ -145,7 +145,7 @@
|
|
|
145
145
|
"jszip": "^3.5.0",
|
|
146
146
|
"knex": "^2.4.2",
|
|
147
147
|
"mkdirp": "^3.0.1",
|
|
148
|
-
"mocha": "^
|
|
148
|
+
"mocha": "^10",
|
|
149
149
|
"msgpack-lite": "^0.1.26",
|
|
150
150
|
"multer": "^1.4.5-lts.1",
|
|
151
151
|
"nock": "^11.3.3",
|
|
@@ -21,8 +21,16 @@ class DatadogStorage {
|
|
|
21
21
|
this._storage.exit(callback, ...args)
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
// TODO: Refactor the Scope class to use a span-only store and remove this.
|
|
25
|
+
getHandle () {
|
|
26
|
+
return this._storage.getStore()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getStore (handle) {
|
|
30
|
+
if (!handle) {
|
|
31
|
+
handle = this._storage.getStore()
|
|
32
|
+
}
|
|
33
|
+
|
|
26
34
|
return stores.get(handle)
|
|
27
35
|
}
|
|
28
36
|
|
|
@@ -50,6 +58,7 @@ const storage = function (namespace) {
|
|
|
50
58
|
storage.disable = legacyStorage.disable.bind(legacyStorage)
|
|
51
59
|
storage.enterWith = legacyStorage.enterWith.bind(legacyStorage)
|
|
52
60
|
storage.exit = legacyStorage.exit.bind(legacyStorage)
|
|
61
|
+
storage.getHandle = legacyStorage.getHandle.bind(legacyStorage)
|
|
53
62
|
storage.getStore = legacyStorage.getStore.bind(legacyStorage)
|
|
54
63
|
storage.run = legacyStorage.run.bind(legacyStorage)
|
|
55
64
|
|
|
@@ -9,6 +9,7 @@ const log = require('../../log')
|
|
|
9
9
|
const { getExtraServices } = require('../../service-naming/extra-services')
|
|
10
10
|
const { UNACKNOWLEDGED, ACKNOWLEDGED, ERROR } = require('./apply_states')
|
|
11
11
|
const Scheduler = require('./scheduler')
|
|
12
|
+
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../../plugins/util/tags')
|
|
12
13
|
|
|
13
14
|
const clientId = uuid()
|
|
14
15
|
|
|
@@ -33,6 +34,14 @@ class RemoteConfigManager extends EventEmitter {
|
|
|
33
34
|
port: config.port
|
|
34
35
|
}))
|
|
35
36
|
|
|
37
|
+
const tags = config.repositoryUrl
|
|
38
|
+
? {
|
|
39
|
+
...config.tags,
|
|
40
|
+
[GIT_REPOSITORY_URL]: config.repositoryUrl,
|
|
41
|
+
[GIT_COMMIT_SHA]: config.commitSHA
|
|
42
|
+
}
|
|
43
|
+
: config.tags
|
|
44
|
+
|
|
36
45
|
this._handlers = new Map()
|
|
37
46
|
const appliedConfigs = this.appliedConfigs = new Map()
|
|
38
47
|
|
|
@@ -67,7 +76,8 @@ class RemoteConfigManager extends EventEmitter {
|
|
|
67
76
|
service: config.service,
|
|
68
77
|
env: config.env,
|
|
69
78
|
app_version: config.version,
|
|
70
|
-
extra_services: []
|
|
79
|
+
extra_services: [],
|
|
80
|
+
tags: Object.entries(tags).map((pair) => pair.join(':'))
|
|
71
81
|
},
|
|
72
82
|
capabilities: DEFAULT_CAPABILITY // updated by `updateCapabilities()`
|
|
73
83
|
},
|
|
@@ -9,7 +9,8 @@ const config = module.exports = {
|
|
|
9
9
|
service: parentConfig.service,
|
|
10
10
|
commitSHA: parentConfig.commitSHA,
|
|
11
11
|
repositoryUrl: parentConfig.repositoryUrl,
|
|
12
|
-
parentThreadId
|
|
12
|
+
parentThreadId,
|
|
13
|
+
maxTotalPayloadSize: 5 * 1024 * 1024 // 5MB
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
updateUrl(parentConfig)
|
|
@@ -129,9 +129,8 @@ session.on('Debugger.paused', async ({ params }) => {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
// TODO: Process template (DEBUG-2628)
|
|
132
|
-
send(probe.template, logger, dd, snapshot, (
|
|
133
|
-
|
|
134
|
-
else ackEmitting(probe)
|
|
132
|
+
send(probe.template, logger, dd, snapshot, () => {
|
|
133
|
+
ackEmitting(probe)
|
|
135
134
|
})
|
|
136
135
|
}
|
|
137
136
|
})
|
|
@@ -141,6 +140,8 @@ function highestOrUndefined (num, max) {
|
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
async function getDD (callFrameId) {
|
|
143
|
+
// TODO: Consider if an `objectGroup` should be used, so it can be explicitly released using
|
|
144
|
+
// `Runtime.releaseObjectGroup`
|
|
144
145
|
const { result } = await session.post('Debugger.evaluateOnCallFrame', {
|
|
145
146
|
callFrameId,
|
|
146
147
|
expression,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
class JSONBuffer {
|
|
4
|
+
constructor ({ size, timeout, onFlush }) {
|
|
5
|
+
this._maxSize = size
|
|
6
|
+
this._timeout = timeout
|
|
7
|
+
this._onFlush = onFlush
|
|
8
|
+
this._reset()
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
_reset () {
|
|
12
|
+
clearTimeout(this._timer)
|
|
13
|
+
this._timer = null
|
|
14
|
+
this._partialJson = null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_flush () {
|
|
18
|
+
const json = `${this._partialJson}]`
|
|
19
|
+
this._reset()
|
|
20
|
+
this._onFlush(json)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
write (str, size = Buffer.byteLength(str)) {
|
|
24
|
+
if (this._timer === null) {
|
|
25
|
+
this._partialJson = `[${str}`
|
|
26
|
+
this._timer = setTimeout(() => this._flush(), this._timeout)
|
|
27
|
+
} else if (Buffer.byteLength(this._partialJson) + size + 2 > this._maxSize) {
|
|
28
|
+
this._flush()
|
|
29
|
+
this.write(str, size)
|
|
30
|
+
} else {
|
|
31
|
+
this._partialJson += `,${str}`
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = JSONBuffer
|
|
@@ -4,32 +4,35 @@ const { hostname: getHostname } = require('os')
|
|
|
4
4
|
const { stringify } = require('querystring')
|
|
5
5
|
|
|
6
6
|
const config = require('./config')
|
|
7
|
+
const JSONBuffer = require('./json-buffer')
|
|
7
8
|
const request = require('../../exporters/common/request')
|
|
8
9
|
const { GIT_COMMIT_SHA, GIT_REPOSITORY_URL } = require('../../plugins/util/tags')
|
|
10
|
+
const log = require('../../log')
|
|
11
|
+
const { version } = require('../../../../../package.json')
|
|
9
12
|
|
|
10
13
|
module.exports = send
|
|
11
14
|
|
|
12
|
-
const
|
|
15
|
+
const MAX_LOG_PAYLOAD_SIZE = 1024 * 1024 // 1MB
|
|
13
16
|
|
|
14
17
|
const ddsource = 'dd_debugger'
|
|
15
18
|
const hostname = getHostname()
|
|
16
19
|
const service = config.service
|
|
17
20
|
|
|
18
21
|
const ddtags = [
|
|
22
|
+
['env', process.env.DD_ENV],
|
|
23
|
+
['version', process.env.DD_VERSION],
|
|
24
|
+
['debugger_version', version],
|
|
25
|
+
['host_name', hostname],
|
|
19
26
|
[GIT_COMMIT_SHA, config.commitSHA],
|
|
20
27
|
[GIT_REPOSITORY_URL, config.repositoryUrl]
|
|
21
28
|
].map((pair) => pair.join(':')).join(',')
|
|
22
29
|
|
|
23
30
|
const path = `/debugger/v1/input?${stringify({ ddtags })}`
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
method: 'POST',
|
|
28
|
-
url: config.url,
|
|
29
|
-
path,
|
|
30
|
-
headers: { 'Content-Type': 'application/json; charset=utf-8' }
|
|
31
|
-
}
|
|
32
|
+
let callbacks = []
|
|
33
|
+
const jsonBuffer = new JSONBuffer({ size: config.maxTotalPayloadSize, timeout: 1000, onFlush })
|
|
32
34
|
|
|
35
|
+
function send (message, logger, dd, snapshot, cb) {
|
|
33
36
|
const payload = {
|
|
34
37
|
ddsource,
|
|
35
38
|
hostname,
|
|
@@ -41,8 +44,9 @@ function send (message, logger, dd, snapshot, cb) {
|
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
let json = JSON.stringify(payload)
|
|
47
|
+
let size = Buffer.byteLength(json)
|
|
44
48
|
|
|
45
|
-
if (
|
|
49
|
+
if (size > MAX_LOG_PAYLOAD_SIZE) {
|
|
46
50
|
// TODO: This is a very crude way to handle large payloads. Proper pruning will be implemented later (DEBUG-2624)
|
|
47
51
|
const line = Object.values(payload['debugger.snapshot'].captures.lines)[0]
|
|
48
52
|
line.locals = {
|
|
@@ -50,7 +54,26 @@ function send (message, logger, dd, snapshot, cb) {
|
|
|
50
54
|
size: Object.keys(line.locals).length
|
|
51
55
|
}
|
|
52
56
|
json = JSON.stringify(payload)
|
|
57
|
+
size = Buffer.byteLength(json)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
jsonBuffer.write(json, size)
|
|
61
|
+
callbacks.push(cb)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function onFlush (payload) {
|
|
65
|
+
const opts = {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
url: config.url,
|
|
68
|
+
path,
|
|
69
|
+
headers: { 'Content-Type': 'application/json; charset=utf-8' }
|
|
53
70
|
}
|
|
54
71
|
|
|
55
|
-
|
|
72
|
+
const _callbacks = callbacks
|
|
73
|
+
callbacks = []
|
|
74
|
+
|
|
75
|
+
request(payload, opts, (err) => {
|
|
76
|
+
if (err) log.error('Could not send debugger payload', err)
|
|
77
|
+
else _callbacks.forEach(cb => cb())
|
|
78
|
+
})
|
|
56
79
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const LRUCache = require('lru-cache')
|
|
4
4
|
const config = require('./config')
|
|
5
|
+
const JSONBuffer = require('./json-buffer')
|
|
5
6
|
const request = require('../../exporters/common/request')
|
|
6
7
|
const FormData = require('../../exporters/common/form-data')
|
|
7
8
|
const log = require('../../log')
|
|
@@ -25,6 +26,8 @@ const cache = new LRUCache({
|
|
|
25
26
|
ttlAutopurge: true
|
|
26
27
|
})
|
|
27
28
|
|
|
29
|
+
const jsonBuffer = new JSONBuffer({ size: config.maxTotalPayloadSize, timeout: 1000, onFlush })
|
|
30
|
+
|
|
28
31
|
const STATUSES = {
|
|
29
32
|
RECEIVED: 'RECEIVED',
|
|
30
33
|
INSTALLED: 'INSTALLED',
|
|
@@ -71,11 +74,15 @@ function ackError (err, { id: probeId, version }) {
|
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
function send (payload) {
|
|
77
|
+
jsonBuffer.write(JSON.stringify(payload))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function onFlush (payload) {
|
|
74
81
|
const form = new FormData()
|
|
75
82
|
|
|
76
83
|
form.append(
|
|
77
84
|
'event',
|
|
78
|
-
|
|
85
|
+
payload,
|
|
79
86
|
{ filename: 'event.json', contentType: 'application/json; charset=utf-8' }
|
|
80
87
|
)
|
|
81
88
|
|
|
@@ -87,7 +94,7 @@ function send (payload) {
|
|
|
87
94
|
}
|
|
88
95
|
|
|
89
96
|
request(form, options, (err) => {
|
|
90
|
-
if (err) log.error('[debugger:devtools_client] Error sending
|
|
97
|
+
if (err) log.error('[debugger:devtools_client] Error sending probe payload', err)
|
|
91
98
|
})
|
|
92
99
|
}
|
|
93
100
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { SPAN_KIND, OUTPUT_VALUE } = require('./constants/tags')
|
|
3
|
+
const { SPAN_KIND, OUTPUT_VALUE, INPUT_VALUE } = require('./constants/tags')
|
|
4
4
|
|
|
5
5
|
const {
|
|
6
6
|
getFunctionArguments,
|
|
7
7
|
validateKind
|
|
8
8
|
} = require('./util')
|
|
9
|
-
const { isTrue } = require('../util')
|
|
9
|
+
const { isTrue, isError } = require('../util')
|
|
10
10
|
|
|
11
11
|
const { storage } = require('./storage')
|
|
12
12
|
|
|
@@ -134,29 +134,63 @@ class LLMObs extends NoopLLMObs {
|
|
|
134
134
|
|
|
135
135
|
function wrapped () {
|
|
136
136
|
const span = llmobs._tracer.scope().active()
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
const fnArgs = arguments
|
|
138
|
+
|
|
139
|
+
const lastArgId = fnArgs.length - 1
|
|
140
|
+
const cb = fnArgs[lastArgId]
|
|
141
|
+
const hasCallback = typeof cb === 'function'
|
|
142
|
+
|
|
143
|
+
if (hasCallback) {
|
|
144
|
+
const scopeBoundCb = llmobs._bind(cb)
|
|
145
|
+
fnArgs[lastArgId] = function () {
|
|
146
|
+
// it is standard practice to follow the callback signature (err, result)
|
|
147
|
+
// however, we try to parse the arguments to determine if the first argument is an error
|
|
148
|
+
// if it is not, and is not undefined, we will use that for the output value
|
|
149
|
+
const maybeError = arguments[0]
|
|
150
|
+
const maybeResult = arguments[1]
|
|
151
|
+
|
|
152
|
+
llmobs._autoAnnotate(
|
|
153
|
+
span,
|
|
154
|
+
kind,
|
|
155
|
+
getFunctionArguments(fn, fnArgs),
|
|
156
|
+
isError(maybeError) || maybeError == null ? maybeResult : maybeError
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
return scopeBoundCb.apply(this, arguments)
|
|
141
160
|
}
|
|
161
|
+
}
|
|
142
162
|
|
|
143
|
-
|
|
144
|
-
|
|
163
|
+
try {
|
|
164
|
+
const result = llmobs._activate(span, { kind, options: llmobsOptions }, () => fn.apply(this, fnArgs))
|
|
165
|
+
|
|
166
|
+
if (result && typeof result.then === 'function') {
|
|
167
|
+
return result.then(
|
|
168
|
+
value => {
|
|
169
|
+
if (!hasCallback) {
|
|
170
|
+
llmobs._autoAnnotate(span, kind, getFunctionArguments(fn, fnArgs), value)
|
|
171
|
+
}
|
|
172
|
+
return value
|
|
173
|
+
},
|
|
174
|
+
err => {
|
|
175
|
+
llmobs._autoAnnotate(span, kind, getFunctionArguments(fn, fnArgs))
|
|
176
|
+
throw err
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
}
|
|
145
180
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
}
|
|
181
|
+
// it is possible to return a value and have a callback
|
|
182
|
+
// however, since the span finishes when the callback is called, it is possible that
|
|
183
|
+
// the callback is called before the function returns (although unlikely)
|
|
184
|
+
// we do not want to throw for "annotating a finished span" in this case
|
|
185
|
+
if (!hasCallback) {
|
|
186
|
+
llmobs._autoAnnotate(span, kind, getFunctionArguments(fn, fnArgs), result)
|
|
187
|
+
}
|
|
154
188
|
|
|
155
|
-
|
|
156
|
-
|
|
189
|
+
return result
|
|
190
|
+
} catch (e) {
|
|
191
|
+
llmobs._autoAnnotate(span, kind, getFunctionArguments(fn, fnArgs))
|
|
192
|
+
throw e
|
|
157
193
|
}
|
|
158
|
-
|
|
159
|
-
return result
|
|
160
194
|
}
|
|
161
195
|
|
|
162
196
|
return this._tracer.wrap(name, spanOptions, wrapped)
|
|
@@ -333,20 +367,34 @@ class LLMObs extends NoopLLMObs {
|
|
|
333
367
|
flushCh.publish()
|
|
334
368
|
}
|
|
335
369
|
|
|
370
|
+
_autoAnnotate (span, kind, input, output) {
|
|
371
|
+
const annotations = {}
|
|
372
|
+
if (input && !['llm', 'embedding'].includes(kind) && !LLMObsTagger.tagMap.get(span)?.[INPUT_VALUE]) {
|
|
373
|
+
annotations.inputData = input
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (output && !['llm', 'retrieval'].includes(kind) && !LLMObsTagger.tagMap.get(span)?.[OUTPUT_VALUE]) {
|
|
377
|
+
annotations.outputData = output
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
this.annotate(span, annotations)
|
|
381
|
+
}
|
|
382
|
+
|
|
336
383
|
_active () {
|
|
337
384
|
const store = storage.getStore()
|
|
338
385
|
return store?.span
|
|
339
386
|
}
|
|
340
387
|
|
|
341
|
-
_activate (span,
|
|
388
|
+
_activate (span, options, fn) {
|
|
342
389
|
const parent = this._active()
|
|
343
390
|
if (this.enabled) storage.enterWith({ span })
|
|
344
391
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
392
|
+
if (options) {
|
|
393
|
+
this._tagger.registerLLMObsSpan(span, {
|
|
394
|
+
...options,
|
|
395
|
+
parent
|
|
396
|
+
})
|
|
397
|
+
}
|
|
350
398
|
|
|
351
399
|
try {
|
|
352
400
|
return fn()
|
|
@@ -355,6 +403,22 @@ class LLMObs extends NoopLLMObs {
|
|
|
355
403
|
}
|
|
356
404
|
}
|
|
357
405
|
|
|
406
|
+
// bind function to active LLMObs span
|
|
407
|
+
_bind (fn) {
|
|
408
|
+
if (typeof fn !== 'function') return fn
|
|
409
|
+
|
|
410
|
+
const llmobs = this
|
|
411
|
+
const activeSpan = llmobs._active()
|
|
412
|
+
|
|
413
|
+
const bound = function () {
|
|
414
|
+
return llmobs._activate(activeSpan, null, () => {
|
|
415
|
+
return fn.apply(this, arguments)
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return bound
|
|
420
|
+
}
|
|
421
|
+
|
|
358
422
|
_extractOptions (options) {
|
|
359
423
|
const {
|
|
360
424
|
modelName,
|
|
@@ -63,15 +63,14 @@ const log = {
|
|
|
63
63
|
|
|
64
64
|
Error.captureStackTrace(logRecord, this.trace)
|
|
65
65
|
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
traceChannel.publish(Log.parse(formatted))
|
|
66
|
+
const stack = logRecord.stack.split('\n')
|
|
67
|
+
const fn = stack[1].replace(/^\s+at ([^\s]+) .+/, '$1')
|
|
68
|
+
const options = { depth: 2, breakLength: Infinity, compact: true, maxArrayLength: Infinity }
|
|
69
|
+
const params = args.map(a => inspect(a, options)).join(', ')
|
|
70
|
+
|
|
71
|
+
stack[0] = `Trace: ${fn}(${params})`
|
|
72
|
+
|
|
73
|
+
traceChannel.publish(Log.parse(stack.join('\n')))
|
|
75
74
|
}
|
|
76
75
|
return this
|
|
77
76
|
},
|
|
@@ -10,7 +10,7 @@ const noopAppsec = new NoopAppsecSdk()
|
|
|
10
10
|
const noopDogStatsDClient = new NoopDogStatsDClient()
|
|
11
11
|
const noopLLMObs = new NoopLLMObsSDK(noop)
|
|
12
12
|
|
|
13
|
-
class
|
|
13
|
+
class NoopProxy {
|
|
14
14
|
constructor () {
|
|
15
15
|
this._tracer = noop
|
|
16
16
|
this.appsec = noopAppsec
|
|
@@ -91,4 +91,4 @@ class Tracer {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
module.exports =
|
|
94
|
+
module.exports = NoopProxy
|
|
@@ -6,7 +6,7 @@ const { storage } = require('../../../datadog-core') // TODO: noop storage?
|
|
|
6
6
|
|
|
7
7
|
class NoopSpan {
|
|
8
8
|
constructor (tracer, parent) {
|
|
9
|
-
this._store = storage.
|
|
9
|
+
this._store = storage.getHandle()
|
|
10
10
|
this._noopTracer = tracer
|
|
11
11
|
this._noopContext = this._createContext(parent)
|
|
12
12
|
}
|
|
@@ -14,6 +14,7 @@ const { storage } = require('../../../datadog-core')
|
|
|
14
14
|
const telemetryMetrics = require('../telemetry/metrics')
|
|
15
15
|
const { channel } = require('dc-polyfill')
|
|
16
16
|
const spanleak = require('../spanleak')
|
|
17
|
+
const util = require('util')
|
|
17
18
|
|
|
18
19
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
19
20
|
|
|
@@ -64,7 +65,7 @@ class DatadogSpan {
|
|
|
64
65
|
this._debug = debug
|
|
65
66
|
this._processor = processor
|
|
66
67
|
this._prioritySampler = prioritySampler
|
|
67
|
-
this._store = storage.
|
|
68
|
+
this._store = storage.getHandle()
|
|
68
69
|
this._duration = undefined
|
|
69
70
|
|
|
70
71
|
this._events = []
|
|
@@ -105,6 +106,15 @@ class DatadogSpan {
|
|
|
105
106
|
}
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
[util.inspect.custom] () {
|
|
110
|
+
return {
|
|
111
|
+
...this,
|
|
112
|
+
_parentTracer: `[${this._parentTracer.constructor.name}]`,
|
|
113
|
+
_prioritySampler: `[${this._prioritySampler.constructor.name}]`,
|
|
114
|
+
_processor: `[${this._processor.constructor.name}]`
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
108
118
|
toString () {
|
|
109
119
|
const spanContext = this.context()
|
|
110
120
|
const resourceName = spanContext._tags['resource.name'] || ''
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const util = require('util')
|
|
3
4
|
const { AUTO_KEEP } = require('../../../../ext/priority')
|
|
4
5
|
|
|
5
6
|
// the lowercase, hex encoded upper 64 bits of a 128-bit trace id, if present
|
|
@@ -31,6 +32,17 @@ class DatadogSpanContext {
|
|
|
31
32
|
this._otelSpanContext = undefined
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
[util.inspect.custom] () {
|
|
36
|
+
return {
|
|
37
|
+
...this,
|
|
38
|
+
_trace: {
|
|
39
|
+
...this._trace,
|
|
40
|
+
started: '[Array]',
|
|
41
|
+
finished: '[Array]'
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
34
46
|
toTraceId (get128bitId = false) {
|
|
35
47
|
if (get128bitId) {
|
|
36
48
|
return this._traceId.toBuffer().length <= 8 && this._trace.tags[TRACE_ID_128]
|
|
@@ -120,13 +120,15 @@ class PrioritySampler {
|
|
|
120
120
|
if (!span || !this.validate(samplingPriority)) return
|
|
121
121
|
|
|
122
122
|
const context = this._getContext(span)
|
|
123
|
+
const root = context._trace.started[0]
|
|
124
|
+
|
|
125
|
+
if (!root) return // noop span
|
|
123
126
|
|
|
124
127
|
context._sampling.priority = samplingPriority
|
|
125
128
|
context._sampling.mechanism = mechanism
|
|
126
129
|
|
|
127
|
-
const root = context._trace.started[0]
|
|
128
|
-
|
|
129
130
|
log.trace(span, samplingPriority, mechanism)
|
|
131
|
+
|
|
130
132
|
this._addDecisionMaker(root)
|
|
131
133
|
}
|
|
132
134
|
|
|
@@ -17,7 +17,7 @@ class Scope {
|
|
|
17
17
|
if (typeof callback !== 'function') return callback
|
|
18
18
|
|
|
19
19
|
const oldStore = storage.getStore()
|
|
20
|
-
const newStore = span ? span._store : oldStore
|
|
20
|
+
const newStore = span ? storage.getStore(span._store) : oldStore
|
|
21
21
|
|
|
22
22
|
storage.enterWith({ ...newStore, span })
|
|
23
23
|
|