dd-trace 3.38.1 → 3.40.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 +2 -2
- package/README.md +3 -3
- package/ext/kinds.d.ts +1 -0
- package/ext/kinds.js +2 -1
- package/ext/tags.d.ts +2 -1
- package/ext/tags.js +6 -1
- package/index.d.ts +9 -1
- package/package.json +8 -8
- package/packages/datadog-core/src/storage/async_resource.js +1 -1
- package/packages/datadog-esbuild/index.js +1 -20
- package/packages/datadog-instrumentations/src/cucumber.js +5 -0
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/instrument.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +39 -10
- package/packages/datadog-instrumentations/src/knex.js +24 -17
- package/packages/datadog-instrumentations/src/mocha.js +16 -1
- package/packages/datadog-instrumentations/src/next.js +58 -23
- package/packages/datadog-instrumentations/src/playwright.js +11 -6
- package/packages/datadog-instrumentations/src/restify.js +14 -1
- package/packages/datadog-plugin-http/src/client.js +2 -0
- package/packages/datadog-plugin-jest/src/index.js +11 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +8 -6
- package/packages/datadog-plugin-kafkajs/src/producer.js +9 -6
- package/packages/datadog-plugin-mocha/src/index.js +7 -1
- package/packages/datadog-plugin-next/src/index.js +4 -3
- package/packages/datadog-plugin-playwright/src/index.js +4 -1
- package/packages/dd-trace/src/appsec/channels.js +1 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secret-analyzer.js +60 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hardcoded-secrets-rules.js +269 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +5 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +22 -4
- package/packages/dd-trace/src/appsec/iast/analyzers/nosql-injection-mongodb-analyzer.js +9 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/xcontenttype-header-missing-analyzer.js +2 -2
- package/packages/dd-trace/src/appsec/iast/iast-log.js +9 -4
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/index.js +1 -1
- package/packages/dd-trace/src/appsec/iast/path-line.js +7 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +13 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/index.js +1 -14
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +19 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +2 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +5 -1
- package/packages/dd-trace/src/appsec/recommended.json +272 -48
- package/packages/dd-trace/src/appsec/reporter.js +31 -34
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +16 -4
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -0
- package/packages/dd-trace/src/config.js +35 -17
- package/packages/dd-trace/src/datastreams/processor.js +60 -15
- package/packages/dd-trace/src/format.js +6 -1
- package/packages/dd-trace/src/git_properties.js +16 -15
- package/packages/dd-trace/src/iitm.js +1 -1
- package/packages/dd-trace/src/log/channels.js +1 -1
- package/packages/dd-trace/src/opentelemetry/span.js +95 -2
- package/packages/dd-trace/src/opentelemetry/tracer.js +9 -10
- package/packages/dd-trace/src/opentracing/span.js +4 -0
- package/packages/dd-trace/src/opentracing/span_context.js +5 -2
- package/packages/dd-trace/src/plugin_manager.js +1 -1
- package/packages/dd-trace/src/plugins/database.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +1 -1
- package/packages/dd-trace/src/plugins/util/ci.js +6 -19
- package/packages/dd-trace/src/plugins/util/git.js +2 -1
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +7 -6
- package/packages/dd-trace/src/plugins/util/test.js +29 -1
- package/packages/dd-trace/src/plugins/util/url.js +26 -0
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +1 -14
- package/packages/dd-trace/src/profiling/config.js +23 -20
- package/packages/dd-trace/src/profiling/profilers/events.js +161 -0
- package/packages/dd-trace/src/profiling/profilers/shared.js +9 -0
- package/packages/dd-trace/src/profiling/profilers/wall.js +84 -47
- package/packages/dd-trace/src/ritm.js +1 -1
- package/packages/dd-trace/src/span_processor.js +4 -0
- package/packages/dd-trace/src/telemetry/dependencies.js +1 -1
- package/packages/dd-trace/src/telemetry/index.js +5 -1
- package/packages/dd-trace/src/telemetry/logs/index.js +65 -0
- package/packages/dd-trace/src/{appsec/iast/telemetry/log → telemetry/logs}/log-collector.js +9 -22
- package/packages/dd-trace/src/tracer.js +4 -2
- package/packages/dd-trace/src/appsec/iast/telemetry/log/index.js +0 -87
- package/packages/diagnostics_channel/index.js +0 -3
- package/packages/diagnostics_channel/src/index.js +0 -121
|
@@ -10,7 +10,7 @@ const coalesce = require('koalas')
|
|
|
10
10
|
const tagger = require('./tagger')
|
|
11
11
|
const { isTrue, isFalse } = require('./util')
|
|
12
12
|
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
|
|
13
|
-
const { getGitMetadataFromGitProperties } = require('./git_properties')
|
|
13
|
+
const { getGitMetadataFromGitProperties, removeUserSensitiveInfo } = require('./git_properties')
|
|
14
14
|
const { updateConfig } = require('./telemetry')
|
|
15
15
|
const { getIsGCPFunction, getIsAzureFunctionConsumptionPlan } = require('./serverless')
|
|
16
16
|
|
|
@@ -235,8 +235,9 @@ class Config {
|
|
|
235
235
|
|
|
236
236
|
const inServerlessEnvironment = inAWSLambda || isGCPFunction || isAzureFunctionConsumptionPlan
|
|
237
237
|
|
|
238
|
-
const
|
|
239
|
-
process.env.DD_TRACE_TELEMETRY_ENABLED,
|
|
238
|
+
const DD_INSTRUMENTATION_TELEMETRY_ENABLED = coalesce(
|
|
239
|
+
process.env.DD_TRACE_TELEMETRY_ENABLED, // for backward compatibility
|
|
240
|
+
process.env.DD_INSTRUMENTATION_TELEMETRY_ENABLED, // to comply with instrumentation telemetry specs
|
|
240
241
|
!inServerlessEnvironment
|
|
241
242
|
)
|
|
242
243
|
const DD_TELEMETRY_HEARTBEAT_INTERVAL = process.env.DD_TELEMETRY_HEARTBEAT_INTERVAL
|
|
@@ -251,7 +252,7 @@ class Config {
|
|
|
251
252
|
)
|
|
252
253
|
const DD_TELEMETRY_METRICS_ENABLED = coalesce(
|
|
253
254
|
process.env.DD_TELEMETRY_METRICS_ENABLED,
|
|
254
|
-
|
|
255
|
+
true
|
|
255
256
|
)
|
|
256
257
|
const DD_TRACE_AGENT_PROTOCOL_VERSION = coalesce(
|
|
257
258
|
options.protocolVersion,
|
|
@@ -367,10 +368,11 @@ class Config {
|
|
|
367
368
|
isGCPFunction || isAzureFunctionConsumptionPlan
|
|
368
369
|
)
|
|
369
370
|
|
|
371
|
+
// the tracer generates 128 bit IDs by default as of v5
|
|
370
372
|
const DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED = coalesce(
|
|
371
373
|
options.traceId128BitGenerationEnabled,
|
|
372
374
|
process.env.DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED,
|
|
373
|
-
|
|
375
|
+
true
|
|
374
376
|
)
|
|
375
377
|
|
|
376
378
|
const DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED = coalesce(
|
|
@@ -447,7 +449,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
447
449
|
5 // seconds
|
|
448
450
|
)
|
|
449
451
|
|
|
450
|
-
const iastOptions = options
|
|
452
|
+
const iastOptions = options?.experimental?.iast
|
|
451
453
|
const DD_IAST_ENABLED = coalesce(
|
|
452
454
|
iastOptions &&
|
|
453
455
|
(iastOptions === true || iastOptions.enabled === true),
|
|
@@ -461,7 +463,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
461
463
|
|
|
462
464
|
const defaultIastRequestSampling = 30
|
|
463
465
|
const iastRequestSampling = coalesce(
|
|
464
|
-
parseInt(iastOptions
|
|
466
|
+
parseInt(iastOptions?.requestSampling),
|
|
465
467
|
parseInt(process.env.DD_IAST_REQUEST_SAMPLING),
|
|
466
468
|
defaultIastRequestSampling
|
|
467
469
|
)
|
|
@@ -469,31 +471,43 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
469
471
|
iastRequestSampling > 100 ? defaultIastRequestSampling : iastRequestSampling
|
|
470
472
|
|
|
471
473
|
const DD_IAST_MAX_CONCURRENT_REQUESTS = coalesce(
|
|
472
|
-
parseInt(iastOptions
|
|
474
|
+
parseInt(iastOptions?.maxConcurrentRequests),
|
|
473
475
|
parseInt(process.env.DD_IAST_MAX_CONCURRENT_REQUESTS),
|
|
474
476
|
2
|
|
475
477
|
)
|
|
476
478
|
|
|
477
479
|
const DD_IAST_MAX_CONTEXT_OPERATIONS = coalesce(
|
|
478
|
-
parseInt(iastOptions
|
|
480
|
+
parseInt(iastOptions?.maxContextOperations),
|
|
479
481
|
parseInt(process.env.DD_IAST_MAX_CONTEXT_OPERATIONS),
|
|
480
482
|
2
|
|
481
483
|
)
|
|
482
484
|
|
|
483
485
|
const DD_IAST_DEDUPLICATION_ENABLED = coalesce(
|
|
484
|
-
iastOptions
|
|
486
|
+
iastOptions?.deduplicationEnabled,
|
|
485
487
|
process.env.DD_IAST_DEDUPLICATION_ENABLED && isTrue(process.env.DD_IAST_DEDUPLICATION_ENABLED),
|
|
486
488
|
true
|
|
487
489
|
)
|
|
488
490
|
|
|
489
491
|
const DD_IAST_REDACTION_ENABLED = coalesce(
|
|
490
|
-
iastOptions
|
|
492
|
+
iastOptions?.redactionEnabled,
|
|
491
493
|
!isFalse(process.env.DD_IAST_REDACTION_ENABLED),
|
|
492
494
|
true
|
|
493
495
|
)
|
|
494
496
|
|
|
497
|
+
const DD_IAST_REDACTION_NAME_PATTERN = coalesce(
|
|
498
|
+
iastOptions?.redactionNamePattern,
|
|
499
|
+
process.env.DD_IAST_REDACTION_NAME_PATTERN,
|
|
500
|
+
null
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
const DD_IAST_REDACTION_VALUE_PATTERN = coalesce(
|
|
504
|
+
iastOptions?.redactionValuePattern,
|
|
505
|
+
process.env.DD_IAST_REDACTION_VALUE_PATTERN,
|
|
506
|
+
null
|
|
507
|
+
)
|
|
508
|
+
|
|
495
509
|
const DD_IAST_TELEMETRY_VERBOSITY = coalesce(
|
|
496
|
-
iastOptions
|
|
510
|
+
iastOptions?.telemetryVerbosity,
|
|
497
511
|
process.env.DD_IAST_TELEMETRY_VERBOSITY,
|
|
498
512
|
'INFORMATION'
|
|
499
513
|
)
|
|
@@ -586,10 +600,10 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
586
600
|
this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
|
|
587
601
|
// Disabled for CI Visibility's agentless
|
|
588
602
|
this.telemetry = {
|
|
589
|
-
enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(
|
|
603
|
+
enabled: DD_TRACE_EXPORTER !== 'datadog' && isTrue(DD_INSTRUMENTATION_TELEMETRY_ENABLED),
|
|
590
604
|
heartbeatInterval: DD_TELEMETRY_HEARTBEAT_INTERVAL,
|
|
591
|
-
logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
|
|
592
605
|
debug: isTrue(DD_TELEMETRY_DEBUG),
|
|
606
|
+
logCollection: isTrue(DD_TELEMETRY_LOG_COLLECTION_ENABLED),
|
|
593
607
|
metrics: isTrue(DD_TELEMETRY_METRICS_ENABLED)
|
|
594
608
|
}
|
|
595
609
|
this.protocolVersion = DD_TRACE_AGENT_PROTOCOL_VERSION
|
|
@@ -620,6 +634,8 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
620
634
|
maxContextOperations: DD_IAST_MAX_CONTEXT_OPERATIONS,
|
|
621
635
|
deduplicationEnabled: DD_IAST_DEDUPLICATION_ENABLED,
|
|
622
636
|
redactionEnabled: DD_IAST_REDACTION_ENABLED,
|
|
637
|
+
redactionNamePattern: DD_IAST_REDACTION_NAME_PATTERN,
|
|
638
|
+
redactionValuePattern: DD_IAST_REDACTION_VALUE_PATTERN,
|
|
623
639
|
telemetryVerbosity: DD_IAST_TELEMETRY_VERBOSITY
|
|
624
640
|
}
|
|
625
641
|
|
|
@@ -638,9 +654,11 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
638
654
|
this.memcachedCommandEnabled = isTrue(DD_TRACE_MEMCACHED_COMMAND_ENABLED)
|
|
639
655
|
|
|
640
656
|
if (this.gitMetadataEnabled) {
|
|
641
|
-
this.repositoryUrl =
|
|
642
|
-
|
|
643
|
-
|
|
657
|
+
this.repositoryUrl = removeUserSensitiveInfo(
|
|
658
|
+
coalesce(
|
|
659
|
+
process.env.DD_GIT_REPOSITORY_URL,
|
|
660
|
+
this.tags[GIT_REPOSITORY_URL]
|
|
661
|
+
)
|
|
644
662
|
)
|
|
645
663
|
this.commitSHA = coalesce(
|
|
646
664
|
process.env.DD_GIT_COMMIT_SHA,
|
|
@@ -4,12 +4,16 @@ const pkg = require('../../../../package.json')
|
|
|
4
4
|
const Uint64 = require('int64-buffer').Uint64BE
|
|
5
5
|
|
|
6
6
|
const { LogCollapsingLowestDenseDDSketch } = require('@datadog/sketches-js')
|
|
7
|
-
|
|
7
|
+
const { encodePathwayContext } = require('./pathway')
|
|
8
8
|
const { DataStreamsWriter } = require('./writer')
|
|
9
9
|
const { computePathwayHash } = require('./pathway')
|
|
10
|
+
const { types } = require('util')
|
|
11
|
+
const { PATHWAY_HASH } = require('../../../../ext/tags')
|
|
12
|
+
|
|
10
13
|
const ENTRY_PARENT_HASH = Buffer.from('0000000000000000', 'hex')
|
|
11
14
|
|
|
12
15
|
const HIGH_ACCURACY_DISTRIBUTION = 0.0075
|
|
16
|
+
const CONTEXT_PROPAGATION_KEY = 'dd-pathway-ctx'
|
|
13
17
|
|
|
14
18
|
class StatsPoint {
|
|
15
19
|
constructor (hash, parentHash, edgeTags) {
|
|
@@ -18,6 +22,7 @@ class StatsPoint {
|
|
|
18
22
|
this.edgeTags = edgeTags
|
|
19
23
|
this.edgeLatency = new LogCollapsingLowestDenseDDSketch(HIGH_ACCURACY_DISTRIBUTION)
|
|
20
24
|
this.pathwayLatency = new LogCollapsingLowestDenseDDSketch(HIGH_ACCURACY_DISTRIBUTION)
|
|
25
|
+
this.payloadSize = new LogCollapsingLowestDenseDDSketch(HIGH_ACCURACY_DISTRIBUTION)
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
addLatencies (checkpoint) {
|
|
@@ -25,6 +30,7 @@ class StatsPoint {
|
|
|
25
30
|
const pathwayLatencySec = checkpoint.pathwayLatencyNs / 1e9
|
|
26
31
|
this.edgeLatency.accept(edgeLatencySec)
|
|
27
32
|
this.pathwayLatency.accept(pathwayLatencySec)
|
|
33
|
+
this.payloadSize.accept(checkpoint.payloadSize)
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
encode () {
|
|
@@ -33,7 +39,8 @@ class StatsPoint {
|
|
|
33
39
|
ParentHash: this.parentHash,
|
|
34
40
|
EdgeTags: this.edgeTags,
|
|
35
41
|
EdgeLatency: this.edgeLatency.toProto(),
|
|
36
|
-
PathwayLatency: this.pathwayLatency.toProto()
|
|
42
|
+
PathwayLatency: this.pathwayLatency.toProto(),
|
|
43
|
+
PayloadSize: this.payloadSize.toProto()
|
|
37
44
|
}
|
|
38
45
|
}
|
|
39
46
|
}
|
|
@@ -49,6 +56,29 @@ class StatsBucket extends Map {
|
|
|
49
56
|
}
|
|
50
57
|
}
|
|
51
58
|
|
|
59
|
+
function getSizeOrZero (obj) {
|
|
60
|
+
if (typeof obj === 'string') {
|
|
61
|
+
return Buffer.from(obj, 'utf-8').length
|
|
62
|
+
}
|
|
63
|
+
if (types.isArrayBuffer(obj)) {
|
|
64
|
+
return obj.byteLength
|
|
65
|
+
}
|
|
66
|
+
if (Buffer.isBuffer(obj)) {
|
|
67
|
+
return obj.length
|
|
68
|
+
}
|
|
69
|
+
return 0
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function getHeadersSize (headers) {
|
|
73
|
+
if (headers === undefined) return 0
|
|
74
|
+
return Object.entries(headers).reduce((prev, [key, val]) => getSizeOrZero(key) + getSizeOrZero(val) + prev, 0)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function getMessageSize (message) {
|
|
78
|
+
const { key, value, headers } = message
|
|
79
|
+
return getSizeOrZero(key) + getSizeOrZero(value) + getHeadersSize(headers)
|
|
80
|
+
}
|
|
81
|
+
|
|
52
82
|
class TimeBuckets extends Map {
|
|
53
83
|
forTime (time) {
|
|
54
84
|
if (!this.has(time)) {
|
|
@@ -105,15 +135,19 @@ class DataStreamsProcessor {
|
|
|
105
135
|
this.writer.flush(payload)
|
|
106
136
|
}
|
|
107
137
|
|
|
108
|
-
recordCheckpoint (checkpoint) {
|
|
138
|
+
recordCheckpoint (checkpoint, span = null) {
|
|
109
139
|
if (!this.enabled) return
|
|
110
140
|
const bucketTime = Math.round(checkpoint.currentTimestamp - (checkpoint.currentTimestamp % this.bucketSizeNs))
|
|
111
141
|
this.buckets.forTime(bucketTime)
|
|
112
142
|
.forCheckpoint(checkpoint)
|
|
113
143
|
.addLatencies(checkpoint)
|
|
144
|
+
// set DSM pathway hash on span to enable related traces feature on DSM tab, convert from buffer to uint64
|
|
145
|
+
if (span) {
|
|
146
|
+
span.setTag(PATHWAY_HASH, checkpoint.hash.readBigUInt64BE(0).toString())
|
|
147
|
+
}
|
|
114
148
|
}
|
|
115
149
|
|
|
116
|
-
setCheckpoint (edgeTags, ctx = null) {
|
|
150
|
+
setCheckpoint (edgeTags, span, ctx = null, payloadSize = 0) {
|
|
117
151
|
if (!this.enabled) return null
|
|
118
152
|
const nowNs = Date.now() * 1e6
|
|
119
153
|
const direction = edgeTags.find(t => t.startsWith('direction:'))
|
|
@@ -147,16 +181,7 @@ class DataStreamsProcessor {
|
|
|
147
181
|
const hash = computePathwayHash(this.service, this.env, edgeTags, parentHash)
|
|
148
182
|
const edgeLatencyNs = nowNs - edgeStartNs
|
|
149
183
|
const pathwayLatencyNs = nowNs - pathwayStartNs
|
|
150
|
-
const
|
|
151
|
-
currentTimestamp: nowNs,
|
|
152
|
-
parentHash: parentHash,
|
|
153
|
-
hash: hash,
|
|
154
|
-
edgeTags: edgeTags,
|
|
155
|
-
edgeLatencyNs: edgeLatencyNs,
|
|
156
|
-
pathwayLatencyNs: pathwayLatencyNs
|
|
157
|
-
}
|
|
158
|
-
this.recordCheckpoint(checkpoint)
|
|
159
|
-
return {
|
|
184
|
+
const dataStreamsContext = {
|
|
160
185
|
hash: hash,
|
|
161
186
|
edgeStartNs: edgeStartNs,
|
|
162
187
|
pathwayStartNs: pathwayStartNs,
|
|
@@ -164,6 +189,22 @@ class DataStreamsProcessor {
|
|
|
164
189
|
closestOppositeDirectionHash: closestOppositeDirectionHash,
|
|
165
190
|
closestOppositeDirectionEdgeStart: closestOppositeDirectionEdgeStart
|
|
166
191
|
}
|
|
192
|
+
if (direction === 'direction:out') {
|
|
193
|
+
// Add the header for this now, as the callee doesn't have access to context when producing
|
|
194
|
+
payloadSize += getSizeOrZero(encodePathwayContext(dataStreamsContext))
|
|
195
|
+
payloadSize += CONTEXT_PROPAGATION_KEY.length
|
|
196
|
+
}
|
|
197
|
+
const checkpoint = {
|
|
198
|
+
currentTimestamp: nowNs,
|
|
199
|
+
parentHash: parentHash,
|
|
200
|
+
hash: hash,
|
|
201
|
+
edgeTags: edgeTags,
|
|
202
|
+
edgeLatencyNs: edgeLatencyNs,
|
|
203
|
+
pathwayLatencyNs: pathwayLatencyNs,
|
|
204
|
+
payloadSize: payloadSize
|
|
205
|
+
}
|
|
206
|
+
this.recordCheckpoint(checkpoint, span)
|
|
207
|
+
return dataStreamsContext
|
|
167
208
|
}
|
|
168
209
|
|
|
169
210
|
_serializeBuckets () {
|
|
@@ -194,5 +235,9 @@ module.exports = {
|
|
|
194
235
|
StatsPoint: StatsPoint,
|
|
195
236
|
StatsBucket: StatsBucket,
|
|
196
237
|
TimeBuckets,
|
|
197
|
-
|
|
238
|
+
getMessageSize,
|
|
239
|
+
getHeadersSize,
|
|
240
|
+
getSizeOrZero,
|
|
241
|
+
ENTRY_PARENT_HASH,
|
|
242
|
+
CONTEXT_PROPAGATION_KEY
|
|
198
243
|
}
|
|
@@ -14,7 +14,7 @@ const SPAN_SAMPLING_MECHANISM = constants.SPAN_SAMPLING_MECHANISM
|
|
|
14
14
|
const SPAN_SAMPLING_RULE_RATE = constants.SPAN_SAMPLING_RULE_RATE
|
|
15
15
|
const SPAN_SAMPLING_MAX_PER_SECOND = constants.SPAN_SAMPLING_MAX_PER_SECOND
|
|
16
16
|
const SAMPLING_MECHANISM_SPAN = constants.SAMPLING_MECHANISM_SPAN
|
|
17
|
-
const { MEASURED, BASE_SERVICE } = tags
|
|
17
|
+
const { MEASURED, BASE_SERVICE, ANALYTICS } = tags
|
|
18
18
|
const ORIGIN_KEY = constants.ORIGIN_KEY
|
|
19
19
|
const HOSTNAME_KEY = constants.HOSTNAME_KEY
|
|
20
20
|
const TOP_LEVEL_KEY = constants.TOP_LEVEL_KEY
|
|
@@ -24,6 +24,7 @@ const ERROR_STACK = constants.ERROR_STACK
|
|
|
24
24
|
const ERROR_TYPE = constants.ERROR_TYPE
|
|
25
25
|
|
|
26
26
|
const map = {
|
|
27
|
+
'operation.name': 'name',
|
|
27
28
|
'service.name': 'service',
|
|
28
29
|
'span.type': 'type',
|
|
29
30
|
'resource.name': 'resource'
|
|
@@ -83,6 +84,7 @@ function extractTags (trace, span) {
|
|
|
83
84
|
|
|
84
85
|
for (const tag in tags) {
|
|
85
86
|
switch (tag) {
|
|
87
|
+
case 'operation.name':
|
|
86
88
|
case 'service.name':
|
|
87
89
|
case 'span.type':
|
|
88
90
|
case 'resource.name':
|
|
@@ -92,6 +94,9 @@ function extractTags (trace, span) {
|
|
|
92
94
|
case 'http.status_code':
|
|
93
95
|
addTag(trace.meta, {}, tag, tags[tag] && String(tags[tag]))
|
|
94
96
|
break
|
|
97
|
+
case 'analytics.event':
|
|
98
|
+
addTag({}, trace.metrics, ANALYTICS, tags[tag] === undefined || tags[tag] ? 1 : 0)
|
|
99
|
+
break
|
|
95
100
|
case HOSTNAME_KEY:
|
|
96
101
|
case MEASURED:
|
|
97
102
|
addTag({}, trace.metrics, tag, tags[tag] === undefined || tags[tag] ? 1 : 0)
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
const commitSHARegex = /git\.commit\.sha=([a-f\d]{40})/
|
|
2
2
|
const repositoryUrlRegex = /git\.repository_url=([\w\d:@/.-]+)/
|
|
3
3
|
|
|
4
|
+
function removeUserSensitiveInfo (repositoryUrl) {
|
|
5
|
+
try {
|
|
6
|
+
// repository URLs can contain username and password, so we want to filter those out
|
|
7
|
+
const parsedUrl = new URL(repositoryUrl)
|
|
8
|
+
if (parsedUrl.username || parsedUrl.password) {
|
|
9
|
+
return `${parsedUrl.origin}${parsedUrl.pathname}`
|
|
10
|
+
}
|
|
11
|
+
return repositoryUrl
|
|
12
|
+
} catch (e) {
|
|
13
|
+
// if protocol isn't https, no password will be used
|
|
14
|
+
return repositoryUrl
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
4
18
|
function getGitMetadataFromGitProperties (gitPropertiesString) {
|
|
5
19
|
if (!gitPropertiesString) {
|
|
6
20
|
return {}
|
|
@@ -9,24 +23,11 @@ function getGitMetadataFromGitProperties (gitPropertiesString) {
|
|
|
9
23
|
const repositoryUrlMatch = gitPropertiesString.match(repositoryUrlRegex)
|
|
10
24
|
|
|
11
25
|
const repositoryUrl = repositoryUrlMatch ? repositoryUrlMatch[1] : undefined
|
|
12
|
-
let parsedUrl = repositoryUrl
|
|
13
|
-
|
|
14
|
-
if (repositoryUrl) {
|
|
15
|
-
try {
|
|
16
|
-
// repository URLs can contain username and password, so we want to filter those out
|
|
17
|
-
parsedUrl = new URL(repositoryUrl)
|
|
18
|
-
if (parsedUrl.password) {
|
|
19
|
-
parsedUrl = `${parsedUrl.origin}${parsedUrl.pathname}`
|
|
20
|
-
}
|
|
21
|
-
} catch (e) {
|
|
22
|
-
// if protocol isn't https, no password will be used
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
26
|
|
|
26
27
|
return {
|
|
27
28
|
commitSHA: commitSHAMatch ? commitSHAMatch[1] : undefined,
|
|
28
|
-
repositoryUrl:
|
|
29
|
+
repositoryUrl: removeUserSensitiveInfo(repositoryUrl)
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
module.exports = { getGitMetadataFromGitProperties }
|
|
33
|
+
module.exports = { getGitMetadataFromGitProperties, removeUserSensitiveInfo }
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const semver = require('semver')
|
|
4
4
|
const logger = require('./log')
|
|
5
5
|
const { addHook } = require('import-in-the-middle')
|
|
6
|
-
const dc = require('
|
|
6
|
+
const dc = require('dc-polyfill')
|
|
7
7
|
|
|
8
8
|
if (semver.satisfies(process.versions.node, '>=14.13.1')) {
|
|
9
9
|
const moduleLoadStartChannel = dc.channel('dd-trace:moduleLoadStart')
|
|
@@ -11,6 +11,7 @@ const tracer = require('../../')
|
|
|
11
11
|
const DatadogSpan = require('../opentracing/span')
|
|
12
12
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../constants')
|
|
13
13
|
const { SERVICE_NAME, RESOURCE_NAME } = require('../../../../ext/tags')
|
|
14
|
+
const kinds = require('../../../../ext/kinds')
|
|
14
15
|
|
|
15
16
|
const SpanContext = require('./span_context')
|
|
16
17
|
|
|
@@ -19,6 +20,93 @@ function hrTimeToMilliseconds (time) {
|
|
|
19
20
|
return time[0] * 1e3 + time[1] / 1e6
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
const spanKindNames = {
|
|
24
|
+
[api.SpanKind.INTERNAL]: kinds.INTERNAL,
|
|
25
|
+
[api.SpanKind.SERVER]: kinds.SERVER,
|
|
26
|
+
[api.SpanKind.CLIENT]: kinds.CLIENT,
|
|
27
|
+
[api.SpanKind.PRODUCER]: kinds.PRODUCER,
|
|
28
|
+
[api.SpanKind.CONSUMER]: kinds.CONSUMER
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Several of these attributes are not yet supported by the Node.js OTel API.
|
|
33
|
+
* We check for old equivalents where we can, but not all had equivalents.
|
|
34
|
+
*/
|
|
35
|
+
function spanNameMapper (spanName, kind, attributes) {
|
|
36
|
+
if (spanName) return spanName
|
|
37
|
+
|
|
38
|
+
const opName = attributes['operation.name']
|
|
39
|
+
if (opName) return opName
|
|
40
|
+
|
|
41
|
+
const { INTERNAL, SERVER, CLIENT } = api.SpanKind
|
|
42
|
+
|
|
43
|
+
// HTTP server and client requests
|
|
44
|
+
// TODO: Drop http.method when http.request.method is supported.
|
|
45
|
+
for (const key of ['http.method', 'http.request.method']) {
|
|
46
|
+
if (key in attributes) {
|
|
47
|
+
if (kind === SERVER) {
|
|
48
|
+
return 'http.server.request'
|
|
49
|
+
}
|
|
50
|
+
if (kind === CLIENT) {
|
|
51
|
+
return 'http.client.request'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Databases
|
|
57
|
+
const dbSystem = attributes['db.system']
|
|
58
|
+
if (dbSystem && kind === CLIENT) {
|
|
59
|
+
return `${dbSystem}.query`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Messaging
|
|
63
|
+
const msgSys = attributes['messaging.system']
|
|
64
|
+
const msgOp = attributes['messaging.operation']
|
|
65
|
+
if (msgSys && msgOp && kind !== INTERNAL) {
|
|
66
|
+
return `${msgSys}.${msgOp}`
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// RPC (and AWS)
|
|
70
|
+
const rpcSystem = attributes['rpc.system']
|
|
71
|
+
if (rpcSystem) {
|
|
72
|
+
if (kind === CLIENT) {
|
|
73
|
+
return rpcSystem === 'aws-api'
|
|
74
|
+
? `aws.${attributes['rpc.service'] || 'client'}.request`
|
|
75
|
+
: `${rpcSystem}.client.request`
|
|
76
|
+
}
|
|
77
|
+
if (kind === SERVER) {
|
|
78
|
+
return `${rpcSystem}.server.request`
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// FaaS
|
|
83
|
+
const faasProvider = attributes['faas.invoked_provider']
|
|
84
|
+
const faasName = attributes['faas.invoked_name']
|
|
85
|
+
const faasTrigger = attributes['faas.trigger']
|
|
86
|
+
if (kind === CLIENT && faasProvider && faasName) {
|
|
87
|
+
return `${faasProvider}.${faasName}.invoke`
|
|
88
|
+
}
|
|
89
|
+
if (kind === SERVER && faasTrigger) {
|
|
90
|
+
return `${faasTrigger}.invoke`
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// GraphQL
|
|
94
|
+
// NOTE: Not part of Semantic Convention spec yet, but is used in the GraphQL
|
|
95
|
+
// integration.
|
|
96
|
+
const isGraphQL = 'graphql.operation.type' in attributes
|
|
97
|
+
if (isGraphQL) return 'graphql.server.request'
|
|
98
|
+
|
|
99
|
+
// Network
|
|
100
|
+
// TODO: Doesn't exist yet. No equivalent.
|
|
101
|
+
const protocol = attributes['network.protocol.name']
|
|
102
|
+
const protocolPrefix = protocol ? `${protocol}.` : ''
|
|
103
|
+
if (kind === SERVER) return `${protocolPrefix}server.request`
|
|
104
|
+
if (kind === CLIENT) return `${protocolPrefix}client.request`
|
|
105
|
+
|
|
106
|
+
// If all else fails, default to stringified span.kind.
|
|
107
|
+
return spanKindNames[kind]
|
|
108
|
+
}
|
|
109
|
+
|
|
22
110
|
class Span {
|
|
23
111
|
constructor (
|
|
24
112
|
parentTracer,
|
|
@@ -27,7 +115,8 @@ class Span {
|
|
|
27
115
|
spanContext,
|
|
28
116
|
kind,
|
|
29
117
|
links = [],
|
|
30
|
-
timeInput
|
|
118
|
+
timeInput,
|
|
119
|
+
attributes
|
|
31
120
|
) {
|
|
32
121
|
const { _tracer } = tracer
|
|
33
122
|
|
|
@@ -35,7 +124,7 @@ class Span {
|
|
|
35
124
|
const startTime = hrTimeToMilliseconds(hrStartTime)
|
|
36
125
|
|
|
37
126
|
this._ddSpan = new DatadogSpan(_tracer, _tracer._processor, _tracer._prioritySampler, {
|
|
38
|
-
operationName: spanName,
|
|
127
|
+
operationName: spanNameMapper(spanName, kind, attributes),
|
|
39
128
|
context: spanContext._ddContext,
|
|
40
129
|
startTime,
|
|
41
130
|
hostname: _tracer._hostname,
|
|
@@ -46,6 +135,10 @@ class Span {
|
|
|
46
135
|
}
|
|
47
136
|
}, _tracer._debug)
|
|
48
137
|
|
|
138
|
+
if (attributes) {
|
|
139
|
+
this.setAttributes(attributes)
|
|
140
|
+
}
|
|
141
|
+
|
|
49
142
|
this._parentTracer = parentTracer
|
|
50
143
|
this._context = context
|
|
51
144
|
|
|
@@ -78,23 +78,22 @@ class Tracer {
|
|
|
78
78
|
// return api.trace.wrapSpanContext(spanContext)
|
|
79
79
|
// }
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
return new Span(
|
|
82
82
|
this,
|
|
83
83
|
context,
|
|
84
84
|
name,
|
|
85
85
|
spanContext,
|
|
86
86
|
spanKind,
|
|
87
87
|
links,
|
|
88
|
-
options.startTime
|
|
88
|
+
options.startTime,
|
|
89
|
+
|
|
90
|
+
// Set initial span attributes. The attributes object may have been mutated
|
|
91
|
+
// by the sampler, so we sanitize the merged attributes before setting them.
|
|
92
|
+
sanitizeAttributes(
|
|
93
|
+
// Object.assign(attributes, samplingResult.attributes)
|
|
94
|
+
attributes
|
|
95
|
+
)
|
|
89
96
|
)
|
|
90
|
-
// Set initial span attributes. The attributes object may have been mutated
|
|
91
|
-
// by the sampler, so we sanitize the merged attributes before setting them.
|
|
92
|
-
const initAttributes = sanitizeAttributes(
|
|
93
|
-
// Object.assign(attributes, samplingResult.attributes)
|
|
94
|
-
attributes
|
|
95
|
-
)
|
|
96
|
-
span.setAttributes(initAttributes)
|
|
97
|
-
return span
|
|
98
97
|
}
|
|
99
98
|
|
|
100
99
|
startActiveSpan (name, options, context, fn) {
|
|
@@ -12,6 +12,7 @@ const runtimeMetrics = require('../runtime_metrics')
|
|
|
12
12
|
const log = require('../log')
|
|
13
13
|
const { storage } = require('../../../datadog-core')
|
|
14
14
|
const telemetryMetrics = require('../telemetry/metrics')
|
|
15
|
+
const { channel } = require('dc-polyfill')
|
|
15
16
|
|
|
16
17
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
17
18
|
|
|
@@ -30,6 +31,8 @@ const integrationCounters = {
|
|
|
30
31
|
span_finished: {}
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
const finishCh = channel('dd-trace:span:finish')
|
|
35
|
+
|
|
33
36
|
function getIntegrationCounter (event, integration) {
|
|
34
37
|
const counters = integrationCounters[event]
|
|
35
38
|
|
|
@@ -176,6 +179,7 @@ class DatadogSpan {
|
|
|
176
179
|
this._duration = finishTime - this._startTime
|
|
177
180
|
this._spanContext._trace.finished.push(this)
|
|
178
181
|
this._spanContext._isFinished = true
|
|
182
|
+
finishCh.publish(this)
|
|
179
183
|
this._processor.process(this)
|
|
180
184
|
}
|
|
181
185
|
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
const { AUTO_KEEP } = require('../../../../ext/priority')
|
|
4
4
|
|
|
5
|
+
// the lowercase, hex encoded upper 64 bits of a 128-bit trace id, if present
|
|
6
|
+
const TRACE_ID_128 = '_dd.p.tid'
|
|
7
|
+
|
|
5
8
|
class DatadogSpanContext {
|
|
6
9
|
constructor (props) {
|
|
7
10
|
props = props || {}
|
|
@@ -35,8 +38,8 @@ class DatadogSpanContext {
|
|
|
35
38
|
|
|
36
39
|
toTraceparent () {
|
|
37
40
|
const flags = this._sampling.priority >= AUTO_KEEP ? '01' : '00'
|
|
38
|
-
const traceId = this._traceId.toBuffer().length <= 8 && this._trace.tags[
|
|
39
|
-
? this._trace.tags[
|
|
41
|
+
const traceId = this._traceId.toBuffer().length <= 8 && this._trace.tags[TRACE_ID_128]
|
|
42
|
+
? this._trace.tags[TRACE_ID_128] + this._traceId.toString(16).padStart(16, '0')
|
|
40
43
|
: this._traceId.toString(16).padStart(32, '0')
|
|
41
44
|
const spanId = this._spanId.toString(16).padStart(16, '0')
|
|
42
45
|
const version = (this._traceparent && this._traceparent.version) || '00'
|
|
@@ -36,7 +36,7 @@ class DatabasePlugin extends StoragePlugin {
|
|
|
36
36
|
const { encodedDddbs, encodedDde, encodedDdps, encodedDdpv } = this.serviceTags
|
|
37
37
|
|
|
38
38
|
return `dddbs='${encodedDddbs}',dde='${encodedDde}',` +
|
|
39
|
-
|
|
39
|
+
`ddps='${encodedDdps}',ddpv='${encodedDdpv}'`
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
getDbmServiceName (span, tracerService) {
|