dd-trace 5.88.0 → 5.89.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/ext/tags.js +2 -0
- package/index.d.ts +9 -0
- package/package.json +12 -8
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +26 -111
- package/packages/datadog-instrumentations/src/helpers/rewriter/{compiler.js → orchestrion/compiler.js} +5 -5
- package/packages/datadog-instrumentations/src/helpers/rewriter/orchestrion/index.js +43 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/orchestrion/matcher.js +49 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/orchestrion/transformer.js +121 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/{transforms.js → orchestrion/transforms.js} +6 -6
- package/packages/datadog-instrumentations/src/jest.js +101 -43
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +36 -5
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +297 -0
- package/packages/datadog-plugin-cypress/src/support.js +4 -1
- package/packages/dd-trace/src/aiguard/sdk.js +5 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +1 -0
- package/packages/dd-trace/src/config/index.js +2 -0
- package/packages/dd-trace/src/config/supported-configurations.json +10 -0
- package/packages/dd-trace/src/datastreams/checkpointer.js +13 -0
- package/packages/dd-trace/src/datastreams/index.js +3 -0
- package/packages/dd-trace/src/datastreams/manager.js +9 -0
- package/packages/dd-trace/src/datastreams/processor.js +126 -3
- package/packages/dd-trace/src/encode/agentless-json.js +16 -2
- package/packages/dd-trace/src/exporters/agent/writer.js +7 -8
- package/packages/dd-trace/src/pkg.js +1 -1
- package/packages/dd-trace/src/proxy.js +2 -1
- package/packages/dd-trace/src/startup-log.js +52 -18
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/@datadog/source-map/index.js +1 -1
- package/vendor/dist/@isaacs/ttlcache/index.js +1 -1
- package/vendor/dist/@opentelemetry/core/index.js +1 -1
- package/vendor/dist/@opentelemetry/resources/index.js +1 -1
- package/vendor/dist/astring/index.js +1 -1
- package/vendor/dist/crypto-randomuuid/index.js +1 -1
- package/vendor/dist/escape-string-regexp/index.js +1 -1
- package/vendor/dist/esquery/index.js +1 -1
- package/vendor/dist/ignore/index.js +1 -1
- package/vendor/dist/istanbul-lib-coverage/index.js +1 -1
- package/vendor/dist/jest-docblock/index.js +1 -1
- package/vendor/dist/jsonpath-plus/index.js +1 -1
- package/vendor/dist/limiter/index.js +1 -1
- package/vendor/dist/lodash.sortby/index.js +1 -1
- package/vendor/dist/lru-cache/index.js +1 -1
- package/vendor/dist/meriyah/index.js +1 -1
- package/vendor/dist/module-details-from-path/index.js +1 -1
- package/vendor/dist/mutexify/promise/index.js +1 -1
- package/vendor/dist/opentracing/index.js +1 -1
- package/vendor/dist/path-to-regexp/index.js +1 -1
- package/vendor/dist/pprof-format/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/vendor/dist/retry/index.js +1 -1
- package/vendor/dist/rfdc/index.js +1 -1
- package/vendor/dist/semifies/index.js +1 -1
- package/vendor/dist/shell-quote/index.js +1 -1
- package/vendor/dist/source-map/index.js +1 -1
- package/vendor/dist/source-map/lib/util/index.js +1 -1
- package/vendor/dist/tlhunter-sorted-set/index.js +1 -1
- package/vendor/dist/ttl-set/index.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/transformer.js +0 -21
|
@@ -60,6 +60,19 @@ class DataStreamsCheckpointer {
|
|
|
60
60
|
|
|
61
61
|
return ctx
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Records a transaction ID at a named checkpoint without pathway propagation.
|
|
66
|
+
* Tags the active span (or the provided span) with the transaction ID and checkpoint name.
|
|
67
|
+
* @param {string} transactionId - The transaction identifier to track.
|
|
68
|
+
* @param {string} checkpointName - The logical checkpoint name.
|
|
69
|
+
* @param {object|null} [span=null] - Span to tag. Defaults to the currently active span.
|
|
70
|
+
*/
|
|
71
|
+
trackTransaction (transactionId, checkpointName, span = null) {
|
|
72
|
+
if (!this.config.dsmEnabled) return
|
|
73
|
+
const activeSpan = span ?? this.tracer.scope().active()
|
|
74
|
+
this.dsmProcessor.trackTransaction(transactionId, checkpointName, activeSpan)
|
|
75
|
+
}
|
|
63
76
|
}
|
|
64
77
|
|
|
65
78
|
module.exports = {
|
|
@@ -71,6 +71,7 @@ const DsmPathwayCodec = lazyClass(() => require('./pathway').DsmPathwayCodec, []
|
|
|
71
71
|
const DataStreamsCheckpointer = lazyClass(() => require('./checkpointer').DataStreamsCheckpointer, [
|
|
72
72
|
'setProduceCheckpoint',
|
|
73
73
|
'setConsumeCheckpoint',
|
|
74
|
+
'trackTransaction',
|
|
74
75
|
])
|
|
75
76
|
|
|
76
77
|
/**
|
|
@@ -79,6 +80,7 @@ const DataStreamsCheckpointer = lazyClass(() => require('./checkpointer').DataSt
|
|
|
79
80
|
const DataStreamsManager = lazyClass(() => require('./manager').DataStreamsManager, [
|
|
80
81
|
'setCheckpoint',
|
|
81
82
|
'decodeDataStreamsContext',
|
|
83
|
+
'trackTransaction',
|
|
82
84
|
])
|
|
83
85
|
|
|
84
86
|
// TODO: Are all those methods actually public?
|
|
@@ -92,6 +94,7 @@ const DataStreamsProcessor = lazyClass(() => require('./processor').DataStreamsP
|
|
|
92
94
|
'setCheckpoint',
|
|
93
95
|
'recordOffset',
|
|
94
96
|
'setOffset',
|
|
97
|
+
'trackTransaction',
|
|
95
98
|
'setUrl',
|
|
96
99
|
'trySampleSchema',
|
|
97
100
|
'canSampleSchema',
|
|
@@ -22,6 +22,15 @@ class DataStreamsManager {
|
|
|
22
22
|
DataStreamsContext.setDataStreamsContext(ctx)
|
|
23
23
|
return ctx
|
|
24
24
|
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} transactionId
|
|
28
|
+
* @param {string} checkpointName
|
|
29
|
+
* @param {object|null} [span=null]
|
|
30
|
+
*/
|
|
31
|
+
trackTransaction (transactionId, checkpointName, span = null) {
|
|
32
|
+
this._dataStreamsProcessor.trackTransaction(transactionId, checkpointName, span)
|
|
33
|
+
}
|
|
25
34
|
}
|
|
26
35
|
|
|
27
36
|
module.exports = { DataStreamsManager }
|
|
@@ -4,7 +4,7 @@ const os = require('os')
|
|
|
4
4
|
const pkg = require('../../../../package.json')
|
|
5
5
|
|
|
6
6
|
const { LogCollapsingLowestDenseDDSketch } = require('../../../../vendor/dist/@datadog/sketches-js')
|
|
7
|
-
const { PATHWAY_HASH } = require('../../../../ext/tags')
|
|
7
|
+
const { PATHWAY_HASH, DSM_TRANSACTION_ID, DSM_TRANSACTION_CHECKPOINT } = require('../../../../ext/tags')
|
|
8
8
|
const log = require('../log')
|
|
9
9
|
const processTags = require('../process-tags')
|
|
10
10
|
const propagationHash = require('../propagation-hash')
|
|
@@ -69,10 +69,66 @@ class Backlog {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Maps checkpoint name strings to single-byte IDs (1–254).
|
|
74
|
+
* ID 0 is reserved; 254 is the maximum number of unique names.
|
|
75
|
+
* Scope is per-processor so IDs are stable across bucket boundaries within a process lifetime.
|
|
76
|
+
*/
|
|
77
|
+
class CheckpointRegistry {
|
|
78
|
+
/** @type {Map<string, number>} */
|
|
79
|
+
#nameToId = new Map()
|
|
80
|
+
#nextId = 1
|
|
81
|
+
/** @type {Buffer[]} Pre-built [id uint8][nameLen uint8][name bytes] entries, one per registered name. */
|
|
82
|
+
#entryBuffers = []
|
|
83
|
+
/** @type {Buffer | null} Cached concat of #entryBuffers; reset when a new name is added. */
|
|
84
|
+
#encodedKeysCache = null
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns the byte ID for the given checkpoint name, assigning one if not seen before.
|
|
88
|
+
* Returns undefined when registry is full (254 entries exhausted).
|
|
89
|
+
* @param {string} name
|
|
90
|
+
* @returns {number | undefined}
|
|
91
|
+
*/
|
|
92
|
+
getId (name) {
|
|
93
|
+
const existing = this.#nameToId.get(name)
|
|
94
|
+
if (existing !== undefined) return existing
|
|
95
|
+
if (this.#nextId > 254) return
|
|
96
|
+
const id = this.#nextId++
|
|
97
|
+
this.#nameToId.set(name, id)
|
|
98
|
+
// Build the wire entry now with a bounded write so long names never materialise
|
|
99
|
+
// their full UTF-8 encoding — buf.write() stops at the supplied byte limit.
|
|
100
|
+
const nameBuf = Buffer.allocUnsafe(255)
|
|
101
|
+
const nameByteLen = nameBuf.write(name, 0, 255, 'utf8')
|
|
102
|
+
const entry = Buffer.allocUnsafe(2 + nameByteLen)
|
|
103
|
+
entry.writeUInt8(id, 0)
|
|
104
|
+
entry.writeUInt8(nameByteLen, 1)
|
|
105
|
+
nameBuf.copy(entry, 2, 0, nameByteLen)
|
|
106
|
+
this.#entryBuffers.push(entry)
|
|
107
|
+
this.#encodedKeysCache = null
|
|
108
|
+
return id
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Returns a Buffer encoding all registered names as [id uint8][nameLen uint8][name bytes].
|
|
113
|
+
* Names are truncated to 255 UTF-8 bytes.
|
|
114
|
+
* Result is cached and only recomputed when new names are registered.
|
|
115
|
+
* @returns {Buffer}
|
|
116
|
+
*/
|
|
117
|
+
get encodedKeys () {
|
|
118
|
+
if (this.#encodedKeysCache !== null) return this.#encodedKeysCache
|
|
119
|
+
this.#encodedKeysCache = this.#entryBuffers.length > 0
|
|
120
|
+
? Buffer.concat(this.#entryBuffers)
|
|
121
|
+
: Buffer.alloc(0)
|
|
122
|
+
return this.#encodedKeysCache
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
72
126
|
class StatsBucket {
|
|
73
127
|
constructor () {
|
|
74
128
|
this._checkpoints = new Map()
|
|
75
129
|
this._backlogs = new Map()
|
|
130
|
+
/** @type {Buffer[]} Accumulated transaction byte chunks, concatenated lazily. */
|
|
131
|
+
this._transactionChunks = []
|
|
76
132
|
}
|
|
77
133
|
|
|
78
134
|
get checkpoints () {
|
|
@@ -83,6 +139,16 @@ class StatsBucket {
|
|
|
83
139
|
return this._backlogs
|
|
84
140
|
}
|
|
85
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Returns the concatenated transaction bytes, or null if no transactions have been added.
|
|
144
|
+
* Concatenation is deferred to read time to avoid O(N²) copies during accumulation.
|
|
145
|
+
* @returns {Buffer | null}
|
|
146
|
+
*/
|
|
147
|
+
get transactions () {
|
|
148
|
+
if (this._transactionChunks.length === 0) return null
|
|
149
|
+
return Buffer.concat(this._transactionChunks)
|
|
150
|
+
}
|
|
151
|
+
|
|
86
152
|
forCheckpoint ({ hash, parentHash, edgeTags }) {
|
|
87
153
|
let checkpoint = this._checkpoints.get(hash)
|
|
88
154
|
if (!checkpoint) {
|
|
@@ -93,6 +159,14 @@ class StatsBucket {
|
|
|
93
159
|
return checkpoint
|
|
94
160
|
}
|
|
95
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Appends pre-encoded transaction bytes to this bucket.
|
|
164
|
+
* @param {Buffer} bytes
|
|
165
|
+
*/
|
|
166
|
+
addTransaction (bytes) {
|
|
167
|
+
this._transactionChunks.push(bytes)
|
|
168
|
+
}
|
|
169
|
+
|
|
96
170
|
/**
|
|
97
171
|
* Conditionally add a backlog to the bucket. If there is currently an offset
|
|
98
172
|
* matching the backlog's tags, overwrite the offset IFF the backlog's offset
|
|
@@ -153,6 +227,7 @@ class DataStreamsProcessor {
|
|
|
153
227
|
this.sequence = 0
|
|
154
228
|
this.flushInterval = flushInterval
|
|
155
229
|
this._schemaSamplers = {}
|
|
230
|
+
this._checkpointRegistry = new CheckpointRegistry()
|
|
156
231
|
|
|
157
232
|
if (this.enabled) {
|
|
158
233
|
this.timer = setInterval(this.onInterval.bind(this), flushInterval)
|
|
@@ -294,9 +369,47 @@ class DataStreamsProcessor {
|
|
|
294
369
|
this.recordOffset(backlogData)
|
|
295
370
|
}
|
|
296
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Records a transaction ID at a named checkpoint using the binary wire format shared with Go/Java tracers.
|
|
374
|
+
*
|
|
375
|
+
* Wire format per entry: [checkpointId uint8][timestamp int64 big-endian 8 bytes][idLen uint8][id bytes]
|
|
376
|
+
*
|
|
377
|
+
* @param {string} transactionId - Truncated to 255 UTF-8 bytes.
|
|
378
|
+
* @param {string} checkpointName - Mapped to a stable 1-byte ID; silently dropped if registry full.
|
|
379
|
+
* @param {import('../opentelemetry/span').Span|null} [span=null] - Active span to tag with DSM transaction metadata.
|
|
380
|
+
*/
|
|
381
|
+
trackTransaction (transactionId, checkpointName, span = null) {
|
|
382
|
+
if (!this.enabled) {
|
|
383
|
+
log.warn('trackTransaction called but DD_DATA_STREAMS_ENABLED is not set. Transaction will not be tracked.')
|
|
384
|
+
return
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const checkpointId = this._checkpointRegistry.getId(checkpointName)
|
|
388
|
+
if (checkpointId === undefined) return
|
|
389
|
+
|
|
390
|
+
const idBytes = Buffer.from(transactionId, 'utf8').subarray(0, 255)
|
|
391
|
+
// Multiply as BigInt to avoid precision loss past MAX_SAFE_INTEGER
|
|
392
|
+
const timestampNs = BigInt(Date.now()) * 1_000_000n
|
|
393
|
+
|
|
394
|
+
const entry = Buffer.alloc(1 + 8 + 1 + idBytes.length)
|
|
395
|
+
entry.writeUInt8(checkpointId, 0)
|
|
396
|
+
entry.writeBigInt64BE(timestampNs, 1)
|
|
397
|
+
entry.writeUInt8(idBytes.length, 9)
|
|
398
|
+
idBytes.copy(entry, 10)
|
|
399
|
+
|
|
400
|
+
// Number() cast is safe here: 10s bucket granularity tolerates ~0.5ns precision loss
|
|
401
|
+
this.bucketFromTimestamp(Number(timestampNs)).addTransaction(entry)
|
|
402
|
+
|
|
403
|
+
if (span) {
|
|
404
|
+
span.setTag(DSM_TRANSACTION_ID, transactionId)
|
|
405
|
+
span.setTag(DSM_TRANSACTION_CHECKPOINT, checkpointName)
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
297
409
|
_serializeBuckets () {
|
|
298
410
|
// TimeBuckets
|
|
299
411
|
const serializedBuckets = []
|
|
412
|
+
const registrySnapshot = this._checkpointRegistry.encodedKeys
|
|
300
413
|
|
|
301
414
|
for (const [timeNs, bucket] of this.buckets.entries()) {
|
|
302
415
|
const points = []
|
|
@@ -311,12 +424,21 @@ class DataStreamsProcessor {
|
|
|
311
424
|
for (const backlog of bucket._backlogs.values()) {
|
|
312
425
|
backlogs.push(backlog.encode())
|
|
313
426
|
}
|
|
314
|
-
|
|
427
|
+
|
|
428
|
+
const serializedBucket = {
|
|
315
429
|
Start: BigInt(timeNs),
|
|
316
430
|
Duration: BigInt(this.bucketSizeNs),
|
|
317
431
|
Stats: points,
|
|
318
432
|
Backlogs: backlogs,
|
|
319
|
-
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
const transactions = bucket.transactions
|
|
436
|
+
if (transactions !== null) {
|
|
437
|
+
serializedBucket.Transactions = transactions
|
|
438
|
+
serializedBucket.TransactionCheckpointIds = registrySnapshot
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
serializedBuckets.push(serializedBucket)
|
|
320
442
|
}
|
|
321
443
|
|
|
322
444
|
this.buckets.clear()
|
|
@@ -358,6 +480,7 @@ class DataStreamsProcessor {
|
|
|
358
480
|
}
|
|
359
481
|
|
|
360
482
|
module.exports = {
|
|
483
|
+
CheckpointRegistry,
|
|
361
484
|
DataStreamsProcessor,
|
|
362
485
|
StatsPoint,
|
|
363
486
|
StatsBucket,
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const log = require('../log')
|
|
4
|
+
const { TOP_LEVEL_KEY } = require('../constants')
|
|
4
5
|
const { truncateSpan, normalizeSpan } = require('./tags-processors')
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Formats a span for JSON encoding.
|
|
8
9
|
* @param {object} span - The span to format
|
|
10
|
+
* @param {boolean} isFirstSpan - Whether this is the first span in the trace
|
|
9
11
|
* @returns {object} The formatted span
|
|
10
12
|
*/
|
|
11
|
-
function formatSpan (span) {
|
|
13
|
+
function formatSpan (span, isFirstSpan) {
|
|
12
14
|
span = normalizeSpan(truncateSpan(span, false))
|
|
13
15
|
|
|
14
16
|
if (span.span_events) {
|
|
@@ -16,6 +18,18 @@ function formatSpan (span) {
|
|
|
16
18
|
delete span.span_events
|
|
17
19
|
}
|
|
18
20
|
|
|
21
|
+
if (isFirstSpan) {
|
|
22
|
+
span.meta['_dd.compute_stats'] = '1'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (span.parent_id?.toString(10) === '0') {
|
|
26
|
+
span.metrics._trace_root = 1
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (span.metrics[TOP_LEVEL_KEY]) {
|
|
30
|
+
span.metrics._top_level = 1
|
|
31
|
+
}
|
|
32
|
+
|
|
19
33
|
return span
|
|
20
34
|
}
|
|
21
35
|
|
|
@@ -83,7 +97,7 @@ class AgentlessJSONEncoder {
|
|
|
83
97
|
encode (trace) {
|
|
84
98
|
for (const span of trace) {
|
|
85
99
|
try {
|
|
86
|
-
const formattedSpan = formatSpan(span)
|
|
100
|
+
const formattedSpan = formatSpan(span, this._spanCount === 0)
|
|
87
101
|
const jsonSpan = spanToJSON(formattedSpan)
|
|
88
102
|
|
|
89
103
|
this._spans.push(jsonSpan)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { inspect } = require('node:util')
|
|
3
4
|
const request = require('../common/request')
|
|
4
|
-
const {
|
|
5
|
+
const { logIntegrations, logAgentError } = require('../../startup-log')
|
|
5
6
|
const runtimeMetrics = require('../../runtime_metrics')
|
|
6
7
|
const log = require('../../log')
|
|
7
8
|
const tracerVersion = require('../../../../../package.json').version
|
|
@@ -28,7 +29,7 @@ class AgentWriter extends BaseWriter {
|
|
|
28
29
|
runtimeMetrics.increment(`${METRIC_PREFIX}.requests`, true)
|
|
29
30
|
|
|
30
31
|
const { _headers, _lookup, _protocolVersion, _url } = this
|
|
31
|
-
makeRequest(_protocolVersion, data, count, _url, _headers, _lookup,
|
|
32
|
+
makeRequest(_protocolVersion, data, count, _url, _headers, _lookup, (err, res, status, headers) => {
|
|
32
33
|
if (status) {
|
|
33
34
|
runtimeMetrics.increment(`${METRIC_PREFIX}.responses`, true)
|
|
34
35
|
runtimeMetrics.increment(`${METRIC_PREFIX}.responses.by.status`, `status:${status}`, true)
|
|
@@ -78,7 +79,7 @@ function getEncoder (protocolVersion) {
|
|
|
78
79
|
: require('../../encode/0.4').AgentEncoder
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
function makeRequest (version, data, count, url, headers, lookup,
|
|
82
|
+
function makeRequest (version, data, count, url, headers, lookup, cb) {
|
|
82
83
|
const options = {
|
|
83
84
|
path: `/v${version}/traces`,
|
|
84
85
|
method: 'PUT',
|
|
@@ -98,11 +99,9 @@ function makeRequest (version, data, count, url, headers, lookup, needsStartupLo
|
|
|
98
99
|
log.debug('Request to the agent: %j', options)
|
|
99
100
|
|
|
100
101
|
request(data, options, (err, res, status, headers) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
agentError: status !== 404 && status !== 200 ? err : undefined,
|
|
105
|
-
})
|
|
102
|
+
logIntegrations()
|
|
103
|
+
if (status !== 404 && status !== 200 && err) {
|
|
104
|
+
logAgentError({ status, message: err.message ?? inspect(err) })
|
|
106
105
|
}
|
|
107
106
|
cb(err, res, status, headers)
|
|
108
107
|
})
|
|
@@ -6,7 +6,7 @@ const DatadogTracer = require('./tracer')
|
|
|
6
6
|
const getConfig = require('./config')
|
|
7
7
|
const runtimeMetrics = require('./runtime_metrics')
|
|
8
8
|
const log = require('./log')
|
|
9
|
-
const { setStartupLogPluginManager } = require('./startup-log')
|
|
9
|
+
const { setStartupLogPluginManager, startupLog } = require('./startup-log')
|
|
10
10
|
const DynamicInstrumentation = require('./debugger')
|
|
11
11
|
const telemetry = require('./telemetry')
|
|
12
12
|
const nomenclature = require('./service-naming')
|
|
@@ -292,6 +292,7 @@ class Tracer extends NoopProxy {
|
|
|
292
292
|
this._pluginManager.configure(config)
|
|
293
293
|
DynamicInstrumentation.configure(config)
|
|
294
294
|
setStartupLogPluginManager(this._pluginManager)
|
|
295
|
+
startupLog()
|
|
295
296
|
}
|
|
296
297
|
}
|
|
297
298
|
|
|
@@ -11,41 +11,66 @@ let config
|
|
|
11
11
|
let pluginManager
|
|
12
12
|
/** @type {import('./sampling_rule')[]} */
|
|
13
13
|
let samplingRules = []
|
|
14
|
-
let
|
|
14
|
+
let configAlreadyRan = false
|
|
15
|
+
let integrationsAlreadyRan = false
|
|
16
|
+
let agentErrorAlreadyRan = false
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* Logs DATADOG TRACER CONFIGURATION immediately at init time.
|
|
20
|
+
* Excludes integrations_loaded since plugins haven't loaded yet.
|
|
18
21
|
*/
|
|
19
|
-
function startupLog (
|
|
20
|
-
if (
|
|
22
|
+
function startupLog () {
|
|
23
|
+
if (configAlreadyRan || !config || !config.startupLogs) {
|
|
21
24
|
return
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
configAlreadyRan = true
|
|
25
28
|
|
|
26
|
-
const out =
|
|
29
|
+
const out = configInfo()
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
warn('DATADOG TRACER CONFIGURATION - ' + out)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Logs loaded integrations. Called from writer.js on first agent payload,
|
|
36
|
+
* by which time the app has loaded its dependencies.
|
|
37
|
+
*/
|
|
38
|
+
function logIntegrations () {
|
|
39
|
+
if (integrationsAlreadyRan || !config || !config.startupLogs || !pluginManager) {
|
|
40
|
+
return
|
|
30
41
|
}
|
|
31
42
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
integrationsAlreadyRan = true
|
|
44
|
+
|
|
45
|
+
warn('DATADOG TRACER INTEGRATIONS LOADED - ' + JSON.stringify(Object.keys(pluginManager._pluginsByName)))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Logs agent error diagnostic.
|
|
50
|
+
* @param {{ status: number, message: string }} agentError
|
|
51
|
+
*/
|
|
52
|
+
function logAgentError (agentError) {
|
|
53
|
+
if (agentErrorAlreadyRan || !config || !config.startupLogs) {
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
agentErrorAlreadyRan = true
|
|
58
|
+
|
|
59
|
+
warn('DATADOG TRACER DIAGNOSTIC - Agent Error: ' + agentError.message)
|
|
60
|
+
errors.agentError = {
|
|
61
|
+
code: agentError.status,
|
|
62
|
+
message: `Agent Error: ${agentError.message}`,
|
|
39
63
|
}
|
|
40
64
|
}
|
|
41
65
|
|
|
42
66
|
/**
|
|
67
|
+
* Returns config info without integrations (used by startupLog).
|
|
43
68
|
* @returns {Record<string, unknown>}
|
|
44
69
|
*/
|
|
45
|
-
function
|
|
70
|
+
function configInfo () {
|
|
46
71
|
const url = getAgentUrl(config)
|
|
47
72
|
|
|
48
|
-
|
|
73
|
+
return {
|
|
49
74
|
[inspect.custom] () {
|
|
50
75
|
return String(this)
|
|
51
76
|
},
|
|
@@ -73,11 +98,18 @@ function tracerInfo () {
|
|
|
73
98
|
log_injection_enabled: !!config.logInjection,
|
|
74
99
|
runtime_metrics_enabled: !!config.runtimeMetrics,
|
|
75
100
|
profiling_enabled: config.profiling?.enabled === 'true' || config.profiling?.enabled === 'auto',
|
|
76
|
-
integrations_loaded: Object.keys(pluginManager._pluginsByName),
|
|
77
101
|
appsec_enabled: config.appsec.enabled,
|
|
78
102
|
data_streams_enabled: !!config.dsmEnabled,
|
|
79
103
|
}
|
|
104
|
+
}
|
|
80
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Returns full tracer info including integrations (used by flare module).
|
|
108
|
+
* @returns {Record<string, unknown>}
|
|
109
|
+
*/
|
|
110
|
+
function tracerInfo () {
|
|
111
|
+
const out = configInfo()
|
|
112
|
+
out.integrations_loaded = Object.keys(pluginManager._pluginsByName)
|
|
81
113
|
return out
|
|
82
114
|
}
|
|
83
115
|
|
|
@@ -104,6 +136,8 @@ function setSamplingRules (theRules) {
|
|
|
104
136
|
|
|
105
137
|
module.exports = {
|
|
106
138
|
startupLog,
|
|
139
|
+
logIntegrations,
|
|
140
|
+
logAgentError,
|
|
107
141
|
setStartupLogConfig,
|
|
108
142
|
setStartupLogPluginManager,
|
|
109
143
|
setSamplingRules,
|