dd-trace 4.18.0 → 4.22.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 +3 -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 +29 -0
- package/package.json +11 -10
- package/packages/datadog-core/src/storage/async_resource.js +1 -1
- package/packages/datadog-esbuild/index.js +1 -20
- package/packages/datadog-instrumentations/src/aerospike.js +47 -0
- package/packages/datadog-instrumentations/src/apollo-server-core.js +41 -0
- package/packages/datadog-instrumentations/src/apollo-server.js +83 -0
- package/packages/datadog-instrumentations/src/graphql.js +18 -4
- package/packages/datadog-instrumentations/src/helpers/bundler-register.js +1 -2
- package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
- 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/http/client.js +10 -0
- package/packages/datadog-instrumentations/src/jest.js +11 -5
- package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
- package/packages/datadog-instrumentations/src/next.js +18 -6
- package/packages/datadog-instrumentations/src/restify.js +14 -1
- package/packages/datadog-instrumentations/src/rhea.js +15 -9
- package/packages/datadog-plugin-aerospike/src/index.js +113 -0
- package/packages/datadog-plugin-graphql/src/resolve.js +26 -18
- package/packages/datadog-plugin-http/src/client.js +19 -2
- package/packages/datadog-plugin-kafkajs/src/consumer.js +59 -6
- package/packages/datadog-plugin-kafkajs/src/producer.js +64 -6
- package/packages/datadog-plugin-next/src/index.js +40 -14
- package/packages/dd-trace/src/appsec/activation.js +29 -0
- package/packages/dd-trace/src/appsec/addresses.js +3 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +48 -0
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -1
- package/packages/dd-trace/src/appsec/blocking.js +95 -43
- package/packages/dd-trace/src/appsec/channels.js +5 -2
- package/packages/dd-trace/src/appsec/graphql.js +146 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +105 -0
- package/packages/dd-trace/src/appsec/iast/iast-log.js +1 -1
- 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 +1 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +1 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/constants.js +7 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/command-sensitive-analyzer.js +12 -19
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/header-sensitive-analyzer.js +20 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/json-sensitive-analyzer.js +6 -10
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/ldap-sensitive-analyzer.js +18 -25
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/sql-sensitive-analyzer.js +79 -85
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/url-sensitive-analyzer.js +27 -36
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +14 -11
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +33 -32
- package/packages/dd-trace/src/appsec/recommended.json +1737 -120
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +36 -15
- package/packages/dd-trace/src/appsec/reporter.js +50 -34
- package/packages/dd-trace/src/appsec/rule_manager.js +9 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +28 -13
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +0 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +17 -1
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +75 -56
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +22 -6
- package/packages/dd-trace/src/config.js +48 -7
- package/packages/dd-trace/src/datastreams/processor.js +166 -26
- package/packages/dd-trace/src/format.js +6 -1
- package/packages/dd-trace/src/id.js +12 -0
- package/packages/dd-trace/src/iitm.js +1 -1
- package/packages/dd-trace/src/log/channels.js +1 -1
- package/packages/dd-trace/src/noop/proxy.js +4 -0
- 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/propagation/text_map.js +14 -5
- package/packages/dd-trace/src/opentracing/span.js +6 -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/ci_plugin.js +2 -1
- package/packages/dd-trace/src/plugins/database.js +1 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- 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 +4 -3
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +7 -6
- package/packages/dd-trace/src/plugins/util/test.js +3 -2
- package/packages/dd-trace/src/plugins/util/url.js +26 -0
- package/packages/dd-trace/src/plugins/util/user-provided-git.js +4 -16
- package/packages/dd-trace/src/profiler.js +5 -3
- package/packages/dd-trace/src/profiling/config.js +26 -2
- package/packages/dd-trace/src/profiling/profiler.js +17 -10
- package/packages/dd-trace/src/profiling/profilers/events.js +264 -0
- package/packages/dd-trace/src/profiling/profilers/shared.js +39 -0
- package/packages/dd-trace/src/profiling/profilers/space.js +2 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +121 -58
- package/packages/dd-trace/src/proxy.js +25 -1
- package/packages/dd-trace/src/ritm.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +4 -0
- package/packages/dd-trace/src/span_processor.js +4 -0
- package/packages/dd-trace/src/spanleak.js +98 -0
- package/packages/dd-trace/src/startup-log.js +7 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +56 -10
- package/packages/dd-trace/src/telemetry/index.js +136 -44
- package/packages/dd-trace/src/telemetry/logs/index.js +2 -2
- package/packages/dd-trace/src/telemetry/send-data.js +47 -5
- package/packages/dd-trace/src/tracer.js +8 -2
- package/scripts/install_plugin_modules.js +11 -3
- package/packages/diagnostics_channel/index.js +0 -3
- package/packages/diagnostics_channel/src/index.js +0 -121
|
@@ -236,11 +236,20 @@ class TextMapPropagator {
|
|
|
236
236
|
_extractDatadogContext (carrier) {
|
|
237
237
|
const spanContext = this._extractGenericContext(carrier, traceKey, spanKey, 10)
|
|
238
238
|
|
|
239
|
-
if (spanContext)
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
239
|
+
if (!spanContext) return spanContext
|
|
240
|
+
|
|
241
|
+
this._extractOrigin(carrier, spanContext)
|
|
242
|
+
this._extractBaggageItems(carrier, spanContext)
|
|
243
|
+
this._extractSamplingPriority(carrier, spanContext)
|
|
244
|
+
this._extractTags(carrier, spanContext)
|
|
245
|
+
|
|
246
|
+
if (this._config.tracePropagationExtractFirst) return spanContext
|
|
247
|
+
|
|
248
|
+
const tc = this._extractTraceparentContext(carrier)
|
|
249
|
+
|
|
250
|
+
if (tc && spanContext._traceId.equals(tc._traceId)) {
|
|
251
|
+
spanContext._traceparent = tc._traceparent
|
|
252
|
+
spanContext._tracestate = tc._tracestate
|
|
244
253
|
}
|
|
245
254
|
|
|
246
255
|
return spanContext
|
|
@@ -12,6 +12,8 @@ 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')
|
|
16
|
+
const spanleak = require('../spanleak')
|
|
15
17
|
|
|
16
18
|
const tracerMetrics = telemetryMetrics.manager.namespace('tracers')
|
|
17
19
|
|
|
@@ -30,6 +32,8 @@ const integrationCounters = {
|
|
|
30
32
|
span_finished: {}
|
|
31
33
|
}
|
|
32
34
|
|
|
35
|
+
const finishCh = channel('dd-trace:span:finish')
|
|
36
|
+
|
|
33
37
|
function getIntegrationCounter (event, integration) {
|
|
34
38
|
const counters = integrationCounters[event]
|
|
35
39
|
|
|
@@ -87,6 +91,7 @@ class DatadogSpan {
|
|
|
87
91
|
|
|
88
92
|
unfinishedRegistry.register(this, operationName, this)
|
|
89
93
|
}
|
|
94
|
+
spanleak.addSpan(this, operationName)
|
|
90
95
|
}
|
|
91
96
|
|
|
92
97
|
toString () {
|
|
@@ -176,6 +181,7 @@ class DatadogSpan {
|
|
|
176
181
|
this._duration = finishTime - this._startTime
|
|
177
182
|
this._spanContext._trace.finished.push(this)
|
|
178
183
|
this._spanContext._isFinished = true
|
|
184
|
+
finishCh.publish(this)
|
|
179
185
|
this._processor.process(this)
|
|
180
186
|
}
|
|
181
187
|
|
|
@@ -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) {
|
|
@@ -17,6 +17,7 @@ module.exports = {
|
|
|
17
17
|
get '@opensearch-project/opensearch' () { return require('../../../datadog-plugin-opensearch/src') },
|
|
18
18
|
get '@redis/client' () { return require('../../../datadog-plugin-redis/src') },
|
|
19
19
|
get '@smithy/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
|
|
20
|
+
get 'aerospike' () { return require('../../../datadog-plugin-aerospike/src') },
|
|
20
21
|
get 'amqp10' () { return require('../../../datadog-plugin-amqp10/src') },
|
|
21
22
|
get 'amqplib' () { return require('../../../datadog-plugin-amqplib/src') },
|
|
22
23
|
get 'aws-sdk' () { return require('../../../datadog-plugin-aws-sdk/src') },
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
const URL = require('url').URL
|
|
2
|
-
|
|
3
1
|
const {
|
|
4
2
|
GIT_BRANCH,
|
|
5
3
|
GIT_COMMIT_SHA,
|
|
@@ -24,6 +22,7 @@ const {
|
|
|
24
22
|
CI_NODE_LABELS,
|
|
25
23
|
CI_NODE_NAME
|
|
26
24
|
} = require('./tags')
|
|
25
|
+
const { filterSensitiveInfoFromRepository } = require('./url')
|
|
27
26
|
|
|
28
27
|
// Receives a string with the form 'John Doe <john.doe@gmail.com>'
|
|
29
28
|
// and returns { name: 'John Doe', email: 'john.doe@gmail.com' }
|
|
@@ -67,20 +66,6 @@ function normalizeRef (ref) {
|
|
|
67
66
|
return ref.replace(/origin\/|refs\/heads\/|tags\//gm, '')
|
|
68
67
|
}
|
|
69
68
|
|
|
70
|
-
function filterSensitiveInfoFromRepository (repositoryUrl) {
|
|
71
|
-
if (repositoryUrl.startsWith('git@')) {
|
|
72
|
-
return repositoryUrl
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
const { protocol, hostname, pathname } = new URL(repositoryUrl)
|
|
77
|
-
|
|
78
|
-
return `${protocol}//${hostname}${pathname}`
|
|
79
|
-
} catch (e) {
|
|
80
|
-
return ''
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
69
|
function resolveTilde (filePath) {
|
|
85
70
|
if (!filePath || typeof filePath !== 'string') {
|
|
86
71
|
return ''
|
|
@@ -271,20 +256,22 @@ module.exports = {
|
|
|
271
256
|
const ref = GITHUB_HEAD_REF || GITHUB_REF || ''
|
|
272
257
|
const refKey = ref.includes('tags/') ? GIT_TAG : GIT_BRANCH
|
|
273
258
|
|
|
259
|
+
// Both pipeline URL and job URL include GITHUB_SERVER_URL, which can include user credentials,
|
|
260
|
+
// so we pass them through `filterSensitiveInfoFromRepository`.
|
|
274
261
|
tags = {
|
|
275
262
|
[CI_PIPELINE_ID]: GITHUB_RUN_ID,
|
|
276
263
|
[CI_PIPELINE_NAME]: GITHUB_WORKFLOW,
|
|
277
264
|
[CI_PIPELINE_NUMBER]: GITHUB_RUN_NUMBER,
|
|
278
|
-
[CI_PIPELINE_URL]: pipelineURL,
|
|
265
|
+
[CI_PIPELINE_URL]: filterSensitiveInfoFromRepository(pipelineURL),
|
|
279
266
|
[CI_PROVIDER_NAME]: 'github',
|
|
280
267
|
[GIT_COMMIT_SHA]: GITHUB_SHA,
|
|
281
268
|
[GIT_REPOSITORY_URL]: repositoryURL,
|
|
282
|
-
[CI_JOB_URL]: jobUrl,
|
|
269
|
+
[CI_JOB_URL]: filterSensitiveInfoFromRepository(jobUrl),
|
|
283
270
|
[CI_JOB_NAME]: GITHUB_JOB,
|
|
284
271
|
[CI_WORKSPACE_PATH]: GITHUB_WORKSPACE,
|
|
285
272
|
[refKey]: ref,
|
|
286
273
|
[CI_ENV_VARS]: JSON.stringify({
|
|
287
|
-
GITHUB_SERVER_URL,
|
|
274
|
+
GITHUB_SERVER_URL: filterSensitiveInfoFromRepository(GITHUB_SERVER_URL),
|
|
288
275
|
GITHUB_REPOSITORY,
|
|
289
276
|
GITHUB_RUN_ID,
|
|
290
277
|
GITHUB_RUN_ATTEMPT
|
|
@@ -19,6 +19,7 @@ const {
|
|
|
19
19
|
GIT_COMMIT_AUTHOR_NAME,
|
|
20
20
|
CI_WORKSPACE_PATH
|
|
21
21
|
} = require('./tags')
|
|
22
|
+
const { filterSensitiveInfoFromRepository } = require('./url')
|
|
22
23
|
|
|
23
24
|
const GIT_REV_LIST_MAX_BUFFER = 8 * 1024 * 1024 // 8MB
|
|
24
25
|
|
|
@@ -110,7 +111,7 @@ function getLatestCommits () {
|
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
function
|
|
114
|
+
function getCommitsRevList (commitsToExclude, commitsToInclude) {
|
|
114
115
|
const commitsToExcludeString = commitsToExclude.map(commit => `^${commit}`)
|
|
115
116
|
|
|
116
117
|
try {
|
|
@@ -214,7 +215,7 @@ function getGitMetadata (ciMetadata) {
|
|
|
214
215
|
|
|
215
216
|
return {
|
|
216
217
|
[GIT_REPOSITORY_URL]:
|
|
217
|
-
repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url']),
|
|
218
|
+
filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
|
|
218
219
|
[GIT_COMMIT_MESSAGE]:
|
|
219
220
|
commitMessage || sanitizedExec('git', ['show', '-s', '--format=%s']),
|
|
220
221
|
[GIT_COMMIT_AUTHOR_DATE]: authorDate,
|
|
@@ -235,7 +236,7 @@ module.exports = {
|
|
|
235
236
|
getLatestCommits,
|
|
236
237
|
getRepositoryUrl,
|
|
237
238
|
generatePackFilesForCommits,
|
|
238
|
-
|
|
239
|
+
getCommitsRevList,
|
|
239
240
|
GIT_REV_LIST_MAX_BUFFER,
|
|
240
241
|
isShallowRepository,
|
|
241
242
|
unshallowRepository
|
|
@@ -48,8 +48,8 @@ function extractIp (config, req) {
|
|
|
48
48
|
|
|
49
49
|
let firstPrivateIp
|
|
50
50
|
if (headers) {
|
|
51
|
-
for (
|
|
52
|
-
const firstIp = findFirstIp(headers[
|
|
51
|
+
for (const ipHeaderName of ipHeaderList) {
|
|
52
|
+
const firstIp = findFirstIp(headers[ipHeaderName])
|
|
53
53
|
|
|
54
54
|
if (firstIp.public) {
|
|
55
55
|
return firstIp.public
|
|
@@ -59,7 +59,7 @@ function extractIp (config, req) {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
return firstPrivateIp ||
|
|
62
|
+
return firstPrivateIp || req.socket?.remoteAddress
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function findFirstIp (str) {
|
|
@@ -68,8 +68,8 @@ function findFirstIp (str) {
|
|
|
68
68
|
|
|
69
69
|
const splitted = str.split(',')
|
|
70
70
|
|
|
71
|
-
for (
|
|
72
|
-
const chunk =
|
|
71
|
+
for (const part of splitted) {
|
|
72
|
+
const chunk = part.trim()
|
|
73
73
|
|
|
74
74
|
// TODO: strip port and interface data ?
|
|
75
75
|
|
|
@@ -90,5 +90,6 @@ function findFirstIp (str) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
module.exports = {
|
|
93
|
-
extractIp
|
|
93
|
+
extractIp,
|
|
94
|
+
ipHeaderList
|
|
94
95
|
}
|
|
@@ -397,8 +397,9 @@ function addIntelligentTestRunnerSpanTags (
|
|
|
397
397
|
testModuleSpan.setTag(TEST_ITR_FORCED_RUN, 'true')
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
//
|
|
401
|
-
|
|
400
|
+
// This will not be reported unless the user has manually added code coverage.
|
|
401
|
+
// This is always the case for Mocha and Cucumber, but not for Jest.
|
|
402
|
+
if (testCodeCoverageLinesTotal !== undefined) {
|
|
402
403
|
testSessionSpan.setTag(TEST_CODE_COVERAGE_LINES_PCT, testCodeCoverageLinesTotal)
|
|
403
404
|
testModuleSpan.setTag(TEST_CODE_COVERAGE_LINES_PCT, testCodeCoverageLinesTotal)
|
|
404
405
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const { URL } = require('url')
|
|
2
|
+
|
|
3
|
+
function filterSensitiveInfoFromRepository (repositoryUrl) {
|
|
4
|
+
if (!repositoryUrl) {
|
|
5
|
+
return ''
|
|
6
|
+
}
|
|
7
|
+
if (repositoryUrl.startsWith('git@')) {
|
|
8
|
+
return repositoryUrl
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Remove the username from ssh URLs
|
|
12
|
+
if (repositoryUrl.startsWith('ssh://')) {
|
|
13
|
+
const sshRegex = /^(ssh:\/\/)[^@/]*@/
|
|
14
|
+
return repositoryUrl.replace(sshRegex, '$1')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
const { protocol, host, pathname } = new URL(repositoryUrl)
|
|
19
|
+
|
|
20
|
+
return `${protocol}//${host}${pathname === '/' ? '' : pathname}`
|
|
21
|
+
} catch (e) {
|
|
22
|
+
return ''
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = { filterSensitiveInfoFromRepository }
|
|
@@ -13,7 +13,7 @@ const {
|
|
|
13
13
|
} = require('./tags')
|
|
14
14
|
|
|
15
15
|
const { normalizeRef } = require('./ci')
|
|
16
|
-
const {
|
|
16
|
+
const { filterSensitiveInfoFromRepository } = require('./url')
|
|
17
17
|
|
|
18
18
|
function removeEmptyValues (tags) {
|
|
19
19
|
return Object.keys(tags).reduce((filteredTags, tag) => {
|
|
@@ -27,23 +27,11 @@ function removeEmptyValues (tags) {
|
|
|
27
27
|
}, {})
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
try {
|
|
32
|
-
if (repositoryUrl.startsWith('git@')) {
|
|
33
|
-
return repositoryUrl
|
|
34
|
-
}
|
|
35
|
-
const { protocol, hostname, pathname } = new URL(repositoryUrl)
|
|
36
|
-
|
|
37
|
-
return `${protocol}//${hostname}${pathname}`
|
|
38
|
-
} catch (e) {
|
|
39
|
-
return repositoryUrl
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// The regex is extracted from
|
|
30
|
+
// The regex is inspired by
|
|
44
31
|
// https://github.com/jonschlinkert/is-git-url/blob/396965ffabf2f46656c8af4c47bef1d69f09292e/index.js#L9C15-L9C87
|
|
32
|
+
// The `.git` suffix is optional in this version
|
|
45
33
|
function validateGitRepositoryUrl (repoUrl) {
|
|
46
|
-
return /(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(
|
|
34
|
+
return /(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\/?|#[-\d\w._]+?)$/.test(repoUrl)
|
|
47
35
|
}
|
|
48
36
|
|
|
49
37
|
function validateGitCommitSha (gitCommitSha) {
|
|
@@ -8,7 +8,7 @@ process.once('beforeExit', () => { profiler.stop() })
|
|
|
8
8
|
|
|
9
9
|
module.exports = {
|
|
10
10
|
start: config => {
|
|
11
|
-
const { service, version, env, url, hostname, port, tags } = config
|
|
11
|
+
const { service, version, env, url, hostname, port, tags, repositoryUrl, commitSHA } = config
|
|
12
12
|
const { enabled, sourceMap, exporters } = config.profiling
|
|
13
13
|
const logger = {
|
|
14
14
|
debug: (message) => log.debug(message),
|
|
@@ -17,7 +17,7 @@ module.exports = {
|
|
|
17
17
|
error: (message) => log.error(message)
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
profiler.start({
|
|
20
|
+
return profiler.start({
|
|
21
21
|
enabled,
|
|
22
22
|
service,
|
|
23
23
|
version,
|
|
@@ -28,7 +28,9 @@ module.exports = {
|
|
|
28
28
|
url,
|
|
29
29
|
hostname,
|
|
30
30
|
port,
|
|
31
|
-
tags
|
|
31
|
+
tags,
|
|
32
|
+
repositoryUrl,
|
|
33
|
+
commitSHA
|
|
32
34
|
})
|
|
33
35
|
},
|
|
34
36
|
|
|
@@ -9,7 +9,9 @@ const { FileExporter } = require('./exporters/file')
|
|
|
9
9
|
const { ConsoleLogger } = require('./loggers/console')
|
|
10
10
|
const WallProfiler = require('./profilers/wall')
|
|
11
11
|
const SpaceProfiler = require('./profilers/space')
|
|
12
|
+
const EventsProfiler = require('./profilers/events')
|
|
12
13
|
const { oomExportStrategies, snapshotKinds } = require('./constants')
|
|
14
|
+
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
|
|
13
15
|
const { tagger } = require('./tagger')
|
|
14
16
|
const { isFalse, isTrue } = require('../util')
|
|
15
17
|
|
|
@@ -37,6 +39,7 @@ class Config {
|
|
|
37
39
|
DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE,
|
|
38
40
|
DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT,
|
|
39
41
|
DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES,
|
|
42
|
+
DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED,
|
|
40
43
|
DD_PROFILING_CODEHOTSPOTS_ENABLED,
|
|
41
44
|
DD_PROFILING_ENDPOINT_COLLECTION_ENABLED,
|
|
42
45
|
DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED,
|
|
@@ -70,6 +73,13 @@ class Config {
|
|
|
70
73
|
tagger.parse(options.tags),
|
|
71
74
|
tagger.parse({ env, host, service, version, functionname })
|
|
72
75
|
)
|
|
76
|
+
|
|
77
|
+
// Add source code integration tags if available
|
|
78
|
+
if (options.repositoryUrl && options.commitSHA) {
|
|
79
|
+
this.tags[GIT_REPOSITORY_URL] = options.repositoryUrl
|
|
80
|
+
this.tags[GIT_COMMIT_SHA] = options.commitSHA
|
|
81
|
+
}
|
|
82
|
+
|
|
73
83
|
this.logger = ensureLogger(options.logger)
|
|
74
84
|
const logger = this.logger
|
|
75
85
|
function logExperimentalVarDeprecation (shortVarName) {
|
|
@@ -126,7 +136,14 @@ class Config {
|
|
|
126
136
|
|
|
127
137
|
const profilers = options.profilers
|
|
128
138
|
? options.profilers
|
|
129
|
-
: getProfilers({
|
|
139
|
+
: getProfilers({
|
|
140
|
+
DD_PROFILING_HEAP_ENABLED,
|
|
141
|
+
DD_PROFILING_WALLTIME_ENABLED,
|
|
142
|
+
DD_PROFILING_PROFILERS
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
this.timelineEnabled = isTrue(coalesce(options.timelineEnabled,
|
|
146
|
+
DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED, false))
|
|
130
147
|
|
|
131
148
|
this.codeHotspotsEnabled = isTrue(coalesce(options.codeHotspotsEnabled,
|
|
132
149
|
DD_PROFILING_CODEHOTSPOTS_ENABLED,
|
|
@@ -139,7 +156,9 @@ class Config {
|
|
|
139
156
|
|
|
140
157
|
module.exports = { Config }
|
|
141
158
|
|
|
142
|
-
function getProfilers ({
|
|
159
|
+
function getProfilers ({
|
|
160
|
+
DD_PROFILING_HEAP_ENABLED, DD_PROFILING_WALLTIME_ENABLED, DD_PROFILING_PROFILERS
|
|
161
|
+
}) {
|
|
143
162
|
// First consider "legacy" DD_PROFILING_PROFILERS env variable, defaulting to wall + space
|
|
144
163
|
// Use a Set to avoid duplicates
|
|
145
164
|
const profilers = new Set(coalesce(DD_PROFILING_PROFILERS, 'wall,space').split(','))
|
|
@@ -240,6 +259,11 @@ function ensureProfilers (profilers, options) {
|
|
|
240
259
|
}
|
|
241
260
|
}
|
|
242
261
|
|
|
262
|
+
// Events profiler is a profiler for timeline events
|
|
263
|
+
if (options.timelineEnabled) {
|
|
264
|
+
profilers.push(new EventsProfiler(options))
|
|
265
|
+
}
|
|
266
|
+
|
|
243
267
|
// Filter out any invalid profilers
|
|
244
268
|
return profilers.filter(v => v)
|
|
245
269
|
}
|
|
@@ -23,15 +23,19 @@ class Profiler extends EventEmitter {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
start (options) {
|
|
26
|
-
this._start(options).catch((err) => {
|
|
27
|
-
|
|
26
|
+
return this._start(options).catch((err) => {
|
|
27
|
+
if (options.logger) {
|
|
28
|
+
options.logger.error(err)
|
|
29
|
+
}
|
|
30
|
+
return false
|
|
31
|
+
})
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
async _start (options) {
|
|
31
|
-
if (this._enabled) return
|
|
35
|
+
if (this._enabled) return true
|
|
32
36
|
|
|
33
37
|
const config = this._config = new Config(options)
|
|
34
|
-
if (!config.enabled) return
|
|
38
|
+
if (!config.enabled) return false
|
|
35
39
|
|
|
36
40
|
this._logger = config.logger
|
|
37
41
|
this._enabled = true
|
|
@@ -57,6 +61,7 @@ class Profiler extends EventEmitter {
|
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
try {
|
|
64
|
+
const start = new Date()
|
|
60
65
|
for (const profiler of config.profilers) {
|
|
61
66
|
// TODO: move this out of Profiler when restoring sourcemap support
|
|
62
67
|
profiler.start({
|
|
@@ -66,10 +71,12 @@ class Profiler extends EventEmitter {
|
|
|
66
71
|
this._logger.debug(`Started ${profiler.type} profiler`)
|
|
67
72
|
}
|
|
68
73
|
|
|
69
|
-
this._capture(this._timeoutInterval)
|
|
74
|
+
this._capture(this._timeoutInterval, start)
|
|
75
|
+
return true
|
|
70
76
|
} catch (e) {
|
|
71
77
|
this._logger.error(e)
|
|
72
78
|
this._stop()
|
|
79
|
+
return false
|
|
73
80
|
}
|
|
74
81
|
}
|
|
75
82
|
|
|
@@ -110,9 +117,9 @@ class Profiler extends EventEmitter {
|
|
|
110
117
|
return this
|
|
111
118
|
}
|
|
112
119
|
|
|
113
|
-
_capture (timeout) {
|
|
120
|
+
_capture (timeout, start) {
|
|
114
121
|
if (!this._enabled) return
|
|
115
|
-
this._lastStart =
|
|
122
|
+
this._lastStart = start
|
|
116
123
|
if (!this._timer || timeout !== this._timeoutInterval) {
|
|
117
124
|
this._timer = setTimeout(() => this._collect(snapshotKinds.PERIODIC), timeout)
|
|
118
125
|
this._timer.unref()
|
|
@@ -132,7 +139,7 @@ class Profiler extends EventEmitter {
|
|
|
132
139
|
try {
|
|
133
140
|
// collect profiles synchronously so that profilers can be safely stopped asynchronously
|
|
134
141
|
for (const profiler of this._config.profilers) {
|
|
135
|
-
const profile = profiler.profile()
|
|
142
|
+
const profile = profiler.profile(start, end)
|
|
136
143
|
if (!profile) continue
|
|
137
144
|
profiles.push({ profiler, profile })
|
|
138
145
|
}
|
|
@@ -148,7 +155,7 @@ class Profiler extends EventEmitter {
|
|
|
148
155
|
})
|
|
149
156
|
}
|
|
150
157
|
|
|
151
|
-
this._capture(this._timeoutInterval)
|
|
158
|
+
this._capture(this._timeoutInterval, end)
|
|
152
159
|
await this._submit(encodedProfiles, start, end, snapshotKind)
|
|
153
160
|
this._logger.debug('Submitted profiles')
|
|
154
161
|
} catch (err) {
|
|
@@ -195,7 +202,7 @@ class ServerlessProfiler extends Profiler {
|
|
|
195
202
|
await super._collect(snapshotKind)
|
|
196
203
|
} else {
|
|
197
204
|
this._profiledIntervals += 1
|
|
198
|
-
this._capture(this._timeoutInterval)
|
|
205
|
+
this._capture(this._timeoutInterval, new Date())
|
|
199
206
|
// Don't submit profile until 65 (flushAfterIntervals) intervals have elapsed
|
|
200
207
|
}
|
|
201
208
|
}
|