dd-trace 4.0.0 → 5.0.0-pre-ca96946
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/MIGRATING.md +39 -0
- package/README.md +18 -11
- package/package.json +1 -1
- package/packages/datadog-instrumentations/src/cucumber.js +13 -0
- package/packages/datadog-instrumentations/src/jest.js +2 -3
- package/packages/datadog-instrumentations/src/next.js +2 -2
- package/packages/datadog-plugin-amqp10/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqp10/src/producer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/client.js +4 -3
- package/packages/datadog-plugin-amqplib/src/consumer.js +1 -3
- package/packages/datadog-plugin-amqplib/src/producer.js +1 -3
- package/packages/datadog-plugin-cucumber/src/index.js +2 -2
- package/packages/datadog-plugin-cypress/src/plugin.js +37 -7
- package/packages/datadog-plugin-cypress/src/support.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/client.js +4 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +1 -3
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +1 -3
- package/packages/datadog-plugin-jest/src/index.js +5 -4
- package/packages/datadog-plugin-kafkajs/src/consumer.js +1 -4
- package/packages/datadog-plugin-kafkajs/src/producer.js +1 -3
- package/packages/datadog-plugin-mocha/src/index.js +4 -2
- package/packages/datadog-plugin-rhea/src/consumer.js +1 -3
- package/packages/datadog-plugin-rhea/src/producer.js +1 -5
- package/packages/dd-trace/src/appsec/iast/analyzers/path-traversal-analyzer.js +4 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -7
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +1 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +1 -6
- package/packages/dd-trace/src/config.js +20 -1
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +11 -3
- package/packages/dd-trace/src/exporters/common/util.js +9 -0
- package/packages/dd-trace/src/exporters/common/writer.js +3 -2
- package/packages/dd-trace/src/plugin_manager.js +2 -0
- package/packages/dd-trace/src/plugins/client.js +3 -2
- package/packages/dd-trace/src/plugins/consumer.js +14 -2
- package/packages/dd-trace/src/plugins/inbound.js +7 -0
- package/packages/dd-trace/src/plugins/{outgoing.js → outbound.js} +2 -2
- package/packages/dd-trace/src/plugins/producer.js +19 -2
- package/packages/dd-trace/src/plugins/server.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +11 -0
- package/packages/dd-trace/src/profiling/config.js +4 -2
- package/packages/dd-trace/src/service-naming/index.js +38 -0
- package/packages/dd-trace/src/service-naming/schemas/definition.js +24 -0
- package/packages/dd-trace/src/service-naming/schemas/index.js +6 -0
- package/packages/dd-trace/src/service-naming/schemas/v0.js +66 -0
- package/packages/dd-trace/src/service-naming/schemas/v1.js +58 -0
- package/packages/dd-trace/src/tracer.js +3 -3
- package/version.js +8 -4
- package/packages/dd-trace/src/plugins/incoming.js +0 -7
package/MIGRATING.md
CHANGED
|
@@ -4,6 +4,45 @@ This guide describes the steps to upgrade dd-trace from a major version to the
|
|
|
4
4
|
next. If you are having any issues related to migrating, please feel free to
|
|
5
5
|
open an issue or contact our [support](https://www.datadoghq.com/support/) team.
|
|
6
6
|
|
|
7
|
+
## 3.0 to 4.0
|
|
8
|
+
|
|
9
|
+
### Node 14 is no longer supported
|
|
10
|
+
|
|
11
|
+
Node.js 14 has reached EOL in April 2023 and is no longer supported. Generally
|
|
12
|
+
speaking, we highly recommend always keeping Node.js up to date regardless of
|
|
13
|
+
our support policy.
|
|
14
|
+
|
|
15
|
+
### The `orphanable` option was removed
|
|
16
|
+
|
|
17
|
+
This option was only useful internally for a single integration that has since
|
|
18
|
+
been removed. It was never useful for manual instrumentation since all that is
|
|
19
|
+
needed to orphan a span on creation is to use
|
|
20
|
+
`tracer.trace('web.request', { childOf: null })`.
|
|
21
|
+
|
|
22
|
+
### Support for `jest-jasmine2` has been removed
|
|
23
|
+
|
|
24
|
+
The default test runner for Jest was changed to `jest-circus` around 2 years ago and
|
|
25
|
+
is no longer supported by our Jest integration for CI Visibility. We recommend
|
|
26
|
+
switching to `jest-circus` to anyone still using `jest-jasmine2`.
|
|
27
|
+
|
|
28
|
+
### Support for older Next.js versions was removed
|
|
29
|
+
|
|
30
|
+
We now support only Next.js 10.2 and up.
|
|
31
|
+
|
|
32
|
+
### W3C headers are now prioritized over Datadog headers
|
|
33
|
+
|
|
34
|
+
As we move towards open standards, we have decided to prioritize W3C Trace
|
|
35
|
+
Context headers over our own vendor-specific headers for context propagation
|
|
36
|
+
across services. For most applications this shouldn't change anything and
|
|
37
|
+
distributed tracing should continue to work seamlessly.
|
|
38
|
+
|
|
39
|
+
In some rare cases it's possible that some of the services involved in a trace
|
|
40
|
+
are not instrumented by Datadog at all which can cause spans within the trace to
|
|
41
|
+
become disconnected. While the data would still be available in the UI, the
|
|
42
|
+
relationship between spans would no longer be visible. This can be addressed by
|
|
43
|
+
restoring the previous behaviour using
|
|
44
|
+
`DD_TRACE_PROPAGATION_STYLE='datadog,tracecontext'`.
|
|
45
|
+
|
|
7
46
|
## 2.0 to 3.0
|
|
8
47
|
|
|
9
48
|
### Node 12 is no longer supported
|
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# `dd-trace`: Node.js APM Tracer Library
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/dd-trace)
|
|
4
|
+
[](https://www.npmjs.com/package/dd-trace/v/latest-node12)
|
|
4
5
|
[](https://www.npmjs.com/package/dd-trace/v/latest-node12)
|
|
5
6
|
[](https://www.npmjs.com/package/dd-trace/v/dev)
|
|
6
7
|
[](https://codecov.io/gh/DataDog/dd-trace-js)
|
|
@@ -28,27 +29,28 @@ Most of the documentation for `dd-trace` is available on these webpages:
|
|
|
28
29
|
| :---: | :---: | :---: | :---: | :---: | :---: |
|
|
29
30
|
| [`v1`](https://github.com/DataDog/dd-trace-js/tree/v1.x) |  | `>= v12` | **End of Life** | 2021-07-13 | 2022-02-25 |
|
|
30
31
|
| [`v2`](https://github.com/DataDog/dd-trace-js/tree/v2.x) |  | `>= v12` | **Maintenance** | 2022-01-28 | 2023-08-15 |
|
|
31
|
-
| [`v3`](https://github.com/DataDog/dd-trace-js/tree/v3.x) | 
|
|
32
|
+
| [`v3`](https://github.com/DataDog/dd-trace-js/tree/v3.x) |  | `>= v14` | **Maintenance** | 2022-08-15 | 2024-05-15 |
|
|
33
|
+
| [`v4`](https://github.com/DataDog/dd-trace-js/tree/v4.x) |  | `>= v16` | **Current** | 2023-05-12 | Unknown |
|
|
32
34
|
|
|
33
|
-
We currently maintain
|
|
34
|
-
Features and bug fixes that are merged are released to the `
|
|
35
|
+
We currently maintain three release lines, namely `v2`, `v3` and `v4`.
|
|
36
|
+
Features and bug fixes that are merged are released to the `v4` line and, if appropriate, also the `v2` and `v3` line.
|
|
35
37
|
|
|
36
|
-
For any new projects it is recommended to use the `
|
|
38
|
+
For any new projects it is recommended to use the `v4` release line:
|
|
37
39
|
|
|
38
40
|
```sh
|
|
39
41
|
$ npm install dd-trace
|
|
40
42
|
$ yarn add dd-trace
|
|
41
43
|
```
|
|
42
44
|
|
|
43
|
-
However, existing projects that already use the `v2` release
|
|
45
|
+
However, existing projects that already use the `v2` or `v3` release lines, or projects that need to support EOL versions of Node.js, may continue to use these release lines.
|
|
44
46
|
This is done by specifying the version when installing the package.
|
|
45
|
-
Note that we also publish to npm using a `latest-node12` tag that can also be used for install:
|
|
47
|
+
Note that we also publish to npm using a `latest-node12` and `latest-node14` tag that can also be used for install:
|
|
46
48
|
|
|
47
49
|
```sh
|
|
48
|
-
$ npm install dd-trace@
|
|
49
|
-
$ yarn add dd-trace@
|
|
50
|
-
$ npm install dd-trace@latest-
|
|
51
|
-
$ yarn add dd-trace@latest-
|
|
50
|
+
$ npm install dd-trace@3
|
|
51
|
+
$ yarn add dd-trace@3
|
|
52
|
+
$ npm install dd-trace@latest-node14
|
|
53
|
+
$ yarn add dd-trace@latest-node14
|
|
52
54
|
```
|
|
53
55
|
|
|
54
56
|
Any backwards-breaking functionality that is introduced into the library will result in an increase of the major version of the library and therefore a new release line.
|
|
@@ -153,6 +155,11 @@ $ yarn lint
|
|
|
153
155
|
|
|
154
156
|
### Experimental ESM Support
|
|
155
157
|
|
|
158
|
+
> **Warning**
|
|
159
|
+
>
|
|
160
|
+
> ESM support has been temporarily disabled starting from Node 20 as significant
|
|
161
|
+
> changes are in progress.
|
|
162
|
+
|
|
156
163
|
ESM support is currently in the experimental stages, while CJS has been supported
|
|
157
164
|
since inception. This means that code loaded using `require()` should work fine
|
|
158
165
|
but code loaded using `import` might not always work.
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ const { createCoverageMap } = require('istanbul-lib-coverage')
|
|
|
3
3
|
|
|
4
4
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
5
5
|
const shimmer = require('../../datadog-shimmer')
|
|
6
|
+
const log = require('../../dd-trace/src/log')
|
|
6
7
|
|
|
7
8
|
const testStartCh = channel('ci:cucumber:test:start')
|
|
8
9
|
const testFinishCh = channel('ci:cucumber:test:finish') // used for test steps too
|
|
@@ -175,6 +176,12 @@ function wrapRun (pl, isLatestVersion) {
|
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
function pickleHook (PickleRunner) {
|
|
179
|
+
if (process.env.CUCUMBER_WORKER_ID) {
|
|
180
|
+
// Parallel mode is not supported
|
|
181
|
+
log.warn('Unable to initialize CI Visibility because Cucumber is running in parallel mode.')
|
|
182
|
+
return PickleRunner
|
|
183
|
+
}
|
|
184
|
+
|
|
178
185
|
const pl = PickleRunner.default
|
|
179
186
|
|
|
180
187
|
wrapRun(pl, false)
|
|
@@ -183,6 +190,12 @@ function pickleHook (PickleRunner) {
|
|
|
183
190
|
}
|
|
184
191
|
|
|
185
192
|
function testCaseHook (TestCaseRunner) {
|
|
193
|
+
if (process.env.CUCUMBER_WORKER_ID) {
|
|
194
|
+
// Parallel mode is not supported
|
|
195
|
+
log.warn('Unable to initialize CI Visibility because Cucumber is running in parallel mode.')
|
|
196
|
+
return TestCaseRunner
|
|
197
|
+
}
|
|
198
|
+
|
|
186
199
|
const pl = TestCaseRunner.default
|
|
187
200
|
|
|
188
201
|
wrapRun(pl, true)
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
const semver = require('semver')
|
|
3
2
|
|
|
4
3
|
const { addHook, channel, AsyncResource } = require('./helpers/instrument')
|
|
5
4
|
const shimmer = require('../../datadog-shimmer')
|
|
6
5
|
const log = require('../../dd-trace/src/log')
|
|
7
|
-
const { version: ddTraceVersion } = require('../../../package.json')
|
|
8
6
|
const {
|
|
9
7
|
getCoveredFilenamesFromCoverage,
|
|
10
8
|
JEST_WORKER_TRACE_PAYLOAD_CODE,
|
|
@@ -18,6 +16,7 @@ const {
|
|
|
18
16
|
getJestTestName,
|
|
19
17
|
getJestSuitesToRun
|
|
20
18
|
} = require('../../datadog-plugin-jest/src/util')
|
|
19
|
+
const { DD_MAJOR } = require('../../../version')
|
|
21
20
|
|
|
22
21
|
const testSessionStartCh = channel('ci:jest:session:start')
|
|
23
22
|
const testSessionFinishCh = channel('ci:jest:session:finish')
|
|
@@ -481,7 +480,7 @@ function jasmineAsyncInstallWraper (jasmineAsyncInstallExport, jestVersion) {
|
|
|
481
480
|
}
|
|
482
481
|
}
|
|
483
482
|
|
|
484
|
-
if (
|
|
483
|
+
if (DD_MAJOR < 4) {
|
|
485
484
|
addHook({
|
|
486
485
|
name: 'jest-jasmine2',
|
|
487
486
|
versions: ['>=24.8.0'],
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const { channel, addHook, AsyncResource } = require('./helpers/instrument')
|
|
6
6
|
const shimmer = require('../../datadog-shimmer')
|
|
7
|
-
const {
|
|
7
|
+
const { DD_MAJOR } = require('../../../version')
|
|
8
8
|
|
|
9
9
|
const startChannel = channel('apm:next:request:start')
|
|
10
10
|
const finishChannel = channel('apm:next:request:finish')
|
|
@@ -171,7 +171,7 @@ addHook({ name: 'next', versions: ['>=11.1 <13.2'], file: 'dist/server/next-serv
|
|
|
171
171
|
|
|
172
172
|
addHook({
|
|
173
173
|
name: 'next',
|
|
174
|
-
versions:
|
|
174
|
+
versions: DD_MAJOR >= 4 ? ['>=10.2 <11.1'] : ['>=9.5 <11.1'],
|
|
175
175
|
file: 'dist/next-server/server/next-server.js'
|
|
176
176
|
}, nextServer => {
|
|
177
177
|
const Server = nextServer.default
|
|
@@ -11,11 +11,9 @@ class Amqp10ConsumerPlugin extends ConsumerPlugin {
|
|
|
11
11
|
const source = getShortName(link)
|
|
12
12
|
const address = getAddress(link)
|
|
13
13
|
|
|
14
|
-
this.startSpan(
|
|
15
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
14
|
+
this.startSpan({
|
|
16
15
|
resource: ['receive', source].filter(v => v).join(' '),
|
|
17
16
|
type: 'worker',
|
|
18
|
-
kind: 'consumer',
|
|
19
17
|
meta: {
|
|
20
18
|
'amqp.link.source.address': source,
|
|
21
19
|
'amqp.link.role': 'receiver',
|
|
@@ -13,10 +13,8 @@ class Amqp10ProducerPlugin extends ProducerPlugin {
|
|
|
13
13
|
const address = getAddress(link)
|
|
14
14
|
const target = getShortName(link)
|
|
15
15
|
|
|
16
|
-
this.startSpan(
|
|
17
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
16
|
+
this.startSpan({
|
|
18
17
|
resource: ['send', target].filter(v => v).join(' '),
|
|
19
|
-
kind: 'producer',
|
|
20
18
|
meta: {
|
|
21
19
|
'amqp.link.target.address': target,
|
|
22
20
|
'amqp.link.role': 'sender',
|
|
@@ -7,6 +7,7 @@ const { getResourceName } = require('./util')
|
|
|
7
7
|
|
|
8
8
|
class AmqplibClientPlugin extends ClientPlugin {
|
|
9
9
|
static get id () { return 'amqplib' }
|
|
10
|
+
static get type () { return 'messaging' }
|
|
10
11
|
static get operation () { return 'command' }
|
|
11
12
|
|
|
12
13
|
start ({ channel = {}, method, fields }) {
|
|
@@ -14,10 +15,10 @@ class AmqplibClientPlugin extends ClientPlugin {
|
|
|
14
15
|
if (method === 'basic.publish') return
|
|
15
16
|
|
|
16
17
|
const stream = (channel.connection && channel.connection.stream) || {}
|
|
17
|
-
const span = this.startSpan(
|
|
18
|
-
service: this.config.service ||
|
|
18
|
+
const span = this.startSpan(this.operationName(), {
|
|
19
|
+
service: this.config.service || this.serviceName(),
|
|
19
20
|
resource: getResourceName(method, fields),
|
|
20
|
-
kind:
|
|
21
|
+
kind: this.constructor.kind,
|
|
21
22
|
meta: {
|
|
22
23
|
'out.host': stream._host,
|
|
23
24
|
[CLIENT_PORT_KEY]: stream.remotePort,
|
|
@@ -13,11 +13,9 @@ class AmqplibConsumerPlugin extends ConsumerPlugin {
|
|
|
13
13
|
|
|
14
14
|
const childOf = extract(this.tracer, message)
|
|
15
15
|
|
|
16
|
-
this.startSpan(
|
|
16
|
+
this.startSpan({
|
|
17
17
|
childOf,
|
|
18
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
19
18
|
resource: getResourceName(method, fields),
|
|
20
|
-
kind: 'consumer',
|
|
21
19
|
type: 'worker',
|
|
22
20
|
meta: {
|
|
23
21
|
'amqp.queue': fields.queue,
|
|
@@ -13,10 +13,8 @@ class AmqplibProducerPlugin extends ProducerPlugin {
|
|
|
13
13
|
if (method !== 'basic.publish') return
|
|
14
14
|
|
|
15
15
|
const stream = (channel.connection && channel.connection.stream) || {}
|
|
16
|
-
const span = this.startSpan(
|
|
17
|
-
service: this.config.service || `${this.tracer._service}-amqp`,
|
|
16
|
+
const span = this.startSpan({
|
|
18
17
|
resource: getResourceName(method, fields),
|
|
19
|
-
kind: 'producer',
|
|
20
18
|
meta: {
|
|
21
19
|
'out.host': stream._host,
|
|
22
20
|
[CLIENT_PORT_KEY]: stream.remotePort,
|
|
@@ -73,8 +73,8 @@ class CucumberPlugin extends CiPlugin {
|
|
|
73
73
|
.map(filename => getTestSuitePath(filename, this.sourceRoot))
|
|
74
74
|
|
|
75
75
|
const formattedCoverage = {
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
sessionId: this.testSuiteSpan.context()._traceId,
|
|
77
|
+
suiteId: this.testSuiteSpan.context()._spanId,
|
|
78
78
|
files: relativeCoverageFiles
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -17,7 +17,9 @@ const {
|
|
|
17
17
|
TEST_COMMAND,
|
|
18
18
|
TEST_MODULE,
|
|
19
19
|
TEST_SOURCE_START,
|
|
20
|
-
finishAllTraceSpans
|
|
20
|
+
finishAllTraceSpans,
|
|
21
|
+
getCoveredFilenamesFromCoverage,
|
|
22
|
+
getTestSuitePath
|
|
21
23
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
22
24
|
|
|
23
25
|
const TEST_FRAMEWORK_NAME = 'cypress'
|
|
@@ -52,6 +54,13 @@ function getCypressVersion (details) {
|
|
|
52
54
|
return ''
|
|
53
55
|
}
|
|
54
56
|
|
|
57
|
+
function getRootDir (details) {
|
|
58
|
+
if (details && details.config) {
|
|
59
|
+
return details.config.repoRoot || details.config.projectRoot || process.cwd()
|
|
60
|
+
}
|
|
61
|
+
return process.cwd()
|
|
62
|
+
}
|
|
63
|
+
|
|
55
64
|
function getCypressCommand (details) {
|
|
56
65
|
if (!details) {
|
|
57
66
|
return TEST_FRAMEWORK_NAME
|
|
@@ -91,10 +100,12 @@ module.exports = (on, config) => {
|
|
|
91
100
|
let testSuiteSpan = null
|
|
92
101
|
let command = null
|
|
93
102
|
let frameworkVersion
|
|
103
|
+
let rootDir
|
|
94
104
|
|
|
95
105
|
on('before:run', (details) => {
|
|
96
106
|
const childOf = getTestParentSpan(tracer)
|
|
97
107
|
|
|
108
|
+
rootDir = getRootDir(details)
|
|
98
109
|
command = getCypressCommand(details)
|
|
99
110
|
frameworkVersion = getCypressVersion(details)
|
|
100
111
|
|
|
@@ -132,9 +143,15 @@ module.exports = (on, config) => {
|
|
|
132
143
|
}
|
|
133
144
|
|
|
134
145
|
return new Promise(resolve => {
|
|
135
|
-
tracer._tracer._exporter.
|
|
136
|
-
|
|
137
|
-
|
|
146
|
+
if (tracer._tracer._exporter.flush) {
|
|
147
|
+
tracer._tracer._exporter.flush(() => {
|
|
148
|
+
resolve(null)
|
|
149
|
+
})
|
|
150
|
+
} else {
|
|
151
|
+
tracer._tracer._exporter._writer.flush(() => {
|
|
152
|
+
resolve(null)
|
|
153
|
+
})
|
|
154
|
+
}
|
|
138
155
|
})
|
|
139
156
|
})
|
|
140
157
|
on('task', {
|
|
@@ -153,9 +170,9 @@ module.exports = (on, config) => {
|
|
|
153
170
|
})
|
|
154
171
|
return null
|
|
155
172
|
},
|
|
156
|
-
'dd:testSuiteFinish': (
|
|
173
|
+
'dd:testSuiteFinish': (stats) => {
|
|
157
174
|
if (testSuiteSpan) {
|
|
158
|
-
const status = getSuiteStatus(
|
|
175
|
+
const status = getSuiteStatus(stats)
|
|
159
176
|
testSuiteSpan.setTag(TEST_STATUS, status)
|
|
160
177
|
testSuiteSpan.finish()
|
|
161
178
|
testSuiteSpan = null
|
|
@@ -204,9 +221,22 @@ module.exports = (on, config) => {
|
|
|
204
221
|
}
|
|
205
222
|
return activeSpan ? activeSpan.context().toTraceId() : null
|
|
206
223
|
},
|
|
207
|
-
'dd:afterEach': (test) => {
|
|
224
|
+
'dd:afterEach': ({ test, coverage }) => {
|
|
208
225
|
const { state, error, isRUMActive, testSourceLine } = test
|
|
209
226
|
if (activeSpan) {
|
|
227
|
+
if (coverage && tracer._tracer._exporter.exportCoverage) {
|
|
228
|
+
const coverageFiles = getCoveredFilenamesFromCoverage(coverage)
|
|
229
|
+
const relativeCoverageFiles = coverageFiles.map(file => getTestSuitePath(file, rootDir))
|
|
230
|
+
const { _traceId, _spanId } = testSuiteSpan.context()
|
|
231
|
+
const formattedCoverage = {
|
|
232
|
+
sessionId: _traceId,
|
|
233
|
+
suiteId: _spanId,
|
|
234
|
+
testId: activeSpan.context()._spanId,
|
|
235
|
+
files: relativeCoverageFiles
|
|
236
|
+
}
|
|
237
|
+
tracer._tracer._exporter.exportCoverage(formattedCoverage)
|
|
238
|
+
}
|
|
239
|
+
|
|
210
240
|
activeSpan.setTag(TEST_STATUS, CYPRESS_STATUS_TO_TEST_STATUS[state])
|
|
211
241
|
if (error) {
|
|
212
242
|
activeSpan.setTag('error', error)
|
|
@@ -4,15 +4,16 @@ const ClientPlugin = require('../../dd-trace/src/plugins/client')
|
|
|
4
4
|
|
|
5
5
|
class GoogleCloudPubsubClientPlugin extends ClientPlugin {
|
|
6
6
|
static get id () { return 'google-cloud-pubsub' }
|
|
7
|
+
static get type () { return 'messaging' }
|
|
7
8
|
static get operation () { return 'request' }
|
|
8
9
|
|
|
9
10
|
start ({ request, api, projectId }) {
|
|
10
11
|
if (api === 'publish') return
|
|
11
12
|
|
|
12
|
-
this.startSpan(
|
|
13
|
-
service: this.config.service ||
|
|
13
|
+
this.startSpan(this.operationName(), {
|
|
14
|
+
service: this.config.service || this.serviceName(),
|
|
14
15
|
resource: [api, request.name].filter(x => x).join(' '),
|
|
15
|
-
kind:
|
|
16
|
+
kind: this.constructor.kind,
|
|
16
17
|
meta: {
|
|
17
18
|
'pubsub.method': api,
|
|
18
19
|
'gcloud.project_id': projectId
|
|
@@ -11,11 +11,9 @@ class GoogleCloudPubsubConsumerPlugin extends ConsumerPlugin {
|
|
|
11
11
|
const topic = subscription.metadata && subscription.metadata.topic
|
|
12
12
|
const childOf = this.tracer.extract('text_map', message.attributes) || null
|
|
13
13
|
|
|
14
|
-
this.startSpan(
|
|
14
|
+
this.startSpan({
|
|
15
15
|
childOf,
|
|
16
|
-
service: this.config.service,
|
|
17
16
|
resource: topic,
|
|
18
|
-
kind: 'consumer',
|
|
19
17
|
type: 'worker',
|
|
20
18
|
meta: {
|
|
21
19
|
'gcloud.project_id': subscription.pubsub.projectId,
|
|
@@ -11,10 +11,8 @@ class GoogleCloudPubsubProducerPlugin extends ProducerPlugin {
|
|
|
11
11
|
|
|
12
12
|
const messages = request.messages || []
|
|
13
13
|
const topic = request.topic
|
|
14
|
-
const span = this.startSpan(
|
|
15
|
-
service: this.config.service || `${this.tracer._service}-pubsub`,
|
|
14
|
+
const span = this.startSpan({ // TODO: rename
|
|
16
15
|
resource: `${api} ${topic}`,
|
|
17
|
-
kind: 'producer',
|
|
18
16
|
meta: {
|
|
19
17
|
'gcloud.project_id': projectId,
|
|
20
18
|
'pubsub.method': api, // TODO: remove
|
|
@@ -118,8 +118,8 @@ class JestPlugin extends CiPlugin {
|
|
|
118
118
|
|
|
119
119
|
this.addSub('ci:jest:worker-report:coverage', data => {
|
|
120
120
|
const formattedCoverages = JSON.parse(data).map(coverage => ({
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
sessionId: id(coverage.sessionId),
|
|
122
|
+
suiteId: id(coverage.suiteId),
|
|
123
123
|
files: coverage.files
|
|
124
124
|
}))
|
|
125
125
|
formattedCoverages.forEach(formattedCoverage => {
|
|
@@ -150,9 +150,10 @@ class JestPlugin extends CiPlugin {
|
|
|
150
150
|
* fetching the ITR config.
|
|
151
151
|
*/
|
|
152
152
|
this.addSub('ci:jest:test-suite:code-coverage', (coverageFiles) => {
|
|
153
|
+
const { _traceId, _spanId } = this.testSuiteSpan.context()
|
|
153
154
|
const formattedCoverage = {
|
|
154
|
-
|
|
155
|
-
|
|
155
|
+
sessionId: _traceId,
|
|
156
|
+
suiteId: _spanId,
|
|
156
157
|
files: coverageFiles
|
|
157
158
|
}
|
|
158
159
|
this.tracer._exporter.exportCoverage(formattedCoverage)
|
|
@@ -8,12 +8,9 @@ class KafkajsConsumerPlugin extends ConsumerPlugin {
|
|
|
8
8
|
|
|
9
9
|
start ({ topic, partition, message }) {
|
|
10
10
|
const childOf = extract(this.tracer, message.headers)
|
|
11
|
-
|
|
12
|
-
this.startSpan('kafka.consume', {
|
|
11
|
+
this.startSpan({
|
|
13
12
|
childOf,
|
|
14
|
-
service: this.config.service || `${this.tracer._service}-kafka`,
|
|
15
13
|
resource: topic,
|
|
16
|
-
kind: 'consumer',
|
|
17
14
|
type: 'worker',
|
|
18
15
|
meta: {
|
|
19
16
|
'component': 'kafkajs',
|
|
@@ -7,10 +7,8 @@ class KafkajsProducerPlugin extends ProducerPlugin {
|
|
|
7
7
|
static get operation () { return 'produce' }
|
|
8
8
|
|
|
9
9
|
start ({ topic, messages }) {
|
|
10
|
-
const span = this.startSpan(
|
|
11
|
-
service: this.config.service || `${this.tracer._service}-kafka`,
|
|
10
|
+
const span = this.startSpan({
|
|
12
11
|
resource: topic,
|
|
13
|
-
kind: 'producer',
|
|
14
12
|
meta: {
|
|
15
13
|
'component': 'kafkajs',
|
|
16
14
|
'kafka.topic': topic
|
|
@@ -36,9 +36,11 @@ class MochaPlugin extends CiPlugin {
|
|
|
36
36
|
const relativeCoverageFiles = [...coverageFiles, suiteFile]
|
|
37
37
|
.map(filename => getTestSuitePath(filename, this.sourceRoot))
|
|
38
38
|
|
|
39
|
+
const { _traceId, _spanId } = testSuiteSpan.context()
|
|
40
|
+
|
|
39
41
|
const formattedCoverage = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
sessionId: _traceId,
|
|
43
|
+
suiteId: _spanId,
|
|
42
44
|
files: relativeCoverageFiles
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -19,12 +19,10 @@ class RheaConsumerPlugin extends ConsumerPlugin {
|
|
|
19
19
|
const name = getResourceNameFromMessage(msgObj)
|
|
20
20
|
const childOf = extractTextMap(msgObj, this.tracer)
|
|
21
21
|
|
|
22
|
-
this.startSpan(
|
|
22
|
+
this.startSpan({
|
|
23
23
|
childOf,
|
|
24
|
-
service: this.config.service,
|
|
25
24
|
resource: name,
|
|
26
25
|
type: 'worker',
|
|
27
|
-
kind: 'consumer',
|
|
28
26
|
meta: {
|
|
29
27
|
'component': 'rhea',
|
|
30
28
|
'amqp.link.source.address': name,
|
|
@@ -9,17 +9,13 @@ class RheaProducerPlugin extends ProducerPlugin {
|
|
|
9
9
|
|
|
10
10
|
constructor (...args) {
|
|
11
11
|
super(...args)
|
|
12
|
-
|
|
13
12
|
this.addTraceSub('encode', this.encode.bind(this))
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
start ({ targetAddress, host, port }) {
|
|
17
16
|
const name = targetAddress || 'amq.topic'
|
|
18
|
-
|
|
19
|
-
this.startSpan('amqp.send', {
|
|
20
|
-
service: this.config.service || `${this.tracer._service}-amqp-producer`,
|
|
17
|
+
this.startSpan({
|
|
21
18
|
resource: name,
|
|
22
|
-
kind: 'producer',
|
|
23
19
|
meta: {
|
|
24
20
|
'component': 'rhea',
|
|
25
21
|
'amqp.link.target.address': name,
|
|
@@ -6,10 +6,14 @@ const { storage } = require('../../../../../datadog-core')
|
|
|
6
6
|
const InjectionAnalyzer = require('./injection-analyzer')
|
|
7
7
|
const { PATH_TRAVERSAL } = require('../vulnerabilities')
|
|
8
8
|
|
|
9
|
+
const ignoredOperations = ['dir.close', 'close']
|
|
10
|
+
|
|
9
11
|
class PathTraversalAnalyzer extends InjectionAnalyzer {
|
|
10
12
|
constructor () {
|
|
11
13
|
super(PATH_TRAVERSAL)
|
|
12
14
|
this.addSub('apm:fs:operation:start', obj => {
|
|
15
|
+
if (ignoredOperations.includes(obj.operation)) return
|
|
16
|
+
|
|
13
17
|
const pathArguments = []
|
|
14
18
|
if (obj.dest) {
|
|
15
19
|
pathArguments.push(obj.dest)
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const request = require('../../../exporters/common/request')
|
|
3
3
|
const log = require('../../../log')
|
|
4
|
+
const { safeJSONStringify } = require('../../../exporters/common/util')
|
|
4
5
|
|
|
5
6
|
const { CoverageCIVisibilityEncoder } = require('../../../encode/coverage-ci-visibility')
|
|
6
7
|
const BaseWriter = require('../../../exporters/common/writer')
|
|
7
8
|
|
|
8
|
-
function safeJSONStringify (value) {
|
|
9
|
-
return JSON.stringify(value, (key, value) =>
|
|
10
|
-
key !== 'dd-api-key' ? value : undefined
|
|
11
|
-
)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
9
|
class Writer extends BaseWriter {
|
|
15
10
|
constructor ({ url, evpProxyPrefix = '' }) {
|
|
16
11
|
super(...arguments)
|
|
@@ -34,7 +29,7 @@ class Writer extends BaseWriter {
|
|
|
34
29
|
if (this._evpProxyPrefix) {
|
|
35
30
|
options.path = `${this._evpProxyPrefix}/api/v2/citestcov`
|
|
36
31
|
delete options.headers['dd-api-key']
|
|
37
|
-
options.headers['X-Datadog-EVP-Subdomain'] = '
|
|
32
|
+
options.headers['X-Datadog-EVP-Subdomain'] = 'citestcov-intake'
|
|
38
33
|
}
|
|
39
34
|
|
|
40
35
|
log.debug(() => `Request to the intake: ${safeJSONStringify(options)}`)
|
|
@@ -17,7 +17,7 @@ class AgentlessCiVisibilityExporter extends CiVisibilityExporter {
|
|
|
17
17
|
this._url = url || new URL(`https://citestcycle-intake.${site}`)
|
|
18
18
|
this._writer = new Writer({ url: this._url, tags })
|
|
19
19
|
|
|
20
|
-
this._coverageUrl = url || new URL(`https://
|
|
20
|
+
this._coverageUrl = url || new URL(`https://citestcov-intake.${site}`)
|
|
21
21
|
this._coverageWriter = new CoverageWriter({ url: this._coverageUrl })
|
|
22
22
|
|
|
23
23
|
this._apiUrl = url || new URL(`https://api.${site}`)
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const request = require('../../../exporters/common/request')
|
|
3
|
+
const { safeJSONStringify } = require('../../../exporters/common/util')
|
|
3
4
|
const log = require('../../../log')
|
|
4
5
|
|
|
5
6
|
const { AgentlessCiVisibilityEncoder } = require('../../../encode/agentless-ci-visibility')
|
|
6
7
|
const BaseWriter = require('../../../exporters/common/writer')
|
|
7
8
|
|
|
8
|
-
function safeJSONStringify (value) {
|
|
9
|
-
return JSON.stringify(value, (key, value) =>
|
|
10
|
-
key !== 'dd-api-key' ? value : undefined
|
|
11
|
-
)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
9
|
class Writer extends BaseWriter {
|
|
15
10
|
constructor ({ url, tags, evpProxyPrefix = '' }) {
|
|
16
11
|
super(...arguments)
|
|
@@ -36,6 +36,22 @@ function safeJsonParse (input) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
const namingVersions = ['v0', 'v1']
|
|
40
|
+
const defaultNamingVersion = 'v0'
|
|
41
|
+
|
|
42
|
+
function validateNamingVersion (versionString) {
|
|
43
|
+
if (!versionString) {
|
|
44
|
+
return defaultNamingVersion
|
|
45
|
+
}
|
|
46
|
+
if (!namingVersions.includes(versionString)) {
|
|
47
|
+
log.warn(
|
|
48
|
+
`Unexpected input for config.spanAttributeSchema, picked default ${defaultNamingVersion}`
|
|
49
|
+
)
|
|
50
|
+
return defaultNamingVersion
|
|
51
|
+
}
|
|
52
|
+
return versionString
|
|
53
|
+
}
|
|
54
|
+
|
|
39
55
|
// Shallow clone with property name remapping
|
|
40
56
|
function remapify (input, mappings) {
|
|
41
57
|
if (!input) return
|
|
@@ -273,7 +289,9 @@ class Config {
|
|
|
273
289
|
process.env.DD_TRACE_EXPERIMENTAL_GET_RUM_DATA_ENABLED,
|
|
274
290
|
false
|
|
275
291
|
)
|
|
276
|
-
|
|
292
|
+
const DD_TRACE_SPAN_ATTRIBUTE_SCHEMA = validateNamingVersion(
|
|
293
|
+
process.env.DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
|
|
294
|
+
)
|
|
277
295
|
const DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH = coalesce(
|
|
278
296
|
process.env.DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
|
|
279
297
|
'512'
|
|
@@ -489,6 +507,7 @@ ken|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)
|
|
|
489
507
|
sourceMap: !isFalse(DD_PROFILING_SOURCE_MAP),
|
|
490
508
|
exporters: DD_PROFILING_EXPORTERS
|
|
491
509
|
}
|
|
510
|
+
this.spanAttributeSchema = DD_TRACE_SPAN_ATTRIBUTE_SCHEMA
|
|
492
511
|
this.lookup = options.lookup
|
|
493
512
|
this.startupLogs = isTrue(DD_TRACE_STARTUP_LOGS)
|
|
494
513
|
// Disabled for CI Visibility's agentless
|
|
@@ -26,11 +26,19 @@ class CoverageCIVisibilityEncoder extends AgentEncoder {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
encodeCodeCoverage (bytes, coverage) {
|
|
29
|
-
|
|
29
|
+
if (coverage.testId) {
|
|
30
|
+
this._encodeMapPrefix(bytes, 4)
|
|
31
|
+
} else {
|
|
32
|
+
this._encodeMapPrefix(bytes, 3)
|
|
33
|
+
}
|
|
30
34
|
this._encodeString(bytes, 'test_session_id')
|
|
31
|
-
this._encodeId(bytes, coverage.
|
|
35
|
+
this._encodeId(bytes, coverage.sessionId)
|
|
32
36
|
this._encodeString(bytes, 'test_suite_id')
|
|
33
|
-
this._encodeId(bytes, coverage.
|
|
37
|
+
this._encodeId(bytes, coverage.suiteId)
|
|
38
|
+
if (coverage.testId) {
|
|
39
|
+
this._encodeString(bytes, 'span_id')
|
|
40
|
+
this._encodeId(bytes, coverage.testId)
|
|
41
|
+
}
|
|
34
42
|
this._encodeString(bytes, 'files')
|
|
35
43
|
this._encodeArrayPrefix(bytes, coverage.files)
|
|
36
44
|
for (const filename of coverage.files) {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const request = require('./request')
|
|
4
4
|
const log = require('../../log')
|
|
5
|
+
const { safeJSONStringify } = require('./util')
|
|
5
6
|
|
|
6
7
|
class Writer {
|
|
7
8
|
constructor ({ url }) {
|
|
@@ -25,11 +26,11 @@ class Writer {
|
|
|
25
26
|
|
|
26
27
|
append (payload) {
|
|
27
28
|
if (!request.writable) {
|
|
28
|
-
log.debug(() => `Maximum number of active requests reached. Payload discarded: ${
|
|
29
|
+
log.debug(() => `Maximum number of active requests reached. Payload discarded: ${safeJSONStringify(payload)}`)
|
|
29
30
|
return
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
log.debug(() => `Encoding payload: ${
|
|
33
|
+
log.debug(() => `Encoding payload: ${safeJSONStringify(payload)}`)
|
|
33
34
|
|
|
34
35
|
this._encode(payload)
|
|
35
36
|
}
|
|
@@ -4,6 +4,7 @@ const { channel } = require('../../diagnostics_channel')
|
|
|
4
4
|
const { isFalse } = require('./util')
|
|
5
5
|
const plugins = require('./plugins')
|
|
6
6
|
const log = require('./log')
|
|
7
|
+
const Nomenclature = require('./service-naming')
|
|
7
8
|
|
|
8
9
|
const loadChannel = channel('dd-trace:instrumentation:load')
|
|
9
10
|
|
|
@@ -96,6 +97,7 @@ module.exports = class PluginManager {
|
|
|
96
97
|
// like instrumenter.enable()
|
|
97
98
|
configure (config = {}) {
|
|
98
99
|
this._tracerConfig = config
|
|
100
|
+
Nomenclature.configure(config)
|
|
99
101
|
|
|
100
102
|
for (const name in pluginClasses) {
|
|
101
103
|
this.loadPlugin(name)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const OutboundPlugin = require('./outbound')
|
|
4
4
|
|
|
5
|
-
class ClientPlugin extends
|
|
5
|
+
class ClientPlugin extends OutboundPlugin {
|
|
6
6
|
static get operation () { return 'request' }
|
|
7
|
+
static get kind () { return 'client' }
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
module.exports = ClientPlugin
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const InboundPlugin = require('./inbound')
|
|
4
4
|
|
|
5
|
-
class ConsumerPlugin extends
|
|
5
|
+
class ConsumerPlugin extends InboundPlugin {
|
|
6
6
|
static get operation () { return 'receive' }
|
|
7
|
+
static get kind () { return 'consumer' }
|
|
8
|
+
static get type () { return 'messaging' }
|
|
9
|
+
|
|
10
|
+
startSpan (options) {
|
|
11
|
+
if (!options.service) {
|
|
12
|
+
options.service = this.config.service || this.serviceName()
|
|
13
|
+
}
|
|
14
|
+
if (!options.kind) {
|
|
15
|
+
options.kind = this.constructor.kind
|
|
16
|
+
}
|
|
17
|
+
return super.startSpan(this.operationName(), options)
|
|
18
|
+
}
|
|
7
19
|
}
|
|
8
20
|
|
|
9
21
|
module.exports = ConsumerPlugin
|
|
@@ -4,7 +4,7 @@ const { CLIENT_PORT_KEY } = require('../constants')
|
|
|
4
4
|
const TracingPlugin = require('./tracing')
|
|
5
5
|
|
|
6
6
|
// TODO: Exit span on finish when AsyncResource instances are removed.
|
|
7
|
-
class
|
|
7
|
+
class OutboundPlugin extends TracingPlugin {
|
|
8
8
|
constructor (...args) {
|
|
9
9
|
super(...args)
|
|
10
10
|
|
|
@@ -29,4 +29,4 @@ class OutgoingPlugin extends TracingPlugin {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
module.exports =
|
|
32
|
+
module.exports = OutboundPlugin
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const OutboundPlugin = require('./outbound')
|
|
4
4
|
|
|
5
|
-
class ProducerPlugin extends
|
|
5
|
+
class ProducerPlugin extends OutboundPlugin {
|
|
6
6
|
static get operation () { return 'publish' }
|
|
7
|
+
static get kind () { return 'producer' }
|
|
8
|
+
static get type () { return 'messaging' }
|
|
9
|
+
|
|
10
|
+
startSpan (options) {
|
|
11
|
+
const spanDefaults = {
|
|
12
|
+
kind: this.constructor.kind
|
|
13
|
+
}
|
|
14
|
+
if (!options.service) {
|
|
15
|
+
options.service = this.config.service || this.serviceName()
|
|
16
|
+
}
|
|
17
|
+
Object.keys(spanDefaults).forEach(
|
|
18
|
+
key => {
|
|
19
|
+
if (!options[key]) options[key] = spanDefaults[key]
|
|
20
|
+
}
|
|
21
|
+
)
|
|
22
|
+
return super.startSpan(this.operationName(), options)
|
|
23
|
+
}
|
|
7
24
|
}
|
|
8
25
|
|
|
9
26
|
module.exports = ProducerPlugin
|
|
@@ -4,6 +4,7 @@ const Plugin = require('./plugin')
|
|
|
4
4
|
const { storage } = require('../../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../analytics_sampler')
|
|
6
6
|
const { COMPONENT } = require('../constants')
|
|
7
|
+
const Nomenclature = require('../service-naming')
|
|
7
8
|
|
|
8
9
|
class TracingPlugin extends Plugin {
|
|
9
10
|
constructor (...args) {
|
|
@@ -31,6 +32,16 @@ class TracingPlugin extends Plugin {
|
|
|
31
32
|
return store && store.span
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
serviceName (serviceArgs) {
|
|
36
|
+
const { type, id, kind } = this.constructor
|
|
37
|
+
return Nomenclature.serviceName(type, kind, id, serviceArgs)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
operationName (opNameArgs) {
|
|
41
|
+
const { type, id, kind } = this.constructor
|
|
42
|
+
return Nomenclature.opName(type, kind, id, opNameArgs)
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
configure (config) {
|
|
35
46
|
return super.configure({
|
|
36
47
|
...config,
|
|
@@ -91,8 +91,10 @@ class Config {
|
|
|
91
91
|
Number(DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE), 0)
|
|
92
92
|
const maxHeapExtensionCount = coalesce(options.oomMaxHeapExtensionCount,
|
|
93
93
|
Number(DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT), 0)
|
|
94
|
-
const exportStrategies =
|
|
95
|
-
DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES
|
|
94
|
+
const exportStrategies = oomMonitoringEnabled
|
|
95
|
+
? ensureOOMExportStrategies(coalesce(options.oomExportStrategies, DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES,
|
|
96
|
+
[oomExportStrategies.PROCESS]), this)
|
|
97
|
+
: []
|
|
96
98
|
const exportCommand = oomMonitoringEnabled ? buildExportCommand(this) : undefined
|
|
97
99
|
this.oomMonitoring = {
|
|
98
100
|
enabled: oomMonitoringEnabled,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const { schemaDefinitions } = require('./schemas')
|
|
2
|
+
|
|
3
|
+
const kindMap = {
|
|
4
|
+
messaging: {
|
|
5
|
+
client: 'controlPlane',
|
|
6
|
+
consumer: 'inbound',
|
|
7
|
+
producer: 'outbound'
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class SchemaManager {
|
|
12
|
+
constructor () {
|
|
13
|
+
this.schemas = schemaDefinitions
|
|
14
|
+
this.config = { spanAttributeSchema: 'v0' }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get schema () {
|
|
18
|
+
return this.schemas[this.version]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get version () {
|
|
22
|
+
return this.config.spanAttributeSchema
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
opName (type, kind, plugin, opNameArgs) {
|
|
26
|
+
return this.schema.getOpName(type, kindMap[type][kind], plugin, opNameArgs)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
serviceName (type, kind, plugin, serviceNameArgs) {
|
|
30
|
+
return this.schema.getServiceName(type, kindMap[type][kind], plugin, this.config.service, serviceNameArgs)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
configure (config = {}) {
|
|
34
|
+
this.config = config
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
module.exports = new SchemaManager()
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class SchemaDefinition {
|
|
2
|
+
constructor (schema) {
|
|
3
|
+
this.schema = schema
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
getSchemaItem (type, subType, plugin) {
|
|
7
|
+
const schema = this.schema
|
|
8
|
+
if (schema && schema[type] && schema[type][subType] && schema[type][subType][plugin]) {
|
|
9
|
+
return schema[type][subType][plugin]
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getOpName (type, subType, plugin, opNameArgs) {
|
|
14
|
+
const item = this.getSchemaItem(type, subType, plugin)
|
|
15
|
+
return item.opName(opNameArgs)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
getServiceName (type, subType, plugin, service, serviceNameArgs) {
|
|
19
|
+
const item = this.getSchemaItem(type, subType, plugin)
|
|
20
|
+
return item.serviceName(service, serviceNameArgs)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = SchemaDefinition
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
const SchemaDefinition = require('./definition')
|
|
2
|
+
|
|
3
|
+
function amqpServiceName (service) {
|
|
4
|
+
return `${service}-amqp`
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const schema = {
|
|
8
|
+
messaging: {
|
|
9
|
+
outbound: {
|
|
10
|
+
amqplib: {
|
|
11
|
+
opName: () => 'amqp.command',
|
|
12
|
+
serviceName: amqpServiceName
|
|
13
|
+
},
|
|
14
|
+
amqp10: {
|
|
15
|
+
opName: () => 'amqp.send',
|
|
16
|
+
serviceName: amqpServiceName
|
|
17
|
+
},
|
|
18
|
+
'google-cloud-pubsub': {
|
|
19
|
+
opName: () => 'pubsub.request',
|
|
20
|
+
serviceName: service => `${service}-pubsub`
|
|
21
|
+
},
|
|
22
|
+
kafkajs: {
|
|
23
|
+
opName: () => 'kafka.produce',
|
|
24
|
+
serviceName: service => `${service}-kafka`
|
|
25
|
+
},
|
|
26
|
+
rhea: {
|
|
27
|
+
opName: () => 'amqp.send',
|
|
28
|
+
serviceName: service => `${service}-amqp-producer`
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
inbound: {
|
|
32
|
+
amqplib: {
|
|
33
|
+
opName: () => 'amqp.command',
|
|
34
|
+
serviceName: amqpServiceName
|
|
35
|
+
},
|
|
36
|
+
amqp10: {
|
|
37
|
+
opName: () => 'amqp.receive',
|
|
38
|
+
serviceName: amqpServiceName
|
|
39
|
+
},
|
|
40
|
+
'google-cloud-pubsub': {
|
|
41
|
+
opName: () => 'pubsub.receive',
|
|
42
|
+
serviceName: service => service
|
|
43
|
+
},
|
|
44
|
+
kafkajs: {
|
|
45
|
+
opName: () => 'kafka.consume',
|
|
46
|
+
serviceName: service => `${service}-kafka`
|
|
47
|
+
},
|
|
48
|
+
rhea: {
|
|
49
|
+
opName: () => 'amqp.receive',
|
|
50
|
+
serviceName: service => service
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
controlPlane: {
|
|
54
|
+
amqplib: {
|
|
55
|
+
opName: () => 'amqp.command',
|
|
56
|
+
serviceName: amqpServiceName
|
|
57
|
+
},
|
|
58
|
+
'google-cloud-pubsub': {
|
|
59
|
+
opName: () => 'pubsub.request',
|
|
60
|
+
serviceName: service => `${service}-pubsub`
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = new SchemaDefinition(schema)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const SchemaDefinition = require('./definition')
|
|
2
|
+
|
|
3
|
+
function identityService (service) {
|
|
4
|
+
return service
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const amqpInbound = {
|
|
8
|
+
opName: () => 'amqp.process',
|
|
9
|
+
serviceName: identityService
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const amqpOutbound = {
|
|
13
|
+
opName: () => 'amqp.send',
|
|
14
|
+
serviceName: identityService
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const schema = {
|
|
18
|
+
messaging: {
|
|
19
|
+
outbound: {
|
|
20
|
+
amqplib: amqpOutbound,
|
|
21
|
+
amqp10: amqpOutbound,
|
|
22
|
+
'google-cloud-pubsub': {
|
|
23
|
+
opName: () => 'gcp.pubsub.send',
|
|
24
|
+
serviceName: identityService
|
|
25
|
+
},
|
|
26
|
+
kafkajs: {
|
|
27
|
+
opName: () => 'kafka.send',
|
|
28
|
+
serviceName: identityService
|
|
29
|
+
},
|
|
30
|
+
rhea: amqpOutbound
|
|
31
|
+
},
|
|
32
|
+
inbound: {
|
|
33
|
+
amqplib: amqpInbound,
|
|
34
|
+
amqp10: amqpInbound,
|
|
35
|
+
'google-cloud-pubsub': {
|
|
36
|
+
opName: () => 'gcp.pubsub.process',
|
|
37
|
+
serviceName: identityService
|
|
38
|
+
},
|
|
39
|
+
kafkajs: {
|
|
40
|
+
opName: () => 'kafka.process',
|
|
41
|
+
serviceName: identityService
|
|
42
|
+
},
|
|
43
|
+
rhea: amqpInbound
|
|
44
|
+
},
|
|
45
|
+
controlPlane: {
|
|
46
|
+
amqplib: {
|
|
47
|
+
opName: () => 'amqp.command',
|
|
48
|
+
serviceName: identityService
|
|
49
|
+
},
|
|
50
|
+
'google-cloud-pubsub': {
|
|
51
|
+
opName: () => 'gcp.pubsub.request',
|
|
52
|
+
serviceName: identityService
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = new SchemaDefinition(schema)
|
|
@@ -7,7 +7,7 @@ const { storage } = require('../../datadog-core')
|
|
|
7
7
|
const { isError } = require('./util')
|
|
8
8
|
const { setStartupLogConfig } = require('./startup-log')
|
|
9
9
|
const { ERROR_MESSAGE, ERROR_TYPE, ERROR_STACK } = require('../../dd-trace/src/constants')
|
|
10
|
-
const {
|
|
10
|
+
const { DD_MAJOR } = require('../../../version')
|
|
11
11
|
|
|
12
12
|
const SPAN_TYPE = tags.SPAN_TYPE
|
|
13
13
|
const RESOURCE_NAME = tags.RESOURCE_NAME
|
|
@@ -27,7 +27,7 @@ class DatadogTracer extends Tracer {
|
|
|
27
27
|
childOf: this.scope().active()
|
|
28
28
|
}, options)
|
|
29
29
|
|
|
30
|
-
if (!options.childOf && options.orphanable === false &&
|
|
30
|
+
if (!options.childOf && options.orphanable === false && DD_MAJOR < 4) {
|
|
31
31
|
return fn(null, () => {})
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -82,7 +82,7 @@ class DatadogTracer extends Tracer {
|
|
|
82
82
|
optionsObj = optionsObj.apply(this, arguments)
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
if (optionsObj && optionsObj.orphanable === false && !tracer.scope().active() &&
|
|
85
|
+
if (optionsObj && optionsObj.orphanable === false && !tracer.scope().active() && DD_MAJOR < 4) {
|
|
86
86
|
return fn.apply(this, arguments)
|
|
87
87
|
}
|
|
88
88
|
|
package/version.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const ddMatches = require('./package.json').version.match(/^(\d+)\.(\d+)\.(\d+)/)
|
|
4
|
+
const nodeMatches = process.versions.node.match(/^(\d+)\.(\d+)\.(\d+)/)
|
|
4
5
|
|
|
5
6
|
module.exports = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
DD_MAJOR: parseInt(ddMatches[1]),
|
|
8
|
+
DD_MINOR: parseInt(ddMatches[2]),
|
|
9
|
+
DD_PATCH: parseInt(ddMatches[3]),
|
|
10
|
+
NODE_MAJOR: parseInt(nodeMatches[1]),
|
|
11
|
+
NODE_MINOR: parseInt(nodeMatches[2]),
|
|
12
|
+
NODE_PATCH: parseInt(nodeMatches[3])
|
|
9
13
|
}
|