dd-trace 4.18.0 → 4.23.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 +12 -11
- 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/child-process.js +4 -5
- package/packages/datadog-instrumentations/src/couchbase.js +5 -4
- package/packages/datadog-instrumentations/src/crypto.js +2 -1
- package/packages/datadog-instrumentations/src/dns.js +2 -1
- 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 +10 -2
- package/packages/datadog-instrumentations/src/helpers/instrument.js +9 -4
- package/packages/datadog-instrumentations/src/helpers/register.js +19 -3
- package/packages/datadog-instrumentations/src/http/client.js +12 -2
- package/packages/datadog-instrumentations/src/http/server.js +7 -4
- package/packages/datadog-instrumentations/src/http2/client.js +3 -1
- package/packages/datadog-instrumentations/src/http2/server.js +3 -1
- package/packages/datadog-instrumentations/src/jest.js +12 -6
- package/packages/datadog-instrumentations/src/kafkajs.js +27 -0
- package/packages/datadog-instrumentations/src/net.js +10 -2
- 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-cucumber/src/index.js +34 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +60 -8
- package/packages/datadog-plugin-graphql/src/resolve.js +26 -18
- package/packages/datadog-plugin-http/src/client.js +19 -2
- package/packages/datadog-plugin-jest/src/index.js +38 -4
- package/packages/datadog-plugin-kafkajs/src/consumer.js +59 -6
- package/packages/datadog-plugin-kafkajs/src/producer.js +64 -6
- package/packages/datadog-plugin-mocha/src/index.js +32 -1
- package/packages/datadog-plugin-next/src/index.js +40 -14
- package/packages/datadog-plugin-playwright/src/index.js +17 -1
- 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 +6 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +40 -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/agentless/coverage-writer.js +30 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +30 -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 +110 -59
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-itr-configuration.js +40 -7
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +26 -1
- package/packages/dd-trace/src/ci-visibility/telemetry.js +130 -0
- package/packages/dd-trace/src/config.js +145 -63
- package/packages/dd-trace/src/datastreams/processor.js +166 -26
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +14 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +14 -0
- package/packages/dd-trace/src/exporters/common/agent-info-exporter.js +4 -0
- package/packages/dd-trace/src/exporters/common/form-data.js +4 -0
- 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/opentracing/tracer.js +2 -2
- package/packages/dd-trace/src/plugin_manager.js +1 -1
- package/packages/dd-trace/src/plugins/ci_plugin.js +46 -9
- package/packages/dd-trace/src/plugins/database.js +1 -1
- package/packages/dd-trace/src/plugins/index.js +6 -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/exec.js +23 -2
- package/packages/dd-trace/src/plugins/util/git.js +98 -22
- 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/priority_sampler.js +30 -38
- 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/exporters/agent.js +1 -0
- 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/sampling_rule.js +130 -0
- 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/span_sampler.js +6 -64
- 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 +171 -41
- 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
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
const cp = require('child_process')
|
|
2
2
|
const log = require('../../log')
|
|
3
|
+
const { distributionMetric, incrementCountMetric } = require('../../ci-visibility/telemetry')
|
|
3
4
|
|
|
4
|
-
const sanitizedExec = (
|
|
5
|
+
const sanitizedExec = (
|
|
6
|
+
cmd,
|
|
7
|
+
flags,
|
|
8
|
+
operationMetric,
|
|
9
|
+
durationMetric,
|
|
10
|
+
errorMetric
|
|
11
|
+
) => {
|
|
12
|
+
let startTime
|
|
13
|
+
if (operationMetric) {
|
|
14
|
+
incrementCountMetric(operationMetric.name, operationMetric.tags)
|
|
15
|
+
}
|
|
16
|
+
if (durationMetric) {
|
|
17
|
+
startTime = Date.now()
|
|
18
|
+
}
|
|
5
19
|
try {
|
|
6
|
-
|
|
20
|
+
const result = cp.execFileSync(cmd, flags, { stdio: 'pipe' }).toString().replace(/(\r\n|\n|\r)/gm, '')
|
|
21
|
+
if (durationMetric) {
|
|
22
|
+
distributionMetric(durationMetric.name, durationMetric.tags, Date.now() - startTime)
|
|
23
|
+
}
|
|
24
|
+
return result
|
|
7
25
|
} catch (e) {
|
|
26
|
+
if (errorMetric) {
|
|
27
|
+
incrementCountMetric(errorMetric.name, { ...errorMetric.tags, exitCode: e.status })
|
|
28
|
+
}
|
|
8
29
|
log.error(e)
|
|
9
30
|
return ''
|
|
10
31
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
const
|
|
1
|
+
const cp = require('child_process')
|
|
2
2
|
const os = require('os')
|
|
3
3
|
const path = require('path')
|
|
4
4
|
const fs = require('fs')
|
|
5
5
|
|
|
6
6
|
const log = require('../../log')
|
|
7
|
-
const { sanitizedExec } = require('./exec')
|
|
8
7
|
const {
|
|
9
8
|
GIT_COMMIT_SHA,
|
|
10
9
|
GIT_BRANCH,
|
|
@@ -19,9 +18,46 @@ const {
|
|
|
19
18
|
GIT_COMMIT_AUTHOR_NAME,
|
|
20
19
|
CI_WORKSPACE_PATH
|
|
21
20
|
} = require('./tags')
|
|
21
|
+
const {
|
|
22
|
+
incrementCountMetric,
|
|
23
|
+
distributionMetric,
|
|
24
|
+
TELEMETRY_GIT_COMMAND,
|
|
25
|
+
TELEMETRY_GIT_COMMAND_MS,
|
|
26
|
+
TELEMETRY_GIT_COMMAND_ERRORS
|
|
27
|
+
} = require('../../ci-visibility/telemetry')
|
|
28
|
+
const { filterSensitiveInfoFromRepository } = require('./url')
|
|
22
29
|
|
|
23
30
|
const GIT_REV_LIST_MAX_BUFFER = 8 * 1024 * 1024 // 8MB
|
|
24
31
|
|
|
32
|
+
function sanitizedExec (
|
|
33
|
+
cmd,
|
|
34
|
+
flags,
|
|
35
|
+
operationMetric,
|
|
36
|
+
durationMetric,
|
|
37
|
+
errorMetric
|
|
38
|
+
) {
|
|
39
|
+
let startTime
|
|
40
|
+
if (operationMetric) {
|
|
41
|
+
incrementCountMetric(operationMetric.name, operationMetric.tags)
|
|
42
|
+
}
|
|
43
|
+
if (durationMetric) {
|
|
44
|
+
startTime = Date.now()
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const result = cp.execFileSync(cmd, flags, { stdio: 'pipe' }).toString().replace(/(\r\n|\n|\r)/gm, '')
|
|
48
|
+
if (durationMetric) {
|
|
49
|
+
distributionMetric(durationMetric.name, durationMetric.tags, Date.now() - startTime)
|
|
50
|
+
}
|
|
51
|
+
return result
|
|
52
|
+
} catch (e) {
|
|
53
|
+
if (errorMetric) {
|
|
54
|
+
incrementCountMetric(errorMetric.name, { ...errorMetric.tags, exitCode: e.status })
|
|
55
|
+
}
|
|
56
|
+
log.error(e)
|
|
57
|
+
return ''
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
25
61
|
function isDirectory (path) {
|
|
26
62
|
try {
|
|
27
63
|
const stats = fs.statSync(path)
|
|
@@ -32,7 +68,13 @@ function isDirectory (path) {
|
|
|
32
68
|
}
|
|
33
69
|
|
|
34
70
|
function isShallowRepository () {
|
|
35
|
-
return sanitizedExec(
|
|
71
|
+
return sanitizedExec(
|
|
72
|
+
'git',
|
|
73
|
+
['rev-parse', '--is-shallow-repository'],
|
|
74
|
+
{ name: TELEMETRY_GIT_COMMAND, tags: { command: 'check_shallow' } },
|
|
75
|
+
{ name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'check_shallow' } },
|
|
76
|
+
{ name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'check_shallow' } }
|
|
77
|
+
) === 'true'
|
|
36
78
|
}
|
|
37
79
|
|
|
38
80
|
function getGitVersion () {
|
|
@@ -71,50 +113,76 @@ function unshallowRepository () {
|
|
|
71
113
|
defaultRemoteName
|
|
72
114
|
]
|
|
73
115
|
|
|
116
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'unshallow' })
|
|
117
|
+
const start = Date.now()
|
|
74
118
|
try {
|
|
75
|
-
execFileSync('git', [
|
|
119
|
+
cp.execFileSync('git', [
|
|
76
120
|
...baseGitOptions,
|
|
77
121
|
revParseHead
|
|
78
122
|
], { stdio: 'pipe' })
|
|
79
|
-
} catch (
|
|
123
|
+
} catch (err) {
|
|
80
124
|
// If the local HEAD is a commit that has not been pushed to the remote, the above command will fail.
|
|
81
|
-
log.error(
|
|
125
|
+
log.error(err)
|
|
126
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'unshallow', exitCode: err.status })
|
|
82
127
|
const upstreamRemote = sanitizedExec('git', ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{upstream}'])
|
|
83
128
|
try {
|
|
84
|
-
execFileSync('git', [
|
|
129
|
+
cp.execFileSync('git', [
|
|
85
130
|
...baseGitOptions,
|
|
86
131
|
upstreamRemote
|
|
87
132
|
], { stdio: 'pipe' })
|
|
88
|
-
} catch (
|
|
133
|
+
} catch (err) {
|
|
89
134
|
// If the CI is working on a detached HEAD or branch tracking hasn’t been set up, the above command will fail.
|
|
90
|
-
log.error(
|
|
135
|
+
log.error(err)
|
|
136
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'unshallow', exitCode: err.status })
|
|
91
137
|
// We use sanitizedExec here because if this last option fails, we'll give up.
|
|
92
|
-
sanitizedExec(
|
|
138
|
+
sanitizedExec(
|
|
139
|
+
'git',
|
|
140
|
+
baseGitOptions,
|
|
141
|
+
null,
|
|
142
|
+
null,
|
|
143
|
+
{ name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'unshallow' } } // we log the error in sanitizedExec
|
|
144
|
+
)
|
|
93
145
|
}
|
|
94
146
|
}
|
|
147
|
+
distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'unshallow' }, Date.now() - start)
|
|
95
148
|
}
|
|
96
149
|
|
|
97
150
|
function getRepositoryUrl () {
|
|
98
|
-
return sanitizedExec(
|
|
151
|
+
return sanitizedExec(
|
|
152
|
+
'git',
|
|
153
|
+
['config', '--get', 'remote.origin.url'],
|
|
154
|
+
{ name: TELEMETRY_GIT_COMMAND, tags: { command: 'get_repository' } },
|
|
155
|
+
{ name: TELEMETRY_GIT_COMMAND_MS, tags: { command: 'get_repository' } },
|
|
156
|
+
{ name: TELEMETRY_GIT_COMMAND_ERRORS, tags: { command: 'get_repository' } }
|
|
157
|
+
)
|
|
99
158
|
}
|
|
100
159
|
|
|
101
160
|
function getLatestCommits () {
|
|
161
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'get_local_commits' })
|
|
162
|
+
const startTime = Date.now()
|
|
102
163
|
try {
|
|
103
|
-
|
|
164
|
+
const result = cp.execFileSync('git', ['log', '--format=%H', '-n 1000', '--since="1 month ago"'], { stdio: 'pipe' })
|
|
104
165
|
.toString()
|
|
105
166
|
.split('\n')
|
|
106
167
|
.filter(commit => commit)
|
|
168
|
+
distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'get_local_commits' }, Date.now() - startTime)
|
|
169
|
+
return result
|
|
107
170
|
} catch (err) {
|
|
108
171
|
log.error(`Get latest commits failed: ${err.message}`)
|
|
172
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'get_local_commits', errorType: err.status })
|
|
109
173
|
return []
|
|
110
174
|
}
|
|
111
175
|
}
|
|
112
176
|
|
|
113
|
-
function
|
|
177
|
+
function getCommitsRevList (commitsToExclude, commitsToInclude) {
|
|
178
|
+
let result = []
|
|
179
|
+
|
|
114
180
|
const commitsToExcludeString = commitsToExclude.map(commit => `^${commit}`)
|
|
115
181
|
|
|
182
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'get_objects' })
|
|
183
|
+
const startTime = Date.now()
|
|
116
184
|
try {
|
|
117
|
-
|
|
185
|
+
result = cp.execFileSync(
|
|
118
186
|
'git',
|
|
119
187
|
[
|
|
120
188
|
'rev-list',
|
|
@@ -131,11 +199,14 @@ function getCommitsToUpload (commitsToExclude, commitsToInclude) {
|
|
|
131
199
|
.filter(commit => commit)
|
|
132
200
|
} catch (err) {
|
|
133
201
|
log.error(`Get commits to upload failed: ${err.message}`)
|
|
134
|
-
|
|
202
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'get_objects', errorType: err.status })
|
|
135
203
|
}
|
|
204
|
+
distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'get_objects' }, Date.now() - startTime)
|
|
205
|
+
return result
|
|
136
206
|
}
|
|
137
207
|
|
|
138
208
|
function generatePackFilesForCommits (commitsToUpload) {
|
|
209
|
+
let result = []
|
|
139
210
|
const tmpFolder = os.tmpdir()
|
|
140
211
|
|
|
141
212
|
if (!isDirectory(tmpFolder)) {
|
|
@@ -147,10 +218,12 @@ function generatePackFilesForCommits (commitsToUpload) {
|
|
|
147
218
|
const temporaryPath = path.join(tmpFolder, randomPrefix)
|
|
148
219
|
const cwdPath = path.join(process.cwd(), randomPrefix)
|
|
149
220
|
|
|
221
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND, { command: 'pack_objects' })
|
|
222
|
+
const startTime = Date.now()
|
|
150
223
|
// Generates pack files to upload and
|
|
151
224
|
// returns the ordered list of packfiles' paths
|
|
152
225
|
function execGitPackObjects (targetPath) {
|
|
153
|
-
return execFileSync(
|
|
226
|
+
return cp.execFileSync(
|
|
154
227
|
'git',
|
|
155
228
|
[
|
|
156
229
|
'pack-objects',
|
|
@@ -163,9 +236,10 @@ function generatePackFilesForCommits (commitsToUpload) {
|
|
|
163
236
|
}
|
|
164
237
|
|
|
165
238
|
try {
|
|
166
|
-
|
|
239
|
+
result = execGitPackObjects(temporaryPath)
|
|
167
240
|
} catch (err) {
|
|
168
241
|
log.error(err)
|
|
242
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'pack_objects', errorType: err.status })
|
|
169
243
|
/**
|
|
170
244
|
* The generation of pack files in the temporary folder (from `os.tmpdir()`)
|
|
171
245
|
* sometimes fails in certain CI setups with the error message
|
|
@@ -179,13 +253,15 @@ function generatePackFilesForCommits (commitsToUpload) {
|
|
|
179
253
|
* TODO: fix issue and remove workaround.
|
|
180
254
|
*/
|
|
181
255
|
try {
|
|
182
|
-
|
|
256
|
+
result = execGitPackObjects(cwdPath)
|
|
183
257
|
} catch (err) {
|
|
184
258
|
log.error(err)
|
|
259
|
+
incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'pack_objects', errorType: err.status })
|
|
185
260
|
}
|
|
186
|
-
|
|
187
|
-
return []
|
|
188
261
|
}
|
|
262
|
+
distributionMetric(TELEMETRY_GIT_COMMAND_MS, { command: 'pack_objects' }, Date.now() - startTime)
|
|
263
|
+
|
|
264
|
+
return result
|
|
189
265
|
}
|
|
190
266
|
|
|
191
267
|
// If there is ciMetadata, it takes precedence.
|
|
@@ -214,7 +290,7 @@ function getGitMetadata (ciMetadata) {
|
|
|
214
290
|
|
|
215
291
|
return {
|
|
216
292
|
[GIT_REPOSITORY_URL]:
|
|
217
|
-
repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url']),
|
|
293
|
+
filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
|
|
218
294
|
[GIT_COMMIT_MESSAGE]:
|
|
219
295
|
commitMessage || sanitizedExec('git', ['show', '-s', '--format=%s']),
|
|
220
296
|
[GIT_COMMIT_AUTHOR_DATE]: authorDate,
|
|
@@ -235,7 +311,7 @@ module.exports = {
|
|
|
235
311
|
getLatestCommits,
|
|
236
312
|
getRepositoryUrl,
|
|
237
313
|
generatePackFilesForCommits,
|
|
238
|
-
|
|
314
|
+
getCommitsRevList,
|
|
239
315
|
GIT_REV_LIST_MAX_BUFFER,
|
|
240
316
|
isShallowRepository,
|
|
241
317
|
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) {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const RateLimiter = require('./rate_limiter')
|
|
4
3
|
const Sampler = require('./sampler')
|
|
5
|
-
const ext = require('../../../ext')
|
|
6
4
|
const { setSamplingRules } = require('./startup-log')
|
|
5
|
+
const SamplingRule = require('./sampling_rule')
|
|
7
6
|
|
|
8
7
|
const {
|
|
9
8
|
SAMPLING_MECHANISM_DEFAULT,
|
|
@@ -16,14 +15,21 @@ const {
|
|
|
16
15
|
DECISION_MAKER_KEY
|
|
17
16
|
} = require('./constants')
|
|
18
17
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
const {
|
|
19
|
+
tags: {
|
|
20
|
+
MANUAL_KEEP,
|
|
21
|
+
MANUAL_DROP,
|
|
22
|
+
SAMPLING_PRIORITY,
|
|
23
|
+
SERVICE_NAME
|
|
24
|
+
},
|
|
25
|
+
priority: {
|
|
26
|
+
AUTO_REJECT,
|
|
27
|
+
AUTO_KEEP,
|
|
28
|
+
USER_REJECT,
|
|
29
|
+
USER_KEEP
|
|
30
|
+
}
|
|
31
|
+
} = require('../../../ext')
|
|
32
|
+
|
|
27
33
|
const DEFAULT_KEY = 'service:,env:'
|
|
28
34
|
|
|
29
35
|
const defaultSampler = new Sampler(AUTO_KEEP)
|
|
@@ -36,8 +42,7 @@ class PrioritySampler {
|
|
|
36
42
|
|
|
37
43
|
configure (env, { sampleRate, rateLimit = 100, rules = [] } = {}) {
|
|
38
44
|
this._env = env
|
|
39
|
-
this._rules = this._normalizeRules(rules, sampleRate)
|
|
40
|
-
this._limiter = new RateLimiter(rateLimit)
|
|
45
|
+
this._rules = this._normalizeRules(rules, sampleRate, rateLimit)
|
|
41
46
|
|
|
42
47
|
setSamplingRules(this._rules)
|
|
43
48
|
}
|
|
@@ -104,7 +109,7 @@ class PrioritySampler {
|
|
|
104
109
|
|
|
105
110
|
_getPriorityFromAuto (span) {
|
|
106
111
|
const context = this._getContext(span)
|
|
107
|
-
const rule = this._findRule(
|
|
112
|
+
const rule = this._findRule(span)
|
|
108
113
|
|
|
109
114
|
return rule
|
|
110
115
|
? this._getPriorityByRule(context, rule)
|
|
@@ -131,15 +136,14 @@ class PrioritySampler {
|
|
|
131
136
|
context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
|
|
132
137
|
context._sampling.mechanism = SAMPLING_MECHANISM_RULE
|
|
133
138
|
|
|
134
|
-
|
|
135
|
-
|
|
139
|
+
const sampled = rule.sample()
|
|
140
|
+
const priority = sampled ? USER_KEEP : USER_REJECT
|
|
136
141
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
context._trace[SAMPLING_LIMIT_DECISION] = this._limiter.effectiveRate()
|
|
142
|
+
if (sampled) {
|
|
143
|
+
context._trace[SAMPLING_LIMIT_DECISION] = rule.effectiveRate
|
|
144
|
+
}
|
|
141
145
|
|
|
142
|
-
return
|
|
146
|
+
return priority
|
|
143
147
|
}
|
|
144
148
|
|
|
145
149
|
_getPriorityByAgent (context) {
|
|
@@ -172,33 +176,21 @@ class PrioritySampler {
|
|
|
172
176
|
}
|
|
173
177
|
}
|
|
174
178
|
|
|
175
|
-
_normalizeRules (rules, sampleRate) {
|
|
179
|
+
_normalizeRules (rules, sampleRate, rateLimit) {
|
|
176
180
|
rules = [].concat(rules || [])
|
|
177
181
|
|
|
178
182
|
return rules
|
|
179
|
-
.concat({ sampleRate })
|
|
183
|
+
.concat({ sampleRate, maxPerSecond: rateLimit })
|
|
180
184
|
.map(rule => ({ ...rule, sampleRate: parseFloat(rule.sampleRate) }))
|
|
181
185
|
.filter(rule => !isNaN(rule.sampleRate))
|
|
182
|
-
.map(
|
|
186
|
+
.map(SamplingRule.from)
|
|
183
187
|
}
|
|
184
188
|
|
|
185
|
-
_findRule (
|
|
186
|
-
for (
|
|
187
|
-
if (
|
|
189
|
+
_findRule (span) {
|
|
190
|
+
for (const rule of this._rules) {
|
|
191
|
+
if (rule.match(span)) return rule
|
|
188
192
|
}
|
|
189
193
|
}
|
|
190
|
-
|
|
191
|
-
_matchRule (context, rule) {
|
|
192
|
-
const name = context._name
|
|
193
|
-
const service = context._tags['service.name']
|
|
194
|
-
|
|
195
|
-
if (rule.name instanceof RegExp && !rule.name.test(name)) return false
|
|
196
|
-
if (typeof rule.name === 'string' && rule.name !== name) return false
|
|
197
|
-
if (rule.service instanceof RegExp && !rule.service.test(service)) return false
|
|
198
|
-
if (typeof rule.service === 'string' && rule.service !== service) return false
|
|
199
|
-
|
|
200
|
-
return true
|
|
201
|
-
}
|
|
202
194
|
}
|
|
203
195
|
|
|
204
196
|
function hasOwn (object, prop) {
|
|
@@ -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
|
}
|
|
@@ -75,6 +75,7 @@ class AgentExporter {
|
|
|
75
75
|
['tags[]', 'language:javascript'],
|
|
76
76
|
['tags[]', 'runtime:nodejs'],
|
|
77
77
|
['tags[]', `runtime_version:${process.version}`],
|
|
78
|
+
['tags[]', `process_id:${process.pid}`],
|
|
78
79
|
['tags[]', `profiler_version:${version}`],
|
|
79
80
|
['tags[]', 'format:pprof'],
|
|
80
81
|
...Object.entries(tags).map(([key, value]) => ['tags[]', `${key}:${value}`])
|