dd-trace 3.13.2 → 3.14.1
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/ci/init.js +2 -1
- package/index.d.ts +20 -0
- package/package.json +1 -1
- package/packages/datadog-instrumentations/src/aws-sdk.js +86 -0
- package/packages/datadog-instrumentations/src/cucumber.js +74 -15
- package/packages/datadog-instrumentations/src/cypress.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/jest.js +24 -33
- package/packages/datadog-instrumentations/src/mocha.js +4 -7
- package/packages/datadog-instrumentations/src/playwright.js +2 -4
- package/packages/datadog-plugin-aws-sdk/src/base.js +12 -5
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +2 -2
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +29 -24
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +31 -16
- package/packages/datadog-plugin-cucumber/src/index.js +42 -11
- package/packages/datadog-plugin-cypress/src/plugin.js +129 -4
- package/packages/datadog-plugin-cypress/src/support.js +5 -0
- package/packages/datadog-plugin-hapi/src/index.js +5 -1
- package/packages/datadog-plugin-jest/src/index.js +18 -67
- package/packages/datadog-plugin-mocha/src/index.js +35 -84
- package/packages/datadog-plugin-playwright/src/index.js +2 -61
- package/packages/datadog-shimmer/src/shimmer.js +28 -11
- package/packages/dd-trace/src/appsec/reporter.js +14 -14
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +1 -5
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -5
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +32 -10
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +1 -1
- package/packages/dd-trace/src/config.js +55 -6
- package/packages/dd-trace/src/encode/0.4.js +1 -1
- package/packages/dd-trace/src/encode/0.5.js +1 -1
- package/packages/dd-trace/src/encode/tags-processors.js +3 -2
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +188 -36
- package/packages/dd-trace/src/opentracing/propagation/tracestate.js +99 -0
- package/packages/dd-trace/src/opentracing/span.js +2 -1
- package/packages/dd-trace/src/opentracing/span_context.js +5 -2
- package/packages/dd-trace/src/plugins/ci_plugin.js +69 -12
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/telemetry/send-data.js +4 -1
package/ci/init.js
CHANGED
package/index.d.ts
CHANGED
|
@@ -221,6 +221,21 @@ export declare interface SpanSamplingRule {
|
|
|
221
221
|
name?: string
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Selection and priority order of context propagation injection and extraction mechanisms.
|
|
226
|
+
*/
|
|
227
|
+
export declare interface PropagationStyle {
|
|
228
|
+
/**
|
|
229
|
+
* Selection of context propagation injection mechanisms.
|
|
230
|
+
*/
|
|
231
|
+
inject: string[],
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Selection and priority order of context propagation extraction mechanisms.
|
|
235
|
+
*/
|
|
236
|
+
extract: string[]
|
|
237
|
+
}
|
|
238
|
+
|
|
224
239
|
/**
|
|
225
240
|
* List of options available to the tracer.
|
|
226
241
|
*/
|
|
@@ -550,6 +565,11 @@ export declare interface TracerOptions {
|
|
|
550
565
|
* Custom header name to source the http.client_ip tag from.
|
|
551
566
|
*/
|
|
552
567
|
clientIpHeader?: string,
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* The selection and priority order of context propagation injection and extraction mechanisms.
|
|
571
|
+
*/
|
|
572
|
+
propagationStyle?: string[] | PropagationStyle
|
|
553
573
|
}
|
|
554
574
|
|
|
555
575
|
/**
|
package/package.json
CHANGED
|
@@ -39,6 +39,77 @@ function wrapRequest (send) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function wrapSmithySend (send) {
|
|
43
|
+
return function (command, ...args) {
|
|
44
|
+
const cb = args[args.length - 1]
|
|
45
|
+
const innerAr = new AsyncResource('apm:aws:request:inner')
|
|
46
|
+
const outerAr = new AsyncResource('apm:aws:request:outer')
|
|
47
|
+
const serviceIdentifier = this.config.serviceId.toLowerCase()
|
|
48
|
+
const channelSuffix = getChannelSuffix(serviceIdentifier)
|
|
49
|
+
const commandName = command.constructor.name
|
|
50
|
+
const clientName = this.constructor.name.replace(/Client$/, '')
|
|
51
|
+
const operation = `${commandName[0].toLowerCase()}${commandName.slice(1).replace(/Command$/, '')}`
|
|
52
|
+
const request = {
|
|
53
|
+
operation,
|
|
54
|
+
params: command.input
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const startCh = channel(`apm:aws:request:start:${channelSuffix}`)
|
|
58
|
+
const regionCh = channel(`apm:aws:request:region:${channelSuffix}`)
|
|
59
|
+
const completeChannel = channel(`apm:aws:request:complete:${channelSuffix}`)
|
|
60
|
+
const responseStartChannel = channel(`apm:aws:response:start:${channelSuffix}`)
|
|
61
|
+
const responseFinishChannel = channel(`apm:aws:response:finish:${channelSuffix}`)
|
|
62
|
+
|
|
63
|
+
return innerAr.runInAsyncScope(() => {
|
|
64
|
+
startCh.publish({
|
|
65
|
+
serviceIdentifier,
|
|
66
|
+
operation,
|
|
67
|
+
awsService: clientName,
|
|
68
|
+
request
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// When the region is not set this never resolves so we can't await.
|
|
72
|
+
this.config.region().then(region => {
|
|
73
|
+
regionCh.publish(region)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
if (typeof cb === 'function') {
|
|
77
|
+
args[args.length - 1] = function (err, result) {
|
|
78
|
+
const message = getMessage(request, err, result)
|
|
79
|
+
|
|
80
|
+
completeChannel.publish(message)
|
|
81
|
+
|
|
82
|
+
outerAr.runInAsyncScope(() => {
|
|
83
|
+
responseStartChannel.publish(message)
|
|
84
|
+
|
|
85
|
+
cb.apply(this, arguments)
|
|
86
|
+
|
|
87
|
+
if (message.needsFinish) {
|
|
88
|
+
responseFinishChannel.publish(message.response.error)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
} else { // always a promise
|
|
93
|
+
return send.call(this, command, ...args)
|
|
94
|
+
.then(
|
|
95
|
+
result => {
|
|
96
|
+
const message = getMessage(request, null, result)
|
|
97
|
+
completeChannel.publish(message)
|
|
98
|
+
return result
|
|
99
|
+
},
|
|
100
|
+
error => {
|
|
101
|
+
const message = getMessage(request, error)
|
|
102
|
+
completeChannel.publish(message)
|
|
103
|
+
throw error
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return send.call(this, command, ...args)
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
42
113
|
function wrapCb (cb, serviceName, request, ar) {
|
|
43
114
|
return function wrappedCb (err, response) {
|
|
44
115
|
const obj = { request, response }
|
|
@@ -71,6 +142,16 @@ function wrapCb (cb, serviceName, request, ar) {
|
|
|
71
142
|
}
|
|
72
143
|
}
|
|
73
144
|
|
|
145
|
+
function getMessage (request, error, result) {
|
|
146
|
+
const response = { request, error, ...result }
|
|
147
|
+
|
|
148
|
+
if (result && result.$metadata) {
|
|
149
|
+
response.requestId = result.$metadata.requestId
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return { request, response }
|
|
153
|
+
}
|
|
154
|
+
|
|
74
155
|
function getChannelSuffix (name) {
|
|
75
156
|
return [
|
|
76
157
|
'cloudwatchlogs',
|
|
@@ -85,6 +166,11 @@ function getChannelSuffix (name) {
|
|
|
85
166
|
].includes(name) ? name : 'default'
|
|
86
167
|
}
|
|
87
168
|
|
|
169
|
+
addHook({ name: '@aws-sdk/smithy-client', versions: ['>=3'] }, smithy => {
|
|
170
|
+
shimmer.wrap(smithy.Client.prototype, 'send', wrapSmithySend)
|
|
171
|
+
return smithy
|
|
172
|
+
})
|
|
173
|
+
|
|
88
174
|
addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
|
|
89
175
|
shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
|
|
90
176
|
shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
|
|
@@ -3,15 +3,35 @@
|
|
|
3
3
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
6
|
+
const testStartCh = channel('ci:cucumber:test:start')
|
|
7
|
+
const testFinishCh = channel('ci:cucumber:test:finish') // used for test steps too
|
|
8
|
+
|
|
9
|
+
const testStepStartCh = channel('ci:cucumber:test-step:start')
|
|
10
|
+
|
|
9
11
|
const errorCh = channel('ci:cucumber:error')
|
|
12
|
+
|
|
13
|
+
const testSuiteStartCh = channel('ci:cucumber:test-suite:start')
|
|
14
|
+
const testSuiteFinishCh = channel('ci:cucumber:test-suite:finish')
|
|
15
|
+
|
|
16
|
+
const sessionStartCh = channel('ci:cucumber:session:start')
|
|
10
17
|
const sessionFinishCh = channel('ci:cucumber:session:finish')
|
|
11
18
|
|
|
12
19
|
// TODO: remove in a later major version
|
|
13
20
|
const patched = new WeakSet()
|
|
14
21
|
|
|
22
|
+
let pickleByFile = {}
|
|
23
|
+
const pickleResultByFile = {}
|
|
24
|
+
|
|
25
|
+
function getSuiteStatusFromTestStatuses (testStatuses) {
|
|
26
|
+
if (testStatuses.some(status => status === 'fail')) {
|
|
27
|
+
return 'fail'
|
|
28
|
+
}
|
|
29
|
+
if (testStatuses.every(status => status === 'skip')) {
|
|
30
|
+
return 'skip'
|
|
31
|
+
}
|
|
32
|
+
return 'pass'
|
|
33
|
+
}
|
|
34
|
+
|
|
15
35
|
function getStatusFromResult (result) {
|
|
16
36
|
if (result.status === 1) {
|
|
17
37
|
return { status: 'pass' }
|
|
@@ -44,13 +64,18 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
44
64
|
patched.add(pl)
|
|
45
65
|
|
|
46
66
|
shimmer.wrap(pl.prototype, 'run', run => function () {
|
|
47
|
-
if (!
|
|
67
|
+
if (!testStartCh.hasSubscribers) {
|
|
48
68
|
return run.apply(this, arguments)
|
|
49
69
|
}
|
|
50
70
|
|
|
51
71
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
52
72
|
return asyncResource.runInAsyncScope(() => {
|
|
53
|
-
|
|
73
|
+
const testSuiteFullPath = this.pickle.uri
|
|
74
|
+
|
|
75
|
+
if (!pickleResultByFile[testSuiteFullPath]) { // first test in suite
|
|
76
|
+
testSuiteStartCh.publish(testSuiteFullPath)
|
|
77
|
+
}
|
|
78
|
+
testStartCh.publish({ testName: this.pickle.name, fullTestSuite: testSuiteFullPath })
|
|
54
79
|
try {
|
|
55
80
|
const promise = run.apply(this, arguments)
|
|
56
81
|
promise.finally(() => {
|
|
@@ -58,7 +83,17 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
58
83
|
const { status, skipReason, errorMessage } = isLatestVersion
|
|
59
84
|
? getStatusFromResultLatest(result) : getStatusFromResult(result)
|
|
60
85
|
|
|
61
|
-
|
|
86
|
+
if (!pickleResultByFile[testSuiteFullPath]) {
|
|
87
|
+
pickleResultByFile[testSuiteFullPath] = [status]
|
|
88
|
+
} else {
|
|
89
|
+
pickleResultByFile[testSuiteFullPath].push(status)
|
|
90
|
+
}
|
|
91
|
+
// last test in suite
|
|
92
|
+
if (pickleResultByFile[testSuiteFullPath].length === pickleByFile[testSuiteFullPath].length) {
|
|
93
|
+
const testSuiteStatus = getSuiteStatusFromTestStatuses(pickleResultByFile[testSuiteFullPath])
|
|
94
|
+
testSuiteFinishCh.publish(testSuiteStatus)
|
|
95
|
+
}
|
|
96
|
+
testFinishCh.publish({ status, skipReason, errorMessage })
|
|
62
97
|
})
|
|
63
98
|
return promise
|
|
64
99
|
} catch (err) {
|
|
@@ -68,7 +103,7 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
68
103
|
})
|
|
69
104
|
})
|
|
70
105
|
shimmer.wrap(pl.prototype, 'runStep', runStep => function () {
|
|
71
|
-
if (!
|
|
106
|
+
if (!testStepStartCh.hasSubscribers) {
|
|
72
107
|
return runStep.apply(this, arguments)
|
|
73
108
|
}
|
|
74
109
|
const testStep = arguments[0]
|
|
@@ -82,7 +117,7 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
82
117
|
|
|
83
118
|
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
84
119
|
return asyncResource.runInAsyncScope(() => {
|
|
85
|
-
|
|
120
|
+
testStepStartCh.publish({ resource })
|
|
86
121
|
try {
|
|
87
122
|
const promise = runStep.apply(this, arguments)
|
|
88
123
|
|
|
@@ -90,7 +125,7 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
90
125
|
const { status, skipReason, errorMessage } = isLatestVersion
|
|
91
126
|
? getStatusFromResultLatest(result) : getStatusFromResult(result)
|
|
92
127
|
|
|
93
|
-
|
|
128
|
+
testFinishCh.publish({ isStep: true, status, skipReason, errorMessage })
|
|
94
129
|
})
|
|
95
130
|
return promise
|
|
96
131
|
} catch (err) {
|
|
@@ -129,16 +164,40 @@ addHook({
|
|
|
129
164
|
file: 'lib/runtime/test_case_runner.js'
|
|
130
165
|
}, testCaseHook)
|
|
131
166
|
|
|
167
|
+
function getPickleByFile (runtime) {
|
|
168
|
+
return runtime.pickleIds.reduce((acc, pickleId) => {
|
|
169
|
+
const test = runtime.eventDataCollector.getPickle(pickleId)
|
|
170
|
+
if (acc[test.uri]) {
|
|
171
|
+
acc[test.uri].push(test)
|
|
172
|
+
} else {
|
|
173
|
+
acc[test.uri] = [test]
|
|
174
|
+
}
|
|
175
|
+
return acc
|
|
176
|
+
}, {})
|
|
177
|
+
}
|
|
178
|
+
|
|
132
179
|
addHook({
|
|
133
180
|
name: '@cucumber/cucumber',
|
|
134
181
|
versions: ['>=7.0.0'],
|
|
135
182
|
file: 'lib/runtime/index.js'
|
|
136
|
-
}, (
|
|
137
|
-
shimmer.wrap(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
183
|
+
}, (runtimePackage, cucumberVersion) => {
|
|
184
|
+
shimmer.wrap(runtimePackage.default.prototype, 'start', start => async function () {
|
|
185
|
+
pickleByFile = getPickleByFile(this)
|
|
186
|
+
|
|
187
|
+
const processArgv = process.argv.slice(2).join(' ')
|
|
188
|
+
const command = process.env.npm_lifecycle_script || `cucumber-js ${processArgv}`
|
|
189
|
+
|
|
190
|
+
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
191
|
+
asyncResource.runInAsyncScope(() => {
|
|
192
|
+
sessionStartCh.publish({ command, frameworkVersion: cucumberVersion })
|
|
193
|
+
})
|
|
194
|
+
const success = await start.apply(this, arguments)
|
|
195
|
+
|
|
196
|
+
asyncResource.runInAsyncScope(() => {
|
|
197
|
+
sessionFinishCh.publish(success ? 'pass' : 'fail')
|
|
198
|
+
})
|
|
199
|
+
return success
|
|
141
200
|
})
|
|
142
201
|
|
|
143
|
-
return
|
|
202
|
+
return runtimePackage
|
|
144
203
|
})
|
|
@@ -72,7 +72,7 @@ function getTestEnvironmentOptions (config) {
|
|
|
72
72
|
return {}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
function getWrappedEnvironment (BaseEnvironment) {
|
|
75
|
+
function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
76
76
|
return class DatadogEnvironment extends BaseEnvironment {
|
|
77
77
|
constructor (config, context) {
|
|
78
78
|
super(config, context)
|
|
@@ -116,7 +116,8 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
116
116
|
name: getJestTestName(event.test),
|
|
117
117
|
suite: this.testSuite,
|
|
118
118
|
runner: 'jest-circus',
|
|
119
|
-
testParameters
|
|
119
|
+
testParameters,
|
|
120
|
+
frameworkVersion: jestVersion
|
|
120
121
|
})
|
|
121
122
|
originalTestFns.set(event.test, event.test.fn)
|
|
122
123
|
event.test.fn = asyncResource.bind(event.test.fn)
|
|
@@ -142,7 +143,8 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
142
143
|
testSkippedCh.publish({
|
|
143
144
|
name: getJestTestName(event.test),
|
|
144
145
|
suite: this.testSuite,
|
|
145
|
-
runner: 'jest-circus'
|
|
146
|
+
runner: 'jest-circus',
|
|
147
|
+
frameworkVersion: jestVersion
|
|
146
148
|
})
|
|
147
149
|
})
|
|
148
150
|
}
|
|
@@ -150,14 +152,14 @@ function getWrappedEnvironment (BaseEnvironment) {
|
|
|
150
152
|
}
|
|
151
153
|
}
|
|
152
154
|
|
|
153
|
-
function getTestEnvironment (pkg) {
|
|
155
|
+
function getTestEnvironment (pkg, jestVersion) {
|
|
154
156
|
if (pkg.default) {
|
|
155
|
-
const wrappedTestEnvironment = getWrappedEnvironment(pkg.default)
|
|
157
|
+
const wrappedTestEnvironment = getWrappedEnvironment(pkg.default, jestVersion)
|
|
156
158
|
pkg.default = wrappedTestEnvironment
|
|
157
159
|
pkg.TestEnvironment = wrappedTestEnvironment
|
|
158
160
|
return pkg
|
|
159
161
|
}
|
|
160
|
-
return getWrappedEnvironment(pkg)
|
|
162
|
+
return getWrappedEnvironment(pkg, jestVersion)
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
addHook({
|
|
@@ -170,7 +172,7 @@ addHook({
|
|
|
170
172
|
versions: ['>=24.8.0']
|
|
171
173
|
}, getTestEnvironment)
|
|
172
174
|
|
|
173
|
-
function cliWrapper (cli) {
|
|
175
|
+
function cliWrapper (cli, jestVersion) {
|
|
174
176
|
const wrapped = shimmer.wrap(cli, 'runCLI', runCLI => async function () {
|
|
175
177
|
let onDone
|
|
176
178
|
const configurationPromise = new Promise((resolve) => {
|
|
@@ -186,13 +188,12 @@ function cliWrapper (cli) {
|
|
|
186
188
|
|
|
187
189
|
try {
|
|
188
190
|
const { err, itrConfig } = await configurationPromise
|
|
189
|
-
if (err) {
|
|
190
|
-
|
|
191
|
+
if (!err) {
|
|
192
|
+
isCodeCoverageEnabled = itrConfig.isCodeCoverageEnabled
|
|
193
|
+
isSuitesSkippingEnabled = itrConfig.isSuitesSkippingEnabled
|
|
191
194
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
} catch (e) {
|
|
195
|
-
log.error(e)
|
|
195
|
+
} catch (err) {
|
|
196
|
+
log.error(err)
|
|
196
197
|
}
|
|
197
198
|
|
|
198
199
|
if (isSuitesSkippingEnabled) {
|
|
@@ -206,31 +207,19 @@ function cliWrapper (cli) {
|
|
|
206
207
|
|
|
207
208
|
try {
|
|
208
209
|
const { err, skippableSuites: receivedSkippableSuites } = await skippableSuitesPromise
|
|
209
|
-
if (err) {
|
|
210
|
-
log.error(err)
|
|
211
|
-
} else {
|
|
210
|
+
if (!err) {
|
|
212
211
|
skippableSuites = receivedSkippableSuites
|
|
213
212
|
}
|
|
214
|
-
} catch (
|
|
215
|
-
log.error(
|
|
213
|
+
} catch (err) {
|
|
214
|
+
log.error(err)
|
|
216
215
|
}
|
|
217
216
|
}
|
|
218
217
|
|
|
219
218
|
const isSuitesSkipped = !!skippableSuites.length
|
|
220
219
|
|
|
221
|
-
let testFrameworkVersion
|
|
222
|
-
try {
|
|
223
|
-
testFrameworkVersion = this.getVersion()
|
|
224
|
-
} catch (e) {
|
|
225
|
-
try {
|
|
226
|
-
testFrameworkVersion = this.default.getVersion()
|
|
227
|
-
} catch (e) {
|
|
228
|
-
// ignore errors
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
220
|
const processArgv = process.argv.slice(2).join(' ')
|
|
232
221
|
sessionAsyncResource.runInAsyncScope(() => {
|
|
233
|
-
testSessionStartCh.publish({ command: `jest ${processArgv}`,
|
|
222
|
+
testSessionStartCh.publish({ command: `jest ${processArgv}`, frameworkVersion: jestVersion })
|
|
234
223
|
})
|
|
235
224
|
|
|
236
225
|
const result = await runCLI.apply(this, arguments)
|
|
@@ -298,7 +287,7 @@ addHook({
|
|
|
298
287
|
versions: ['>=24.8.0']
|
|
299
288
|
}, cliWrapper)
|
|
300
289
|
|
|
301
|
-
function jestAdapterWrapper (jestAdapter) {
|
|
290
|
+
function jestAdapterWrapper (jestAdapter, jestVersion) {
|
|
302
291
|
const adapter = jestAdapter.default ? jestAdapter.default : jestAdapter
|
|
303
292
|
const newAdapter = shimmer.wrap(adapter, function () {
|
|
304
293
|
const environment = arguments[2]
|
|
@@ -309,7 +298,8 @@ function jestAdapterWrapper (jestAdapter) {
|
|
|
309
298
|
return asyncResource.runInAsyncScope(() => {
|
|
310
299
|
testSuiteStartCh.publish({
|
|
311
300
|
testSuite: environment.testSuite,
|
|
312
|
-
testEnvironmentOptions: environment.testEnvironmentOptions
|
|
301
|
+
testEnvironmentOptions: environment.testEnvironmentOptions,
|
|
302
|
+
frameworkVersion: jestVersion
|
|
313
303
|
})
|
|
314
304
|
return adapter.apply(this, arguments).then(suiteResults => {
|
|
315
305
|
const { numFailingTests, skipped, failureMessage: errorMessage } = suiteResults
|
|
@@ -450,7 +440,7 @@ addHook({
|
|
|
450
440
|
versions: ['24.8.0 - 24.9.0']
|
|
451
441
|
}, jestConfigSyncWrapper)
|
|
452
442
|
|
|
453
|
-
function jasmineAsyncInstallWraper (jasmineAsyncInstallExport) {
|
|
443
|
+
function jasmineAsyncInstallWraper (jasmineAsyncInstallExport, jestVersion) {
|
|
454
444
|
return function (globalConfig, globalInput) {
|
|
455
445
|
globalInput._ddtrace = global._ddtrace
|
|
456
446
|
shimmer.wrap(globalInput.jasmine.Spec.prototype, 'execute', execute => function (onComplete) {
|
|
@@ -460,7 +450,8 @@ function jasmineAsyncInstallWraper (jasmineAsyncInstallExport) {
|
|
|
460
450
|
testStartCh.publish({
|
|
461
451
|
name: this.getFullName(),
|
|
462
452
|
suite: testSuite,
|
|
463
|
-
runner: 'jest-jasmine2'
|
|
453
|
+
runner: 'jest-jasmine2',
|
|
454
|
+
frameworkVersion: jestVersion
|
|
464
455
|
})
|
|
465
456
|
const spec = this
|
|
466
457
|
const callback = asyncResource.bind(function () {
|
|
@@ -2,7 +2,6 @@ const { createCoverageMap } = require('istanbul-lib-coverage')
|
|
|
2
2
|
|
|
3
3
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
4
4
|
const shimmer = require('../../datadog-shimmer')
|
|
5
|
-
const log = require('../../dd-trace/src/log')
|
|
6
5
|
const {
|
|
7
6
|
getCoveredFilenamesFromCoverage,
|
|
8
7
|
resetCoverage,
|
|
@@ -39,7 +38,7 @@ const testFileToSuiteAr = new Map()
|
|
|
39
38
|
const originalCoverageMap = createCoverageMap()
|
|
40
39
|
|
|
41
40
|
let suitesToSkip = []
|
|
42
|
-
let
|
|
41
|
+
let frameworkVersion
|
|
43
42
|
|
|
44
43
|
function getSuitesByTestFile (root) {
|
|
45
44
|
const suitesByTestFile = {}
|
|
@@ -129,7 +128,7 @@ function mochaHook (Runner) {
|
|
|
129
128
|
this.once('start', testRunAsyncResource.bind(function () {
|
|
130
129
|
const processArgv = process.argv.slice(2).join(' ')
|
|
131
130
|
const command = `mocha ${processArgv}`
|
|
132
|
-
testSessionStartCh.publish({ command, frameworkVersion
|
|
131
|
+
testSessionStartCh.publish({ command, frameworkVersion })
|
|
133
132
|
}))
|
|
134
133
|
|
|
135
134
|
this.on('suite', function (suite) {
|
|
@@ -314,14 +313,14 @@ addHook({
|
|
|
314
313
|
name: 'mocha',
|
|
315
314
|
versions: ['>=5.2.0'],
|
|
316
315
|
file: 'lib/mocha.js'
|
|
317
|
-
}, (Mocha) => {
|
|
316
|
+
}, (Mocha, mochaVersion) => {
|
|
317
|
+
frameworkVersion = mochaVersion
|
|
318
318
|
const mochaRunAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
319
319
|
/**
|
|
320
320
|
* Get ITR configuration and skippable suites
|
|
321
321
|
* If ITR is disabled, `onDone` is called immediately on the subscriber
|
|
322
322
|
*/
|
|
323
323
|
shimmer.wrap(Mocha.prototype, 'run', run => function () {
|
|
324
|
-
mochaVersion = this.version
|
|
325
324
|
if (!itrConfigurationCh.hasSubscribers) {
|
|
326
325
|
return run.apply(this, arguments)
|
|
327
326
|
}
|
|
@@ -331,7 +330,6 @@ addHook({
|
|
|
331
330
|
|
|
332
331
|
const onReceivedSkippableSuites = ({ err, skippableSuites }) => {
|
|
333
332
|
if (err) {
|
|
334
|
-
log.error(err)
|
|
335
333
|
suitesToSkip = []
|
|
336
334
|
} else {
|
|
337
335
|
suitesToSkip = skippableSuites
|
|
@@ -343,7 +341,6 @@ addHook({
|
|
|
343
341
|
|
|
344
342
|
const onReceivedConfiguration = ({ err }) => {
|
|
345
343
|
if (err) {
|
|
346
|
-
log.error(err)
|
|
347
344
|
return global.run()
|
|
348
345
|
}
|
|
349
346
|
if (!skippableSuitesCh.hasSubscribers) {
|
|
@@ -181,17 +181,15 @@ function dispatcherHookNew (dispatcherExport) {
|
|
|
181
181
|
return dispatcherExport
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
-
function runnerHook (runnerExport) {
|
|
184
|
+
function runnerHook (runnerExport, playwrightVersion) {
|
|
185
185
|
shimmer.wrap(runnerExport.Runner.prototype, 'runAllTests', runAllTests => async function () {
|
|
186
186
|
const testSessionAsyncResource = new AsyncResource('bound-anonymous-fn')
|
|
187
|
-
const { version: frameworkVersion } = getPlaywrightConfig(this)
|
|
188
|
-
|
|
189
187
|
const rootDir = getRootDir(this)
|
|
190
188
|
|
|
191
189
|
const processArgv = process.argv.slice(2).join(' ')
|
|
192
190
|
const command = `playwright ${processArgv}`
|
|
193
191
|
testSessionAsyncResource.runInAsyncScope(() => {
|
|
194
|
-
testSessionStartCh.publish({ command, frameworkVersion, rootDir })
|
|
192
|
+
testSessionStartCh.publish({ command, frameworkVersion: playwrightVersion, rootDir })
|
|
195
193
|
})
|
|
196
194
|
|
|
197
195
|
const res = await runAllTests.apply(this, arguments)
|
|
@@ -23,13 +23,12 @@ class BaseAwsSdkPlugin extends Plugin {
|
|
|
23
23
|
request,
|
|
24
24
|
operation,
|
|
25
25
|
awsRegion,
|
|
26
|
-
awsService
|
|
27
|
-
serviceIdentifier
|
|
26
|
+
awsService
|
|
28
27
|
}) => {
|
|
29
28
|
if (!this.isEnabled(request)) {
|
|
30
29
|
return
|
|
31
30
|
}
|
|
32
|
-
const serviceName = this.getServiceName(
|
|
31
|
+
const serviceName = this.getServiceName()
|
|
33
32
|
const childOf = this.tracer.scope().active()
|
|
34
33
|
const tags = {
|
|
35
34
|
'span.kind': 'client',
|
|
@@ -52,6 +51,14 @@ class BaseAwsSdkPlugin extends Plugin {
|
|
|
52
51
|
this.enter(span, store)
|
|
53
52
|
})
|
|
54
53
|
|
|
54
|
+
this.addSub(`apm:aws:request:region:${this.serviceIdentifier}`, region => {
|
|
55
|
+
const store = storage.getStore()
|
|
56
|
+
if (!store) return
|
|
57
|
+
const { span } = store
|
|
58
|
+
if (!span) return
|
|
59
|
+
span.setTag('aws.region', region)
|
|
60
|
+
})
|
|
61
|
+
|
|
55
62
|
this.addSub(`apm:aws:request:complete:${this.serviceIdentifier}`, ({ response }) => {
|
|
56
63
|
const store = storage.getStore()
|
|
57
64
|
if (!store) return
|
|
@@ -109,10 +116,10 @@ class BaseAwsSdkPlugin extends Plugin {
|
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
// TODO: test splitByAwsService when the test suite is fixed
|
|
112
|
-
getServiceName (
|
|
119
|
+
getServiceName () {
|
|
113
120
|
return this.config.service
|
|
114
121
|
? this.config.service
|
|
115
|
-
: `${this.tracer._service}-aws-${serviceIdentifier}`
|
|
122
|
+
: `${this.tracer._service}-aws-${this.serviceIdentifier}`
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
|
|
@@ -48,8 +48,8 @@ class Kinesis extends BaseAwsSdkPlugin {
|
|
|
48
48
|
const parsedData = this._tryParse(injectPath.Data)
|
|
49
49
|
if (parsedData) {
|
|
50
50
|
parsedData._datadog = traceData
|
|
51
|
-
const finalData = JSON.stringify(parsedData)
|
|
52
|
-
const byteSize =
|
|
51
|
+
const finalData = Buffer.from(JSON.stringify(parsedData))
|
|
52
|
+
const byteSize = finalData.length
|
|
53
53
|
// Kinesis max payload size is 1MB
|
|
54
54
|
// So we must ensure adding DD context won't go over that (512b is an estimate)
|
|
55
55
|
if (byteSize >= 1048576) {
|
|
@@ -18,30 +18,35 @@ class Sns extends BaseAwsSdkPlugin {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
requestInject (span, request) {
|
|
21
|
-
const operation = request
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
21
|
+
const { operation, params } = request
|
|
22
|
+
|
|
23
|
+
if (!params) return
|
|
24
|
+
|
|
25
|
+
switch (operation) {
|
|
26
|
+
case 'publish':
|
|
27
|
+
this._injectMessageAttributes(span, params)
|
|
28
|
+
break
|
|
29
|
+
case 'publishBatch':
|
|
30
|
+
if (params.PublishBatchRequestEntries && params.PublishBatchRequestEntries.length > 0) {
|
|
31
|
+
this._injectMessageAttributes(span, params.PublishBatchRequestEntries[0])
|
|
32
|
+
}
|
|
33
|
+
break
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
_injectMessageAttributes (span, params) {
|
|
38
|
+
if (!params.MessageAttributes) {
|
|
39
|
+
params.MessageAttributes = {}
|
|
40
|
+
}
|
|
41
|
+
if (Object.keys(params.MessageAttributes).length >= 10) { // SNS quota
|
|
42
|
+
log.info('Message attributes full, skipping trace context injection')
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
const ddInfo = {}
|
|
46
|
+
this.tracer.inject(span, 'text_map', ddInfo)
|
|
47
|
+
params.MessageAttributes._datadog = {
|
|
48
|
+
DataType: 'Binary',
|
|
49
|
+
BinaryValue: Buffer.from(JSON.stringify(ddInfo)) // BINARY types are automatically base64 encoded
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
}
|