dd-trace 4.7.0 → 4.8.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/README.md +2 -2
- package/package.json +3 -3
- package/packages/datadog-core/src/storage/async_resource.js +4 -0
- package/packages/datadog-instrumentations/src/aws-sdk.js +6 -2
- package/packages/datadog-instrumentations/src/couchbase.js +4 -4
- package/packages/datadog-instrumentations/src/fetch.js +24 -21
- package/packages/datadog-instrumentations/src/helpers/hooks.js +1 -0
- package/packages/datadog-instrumentations/src/http/client.js +41 -32
- package/packages/datadog-instrumentations/src/http2/client.js +1 -0
- package/packages/datadog-instrumentations/src/jest.js +32 -4
- package/packages/datadog-plugin-fetch/src/index.js +7 -13
- package/packages/datadog-plugin-graphql/src/execute.js +6 -4
- package/packages/datadog-plugin-http/src/client.js +25 -20
- package/packages/datadog-plugin-jest/src/index.js +8 -3
- package/packages/datadog-plugin-openai/src/index.js +39 -16
- package/packages/datadog-plugin-openai/src/services.js +13 -9
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +3 -1
- package/packages/dd-trace/src/appsec/iast/analyzers/hsts-header-missing-analyzer.js +45 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/index.js +3 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/missing-header-analyzer.js +66 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +25 -8
- package/packages/dd-trace/src/appsec/iast/analyzers/xcontenttype-header-missing-analyzer.js +19 -0
- package/packages/dd-trace/src/appsec/iast/index.js +5 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +4 -2
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +17 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/source-types.js +1 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/index.js +5 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +3 -1
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +1 -1
- package/packages/dd-trace/src/config.js +26 -10
- package/packages/dd-trace/src/external-logger/src/index.js +9 -1
- package/packages/dd-trace/src/external-logger/test/index.spec.js +1 -1
- package/packages/dd-trace/src/format.js +1 -1
- package/packages/dd-trace/src/lambda/handler.js +8 -1
- package/packages/dd-trace/src/opentelemetry/span.js +3 -1
- package/packages/dd-trace/src/opentracing/span_context.js +2 -1
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/ci.js +2 -1
- package/packages/dd-trace/src/plugins/util/web.js +1 -0
- package/packages/dd-trace/src/profiling/config.js +8 -5
- package/packages/dd-trace/src/profiling/exporters/agent.js +4 -1
- package/packages/dd-trace/src/profiling/profiler.js +1 -1
- package/packages/dd-trace/src/profiling/profilers/wall.js +144 -4
- package/packages/dd-trace/src/service-naming/index.js +2 -2
- package/packages/dd-trace/src/service-naming/schemas/v0/graphql.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/index.js +2 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/graphql.js +12 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/index.js +2 -1
- package/packages/dd-trace/src/span_processor.js +0 -4
- package/packages/dd-trace/src/span_sampler.js +1 -1
- package/packages/dd-trace/src/telemetry/dependencies.js +24 -12
- package/packages/dd-trace/src/telemetry/metrics.js +11 -1
- package/packages/diagnostics_channel/src/index.js +1 -1
- package/scripts/install_plugin_modules.js +1 -0
- package/scripts/version.js +0 -66
package/README.md
CHANGED
|
@@ -143,8 +143,8 @@ $ yarn leak:plugins
|
|
|
143
143
|
|
|
144
144
|
### Linting
|
|
145
145
|
|
|
146
|
-
We use [ESLint](https://eslint.org) to make sure that new code
|
|
147
|
-
|
|
146
|
+
We use [ESLint](https://eslint.org) to make sure that new code
|
|
147
|
+
conforms to our coding standards.
|
|
148
148
|
|
|
149
149
|
To run the linter, use:
|
|
150
150
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.1",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -68,9 +68,9 @@
|
|
|
68
68
|
"dependencies": {
|
|
69
69
|
"@datadog/native-appsec": "^3.2.0",
|
|
70
70
|
"@datadog/native-iast-rewriter": "2.0.1",
|
|
71
|
-
"@datadog/native-iast-taint-tracking": "
|
|
71
|
+
"@datadog/native-iast-taint-tracking": "1.5.0",
|
|
72
72
|
"@datadog/native-metrics": "^2.0.0",
|
|
73
|
-
"@datadog/pprof": "3.
|
|
73
|
+
"@datadog/pprof": "3.1.0",
|
|
74
74
|
"@datadog/sketches-js": "^2.1.0",
|
|
75
75
|
"@opentelemetry/api": "^1.0.0",
|
|
76
76
|
"@opentelemetry/core": "^1.14.0",
|
|
@@ -5,6 +5,7 @@ const { channel } = require('../../../diagnostics_channel')
|
|
|
5
5
|
|
|
6
6
|
const beforeCh = channel('dd-trace:storage:before')
|
|
7
7
|
const afterCh = channel('dd-trace:storage:after')
|
|
8
|
+
const enterCh = channel('dd-trace:storage:enter')
|
|
8
9
|
|
|
9
10
|
let PrivateSymbol = Symbol
|
|
10
11
|
function makePrivateSymbol () {
|
|
@@ -52,6 +53,7 @@ class AsyncResourceStorage {
|
|
|
52
53
|
const resource = this._executionAsyncResource()
|
|
53
54
|
|
|
54
55
|
resource[this._ddResourceStore] = store
|
|
56
|
+
enterCh.publish()
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
run (store, callback, ...args) {
|
|
@@ -61,11 +63,13 @@ class AsyncResourceStorage {
|
|
|
61
63
|
const oldStore = resource[this._ddResourceStore]
|
|
62
64
|
|
|
63
65
|
resource[this._ddResourceStore] = store
|
|
66
|
+
enterCh.publish()
|
|
64
67
|
|
|
65
68
|
try {
|
|
66
69
|
return callback(...args)
|
|
67
70
|
} finally {
|
|
68
71
|
resource[this._ddResourceStore] = oldStore
|
|
72
|
+
enterCh.publish()
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
75
|
|
|
@@ -177,7 +177,6 @@ addHook({ name: '@aws-sdk/smithy-client', versions: ['>=3'] }, smithy => {
|
|
|
177
177
|
})
|
|
178
178
|
|
|
179
179
|
addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
|
|
180
|
-
shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
|
|
181
180
|
shimmer.wrap(AWS.config, 'setPromisesDependency', setPromisesDependency => {
|
|
182
181
|
return function wrappedSetPromisesDependency (dep) {
|
|
183
182
|
const result = setPromisesDependency.apply(this, arguments)
|
|
@@ -188,9 +187,14 @@ addHook({ name: 'aws-sdk', versions: ['>=2.3.0'] }, AWS => {
|
|
|
188
187
|
return AWS
|
|
189
188
|
})
|
|
190
189
|
|
|
190
|
+
addHook({ name: 'aws-sdk', file: 'lib/core.js', versions: ['>=2.3.0'] }, AWS => {
|
|
191
|
+
shimmer.wrap(AWS.Request.prototype, 'promise', wrapRequest)
|
|
192
|
+
return AWS
|
|
193
|
+
})
|
|
194
|
+
|
|
191
195
|
// <2.1.35 has breaking changes for instrumentation
|
|
192
196
|
// https://github.com/aws/aws-sdk-js/pull/629
|
|
193
|
-
addHook({ name: 'aws-sdk', versions: ['>=2.1.35'] }, AWS => {
|
|
197
|
+
addHook({ name: 'aws-sdk', file: 'lib/core.js', versions: ['>=2.1.35'] }, AWS => {
|
|
194
198
|
shimmer.wrap(AWS.Request.prototype, 'send', wrapRequest)
|
|
195
199
|
return AWS
|
|
196
200
|
})
|
|
@@ -160,7 +160,7 @@ function wrapV3Query (query) {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
// semver >=2 <3
|
|
163
|
-
addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.
|
|
163
|
+
addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.12'] }, Bucket => {
|
|
164
164
|
const startCh = channel('apm:couchbase:query:start')
|
|
165
165
|
const finishCh = channel('apm:couchbase:query:finish')
|
|
166
166
|
const errorCh = channel('apm:couchbase:query:error')
|
|
@@ -208,7 +208,7 @@ addHook({ name: 'couchbase', file: 'lib/bucket.js', versions: ['^2.6.5'] }, Buck
|
|
|
208
208
|
return Bucket
|
|
209
209
|
})
|
|
210
210
|
|
|
211
|
-
addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.
|
|
211
|
+
addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.12'] }, Cluster => {
|
|
212
212
|
Cluster.prototype._maybeInvoke = wrapMaybeInvoke(Cluster.prototype._maybeInvoke)
|
|
213
213
|
Cluster.prototype.query = wrapQuery(Cluster.prototype.query)
|
|
214
214
|
|
|
@@ -217,7 +217,7 @@ addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^2.6.5'] }, Clu
|
|
|
217
217
|
|
|
218
218
|
// semver >=3 <3.2.0
|
|
219
219
|
|
|
220
|
-
addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['
|
|
220
|
+
addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['^3.0.7', '^3.1.3'] }, Collection => {
|
|
221
221
|
wrapAllNames(['upsert', 'insert', 'replace'], name => {
|
|
222
222
|
shimmer.wrap(Collection.prototype, name, wrapWithName(name))
|
|
223
223
|
})
|
|
@@ -225,7 +225,7 @@ addHook({ name: 'couchbase', file: 'lib/collection.js', versions: ['>=3.0.0 <3.2
|
|
|
225
225
|
return Collection
|
|
226
226
|
})
|
|
227
227
|
|
|
228
|
-
addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['
|
|
228
|
+
addHook({ name: 'couchbase', file: 'lib/cluster.js', versions: ['^3.0.7', '^3.1.3'] }, Cluster => {
|
|
229
229
|
shimmer.wrap(Cluster.prototype, 'query', wrapV3Query)
|
|
230
230
|
return Cluster
|
|
231
231
|
})
|
|
@@ -17,29 +17,32 @@ function wrapFetch (fetch, Request) {
|
|
|
17
17
|
const headers = req.headers
|
|
18
18
|
const message = { req, headers }
|
|
19
19
|
|
|
20
|
-
startChannel.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return res
|
|
32
|
-
},
|
|
33
|
-
err => {
|
|
34
|
-
if (err.name !== 'AbortError') {
|
|
35
|
-
errorChannel.publish(err)
|
|
36
|
-
}
|
|
20
|
+
return startChannel.runStores(message, () => {
|
|
21
|
+
// Request object is read-only so we need new objects to change headers.
|
|
22
|
+
arguments[0] = message.req
|
|
23
|
+
arguments[1] = { headers: message.headers }
|
|
24
|
+
|
|
25
|
+
return fetch.apply(this, arguments)
|
|
26
|
+
.then(
|
|
27
|
+
res => {
|
|
28
|
+
message.res = res
|
|
29
|
+
|
|
30
|
+
finishChannel.publish(message)
|
|
37
31
|
|
|
38
|
-
|
|
32
|
+
return res
|
|
33
|
+
},
|
|
34
|
+
err => {
|
|
35
|
+
if (err.name !== 'AbortError') {
|
|
36
|
+
message.error = err
|
|
37
|
+
errorChannel.publish(message)
|
|
38
|
+
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
finishChannel.publish(message)
|
|
41
|
+
|
|
42
|
+
throw err
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
})
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
|
|
@@ -10,6 +10,7 @@ module.exports = {
|
|
|
10
10
|
'@grpc/grpc-js': () => require('../grpc'),
|
|
11
11
|
'@hapi/hapi': () => require('../hapi'),
|
|
12
12
|
'@jest/core': () => require('../jest'),
|
|
13
|
+
'@jest/transform': () => require('../jest'),
|
|
13
14
|
'@jest/reporters': () => require('../jest'),
|
|
14
15
|
'@koa/router': () => require('../koa'),
|
|
15
16
|
'@node-redis/client': () => require('../redis'),
|
|
@@ -3,18 +3,16 @@
|
|
|
3
3
|
/* eslint-disable no-fallthrough */
|
|
4
4
|
|
|
5
5
|
const url = require('url')
|
|
6
|
-
const {
|
|
7
|
-
channel,
|
|
8
|
-
addHook,
|
|
9
|
-
AsyncResource
|
|
10
|
-
} = require('../helpers/instrument')
|
|
6
|
+
const { channel, addHook } = require('../helpers/instrument')
|
|
11
7
|
const shimmer = require('../../../datadog-shimmer')
|
|
12
8
|
|
|
13
9
|
const log = require('../../../dd-trace/src/log')
|
|
14
10
|
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
11
|
+
const startChannel = channel('apm:http:client:request:start')
|
|
12
|
+
const finishChannel = channel('apm:http:client:request:finish')
|
|
13
|
+
const endChannel = channel('apm:http:client:request:end')
|
|
14
|
+
const asyncStartChannel = channel('apm:http:client:request:asyncStart')
|
|
15
|
+
const errorChannel = channel('apm:http:client:request:error')
|
|
18
16
|
|
|
19
17
|
addHook({ name: 'https' }, hookFn)
|
|
20
18
|
|
|
@@ -32,7 +30,7 @@ function patch (http, methodName) {
|
|
|
32
30
|
|
|
33
31
|
function instrumentRequest (request) {
|
|
34
32
|
return function () {
|
|
35
|
-
if (!
|
|
33
|
+
if (!startChannel.hasSubscribers) {
|
|
36
34
|
return request.apply(this, arguments)
|
|
37
35
|
}
|
|
38
36
|
|
|
@@ -45,57 +43,68 @@ function patch (http, methodName) {
|
|
|
45
43
|
return request.apply(this, arguments)
|
|
46
44
|
}
|
|
47
45
|
|
|
48
|
-
const
|
|
49
|
-
const asyncResource = new AsyncResource('bound-anonymous-fn')
|
|
50
|
-
|
|
51
|
-
return asyncResource.runInAsyncScope(() => {
|
|
52
|
-
startClientCh.publish({ args, http })
|
|
46
|
+
const ctx = { args, http }
|
|
53
47
|
|
|
48
|
+
return startChannel.runStores(ctx, () => {
|
|
54
49
|
let finished = false
|
|
55
50
|
let callback = args.callback
|
|
56
51
|
|
|
57
52
|
if (callback) {
|
|
58
|
-
callback =
|
|
53
|
+
callback = function () {
|
|
54
|
+
return asyncStartChannel.runStores(ctx, () => {
|
|
55
|
+
return args.callback.apply(this, arguments)
|
|
56
|
+
})
|
|
57
|
+
}
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
const options = args.options
|
|
62
|
-
const
|
|
63
|
-
const emit = req.emit
|
|
64
|
-
|
|
65
|
-
const finish = (req, res) => {
|
|
61
|
+
const finish = () => {
|
|
66
62
|
if (!finished) {
|
|
67
63
|
finished = true
|
|
68
|
-
|
|
64
|
+
finishChannel.publish(ctx)
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
67
|
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
try {
|
|
69
|
+
const req = request.call(this, options, callback)
|
|
70
|
+
const emit = req.emit
|
|
71
|
+
|
|
72
|
+
ctx.req = req
|
|
73
|
+
|
|
74
|
+
req.emit = function (eventName, arg) {
|
|
74
75
|
switch (eventName) {
|
|
75
76
|
case 'response': {
|
|
76
77
|
const res = arg
|
|
77
|
-
|
|
78
|
-
res.on('end',
|
|
79
|
-
res.on('error',
|
|
78
|
+
ctx.res = res
|
|
79
|
+
res.on('end', finish)
|
|
80
|
+
res.on('error', finish)
|
|
80
81
|
break
|
|
81
82
|
}
|
|
82
83
|
case 'connect':
|
|
83
84
|
case 'upgrade':
|
|
84
|
-
|
|
85
|
+
ctx.res = arg
|
|
86
|
+
finish()
|
|
85
87
|
break
|
|
86
88
|
case 'error':
|
|
87
89
|
case 'timeout':
|
|
88
|
-
|
|
90
|
+
ctx.error = arg
|
|
91
|
+
errorChannel.publish(ctx)
|
|
89
92
|
case 'abort': // deprecated and replaced by `close` in node 17
|
|
90
93
|
case 'close':
|
|
91
|
-
finish(
|
|
94
|
+
finish()
|
|
92
95
|
}
|
|
93
|
-
})
|
|
94
96
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
return emit.apply(this, arguments)
|
|
98
|
+
}
|
|
97
99
|
|
|
98
|
-
|
|
100
|
+
return req
|
|
101
|
+
} catch (e) {
|
|
102
|
+
ctx.error = e
|
|
103
|
+
errorChannel.publish(ctx)
|
|
104
|
+
throw e
|
|
105
|
+
} finally {
|
|
106
|
+
endChannel.publish(ctx)
|
|
107
|
+
}
|
|
99
108
|
})
|
|
100
109
|
}
|
|
101
110
|
}
|
|
@@ -129,8 +129,7 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
129
129
|
suite: this.testSuite,
|
|
130
130
|
runner: 'jest-circus',
|
|
131
131
|
testParameters,
|
|
132
|
-
frameworkVersion: jestVersion
|
|
133
|
-
testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
|
|
132
|
+
frameworkVersion: jestVersion
|
|
134
133
|
})
|
|
135
134
|
originalTestFns.set(event.test, event.test.fn)
|
|
136
135
|
event.test.fn = asyncResource.bind(event.test.fn)
|
|
@@ -145,7 +144,10 @@ function getWrappedEnvironment (BaseEnvironment, jestVersion) {
|
|
|
145
144
|
const formattedError = formatJestError(event.test.errors[0])
|
|
146
145
|
testErrCh.publish(formattedError)
|
|
147
146
|
}
|
|
148
|
-
testRunFinishCh.publish(
|
|
147
|
+
testRunFinishCh.publish({
|
|
148
|
+
status,
|
|
149
|
+
testStartLine: getTestLineStart(event.test.asyncError, this.testSuite)
|
|
150
|
+
})
|
|
149
151
|
// restore in case it is retried
|
|
150
152
|
event.test.fn = originalTestFns.get(event.test)
|
|
151
153
|
})
|
|
@@ -408,6 +410,32 @@ function jestConfigSyncWrapper (jestConfig) {
|
|
|
408
410
|
return jestConfig
|
|
409
411
|
}
|
|
410
412
|
|
|
413
|
+
addHook({
|
|
414
|
+
name: '@jest/transform',
|
|
415
|
+
versions: ['>=24.8.0'],
|
|
416
|
+
file: 'build/ScriptTransformer.js'
|
|
417
|
+
}, transformPackage => {
|
|
418
|
+
const originalCreateScriptTransformer = transformPackage.createScriptTransformer
|
|
419
|
+
|
|
420
|
+
transformPackage.createScriptTransformer = async function (config) {
|
|
421
|
+
const { testEnvironmentOptions, ...restOfConfig } = config
|
|
422
|
+
const {
|
|
423
|
+
_ddTestModuleId,
|
|
424
|
+
_ddTestSessionId,
|
|
425
|
+
_ddTestCommand,
|
|
426
|
+
...restOfTestEnvironmentOptions
|
|
427
|
+
} = testEnvironmentOptions
|
|
428
|
+
|
|
429
|
+
restOfConfig.testEnvironmentOptions = restOfTestEnvironmentOptions
|
|
430
|
+
|
|
431
|
+
arguments[0] = restOfConfig
|
|
432
|
+
|
|
433
|
+
return originalCreateScriptTransformer.apply(this, arguments)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return transformPackage
|
|
437
|
+
})
|
|
438
|
+
|
|
411
439
|
/**
|
|
412
440
|
* Hook to remove the test paths (test suite) that are part of `skippableSuites`
|
|
413
441
|
*/
|
|
@@ -471,7 +499,7 @@ function jasmineAsyncInstallWraper (jasmineAsyncInstallExport, jestVersion) {
|
|
|
471
499
|
const formattedError = formatJestError(spec.result.failedExpectations[0].error)
|
|
472
500
|
testErrCh.publish(formattedError)
|
|
473
501
|
}
|
|
474
|
-
testRunFinishCh.publish(specStatusToTestStatus[spec.result.status])
|
|
502
|
+
testRunFinishCh.publish({ status: specStatusToTestStatus[spec.result.status] })
|
|
475
503
|
onComplete.apply(this, arguments)
|
|
476
504
|
})
|
|
477
505
|
arguments[0] = callback
|
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const HttpClientPlugin = require('../../datadog-plugin-http/src/client')
|
|
4
|
-
const { HTTP_HEADERS } = require('../../../ext/formats')
|
|
5
4
|
|
|
6
5
|
class FetchPlugin extends HttpClientPlugin {
|
|
7
6
|
static get id () { return 'fetch' }
|
|
7
|
+
static get prefix () { return `apm:fetch:request` }
|
|
8
8
|
|
|
9
9
|
addTraceSub (eventName, handler) {
|
|
10
10
|
this.addSub(`apm:${this.constructor.id}:${this.operation}:${eventName}`, handler)
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
bindStart (message) {
|
|
14
14
|
const req = message.req
|
|
15
15
|
const options = new URL(req.url)
|
|
16
16
|
const headers = options.headers = Object.fromEntries(req.headers.entries())
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
options.method = req.method
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
message.args = { options }
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
}
|
|
22
|
+
const store = super.bindStart(message)
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
const carrier = {}
|
|
27
|
-
|
|
28
|
-
this.tracer.inject(span, HTTP_HEADERS, carrier)
|
|
24
|
+
message.req = new globalThis.Request(req, { headers })
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
headers.append(name, carrier[name])
|
|
32
|
-
}
|
|
26
|
+
return store
|
|
33
27
|
}
|
|
34
28
|
}
|
|
35
29
|
|
|
@@ -7,6 +7,8 @@ let tools
|
|
|
7
7
|
class GraphQLExecutePlugin extends TracingPlugin {
|
|
8
8
|
static get id () { return 'graphql' }
|
|
9
9
|
static get operation () { return 'execute' }
|
|
10
|
+
static get type () { return 'graphql' }
|
|
11
|
+
static get kind () { return 'server' }
|
|
10
12
|
|
|
11
13
|
start ({ operation, args, docSource }) {
|
|
12
14
|
const type = operation && operation.operation
|
|
@@ -14,11 +16,11 @@ class GraphQLExecutePlugin extends TracingPlugin {
|
|
|
14
16
|
const document = args.document
|
|
15
17
|
const source = this.config.source && document && docSource
|
|
16
18
|
|
|
17
|
-
const span = this.startSpan(
|
|
18
|
-
service: this.config.service,
|
|
19
|
+
const span = this.startSpan(this.operationName(), {
|
|
20
|
+
service: this.config.service || this.serviceName(),
|
|
19
21
|
resource: getSignature(document, name, type, this.config.signature),
|
|
20
|
-
kind:
|
|
21
|
-
type:
|
|
22
|
+
kind: this.constructor.kind,
|
|
23
|
+
type: this.constructor.type,
|
|
22
24
|
meta: {
|
|
23
25
|
'graphql.operation.type': type,
|
|
24
26
|
'graphql.operation.name': name,
|
|
@@ -16,15 +16,11 @@ const HTTP_REQUEST_HEADERS = tags.HTTP_REQUEST_HEADERS
|
|
|
16
16
|
const HTTP_RESPONSE_HEADERS = tags.HTTP_RESPONSE_HEADERS
|
|
17
17
|
|
|
18
18
|
class HttpClientPlugin extends ClientPlugin {
|
|
19
|
-
static get id () {
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
addTraceSub (eventName, handler) {
|
|
24
|
-
this.addSub(`apm:${this.constructor.id}:client:${this.operation}:${eventName}`, handler)
|
|
25
|
-
}
|
|
19
|
+
static get id () { return 'http' }
|
|
20
|
+
static get prefix () { return `apm:http:client:request` }
|
|
26
21
|
|
|
27
|
-
|
|
22
|
+
bindStart (message) {
|
|
23
|
+
const { args, http = {} } = message
|
|
28
24
|
const store = storage.getStore()
|
|
29
25
|
const options = args.options
|
|
30
26
|
const agent = options.agent || options._defaultAgent || http.globalAgent || {}
|
|
@@ -55,7 +51,7 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
55
51
|
metrics: {
|
|
56
52
|
[CLIENT_PORT_KEY]: parseInt(options.port)
|
|
57
53
|
}
|
|
58
|
-
})
|
|
54
|
+
}, false)
|
|
59
55
|
|
|
60
56
|
// TODO: Figure out a better way to do this for any span.
|
|
61
57
|
if (!allowed) {
|
|
@@ -67,11 +63,19 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
analyticsSampler.sample(span, this.config.measured)
|
|
70
|
-
|
|
66
|
+
|
|
67
|
+
message.span = span
|
|
68
|
+
message.parentStore = store
|
|
69
|
+
message.currentStore = { ...store, span }
|
|
70
|
+
|
|
71
|
+
return message.currentStore
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
bindAsyncStart ({ parentStore }) {
|
|
75
|
+
return parentStore
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
finish ({ req, res, span }) {
|
|
75
79
|
if (res) {
|
|
76
80
|
const status = res.status || res.statusCode
|
|
77
81
|
|
|
@@ -87,17 +91,18 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
87
91
|
addRequestHeaders(req, span, this.config)
|
|
88
92
|
|
|
89
93
|
this.config.hooks.request(span, req, res)
|
|
90
|
-
super.finish()
|
|
91
|
-
}
|
|
92
94
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
+
this.tagPeerService(span)
|
|
96
|
+
|
|
97
|
+
span.finish()
|
|
98
|
+
}
|
|
95
99
|
|
|
96
|
-
|
|
100
|
+
error ({ span, error }) {
|
|
101
|
+
if (error) {
|
|
97
102
|
span.addTags({
|
|
98
|
-
[ERROR_TYPE]:
|
|
99
|
-
[ERROR_MESSAGE]:
|
|
100
|
-
[ERROR_STACK]:
|
|
103
|
+
[ERROR_TYPE]: error.name,
|
|
104
|
+
[ERROR_MESSAGE]: error.message || error.code,
|
|
105
|
+
[ERROR_STACK]: error.stack
|
|
101
106
|
})
|
|
102
107
|
} else {
|
|
103
108
|
span.setTag('error', 1)
|
|
@@ -166,9 +166,12 @@ class JestPlugin extends CiPlugin {
|
|
|
166
166
|
this.enter(span, store)
|
|
167
167
|
})
|
|
168
168
|
|
|
169
|
-
this.addSub('ci:jest:test:finish', (status) => {
|
|
169
|
+
this.addSub('ci:jest:test:finish', ({ status, testStartLine }) => {
|
|
170
170
|
const span = storage.getStore().span
|
|
171
171
|
span.setTag(TEST_STATUS, status)
|
|
172
|
+
if (testStartLine) {
|
|
173
|
+
span.setTag(TEST_SOURCE_START, testStartLine)
|
|
174
|
+
}
|
|
172
175
|
span.finish()
|
|
173
176
|
finishAllTraceSpans(span)
|
|
174
177
|
})
|
|
@@ -197,8 +200,10 @@ class JestPlugin extends CiPlugin {
|
|
|
197
200
|
const extraTags = {
|
|
198
201
|
[JEST_TEST_RUNNER]: runner,
|
|
199
202
|
[TEST_PARAMETERS]: testParameters,
|
|
200
|
-
[TEST_FRAMEWORK_VERSION]: frameworkVersion
|
|
201
|
-
|
|
203
|
+
[TEST_FRAMEWORK_VERSION]: frameworkVersion
|
|
204
|
+
}
|
|
205
|
+
if (testStartLine) {
|
|
206
|
+
extraTags[TEST_SOURCE_START] = testStartLine
|
|
202
207
|
}
|
|
203
208
|
|
|
204
209
|
return super.startTestSpan(name, suite, this.testSuiteSpan, extraTags)
|