dd-trace 4.47.0 → 4.48.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 +0 -1
- package/ext/types.d.ts +1 -0
- package/ext/types.js +1 -0
- package/index.d.ts +26 -0
- package/package.json +6 -7
- package/packages/datadog-code-origin/index.js +38 -0
- package/packages/datadog-core/index.js +2 -2
- package/packages/datadog-instrumentations/src/avsc.js +37 -0
- package/packages/datadog-instrumentations/src/azure-functions.js +48 -0
- package/packages/datadog-instrumentations/src/child_process.js +17 -8
- package/packages/datadog-instrumentations/src/express.js +37 -4
- package/packages/datadog-instrumentations/src/fastify.js +12 -1
- package/packages/datadog-instrumentations/src/fs.js +27 -7
- package/packages/datadog-instrumentations/src/helpers/hooks.js +3 -0
- package/packages/datadog-instrumentations/src/jest.js +2 -1
- package/packages/datadog-instrumentations/src/mocha/common.js +1 -1
- package/packages/datadog-instrumentations/src/mysql2.js +220 -1
- package/packages/datadog-instrumentations/src/protobufjs.js +127 -0
- package/packages/datadog-instrumentations/src/winston.js +22 -0
- package/packages/datadog-plugin-avsc/src/index.js +9 -0
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +169 -0
- package/packages/datadog-plugin-azure-functions/src/index.js +77 -0
- package/packages/datadog-plugin-fastify/src/code_origin.js +31 -0
- package/packages/datadog-plugin-fastify/src/index.js +10 -12
- package/packages/datadog-plugin-fastify/src/tracing.js +19 -0
- package/packages/datadog-plugin-protobufjs/src/index.js +14 -0
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +180 -0
- package/packages/dd-trace/src/appsec/addresses.js +6 -1
- package/packages/dd-trace/src/appsec/channels.js +5 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +13 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +8 -1
- package/packages/dd-trace/src/appsec/iast/iast-plugin.js +1 -1
- package/packages/dd-trace/src/appsec/iast/index.js +3 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/csi-methods.js +1 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/taint-tracking-impl.js +15 -0
- package/packages/dd-trace/src/appsec/index.js +58 -43
- package/packages/dd-trace/src/appsec/rasp/fs-plugin.js +99 -0
- package/packages/dd-trace/src/appsec/rasp/index.js +24 -10
- package/packages/dd-trace/src/appsec/rasp/lfi.js +112 -0
- package/packages/dd-trace/src/appsec/rasp/sql_injection.js +24 -4
- package/packages/dd-trace/src/appsec/rasp/utils.js +2 -1
- package/packages/dd-trace/src/appsec/recommended.json +2 -4
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +5 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +8 -0
- package/packages/dd-trace/src/appsec/reporter.js +12 -5
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -0
- package/packages/dd-trace/src/appsec/waf/waf_context_wrapper.js +1 -1
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -14
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +53 -0
- package/packages/dd-trace/src/config.js +12 -1
- package/packages/dd-trace/src/datastreams/schemas/schema_builder.js +25 -17
- package/packages/dd-trace/src/debugger/devtools_client/config.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +56 -5
- package/packages/dd-trace/src/debugger/devtools_client/remote_config.js +4 -4
- package/packages/dd-trace/src/debugger/devtools_client/send.js +14 -1
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +153 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +30 -0
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +241 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +10 -4
- package/packages/dd-trace/src/exporters/common/request.js +8 -34
- package/packages/dd-trace/src/exporters/common/url-to-http-options-polyfill.js +31 -0
- package/packages/dd-trace/src/payload-tagging/index.js +1 -1
- package/packages/dd-trace/src/payload-tagging/jsonpath-plus.js +2094 -0
- package/packages/dd-trace/src/plugin_manager.js +4 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +2 -0
- package/packages/dd-trace/src/plugins/index.js +3 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +1 -1
- package/packages/dd-trace/src/plugins/schema.js +35 -0
- package/packages/dd-trace/src/plugins/util/ci.js +23 -1
- package/packages/dd-trace/src/plugins/util/serverless.js +7 -0
- package/packages/dd-trace/src/plugins/util/stacktrace.js +94 -0
- package/packages/dd-trace/src/plugins/util/tags.js +7 -0
- package/packages/dd-trace/src/plugins/util/test.js +20 -22
- package/packages/dd-trace/src/plugins/util/web.js +6 -4
- package/packages/dd-trace/src/profiling/profiler.js +24 -14
- package/packages/dd-trace/src/profiling/profilers/events.js +3 -3
- package/packages/dd-trace/src/profiling/profilers/wall.js +94 -66
- package/packages/dd-trace/src/proxy.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/serverless.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/serverless.js +12 -0
- package/packages/datadog-core/src/storage/async_resource.js +0 -108
- package/packages/datadog-core/src/storage/index.js +0 -5
|
@@ -137,7 +137,8 @@ module.exports = class PluginManager {
|
|
|
137
137
|
dsmEnabled,
|
|
138
138
|
clientIpEnabled,
|
|
139
139
|
memcachedCommandEnabled,
|
|
140
|
-
ciVisibilityTestSessionName
|
|
140
|
+
ciVisibilityTestSessionName,
|
|
141
|
+
ciVisAgentlessLogSubmissionEnabled
|
|
141
142
|
} = this._tracerConfig
|
|
142
143
|
|
|
143
144
|
const sharedConfig = {
|
|
@@ -147,7 +148,8 @@ module.exports = class PluginManager {
|
|
|
147
148
|
site,
|
|
148
149
|
url,
|
|
149
150
|
headers: headerTags || [],
|
|
150
|
-
ciVisibilityTestSessionName
|
|
151
|
+
ciVisibilityTestSessionName,
|
|
152
|
+
ciVisAgentlessLogSubmissionEnabled
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
if (logInjection !== undefined) {
|
|
@@ -100,7 +100,9 @@ module.exports = class CiPlugin extends Plugin {
|
|
|
100
100
|
...testSessionSpanMetadata
|
|
101
101
|
}
|
|
102
102
|
})
|
|
103
|
+
// TODO: add telemetry tag when we can add `is_agentless_log_submission_enabled` for agentless log submission
|
|
103
104
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_CREATED, 'session')
|
|
105
|
+
|
|
104
106
|
this.testModuleSpan = this.tracer.startSpan(`${this.constructor.id}.test_module`, {
|
|
105
107
|
childOf: this.testSessionSpan,
|
|
106
108
|
tags: {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
module.exports = {
|
|
4
4
|
get '@apollo/gateway' () { return require('../../../datadog-plugin-apollo/src') },
|
|
5
5
|
get '@aws-sdk/smithy-client' () { return require('../../../datadog-plugin-aws-sdk/src') },
|
|
6
|
+
get '@azure/functions' () { return require('../../../datadog-plugin-azure-functions/src') },
|
|
6
7
|
get '@cucumber/cucumber' () { return require('../../../datadog-plugin-cucumber/src') },
|
|
7
8
|
get '@playwright/test' () { return require('../../../datadog-plugin-playwright/src') },
|
|
8
9
|
get '@elastic/elasticsearch' () { return require('../../../datadog-plugin-elasticsearch/src') },
|
|
@@ -22,6 +23,7 @@ module.exports = {
|
|
|
22
23
|
get aerospike () { return require('../../../datadog-plugin-aerospike/src') },
|
|
23
24
|
get amqp10 () { return require('../../../datadog-plugin-amqp10/src') },
|
|
24
25
|
get amqplib () { return require('../../../datadog-plugin-amqplib/src') },
|
|
26
|
+
get avsc () { return require('../../../datadog-plugin-avsc/src') },
|
|
25
27
|
get 'aws-sdk' () { return require('../../../datadog-plugin-aws-sdk/src') },
|
|
26
28
|
get bunyan () { return require('../../../datadog-plugin-bunyan/src') },
|
|
27
29
|
get 'cassandra-driver' () { return require('../../../datadog-plugin-cassandra-driver/src') },
|
|
@@ -77,6 +79,7 @@ module.exports = {
|
|
|
77
79
|
get pino () { return require('../../../datadog-plugin-pino/src') },
|
|
78
80
|
get 'pino-pretty' () { return require('../../../datadog-plugin-pino/src') },
|
|
79
81
|
get playwright () { return require('../../../datadog-plugin-playwright/src') },
|
|
82
|
+
get protobufjs () { return require('../../../datadog-plugin-protobufjs/src') },
|
|
80
83
|
get redis () { return require('../../../datadog-plugin-redis/src') },
|
|
81
84
|
get restify () { return require('../../../datadog-plugin-restify/src') },
|
|
82
85
|
get rhea () { return require('../../../datadog-plugin-rhea/src') },
|
|
@@ -54,7 +54,7 @@ module.exports = class LogPlugin extends Plugin {
|
|
|
54
54
|
configure (config) {
|
|
55
55
|
return super.configure({
|
|
56
56
|
...config,
|
|
57
|
-
enabled: config.enabled && config.logInjection
|
|
57
|
+
enabled: config.enabled && (config.logInjection || config.ciVisAgentlessLogSubmissionEnabled)
|
|
58
58
|
})
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Plugin = require('./plugin')
|
|
4
|
+
|
|
5
|
+
const SERIALIZATION = 'serialization'
|
|
6
|
+
const DESERIALIZATION = 'deserialization'
|
|
7
|
+
|
|
8
|
+
class SchemaPlugin extends Plugin {
|
|
9
|
+
constructor (...args) {
|
|
10
|
+
super(...args)
|
|
11
|
+
|
|
12
|
+
this.addSub(`apm:${this.constructor.id}:serialize-start`, this.handleSerializeStart.bind(this))
|
|
13
|
+
this.addSub(`apm:${this.constructor.id}:deserialize-end`, this.handleDeserializeFinish.bind(this))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
handleSerializeStart (args) {
|
|
17
|
+
const activeSpan = this.tracer.scope().active()
|
|
18
|
+
if (activeSpan && this.config.dsmEnabled) {
|
|
19
|
+
this.constructor.schemaExtractor.attachSchemaOnSpan(
|
|
20
|
+
args, activeSpan, SERIALIZATION, this.tracer
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
handleDeserializeFinish (args) {
|
|
26
|
+
const activeSpan = this.tracer.scope().active()
|
|
27
|
+
if (activeSpan && this.config.dsmEnabled) {
|
|
28
|
+
this.constructor.schemaExtractor.attachSchemaOnSpan(
|
|
29
|
+
args, activeSpan, DESERIALIZATION, this.tracer
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = SchemaPlugin
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { readFileSync } = require('fs')
|
|
1
2
|
const {
|
|
2
3
|
GIT_BRANCH,
|
|
3
4
|
GIT_COMMIT_SHA,
|
|
@@ -6,6 +7,9 @@ const {
|
|
|
6
7
|
GIT_COMMIT_AUTHOR_NAME,
|
|
7
8
|
GIT_COMMIT_MESSAGE,
|
|
8
9
|
GIT_COMMIT_AUTHOR_DATE,
|
|
10
|
+
GIT_COMMIT_HEAD_SHA,
|
|
11
|
+
GIT_PULL_REQUEST_BASE_BRANCH_SHA,
|
|
12
|
+
GIT_PULL_REQUEST_BASE_BRANCH,
|
|
9
13
|
GIT_REPOSITORY_URL,
|
|
10
14
|
CI_PIPELINE_ID,
|
|
11
15
|
CI_PIPELINE_NAME,
|
|
@@ -77,6 +81,13 @@ function resolveTilde (filePath) {
|
|
|
77
81
|
return filePath
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
function getGitHubEventPayload () {
|
|
85
|
+
if (!process.env.GITHUB_EVENT_PATH) {
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
return JSON.parse(readFileSync(process.env.GITHUB_EVENT_PATH, 'utf8'))
|
|
89
|
+
}
|
|
90
|
+
|
|
80
91
|
module.exports = {
|
|
81
92
|
normalizeRef,
|
|
82
93
|
getCIMetadata () {
|
|
@@ -241,7 +252,8 @@ module.exports = {
|
|
|
241
252
|
GITHUB_REPOSITORY,
|
|
242
253
|
GITHUB_SERVER_URL,
|
|
243
254
|
GITHUB_RUN_ATTEMPT,
|
|
244
|
-
GITHUB_JOB
|
|
255
|
+
GITHUB_JOB,
|
|
256
|
+
GITHUB_BASE_REF
|
|
245
257
|
} = env
|
|
246
258
|
|
|
247
259
|
const repositoryURL = `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git`
|
|
@@ -277,6 +289,16 @@ module.exports = {
|
|
|
277
289
|
GITHUB_RUN_ATTEMPT
|
|
278
290
|
})
|
|
279
291
|
}
|
|
292
|
+
if (GITHUB_BASE_REF) { // `pull_request` or `pull_request_target` event
|
|
293
|
+
tags[GIT_PULL_REQUEST_BASE_BRANCH] = GITHUB_BASE_REF
|
|
294
|
+
try {
|
|
295
|
+
const eventContent = getGitHubEventPayload()
|
|
296
|
+
tags[GIT_PULL_REQUEST_BASE_BRANCH_SHA] = eventContent.pull_request.base.sha
|
|
297
|
+
tags[GIT_COMMIT_HEAD_SHA] = eventContent.pull_request.head.sha
|
|
298
|
+
} catch (e) {
|
|
299
|
+
// ignore malformed event content
|
|
300
|
+
}
|
|
301
|
+
}
|
|
280
302
|
}
|
|
281
303
|
|
|
282
304
|
if (env.APPVEYOR) {
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { relative, sep, isAbsolute } = require('path')
|
|
4
|
+
|
|
5
|
+
const cwd = process.cwd()
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
getCallSites,
|
|
9
|
+
getUserLandFrames
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// From https://github.com/felixge/node-stack-trace/blob/ba06dcdb50d465cd440d84a563836e293b360427/index.js#L1
|
|
13
|
+
function getCallSites (constructorOpt) {
|
|
14
|
+
const oldLimit = Error.stackTraceLimit
|
|
15
|
+
Error.stackTraceLimit = Infinity
|
|
16
|
+
|
|
17
|
+
const dummy = {}
|
|
18
|
+
|
|
19
|
+
const v8Handler = Error.prepareStackTrace
|
|
20
|
+
Error.prepareStackTrace = function (_, v8StackTrace) {
|
|
21
|
+
return v8StackTrace
|
|
22
|
+
}
|
|
23
|
+
Error.captureStackTrace(dummy, constructorOpt)
|
|
24
|
+
|
|
25
|
+
const v8StackTrace = dummy.stack
|
|
26
|
+
Error.prepareStackTrace = v8Handler
|
|
27
|
+
Error.stackTraceLimit = oldLimit
|
|
28
|
+
|
|
29
|
+
return v8StackTrace
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Get stack trace of user-land frames.
|
|
34
|
+
*
|
|
35
|
+
* @param {Function} constructorOpt - Function to pass along to Error.captureStackTrace
|
|
36
|
+
* @param {number} [limit=Infinity] - The maximum number of frames to return
|
|
37
|
+
* @returns {{ file: string, line: number, method: (string|undefined), type: (string|undefined) }[]} - A
|
|
38
|
+
*/
|
|
39
|
+
function getUserLandFrames (constructorOpt, limit = Infinity) {
|
|
40
|
+
const callsites = getCallSites(constructorOpt)
|
|
41
|
+
const frames = []
|
|
42
|
+
|
|
43
|
+
for (const callsite of callsites) {
|
|
44
|
+
if (callsite.isNative()) {
|
|
45
|
+
continue
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const filename = callsite.getFileName()
|
|
49
|
+
|
|
50
|
+
// If the callsite is native, there will be no associated filename. However, there might be other instances where
|
|
51
|
+
// this can happen, so to be sure, we add this additional check
|
|
52
|
+
if (filename === null) {
|
|
53
|
+
continue
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ESM module paths start with the "file://" protocol (because ESM supports https imports)
|
|
57
|
+
// TODO: Node.js also supports `data:` and `node:` imports, should we do something specific for `data:`?
|
|
58
|
+
const containsFileProtocol = filename.startsWith('file:')
|
|
59
|
+
|
|
60
|
+
// TODO: I'm not sure how stable this check is. Alternatively, we could consider reversing it if we can get
|
|
61
|
+
// a comprehensive list of all non-file-based values, eg:
|
|
62
|
+
//
|
|
63
|
+
// filename === '<anonymous>' || filename.startsWith('node:')
|
|
64
|
+
if (containsFileProtocol === false && isAbsolute(filename) === false) {
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// TODO: Technically, the algorithm below could be simplified to not use the relative path, but be simply:
|
|
69
|
+
//
|
|
70
|
+
// if (filename.includes(sep + 'node_modules' + sep)) continue
|
|
71
|
+
//
|
|
72
|
+
// However, the tests in `packages/dd-trace/test/plugins/util/stacktrace.spec.js` will fail on my machine
|
|
73
|
+
// because I have the source code in a parent folder called `node_modules`. So the code below thinks that
|
|
74
|
+
// it's not in user-land
|
|
75
|
+
const relativePath = relative(cwd, containsFileProtocol ? filename.substring(7) : filename)
|
|
76
|
+
if (relativePath.startsWith('node_modules' + sep) || relativePath.includes(sep + 'node_modules' + sep)) {
|
|
77
|
+
continue
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const method = callsite.getFunctionName()
|
|
81
|
+
const type = callsite.getTypeName()
|
|
82
|
+
frames.push({
|
|
83
|
+
file: filename,
|
|
84
|
+
line: callsite.getLineNumber(),
|
|
85
|
+
column: callsite.getColumnNumber(),
|
|
86
|
+
method: method ?? undefined, // force to undefined if null so JSON.stringify will omit it
|
|
87
|
+
type: type ?? undefined // force to undefined if null so JSON.stringify will omit it
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
if (frames.length === limit) break
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return frames
|
|
94
|
+
}
|
|
@@ -9,6 +9,10 @@ const GIT_COMMIT_COMMITTER_NAME = 'git.commit.committer.name'
|
|
|
9
9
|
const GIT_COMMIT_AUTHOR_DATE = 'git.commit.author.date'
|
|
10
10
|
const GIT_COMMIT_AUTHOR_EMAIL = 'git.commit.author.email'
|
|
11
11
|
const GIT_COMMIT_AUTHOR_NAME = 'git.commit.author.name'
|
|
12
|
+
const GIT_COMMIT_HEAD_SHA = 'git.commit.head_sha'
|
|
13
|
+
|
|
14
|
+
const GIT_PULL_REQUEST_BASE_BRANCH_SHA = 'git.pull_request.base_branch_sha'
|
|
15
|
+
const GIT_PULL_REQUEST_BASE_BRANCH = 'git.pull_request.base_branch'
|
|
12
16
|
|
|
13
17
|
const CI_PIPELINE_ID = 'ci.pipeline.id'
|
|
14
18
|
const CI_PIPELINE_NAME = 'ci.pipeline.name'
|
|
@@ -36,6 +40,9 @@ module.exports = {
|
|
|
36
40
|
GIT_COMMIT_AUTHOR_DATE,
|
|
37
41
|
GIT_COMMIT_AUTHOR_EMAIL,
|
|
38
42
|
GIT_COMMIT_AUTHOR_NAME,
|
|
43
|
+
GIT_COMMIT_HEAD_SHA,
|
|
44
|
+
GIT_PULL_REQUEST_BASE_BRANCH_SHA,
|
|
45
|
+
GIT_PULL_REQUEST_BASE_BRANCH,
|
|
39
46
|
CI_PIPELINE_ID,
|
|
40
47
|
CI_PIPELINE_NAME,
|
|
41
48
|
CI_PIPELINE_NUMBER,
|
|
@@ -168,7 +168,6 @@ module.exports = {
|
|
|
168
168
|
mergeCoverage,
|
|
169
169
|
fromCoverageMapToCoverage,
|
|
170
170
|
getTestLineStart,
|
|
171
|
-
getCallSites,
|
|
172
171
|
removeInvalidMetadata,
|
|
173
172
|
parseAnnotations,
|
|
174
173
|
EFD_STRING,
|
|
@@ -181,7 +180,8 @@ module.exports = {
|
|
|
181
180
|
TEST_BROWSER_NAME,
|
|
182
181
|
TEST_BROWSER_VERSION,
|
|
183
182
|
getTestSessionName,
|
|
184
|
-
TEST_LEVEL_EVENT_TYPES
|
|
183
|
+
TEST_LEVEL_EVENT_TYPES,
|
|
184
|
+
getNumFromKnownTests
|
|
185
185
|
}
|
|
186
186
|
|
|
187
187
|
// Returns pkg manager and its version, separated by '-', e.g. npm-8.15.0 or yarn-1.22.19
|
|
@@ -557,26 +557,6 @@ function getTestLineStart (err, testSuitePath) {
|
|
|
557
557
|
}
|
|
558
558
|
}
|
|
559
559
|
|
|
560
|
-
// From https://github.com/felixge/node-stack-trace/blob/ba06dcdb50d465cd440d84a563836e293b360427/index.js#L1
|
|
561
|
-
function getCallSites () {
|
|
562
|
-
const oldLimit = Error.stackTraceLimit
|
|
563
|
-
Error.stackTraceLimit = Infinity
|
|
564
|
-
|
|
565
|
-
const dummy = {}
|
|
566
|
-
|
|
567
|
-
const v8Handler = Error.prepareStackTrace
|
|
568
|
-
Error.prepareStackTrace = function (_, v8StackTrace) {
|
|
569
|
-
return v8StackTrace
|
|
570
|
-
}
|
|
571
|
-
Error.captureStackTrace(dummy)
|
|
572
|
-
|
|
573
|
-
const v8StackTrace = dummy.stack
|
|
574
|
-
Error.prepareStackTrace = v8Handler
|
|
575
|
-
Error.stackTraceLimit = oldLimit
|
|
576
|
-
|
|
577
|
-
return v8StackTrace
|
|
578
|
-
}
|
|
579
|
-
|
|
580
560
|
/**
|
|
581
561
|
* Gets an object of test tags from an Playwright annotations array.
|
|
582
562
|
* @param {Object[]} annotations - Annotations from a Playwright test.
|
|
@@ -639,3 +619,21 @@ function getTestSessionName (config, testCommand, envTags) {
|
|
|
639
619
|
}
|
|
640
620
|
return testCommand
|
|
641
621
|
}
|
|
622
|
+
|
|
623
|
+
// Calculate the number of a tests from the known tests response, which has a shape like:
|
|
624
|
+
// { testModule1: { testSuite1: [test1, test2, test3] }, testModule2: { testSuite2: [test4, test5] } }
|
|
625
|
+
function getNumFromKnownTests (knownTests) {
|
|
626
|
+
if (!knownTests) {
|
|
627
|
+
return 0
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
let totalNumTests = 0
|
|
631
|
+
|
|
632
|
+
for (const testModule of Object.values(knownTests)) {
|
|
633
|
+
for (const testSuite of Object.values(testModule)) {
|
|
634
|
+
totalNumTests += testSuite.length
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
return totalNumTests
|
|
639
|
+
}
|
|
@@ -36,6 +36,8 @@ const contexts = new WeakMap()
|
|
|
36
36
|
const ends = new WeakMap()
|
|
37
37
|
|
|
38
38
|
const web = {
|
|
39
|
+
TYPE: WEB,
|
|
40
|
+
|
|
39
41
|
// Ensure the configuration has the correct structure and defaults.
|
|
40
42
|
normalizeConfig (config) {
|
|
41
43
|
const headers = getHeadersToRecord(config)
|
|
@@ -103,7 +105,7 @@ const web = {
|
|
|
103
105
|
context.res = res
|
|
104
106
|
|
|
105
107
|
this.setConfig(req, config)
|
|
106
|
-
addRequestTags(context)
|
|
108
|
+
addRequestTags(context, this.TYPE)
|
|
107
109
|
|
|
108
110
|
return span
|
|
109
111
|
},
|
|
@@ -296,7 +298,7 @@ const web = {
|
|
|
296
298
|
|
|
297
299
|
if (context.finished && !req.stream) return
|
|
298
300
|
|
|
299
|
-
addRequestTags(context)
|
|
301
|
+
addRequestTags(context, this.TYPE)
|
|
300
302
|
addResponseTags(context)
|
|
301
303
|
|
|
302
304
|
context.config.hooks.request(context.span, req, res)
|
|
@@ -423,7 +425,7 @@ function reactivate (req, fn) {
|
|
|
423
425
|
: fn()
|
|
424
426
|
}
|
|
425
427
|
|
|
426
|
-
function addRequestTags (context) {
|
|
428
|
+
function addRequestTags (context, spanType) {
|
|
427
429
|
const { req, span, config } = context
|
|
428
430
|
const url = extractURL(req)
|
|
429
431
|
|
|
@@ -431,7 +433,7 @@ function addRequestTags (context) {
|
|
|
431
433
|
[HTTP_URL]: web.obfuscateQs(config, url),
|
|
432
434
|
[HTTP_METHOD]: req.method,
|
|
433
435
|
[SPAN_KIND]: SERVER,
|
|
434
|
-
[SPAN_TYPE]:
|
|
436
|
+
[SPAN_TYPE]: spanType,
|
|
435
437
|
[HTTP_USERAGENT]: req.headers['user-agent']
|
|
436
438
|
})
|
|
437
439
|
|
|
@@ -146,6 +146,10 @@ class Profiler extends EventEmitter {
|
|
|
146
146
|
const encodedProfiles = {}
|
|
147
147
|
|
|
148
148
|
try {
|
|
149
|
+
if (Object.keys(this._config.profilers).length === 0) {
|
|
150
|
+
throw new Error('No profile types configured.')
|
|
151
|
+
}
|
|
152
|
+
|
|
149
153
|
// collect profiles synchronously so that profilers can be safely stopped asynchronously
|
|
150
154
|
for (const profiler of this._config.profilers) {
|
|
151
155
|
const profile = profiler.profile(restart, startDate, endDate)
|
|
@@ -156,23 +160,32 @@ class Profiler extends EventEmitter {
|
|
|
156
160
|
profiles.push({ profiler, profile })
|
|
157
161
|
}
|
|
158
162
|
|
|
163
|
+
if (restart) {
|
|
164
|
+
this._capture(this._timeoutInterval, endDate)
|
|
165
|
+
}
|
|
166
|
+
|
|
159
167
|
// encode and export asynchronously
|
|
160
168
|
for (const { profiler, profile } of profiles) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
169
|
+
try {
|
|
170
|
+
encodedProfiles[profiler.type] = await profiler.encode(profile)
|
|
171
|
+
this._logger.debug(() => {
|
|
172
|
+
const profileJson = JSON.stringify(profile, (key, value) => {
|
|
173
|
+
return typeof value === 'bigint' ? value.toString() : value
|
|
174
|
+
})
|
|
175
|
+
return `Collected ${profiler.type} profile: ` + profileJson
|
|
165
176
|
})
|
|
166
|
-
|
|
167
|
-
|
|
177
|
+
} catch (err) {
|
|
178
|
+
// If encoding one of the profile types fails, we should still try to
|
|
179
|
+
// encode and submit the other profile types.
|
|
180
|
+
this._logError(err)
|
|
181
|
+
}
|
|
168
182
|
}
|
|
169
183
|
|
|
170
|
-
if (
|
|
171
|
-
this.
|
|
184
|
+
if (Object.keys(encodedProfiles).length > 0) {
|
|
185
|
+
await this._submit(encodedProfiles, startDate, endDate, snapshotKind)
|
|
186
|
+
profileSubmittedChannel.publish()
|
|
187
|
+
this._logger.debug('Submitted profiles')
|
|
172
188
|
}
|
|
173
|
-
await this._submit(encodedProfiles, startDate, endDate, snapshotKind)
|
|
174
|
-
profileSubmittedChannel.publish()
|
|
175
|
-
this._logger.debug('Submitted profiles')
|
|
176
189
|
} catch (err) {
|
|
177
190
|
this._logError(err)
|
|
178
191
|
this._stop()
|
|
@@ -180,9 +193,6 @@ class Profiler extends EventEmitter {
|
|
|
180
193
|
}
|
|
181
194
|
|
|
182
195
|
_submit (profiles, start, end, snapshotKind) {
|
|
183
|
-
if (!Object.keys(profiles).length) {
|
|
184
|
-
return Promise.reject(new Error('No profiles to submit'))
|
|
185
|
-
}
|
|
186
196
|
const { tags } = this._config
|
|
187
197
|
const tasks = []
|
|
188
198
|
|
|
@@ -330,13 +330,13 @@ class EventsProfiler {
|
|
|
330
330
|
if (!restart) {
|
|
331
331
|
this.stop()
|
|
332
332
|
}
|
|
333
|
-
const
|
|
333
|
+
const thatEventSerializer = this.eventSerializer
|
|
334
334
|
this.eventSerializer = new EventSerializer()
|
|
335
|
-
return
|
|
335
|
+
return () => thatEventSerializer.createProfile(startDate, endDate)
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
encode (profile) {
|
|
339
|
-
return pprof.encode(profile)
|
|
339
|
+
return pprof.encode(profile())
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
|