dd-trace 4.29.0 → 4.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/README.md +7 -0
- package/ci/cypress/after-spec.js +1 -0
- package/index.d.ts +1502 -1485
- package/package.json +4 -4
- package/packages/datadog-core/src/utils/src/get.js +11 -0
- package/packages/datadog-core/src/utils/src/has.js +14 -0
- package/packages/datadog-core/src/utils/src/set.js +16 -0
- package/packages/datadog-instrumentations/src/amqplib.js +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +2 -1
- package/packages/datadog-instrumentations/src/grpc/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +11 -5
- package/packages/datadog-instrumentations/src/mocha.js +4 -1
- package/packages/datadog-instrumentations/src/mongodb-core.js +34 -3
- package/packages/datadog-instrumentations/src/playwright.js +78 -16
- package/packages/datadog-plugin-amqplib/src/consumer.js +5 -4
- package/packages/datadog-plugin-amqplib/src/producer.js +3 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +3 -2
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +4 -11
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +3 -6
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +5 -7
- package/packages/datadog-plugin-cucumber/src/index.js +2 -2
- package/packages/datadog-plugin-cypress/src/after-spec.js +3 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +123 -58
- package/packages/datadog-plugin-cypress/src/support.js +50 -3
- package/packages/datadog-plugin-graphql/src/index.js +1 -1
- package/packages/datadog-plugin-graphql/src/resolve.js +10 -8
- package/packages/datadog-plugin-grpc/src/util.js +1 -1
- package/packages/datadog-plugin-jest/src/index.js +13 -4
- package/packages/datadog-plugin-kafkajs/src/consumer.js +4 -3
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -5
- package/packages/datadog-plugin-mocha/src/index.js +2 -2
- package/packages/datadog-plugin-playwright/src/index.js +34 -3
- package/packages/datadog-plugin-rhea/src/consumer.js +5 -3
- package/packages/datadog-plugin-rhea/src/producer.js +3 -4
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +23 -12
- package/packages/dd-trace/src/appsec/iast/index.js +10 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +9 -6
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +6 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter-telemetry.js +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +14 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +1 -1
- package/packages/dd-trace/src/appsec/iast/telemetry/iast-metric.js +34 -27
- package/packages/dd-trace/src/appsec/iast/telemetry/namespaces.js +39 -11
- package/packages/dd-trace/src/appsec/iast/telemetry/span-tags.js +7 -6
- package/packages/dd-trace/src/appsec/recommended.json +67 -27
- package/packages/dd-trace/src/appsec/remote_config/index.js +1 -1
- package/packages/dd-trace/src/appsec/reporter.js +24 -11
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +1 -3
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +6 -1
- package/packages/dd-trace/src/config.js +451 -460
- package/packages/dd-trace/src/data_streams_context.js +1 -1
- package/packages/dd-trace/src/datastreams/pathway.js +58 -1
- package/packages/dd-trace/src/datastreams/processor.js +3 -5
- package/packages/dd-trace/src/format.js +0 -1
- package/packages/dd-trace/src/lambda/runtime/ritm.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +22 -3
- package/packages/dd-trace/src/opentracing/span.js +2 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/util/test.js +4 -2
- package/packages/dd-trace/src/plugins/util/web.js +1 -1
- package/packages/dd-trace/src/priority_sampler.js +11 -6
- package/packages/dd-trace/src/profiling/exporters/agent.js +38 -2
- package/packages/dd-trace/src/telemetry/index.js +32 -33
- package/packages/dd-trace/src/tracer.js +3 -3
- package/register.js +4 -0
- package/CONTRIBUTING.md +0 -171
- package/MIGRATING.md +0 -224
- package/packages/dd-trace/src/external-logger/test/index.spec.js +0 -147
- package/scripts/check-proposal-labels.js +0 -71
- package/scripts/check_licenses.js +0 -69
- package/scripts/helpers/color.js +0 -8
- package/scripts/helpers/exec.js +0 -22
- package/scripts/helpers/title.js +0 -15
- package/scripts/install_plugin_modules.js +0 -248
- package/scripts/publish_docs.js +0 -21
- package/scripts/st.js +0 -105
- /package/packages/{utils → datadog-core/src/utils}/src/kebabcase.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/pick.js +0 -0
- /package/packages/{utils → datadog-core/src/utils}/src/uniq.js +0 -0
|
@@ -6,7 +6,7 @@ function getDataStreamsContext () {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
function setDataStreamsContext (dataStreamsContext) {
|
|
9
|
-
storage.enterWith({ ...(storage.getStore()), dataStreamsContext })
|
|
9
|
+
if (dataStreamsContext) storage.enterWith({ ...(storage.getStore()), dataStreamsContext })
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
module.exports = {
|
|
@@ -8,6 +8,9 @@ const LRUCache = require('lru-cache')
|
|
|
8
8
|
const options = { max: 500 }
|
|
9
9
|
const cache = new LRUCache(options)
|
|
10
10
|
|
|
11
|
+
const CONTEXT_PROPAGATION_KEY = 'dd-pathway-ctx'
|
|
12
|
+
const CONTEXT_PROPAGATION_KEY_BASE64 = 'dd-pathway-ctx-base64'
|
|
13
|
+
|
|
11
14
|
function shaHash (checkpointString) {
|
|
12
15
|
const hash = crypto.createHash('md5').update(checkpointString).digest('hex').slice(0, 16)
|
|
13
16
|
return Buffer.from(hash, 'hex')
|
|
@@ -33,6 +36,11 @@ function encodePathwayContext (dataStreamsContext) {
|
|
|
33
36
|
], 20)
|
|
34
37
|
}
|
|
35
38
|
|
|
39
|
+
function encodePathwayContextBase64 (dataStreamsContext) {
|
|
40
|
+
const encodedPathway = encodePathwayContext(dataStreamsContext)
|
|
41
|
+
return encodedPathway.toString('base64')
|
|
42
|
+
}
|
|
43
|
+
|
|
36
44
|
function decodePathwayContext (pathwayContext) {
|
|
37
45
|
if (pathwayContext == null || pathwayContext.length < 8) {
|
|
38
46
|
return null
|
|
@@ -51,8 +59,57 @@ function decodePathwayContext (pathwayContext) {
|
|
|
51
59
|
return { hash: pathwayHash, pathwayStartNs: pathwayStartMs * 1e6, edgeStartNs: edgeStartMs * 1e6 }
|
|
52
60
|
}
|
|
53
61
|
|
|
62
|
+
function decodePathwayContextBase64 (pathwayContext) {
|
|
63
|
+
if (pathwayContext == null || pathwayContext.length < 8) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
if (Buffer.isBuffer(pathwayContext)) {
|
|
67
|
+
pathwayContext = pathwayContext.toString()
|
|
68
|
+
}
|
|
69
|
+
const encodedPathway = Buffer.from(pathwayContext, 'base64')
|
|
70
|
+
return decodePathwayContext(encodedPathway)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
class DsmPathwayCodec {
|
|
74
|
+
// we use a class for encoding / decoding in case we update our encoding/decoding. A class will make updates easier
|
|
75
|
+
// instead of using individual functions.
|
|
76
|
+
static encode (dataStreamsContext, carrier) {
|
|
77
|
+
if (!dataStreamsContext || !dataStreamsContext.hash) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
carrier[CONTEXT_PROPAGATION_KEY_BASE64] = encodePathwayContextBase64(dataStreamsContext)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
static decode (carrier) {
|
|
84
|
+
if (carrier == null) return
|
|
85
|
+
|
|
86
|
+
let ctx
|
|
87
|
+
if (CONTEXT_PROPAGATION_KEY_BASE64 in carrier) {
|
|
88
|
+
// decode v2 encoding of base64
|
|
89
|
+
ctx = decodePathwayContextBase64(carrier[CONTEXT_PROPAGATION_KEY_BASE64])
|
|
90
|
+
} else if (CONTEXT_PROPAGATION_KEY in carrier) {
|
|
91
|
+
try {
|
|
92
|
+
// decode v1 encoding
|
|
93
|
+
ctx = decodePathwayContext(carrier[CONTEXT_PROPAGATION_KEY])
|
|
94
|
+
} catch {
|
|
95
|
+
// pass
|
|
96
|
+
}
|
|
97
|
+
// cover case where base64 context was received under wrong key
|
|
98
|
+
if (!ctx) ctx = decodePathwayContextBase64(carrier[CONTEXT_PROPAGATION_KEY])
|
|
99
|
+
}
|
|
100
|
+
return ctx
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static contextExists (carrier) {
|
|
104
|
+
return CONTEXT_PROPAGATION_KEY_BASE64 in carrier || CONTEXT_PROPAGATION_KEY in carrier
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
54
108
|
module.exports = {
|
|
55
109
|
computePathwayHash: computeHash,
|
|
56
110
|
encodePathwayContext,
|
|
57
|
-
decodePathwayContext
|
|
111
|
+
decodePathwayContext,
|
|
112
|
+
encodePathwayContextBase64,
|
|
113
|
+
decodePathwayContextBase64,
|
|
114
|
+
DsmPathwayCodec
|
|
58
115
|
}
|
|
@@ -4,7 +4,7 @@ const pkg = require('../../../../package.json')
|
|
|
4
4
|
const Uint64 = require('int64-buffer').Uint64BE
|
|
5
5
|
|
|
6
6
|
const { LogCollapsingLowestDenseDDSketch } = require('@datadog/sketches-js')
|
|
7
|
-
const {
|
|
7
|
+
const { DsmPathwayCodec } = require('./pathway')
|
|
8
8
|
const { DataStreamsWriter } = require('./writer')
|
|
9
9
|
const { computePathwayHash } = require('./pathway')
|
|
10
10
|
const { types } = require('util')
|
|
@@ -13,7 +13,6 @@ const { PATHWAY_HASH } = require('../../../../ext/tags')
|
|
|
13
13
|
const ENTRY_PARENT_HASH = Buffer.from('0000000000000000', 'hex')
|
|
14
14
|
|
|
15
15
|
const HIGH_ACCURACY_DISTRIBUTION = 0.0075
|
|
16
|
-
const CONTEXT_PROPAGATION_KEY = 'dd-pathway-ctx'
|
|
17
16
|
|
|
18
17
|
class StatsPoint {
|
|
19
18
|
constructor (hash, parentHash, edgeTags) {
|
|
@@ -285,7 +284,7 @@ class DataStreamsProcessor {
|
|
|
285
284
|
// Add the header for this now, as the callee doesn't have access to context when producing
|
|
286
285
|
// - 1 to account for extra byte for {
|
|
287
286
|
const ddInfoContinued = {}
|
|
288
|
-
|
|
287
|
+
DsmPathwayCodec.encode(dataStreamsContext, ddInfoContinued)
|
|
289
288
|
payloadSize += getSizeOrZero(JSON.stringify(ddInfoContinued)) - 1
|
|
290
289
|
}
|
|
291
290
|
const checkpoint = {
|
|
@@ -364,6 +363,5 @@ module.exports = {
|
|
|
364
363
|
getHeadersSize,
|
|
365
364
|
getSizeOrZero,
|
|
366
365
|
getAmqpMessageSize,
|
|
367
|
-
ENTRY_PARENT_HASH
|
|
368
|
-
CONTEXT_PROPAGATION_KEY
|
|
366
|
+
ENTRY_PARENT_HASH
|
|
369
367
|
}
|
|
@@ -87,7 +87,7 @@ const registerLambdaHook = () => {
|
|
|
87
87
|
const lambdaTaskRoot = process.env.LAMBDA_TASK_ROOT
|
|
88
88
|
const originalLambdaHandler = process.env.DD_LAMBDA_HANDLER
|
|
89
89
|
|
|
90
|
-
if (originalLambdaHandler !== undefined) {
|
|
90
|
+
if (originalLambdaHandler !== undefined && lambdaTaskRoot !== undefined) {
|
|
91
91
|
const [moduleRoot, moduleAndHandler] = _extractModuleRootAndHandler(originalLambdaHandler)
|
|
92
92
|
const [_module] = _extractModuleNameAndHandlerPath(moduleAndHandler)
|
|
93
93
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const pick = require('../../../../utils/src/pick')
|
|
3
|
+
const pick = require('../../../../datadog-core/src/utils/src/pick')
|
|
4
4
|
const id = require('../../id')
|
|
5
5
|
const DatadogSpanContext = require('../span_context')
|
|
6
6
|
const log = require('../../log')
|
|
@@ -171,6 +171,14 @@ class TextMapPropagator {
|
|
|
171
171
|
carrier[traceparentKey] = spanContext.toTraceparent()
|
|
172
172
|
|
|
173
173
|
ts.forVendor('dd', state => {
|
|
174
|
+
if (!spanContext._isRemote) {
|
|
175
|
+
// SpanContext was created by a ddtrace span.
|
|
176
|
+
// Last datadog span id should be set to the current span.
|
|
177
|
+
state.set('p', spanContext._spanId)
|
|
178
|
+
} else if (spanContext._trace.tags['_dd.parent_id']) {
|
|
179
|
+
// Propagate the last Datadog span id set on the remote span.
|
|
180
|
+
state.set('p', spanContext._trace.tags['_dd.parent_id'])
|
|
181
|
+
}
|
|
174
182
|
state.set('s', priority)
|
|
175
183
|
if (mechanism) {
|
|
176
184
|
state.set('t.dm', `-${mechanism}`)
|
|
@@ -279,7 +287,8 @@ class TextMapPropagator {
|
|
|
279
287
|
return new DatadogSpanContext({
|
|
280
288
|
traceId: id(),
|
|
281
289
|
spanId: null,
|
|
282
|
-
sampling: { priority }
|
|
290
|
+
sampling: { priority },
|
|
291
|
+
isRemote: true
|
|
283
292
|
})
|
|
284
293
|
}
|
|
285
294
|
|
|
@@ -327,6 +336,7 @@ class TextMapPropagator {
|
|
|
327
336
|
const spanContext = new DatadogSpanContext({
|
|
328
337
|
traceId: id(traceId, 16),
|
|
329
338
|
spanId: id(spanId, 16),
|
|
339
|
+
isRemote: true,
|
|
330
340
|
sampling: { priority: parseInt(flags, 10) & 1 ? 1 : 0 },
|
|
331
341
|
traceparent,
|
|
332
342
|
tracestate
|
|
@@ -337,6 +347,10 @@ class TextMapPropagator {
|
|
|
337
347
|
tracestate.forVendor('dd', state => {
|
|
338
348
|
for (const [key, value] of state.entries()) {
|
|
339
349
|
switch (key) {
|
|
350
|
+
case 'p': {
|
|
351
|
+
spanContext._trace.tags['_dd.parent_id'] = value
|
|
352
|
+
break
|
|
353
|
+
}
|
|
340
354
|
case 's': {
|
|
341
355
|
const priority = parseInt(value, 10)
|
|
342
356
|
if (!Number.isInteger(priority)) continue
|
|
@@ -367,6 +381,10 @@ class TextMapPropagator {
|
|
|
367
381
|
}
|
|
368
382
|
})
|
|
369
383
|
|
|
384
|
+
if (!spanContext._trace.tags['_dd.parent_id']) {
|
|
385
|
+
spanContext._trace.tags['_dd.parent_id'] = '0000000000000000'
|
|
386
|
+
}
|
|
387
|
+
|
|
370
388
|
this._extractBaggageItems(carrier, spanContext)
|
|
371
389
|
return spanContext
|
|
372
390
|
}
|
|
@@ -379,7 +397,8 @@ class TextMapPropagator {
|
|
|
379
397
|
|
|
380
398
|
return new DatadogSpanContext({
|
|
381
399
|
traceId: id(carrier[traceKey], radix),
|
|
382
|
-
spanId: id(carrier[spanKey], radix)
|
|
400
|
+
spanId: id(carrier[spanKey], radix),
|
|
401
|
+
isRemote: true
|
|
383
402
|
})
|
|
384
403
|
}
|
|
385
404
|
|
|
@@ -52,12 +52,13 @@ const TEST_SKIPPED_BY_ITR = 'test.skipped_by_itr'
|
|
|
52
52
|
const TEST_CONFIGURATION_BROWSER_NAME = 'test.configuration.browser_name'
|
|
53
53
|
// Early flake detection
|
|
54
54
|
const TEST_IS_NEW = 'test.is_new'
|
|
55
|
-
const
|
|
55
|
+
const TEST_IS_RETRY = 'test.is_retry'
|
|
56
56
|
const TEST_EARLY_FLAKE_IS_ENABLED = 'test.early_flake.is_enabled'
|
|
57
57
|
|
|
58
58
|
const CI_APP_ORIGIN = 'ciapp-test'
|
|
59
59
|
|
|
60
60
|
const JEST_TEST_RUNNER = 'test.jest.test_runner'
|
|
61
|
+
const JEST_DISPLAY_NAME = 'test.jest.display_name'
|
|
61
62
|
|
|
62
63
|
const TEST_ITR_TESTS_SKIPPED = '_dd.ci.itr.tests_skipped'
|
|
63
64
|
const TEST_ITR_SKIPPING_ENABLED = 'test.itr.tests_skipping.enabled'
|
|
@@ -83,6 +84,7 @@ module.exports = {
|
|
|
83
84
|
TEST_FRAMEWORK,
|
|
84
85
|
TEST_FRAMEWORK_VERSION,
|
|
85
86
|
JEST_TEST_RUNNER,
|
|
87
|
+
JEST_DISPLAY_NAME,
|
|
86
88
|
TEST_TYPE,
|
|
87
89
|
TEST_NAME,
|
|
88
90
|
TEST_SUITE,
|
|
@@ -99,7 +101,7 @@ module.exports = {
|
|
|
99
101
|
TEST_SKIPPED_BY_ITR,
|
|
100
102
|
TEST_CONFIGURATION_BROWSER_NAME,
|
|
101
103
|
TEST_IS_NEW,
|
|
102
|
-
|
|
104
|
+
TEST_IS_RETRY,
|
|
103
105
|
TEST_EARLY_FLAKE_IS_ENABLED,
|
|
104
106
|
getTestEnvironmentMetadata,
|
|
105
107
|
getTestParametersString,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const uniq = require('../../../../utils/src/uniq')
|
|
3
|
+
const uniq = require('../../../../datadog-core/src/utils/src/uniq')
|
|
4
4
|
const analyticsSampler = require('../../analytics_sampler')
|
|
5
5
|
const FORMAT_HTTP_HEADERS = 'http_headers'
|
|
6
6
|
const log = require('../../log')
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const RateLimiter = require('./rate_limiter')
|
|
3
4
|
const Sampler = require('./sampler')
|
|
4
5
|
const { setSamplingRules } = require('./startup-log')
|
|
5
6
|
const SamplingRule = require('./sampling_rule')
|
|
@@ -43,6 +44,7 @@ class PrioritySampler {
|
|
|
43
44
|
configure (env, { sampleRate, rateLimit = 100, rules = [] } = {}) {
|
|
44
45
|
this._env = env
|
|
45
46
|
this._rules = this._normalizeRules(rules, sampleRate, rateLimit)
|
|
47
|
+
this._limiter = new RateLimiter(rateLimit)
|
|
46
48
|
|
|
47
49
|
setSamplingRules(this._rules)
|
|
48
50
|
}
|
|
@@ -136,14 +138,17 @@ class PrioritySampler {
|
|
|
136
138
|
context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
|
|
137
139
|
context._sampling.mechanism = SAMPLING_MECHANISM_RULE
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
+
return rule.sample() && this._isSampledByRateLimit(context)
|
|
142
|
+
? USER_KEEP
|
|
143
|
+
: USER_REJECT
|
|
144
|
+
}
|
|
141
145
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
146
|
+
_isSampledByRateLimit (context) {
|
|
147
|
+
const allowed = this._limiter.isAllowed()
|
|
148
|
+
|
|
149
|
+
context._trace[SAMPLING_LIMIT_DECISION] = this._limiter.effectiveRate()
|
|
145
150
|
|
|
146
|
-
return
|
|
151
|
+
return allowed
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
_getPriorityByAgent (context) {
|
|
@@ -9,6 +9,8 @@ const docker = require('../../exporters/common/docker')
|
|
|
9
9
|
const FormData = require('../../exporters/common/form-data')
|
|
10
10
|
const { storage } = require('../../../../datadog-core')
|
|
11
11
|
const version = require('../../../../../package.json').version
|
|
12
|
+
const os = require('os')
|
|
13
|
+
const perf = require('perf_hooks').performance
|
|
12
14
|
|
|
13
15
|
const containerId = docker.id()
|
|
14
16
|
|
|
@@ -50,7 +52,7 @@ function computeRetries (uploadTimeout) {
|
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
class AgentExporter {
|
|
53
|
-
constructor ({ url, logger, uploadTimeout } = {}) {
|
|
55
|
+
constructor ({ url, logger, uploadTimeout, env, host, service, version } = {}) {
|
|
54
56
|
this._url = url
|
|
55
57
|
this._logger = logger
|
|
56
58
|
|
|
@@ -58,6 +60,10 @@ class AgentExporter {
|
|
|
58
60
|
|
|
59
61
|
this._backoffTime = backoffTime
|
|
60
62
|
this._backoffTries = backoffTries
|
|
63
|
+
this._env = env
|
|
64
|
+
this._host = host
|
|
65
|
+
this._service = service
|
|
66
|
+
this._appVersion = version
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
export ({ profiles, start, end, tags }) {
|
|
@@ -83,7 +89,37 @@ class AgentExporter {
|
|
|
83
89
|
`profiler_version:${version}`,
|
|
84
90
|
'format:pprof',
|
|
85
91
|
...Object.entries(tags).map(([key, value]) => `${key}:${value}`)
|
|
86
|
-
].join(',')
|
|
92
|
+
].join(','),
|
|
93
|
+
info: {
|
|
94
|
+
application: {
|
|
95
|
+
env: this._env,
|
|
96
|
+
service: this._service,
|
|
97
|
+
start_time: new Date(perf.nodeTiming.nodeStart + perf.timeOrigin).toISOString(),
|
|
98
|
+
version: this._appVersion
|
|
99
|
+
},
|
|
100
|
+
platform: {
|
|
101
|
+
hostname: this._host,
|
|
102
|
+
kernel_name: os.type(),
|
|
103
|
+
kernel_release: os.release(),
|
|
104
|
+
kernel_version: os.version()
|
|
105
|
+
},
|
|
106
|
+
profiler: {
|
|
107
|
+
version
|
|
108
|
+
},
|
|
109
|
+
runtime: {
|
|
110
|
+
// Using `nodejs` for consistency with the existing `runtime` tag.
|
|
111
|
+
// Note that the event `family` property uses `node`, as that's what's
|
|
112
|
+
// proscribed by the Intake API, but that's an internal enum and is
|
|
113
|
+
// not customer visible.
|
|
114
|
+
engine: 'nodejs',
|
|
115
|
+
// strip off leading 'v'. This makes the format consistent with other
|
|
116
|
+
// runtimes (e.g. Ruby) but not with the existing `runtime_version` tag.
|
|
117
|
+
// We'll keep it like this as we want cross-engine consistency. We
|
|
118
|
+
// also aren't changing the format of the existing tag as we don't want
|
|
119
|
+
// to break it.
|
|
120
|
+
version: process.version.substring(1)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
87
123
|
})
|
|
88
124
|
|
|
89
125
|
fields.push(['event', event, {
|
|
@@ -20,6 +20,7 @@ let heartbeatTimeout
|
|
|
20
20
|
let heartbeatInterval
|
|
21
21
|
let extendedInterval
|
|
22
22
|
let integrations
|
|
23
|
+
let configWithOrigin = []
|
|
23
24
|
let retryData = null
|
|
24
25
|
const extendedHeartbeatPayload = {}
|
|
25
26
|
|
|
@@ -96,23 +97,6 @@ function getProducts (config) {
|
|
|
96
97
|
return products
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
function flatten (input, result = [], prefix = [], traversedObjects = null) {
|
|
100
|
-
traversedObjects = traversedObjects || new WeakSet()
|
|
101
|
-
if (traversedObjects.has(input)) {
|
|
102
|
-
return
|
|
103
|
-
}
|
|
104
|
-
traversedObjects.add(input)
|
|
105
|
-
for (const [key, value] of Object.entries(input)) {
|
|
106
|
-
if (typeof value === 'object' && value !== null) {
|
|
107
|
-
flatten(value, result, [...prefix, key], traversedObjects)
|
|
108
|
-
} else {
|
|
109
|
-
// TODO: add correct origin value
|
|
110
|
-
result.push({ name: [...prefix, key].join('.'), value, origin: 'unknown' })
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return result
|
|
114
|
-
}
|
|
115
|
-
|
|
116
100
|
function getInstallSignature (config) {
|
|
117
101
|
const { installSignature: sig } = config
|
|
118
102
|
if (sig && (sig.id || sig.time || sig.type)) {
|
|
@@ -127,7 +111,7 @@ function getInstallSignature (config) {
|
|
|
127
111
|
function appStarted (config) {
|
|
128
112
|
const app = {
|
|
129
113
|
products: getProducts(config),
|
|
130
|
-
configuration:
|
|
114
|
+
configuration: configWithOrigin
|
|
131
115
|
}
|
|
132
116
|
const installSignature = getInstallSignature(config)
|
|
133
117
|
if (installSignature) {
|
|
@@ -305,44 +289,59 @@ function updateIntegrations () {
|
|
|
305
289
|
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
306
290
|
}
|
|
307
291
|
|
|
292
|
+
function formatMapForTelemetry (map) {
|
|
293
|
+
// format from an object to a string map in order for
|
|
294
|
+
// telemetry intake to accept the configuration
|
|
295
|
+
return map
|
|
296
|
+
? Object.entries(map).map(([key, value]) => `${key}:${value}`).join(',')
|
|
297
|
+
: ''
|
|
298
|
+
}
|
|
299
|
+
|
|
308
300
|
function updateConfig (changes, config) {
|
|
309
301
|
if (!config.telemetry.enabled) return
|
|
310
302
|
if (changes.length === 0) return
|
|
311
303
|
|
|
312
|
-
// Hack to make system tests happy until we ship telemetry v2
|
|
313
|
-
if (process.env.DD_INTERNAL_TELEMETRY_V2_ENABLED !== '1') return
|
|
314
|
-
|
|
315
304
|
const application = createAppObject(config)
|
|
316
305
|
const host = createHostObject()
|
|
317
306
|
|
|
318
|
-
const
|
|
307
|
+
const nameMapping = {
|
|
319
308
|
sampleRate: 'DD_TRACE_SAMPLE_RATE',
|
|
320
309
|
logInjection: 'DD_LOG_INJECTION',
|
|
321
310
|
headerTags: 'DD_TRACE_HEADER_TAGS',
|
|
322
311
|
tags: 'DD_TAGS'
|
|
323
312
|
}
|
|
324
313
|
|
|
314
|
+
const namesNeedFormatting = new Set(['DD_TAGS', 'peerServiceMapping'])
|
|
315
|
+
|
|
325
316
|
const configuration = []
|
|
317
|
+
const names = [] // list of config names whose values have been changed
|
|
326
318
|
|
|
327
319
|
for (const change of changes) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const name = names[change.name]
|
|
320
|
+
const name = nameMapping[change.name] || change.name
|
|
321
|
+
names.push(name)
|
|
331
322
|
const { origin, value } = change
|
|
332
|
-
const entry = { name,
|
|
323
|
+
const entry = { name, value, origin }
|
|
333
324
|
|
|
334
|
-
if (Array.isArray(value))
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
entry.value = Object.entries(value).map(([key, value]) => `${key}:${value}`)
|
|
338
|
-
}
|
|
325
|
+
if (Array.isArray(value)) entry.value = value.join(',')
|
|
326
|
+
if (namesNeedFormatting.has(entry.name)) entry.value = formatMapForTelemetry(entry.value)
|
|
327
|
+
if (entry.name === 'url' && entry.value) entry.value = entry.value.toString()
|
|
339
328
|
|
|
340
329
|
configuration.push(entry)
|
|
341
330
|
}
|
|
342
331
|
|
|
343
|
-
|
|
332
|
+
function isNotModified (entry) {
|
|
333
|
+
return !names.includes(entry.name)
|
|
334
|
+
}
|
|
344
335
|
|
|
345
|
-
|
|
336
|
+
if (!configWithOrigin.length) {
|
|
337
|
+
configWithOrigin = configuration
|
|
338
|
+
} else {
|
|
339
|
+
// update configWithOrigin to contain up-to-date full list of config values for app-extended-heartbeat
|
|
340
|
+
configWithOrigin = configWithOrigin.filter(isNotModified)
|
|
341
|
+
configWithOrigin = configWithOrigin.concat(configuration)
|
|
342
|
+
const { reqType, payload } = createPayload('app-client-configuration-change', { configuration })
|
|
343
|
+
sendData(config, application, host, reqType, payload, updateRetryData)
|
|
344
|
+
}
|
|
346
345
|
}
|
|
347
346
|
|
|
348
347
|
module.exports = {
|
|
@@ -8,7 +8,7 @@ const { isError } = require('./util')
|
|
|
8
8
|
const { setStartupLogConfig } = require('./startup-log')
|
|
9
9
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
|
|
10
10
|
const { DataStreamsProcessor } = require('./datastreams/processor')
|
|
11
|
-
const {
|
|
11
|
+
const { DsmPathwayCodec } = require('./datastreams/pathway')
|
|
12
12
|
const { DD_MAJOR } = require('../../../version')
|
|
13
13
|
const DataStreamsContext = require('./data_streams_context')
|
|
14
14
|
|
|
@@ -39,8 +39,8 @@ class DatadogTracer extends Tracer {
|
|
|
39
39
|
return ctx
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
decodeDataStreamsContext (
|
|
43
|
-
const ctx =
|
|
42
|
+
decodeDataStreamsContext (carrier) {
|
|
43
|
+
const ctx = DsmPathwayCodec.decode(carrier)
|
|
44
44
|
// we erase the previous context everytime we decode a new one
|
|
45
45
|
DataStreamsContext.setDataStreamsContext(ctx)
|
|
46
46
|
return ctx
|
package/register.js
ADDED