dd-trace 2.36.0 → 2.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATING.md +158 -0
- package/README.md +18 -11
- package/index.d.ts +7 -0
- package/package.json +4 -4
- package/packages/datadog-instrumentations/src/cookie.js +21 -0
- package/packages/datadog-instrumentations/src/fetch.js +48 -0
- package/packages/datadog-instrumentations/src/grpc/server.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +10 -0
- package/packages/datadog-instrumentations/src/jest.js +2 -3
- package/packages/datadog-instrumentations/src/next.js +2 -2
- package/packages/datadog-instrumentations/src/otel-sdk-trace.js +18 -0
- package/packages/datadog-plugin-fetch/src/index.js +36 -0
- package/packages/datadog-plugin-http/src/client.js +24 -8
- package/packages/datadog-plugin-mysql/src/index.js +2 -11
- package/packages/datadog-plugin-tedious/src/index.js +2 -2
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +3 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/cookie-analyzer.js +52 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/insecure-cookie-analyzer.js +3 -22
- package/packages/dd-trace/src/appsec/iast/analyzers/no-httponly-cookie-analyzer.js +12 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/no-samesite-cookie-analyzer.js +12 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/set-cookies-header-interceptor.js +7 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/sql-injection-analyzer.js +3 -3
- package/packages/dd-trace/src/appsec/iast/analyzers/unvalidated-redirect-analyzer.js +48 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/vulnerability-analyzer.js +3 -3
- package/packages/dd-trace/src/appsec/iast/index.js +9 -2
- package/packages/dd-trace/src/appsec/iast/path-line.js +13 -0
- package/packages/dd-trace/src/appsec/iast/tags.js +6 -0
- package/packages/dd-trace/src/appsec/iast/taint-tracking/index.js +2 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/operations.js +13 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/origin-types.js +5 -1
- package/packages/dd-trace/src/appsec/iast/taint-tracking/plugin.js +24 -4
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -1
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +3 -0
- package/packages/dd-trace/src/appsec/iast/vulnerability-reporter.js +7 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +4 -3
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +5 -2
- package/packages/dd-trace/src/config.js +13 -0
- package/packages/dd-trace/src/external-logger/src/index.js +126 -0
- package/packages/dd-trace/src/external-logger/test/index.spec.js +147 -0
- package/packages/dd-trace/src/lambda/handler.js +3 -15
- package/packages/dd-trace/src/noop/proxy.js +4 -0
- package/packages/dd-trace/src/opentelemetry/context_manager.js +1 -1
- package/packages/dd-trace/src/plugin_manager.js +10 -7
- package/packages/dd-trace/src/plugins/database.js +7 -3
- package/packages/dd-trace/src/plugins/plugin.js +3 -1
- package/packages/dd-trace/src/plugins/util/exec.js +2 -2
- package/packages/dd-trace/src/plugins/util/git.js +51 -24
- package/packages/dd-trace/src/profiling/config.js +2 -0
- package/packages/dd-trace/src/profiling/profiler.js +13 -4
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +24 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +18 -1
- package/packages/dd-trace/src/tracer.js +3 -3
- package/packages/dd-trace/src/util.js +1 -1
- package/version.js +8 -4
package/MIGRATING.md
CHANGED
|
@@ -4,6 +4,164 @@ 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
|
+
|
|
46
|
+
## 2.0 to 3.0
|
|
47
|
+
|
|
48
|
+
### Node 12 is no longer supported
|
|
49
|
+
|
|
50
|
+
Node.js 12 has been EOL since April 2022 and is no longer supported. Generally
|
|
51
|
+
speaking, we highly recommend always keeping Node.js up to date regardless of our
|
|
52
|
+
support policy.
|
|
53
|
+
|
|
54
|
+
### HTTP query string reported by default
|
|
55
|
+
|
|
56
|
+
HTTP query strings are now reported by default as part of the `http.url` tag.
|
|
57
|
+
This change is considered breaking only because there might be sensitive data
|
|
58
|
+
in the query string. A default regular expression based obfuscator is provided
|
|
59
|
+
for common use cases like API keys, but if your use case is not covered, the
|
|
60
|
+
[DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP](https://datadoghq.dev/dd-trace-js/#tracer-settings)
|
|
61
|
+
environment variable can be used to control what is obfuscated, and a value of
|
|
62
|
+
`.*` would redact the query string entirely.
|
|
63
|
+
|
|
64
|
+
### HTTP operation name change
|
|
65
|
+
|
|
66
|
+
The HTTP integration now uses `web.request` for incoming requests and continues
|
|
67
|
+
to use `http.request` for outgoing requests. When using a supported web
|
|
68
|
+
framework like Express, this change will have no effect because the root span
|
|
69
|
+
would already have an operation name override like `express.request`.
|
|
70
|
+
Any [monitor](https://docs.datadoghq.com/monitors/create/types/apm/?tab=apmmetrics)
|
|
71
|
+
on `http.request` for incoming requests should be updated to `web.request`.
|
|
72
|
+
|
|
73
|
+
With this change, both operation names also appear under the main service name
|
|
74
|
+
and are no longer split between the server service name and a separate client
|
|
75
|
+
service name suffixed with `-http-client`.
|
|
76
|
+
|
|
77
|
+
### gRPC operation name change
|
|
78
|
+
|
|
79
|
+
The gRPC integration now uses `grpc.server` for incoming requests and
|
|
80
|
+
`grpc.client` for outgoing requests. Any
|
|
81
|
+
[monitor](https://docs.datadoghq.com/monitors/create/types/apm/?tab=apmmetrics)
|
|
82
|
+
on `grpc.request` should be updated to one of these.
|
|
83
|
+
|
|
84
|
+
With this change, both operation names also appear under the main service name
|
|
85
|
+
and are no longer split between the server service name and a separate client
|
|
86
|
+
service name suffixed with `-http-client`.
|
|
87
|
+
|
|
88
|
+
### Removal of `fs` integration
|
|
89
|
+
|
|
90
|
+
The `fs` integration was removed as it was originally added without an actual
|
|
91
|
+
use case, and it's been problematic ever since. It's noisy, the output is
|
|
92
|
+
confusing when using streams, errors that are handled higher in the stack end up
|
|
93
|
+
being captured, etc.
|
|
94
|
+
|
|
95
|
+
If you had any use for file system instrumentation, please let us know so we can
|
|
96
|
+
provide an alternative.
|
|
97
|
+
|
|
98
|
+
### Scope binding for promises and event emitters
|
|
99
|
+
|
|
100
|
+
It's no longer possible to bind promises using `tracer.scope().bind(promise)` or
|
|
101
|
+
event emitters using `tracer.scope().bind(emitter)`. These were historically
|
|
102
|
+
added mostly for internal use, and changes to context propagation over the years
|
|
103
|
+
made them unnecessary, both internally and externaly. If one of these is used
|
|
104
|
+
anywhere, the call will simply be ignored and no binding will occur.
|
|
105
|
+
|
|
106
|
+
To bind the `then` handler of a promise, bind the function directly directly:
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
promise.then(tracer.scope().bind(handler))
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
To bind all listeners for an event, wrap the call to `emit` directly instead:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
tracer.scope().activate(span, () => {
|
|
116
|
+
emitter.emit('event')
|
|
117
|
+
})
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
To bind individual listeners, bind the listener function directly instead:
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
emitter.on('event', tracer.scope().bind(listener, span))
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Removed APIs
|
|
127
|
+
|
|
128
|
+
The following APIs have been deprecated for a long time and have now been
|
|
129
|
+
completely removed:
|
|
130
|
+
|
|
131
|
+
- `tracer.currentSpan()`
|
|
132
|
+
- `tracer.bindEmitter()`
|
|
133
|
+
|
|
134
|
+
Since these have not been recommended nor publicly documented for years at this
|
|
135
|
+
point, there should be no impact as no application is expected to be using them.
|
|
136
|
+
|
|
137
|
+
### CI Visibility new entrypoints
|
|
138
|
+
|
|
139
|
+
#### Cypress
|
|
140
|
+
|
|
141
|
+
`dd-trace/cypress/plugin` and `dd-trace/cypress/support` are removed, so you won't
|
|
142
|
+
be able to use them for your `cypress` instrumentation. Use `dd-trace/ci/cypress/plugin`
|
|
143
|
+
and `dd-trace/ci/cypress/support` instead for your plugin and support configuration
|
|
144
|
+
respectively.
|
|
145
|
+
|
|
146
|
+
#### Jest
|
|
147
|
+
|
|
148
|
+
The use of `'dd-trace/ci/jest/env'` in [`testEnvironment`](https://jestjs.io/docs/configuration#testenvironment-string)
|
|
149
|
+
is no longer supported.
|
|
150
|
+
To instrument `jest` tests now, add `'-r dd-trace/ci/init'` to the `NODE_OPTIONS` environment
|
|
151
|
+
variable passed to the process running the tests, for example, `NODE_OPTIONS='-r dd-trace/ci/init' yarn test`.
|
|
152
|
+
|
|
153
|
+
#### Mocha
|
|
154
|
+
|
|
155
|
+
The use of `--require dd-trace/ci/init` as a `mocha` flag is no longer supported.
|
|
156
|
+
To instrument `mocha` tests now, add `'-r dd-trace/ci/init'` to the `NODE_OPTIONS` environment
|
|
157
|
+
variable passed to the process running the tests, for example, `NODE_OPTIONS='-r dd-trace/ci/init' yarn test`.
|
|
158
|
+
|
|
159
|
+
#### Cucumber
|
|
160
|
+
|
|
161
|
+
The use of `--require-module dd-trace/ci/init` as a `cucumber-js` flag is no longer supported.
|
|
162
|
+
To instrument `cucumber-js` tests now, add `'-r dd-trace/ci/init'` to the `NODE_OPTIONS` environment
|
|
163
|
+
variable passed to the process running the tests, for example, `NODE_OPTIONS='-r dd-trace/ci/init' yarn test`.
|
|
164
|
+
|
|
7
165
|
## 1.0 to 2.0
|
|
8
166
|
|
|
9
167
|
### Configuration
|
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/index.d.ts
CHANGED
|
@@ -759,6 +759,7 @@ interface Plugins {
|
|
|
759
759
|
"elasticsearch": plugins.elasticsearch;
|
|
760
760
|
"express": plugins.express;
|
|
761
761
|
"fastify": plugins.fastify;
|
|
762
|
+
"fetch": plugins.fetch;
|
|
762
763
|
"fs": plugins.fs;
|
|
763
764
|
"generic-pool": plugins.generic_pool;
|
|
764
765
|
"google-cloud-pubsub": plugins.google_cloud_pubsub;
|
|
@@ -1103,6 +1104,12 @@ declare namespace plugins {
|
|
|
1103
1104
|
*/
|
|
1104
1105
|
interface fastify extends HttpServer {}
|
|
1105
1106
|
|
|
1107
|
+
/**
|
|
1108
|
+
* This plugin automatically instruments the
|
|
1109
|
+
* [fetch](https://nodejs.org/api/globals.html#fetch) global.
|
|
1110
|
+
*/
|
|
1111
|
+
interface fetch extends HttpClient {}
|
|
1112
|
+
|
|
1106
1113
|
/**
|
|
1107
1114
|
* This plugin automatically instruments the
|
|
1108
1115
|
* [fs](https://nodejs.org/api/fs.html) module.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.37.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"test:appsec:ci": "nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" -- npm run test:appsec",
|
|
20
20
|
"test:appsec:plugins": "mocha --colors --exit -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\"",
|
|
21
21
|
"test:appsec:plugins:ci": "yarn services && nyc --no-clean --include \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\" -- npm run test:appsec:plugins",
|
|
22
|
-
"test:trace:core": "tap packages/dd-trace/test/*.spec.js \"packages/dd-trace/test/{ci-visibility,encode,exporters,opentelemetry,opentracing,plugins,telemetry}/**/*.spec.js\"",
|
|
22
|
+
"test:trace:core": "tap packages/dd-trace/test/*.spec.js \"packages/dd-trace/test/{ci-visibility,config,encode,exporters,opentelemetry,opentracing,plugins,telemetry}/**/*.spec.js\"",
|
|
23
23
|
"test:trace:core:ci": "npm run test:trace:core -- --coverage --nyc-arg=--include=\"packages/dd-trace/src/**/*.js\"",
|
|
24
24
|
"test:instrumentations": "mocha --colors -r 'packages/dd-trace/test/setup/mocha.js' 'packages/datadog-instrumentations/test/**/*.spec.js'",
|
|
25
25
|
"test:instrumentations:ci": "nyc --no-clean --include 'packages/datadog-instrumentations/src/**/*.js' -- npm run test:instrumentations",
|
|
@@ -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": "^1.
|
|
71
|
+
"@datadog/native-iast-taint-tracking": "^1.5.0",
|
|
72
72
|
"@datadog/native-metrics": "^1.6.0",
|
|
73
|
-
"@datadog/pprof": "
|
|
73
|
+
"@datadog/pprof": "2.2.3",
|
|
74
74
|
"@datadog/sketches-js": "^2.1.0",
|
|
75
75
|
"@types/node": "<18.13",
|
|
76
76
|
"@opentelemetry/api": "^1.0.0",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { channel, addHook } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const cookieParseCh = channel('datadog:cookie:parse:finish')
|
|
7
|
+
|
|
8
|
+
function wrapParse (originalParse) {
|
|
9
|
+
return function () {
|
|
10
|
+
const cookies = originalParse.apply(this, arguments)
|
|
11
|
+
if (cookieParseCh.hasSubscribers && cookies) {
|
|
12
|
+
cookieParseCh.publish({ cookies })
|
|
13
|
+
}
|
|
14
|
+
return cookies
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
addHook({ name: 'cookie', versions: ['>=0.4'] }, cookie => {
|
|
19
|
+
shimmer.wrap(cookie, 'parse', wrapParse)
|
|
20
|
+
return cookie
|
|
21
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const shimmer = require('../../datadog-shimmer')
|
|
4
|
+
const { channel } = require('./helpers/instrument')
|
|
5
|
+
|
|
6
|
+
const startChannel = channel('apm:fetch:request:start')
|
|
7
|
+
const finishChannel = channel('apm:fetch:request:finish')
|
|
8
|
+
const errorChannel = channel('apm:fetch:request:error')
|
|
9
|
+
|
|
10
|
+
function wrapFetch (fetch, Request) {
|
|
11
|
+
if (typeof fetch !== 'function') return fetch
|
|
12
|
+
|
|
13
|
+
return function (input, init) {
|
|
14
|
+
if (!startChannel.hasSubscribers) return fetch.apply(this, arguments)
|
|
15
|
+
|
|
16
|
+
const req = new Request(input, init)
|
|
17
|
+
const headers = req.headers
|
|
18
|
+
const message = { req, headers }
|
|
19
|
+
|
|
20
|
+
startChannel.publish(message)
|
|
21
|
+
|
|
22
|
+
// Request object is read-only so we need new objects to change headers.
|
|
23
|
+
arguments[0] = message.req
|
|
24
|
+
arguments[1] = { headers: message.headers }
|
|
25
|
+
|
|
26
|
+
return fetch.apply(this, arguments)
|
|
27
|
+
.then(
|
|
28
|
+
res => {
|
|
29
|
+
finishChannel.publish({ req, res })
|
|
30
|
+
|
|
31
|
+
return res
|
|
32
|
+
},
|
|
33
|
+
err => {
|
|
34
|
+
if (err.name !== 'AbortError') {
|
|
35
|
+
errorChannel.publish(err)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
finishChannel.publish({ req })
|
|
39
|
+
|
|
40
|
+
throw err
|
|
41
|
+
}
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (globalThis.fetch) {
|
|
47
|
+
globalThis.fetch = shimmer.wrap(fetch, wrapFetch(fetch, globalThis.Request))
|
|
48
|
+
}
|
|
@@ -107,7 +107,7 @@ function wrapStream (call, requestResource, onCancel) {
|
|
|
107
107
|
function wrapCallback (callback, call, requestResource, parentResource, onCancel) {
|
|
108
108
|
return function (err, value, trailer, flags) {
|
|
109
109
|
requestResource.runInAsyncScope(() => {
|
|
110
|
-
if (err
|
|
110
|
+
if (err) {
|
|
111
111
|
errorChannel.publish(err)
|
|
112
112
|
finishChannel.publish(err)
|
|
113
113
|
} else {
|
|
@@ -14,6 +14,7 @@ module.exports = {
|
|
|
14
14
|
'@koa/router': () => require('../koa'),
|
|
15
15
|
'@node-redis/client': () => require('../redis'),
|
|
16
16
|
'@opensearch-project/opensearch': () => require('../opensearch'),
|
|
17
|
+
'@opentelemetry/sdk-trace-node': () => require('../otel-sdk-trace'),
|
|
17
18
|
'@redis/client': () => require('../redis'),
|
|
18
19
|
'amqp10': () => require('../amqp10'),
|
|
19
20
|
'amqplib': () => require('../amqplib'),
|
|
@@ -25,6 +26,7 @@ module.exports = {
|
|
|
25
26
|
'child_process': () => require('../child-process'),
|
|
26
27
|
'node:child_process': () => require('../child-process'),
|
|
27
28
|
'connect': () => require('../connect'),
|
|
29
|
+
'cookie': () => require('../cookie'),
|
|
28
30
|
'couchbase': () => require('../couchbase'),
|
|
29
31
|
'crypto': () => require('../crypto'),
|
|
30
32
|
'cypress': () => require('../cypress'),
|
|
@@ -7,16 +7,26 @@ const Hook = require('./hook')
|
|
|
7
7
|
const requirePackageJson = require('../../../dd-trace/src/require-package-json')
|
|
8
8
|
const log = require('../../../dd-trace/src/log')
|
|
9
9
|
|
|
10
|
+
const { DD_TRACE_DISABLED_INSTRUMENTATIONS = '' } = process.env
|
|
11
|
+
|
|
10
12
|
const hooks = require('./hooks')
|
|
11
13
|
const instrumentations = require('./instrumentations')
|
|
12
14
|
const names = Object.keys(hooks)
|
|
13
15
|
const pathSepExpr = new RegExp(`\\${path.sep}`, 'g')
|
|
16
|
+
const disabledInstrumentations = new Set(
|
|
17
|
+
DD_TRACE_DISABLED_INSTRUMENTATIONS ? DD_TRACE_DISABLED_INSTRUMENTATIONS.split(',') : []
|
|
18
|
+
)
|
|
14
19
|
|
|
15
20
|
const loadChannel = channel('dd-trace:instrumentation:load')
|
|
16
21
|
|
|
22
|
+
// Globals
|
|
23
|
+
require('../fetch')
|
|
24
|
+
|
|
17
25
|
// TODO: make this more efficient
|
|
18
26
|
|
|
19
27
|
for (const packageName of names) {
|
|
28
|
+
if (disabledInstrumentations.has(packageName)) continue
|
|
29
|
+
|
|
20
30
|
Hook([packageName], (moduleExports, moduleName, moduleBaseDir, moduleVersion) => {
|
|
21
31
|
moduleName = moduleName.replace(pathSepExpr, '/')
|
|
22
32
|
|
|
@@ -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
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { addHook } = require('./helpers/instrument')
|
|
4
|
+
const shimmer = require('../../datadog-shimmer')
|
|
5
|
+
const tracer = require('../../dd-trace')
|
|
6
|
+
|
|
7
|
+
if (process.env.DD_TRACE_OTEL_ENABLED) {
|
|
8
|
+
addHook({
|
|
9
|
+
name: '@opentelemetry/sdk-trace-node',
|
|
10
|
+
file: 'build/src/NodeTracerProvider.js',
|
|
11
|
+
versions: ['*']
|
|
12
|
+
}, (mod) => {
|
|
13
|
+
shimmer.wrap(mod, 'NodeTracerProvider', () => {
|
|
14
|
+
return tracer.TracerProvider
|
|
15
|
+
})
|
|
16
|
+
return mod
|
|
17
|
+
})
|
|
18
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const HttpClientPlugin = require('../../datadog-plugin-http/src/client')
|
|
4
|
+
const { HTTP_HEADERS } = require('../../../ext/formats')
|
|
5
|
+
|
|
6
|
+
class FetchPlugin extends HttpClientPlugin {
|
|
7
|
+
static get id () { return 'fetch' }
|
|
8
|
+
|
|
9
|
+
addTraceSub (eventName, handler) {
|
|
10
|
+
this.addSub(`apm:${this.constructor.id}:${this.operation}:${eventName}`, handler)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
start (message) {
|
|
14
|
+
const req = message.req
|
|
15
|
+
const options = new URL(req.url)
|
|
16
|
+
const headers = options.headers = Object.fromEntries(req.headers.entries())
|
|
17
|
+
|
|
18
|
+
const args = { options }
|
|
19
|
+
|
|
20
|
+
super.start({ args })
|
|
21
|
+
|
|
22
|
+
message.req = new globalThis.Request(req, { headers })
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_inject (span, headers) {
|
|
26
|
+
const carrier = {}
|
|
27
|
+
|
|
28
|
+
this.tracer.inject(span, HTTP_HEADERS, carrier)
|
|
29
|
+
|
|
30
|
+
for (const name in carrier) {
|
|
31
|
+
headers.append(name, carrier[name])
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = FetchPlugin
|
|
@@ -24,15 +24,17 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
24
24
|
this.addSub(`apm:${this.constructor.id}:client:${this.operation}:${eventName}`, handler)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
start ({ args, http }) {
|
|
27
|
+
start ({ args, http = {} }) {
|
|
28
28
|
const store = storage.getStore()
|
|
29
29
|
const options = args.options
|
|
30
|
-
const agent = options.agent || options._defaultAgent || http.globalAgent
|
|
30
|
+
const agent = options.agent || options._defaultAgent || http.globalAgent || {}
|
|
31
31
|
const protocol = options.protocol || agent.protocol || 'http:'
|
|
32
32
|
const hostname = options.hostname || options.host || 'localhost'
|
|
33
33
|
const host = options.port ? `${hostname}:${options.port}` : hostname
|
|
34
|
-
const
|
|
34
|
+
const pathname = options.path || options.pathname
|
|
35
|
+
const path = pathname ? pathname.split(/[?#]/)[0] : '/'
|
|
35
36
|
const uri = `${protocol}//${host}${path}`
|
|
37
|
+
|
|
36
38
|
const allowed = this.config.filter(uri)
|
|
37
39
|
|
|
38
40
|
const method = (options.method || 'GET').toUpperCase()
|
|
@@ -71,9 +73,11 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
71
73
|
finish ({ req, res }) {
|
|
72
74
|
const span = storage.getStore().span
|
|
73
75
|
if (res) {
|
|
74
|
-
|
|
76
|
+
const status = res.status || res.statusCode
|
|
77
|
+
|
|
78
|
+
span.setTag(HTTP_STATUS_CODE, status)
|
|
75
79
|
|
|
76
|
-
if (!this.config.validateStatus(
|
|
80
|
+
if (!this.config.validateStatus(status)) {
|
|
77
81
|
span.setTag('error', 1)
|
|
78
82
|
}
|
|
79
83
|
|
|
@@ -106,8 +110,14 @@ class HttpClientPlugin extends ClientPlugin {
|
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
function addResponseHeaders (res, span, config) {
|
|
113
|
+
if (!res.headers) return
|
|
114
|
+
|
|
115
|
+
const headers = typeof res.headers.entries === 'function'
|
|
116
|
+
? Object.fromEntries(res.headers.entries())
|
|
117
|
+
: res.headers
|
|
118
|
+
|
|
109
119
|
config.headers.forEach(key => {
|
|
110
|
-
const value =
|
|
120
|
+
const value = headers[key]
|
|
111
121
|
|
|
112
122
|
if (value) {
|
|
113
123
|
span.setTag(`${HTTP_RESPONSE_HEADERS}.${key}`, value)
|
|
@@ -116,8 +126,12 @@ function addResponseHeaders (res, span, config) {
|
|
|
116
126
|
}
|
|
117
127
|
|
|
118
128
|
function addRequestHeaders (req, span, config) {
|
|
129
|
+
const headers = req.headers && typeof req.headers.entries === 'function'
|
|
130
|
+
? Object.fromEntries(req.headers.entries())
|
|
131
|
+
: req.headers || req.getHeaders()
|
|
132
|
+
|
|
119
133
|
config.headers.forEach(key => {
|
|
120
|
-
const value =
|
|
134
|
+
const value = headers[key]
|
|
121
135
|
|
|
122
136
|
if (value) {
|
|
123
137
|
span.setTag(`${HTTP_REQUEST_HEADERS}.${key}`, Array.isArray(value) ? value.toString() : value)
|
|
@@ -193,7 +207,9 @@ function hasAmazonSignature (options) {
|
|
|
193
207
|
}
|
|
194
208
|
}
|
|
195
209
|
|
|
196
|
-
|
|
210
|
+
const search = options.search || options.path
|
|
211
|
+
|
|
212
|
+
return search && search.toLowerCase().indexOf('x-amz-signature=') !== -1
|
|
197
213
|
}
|
|
198
214
|
|
|
199
215
|
function getServiceName (tracer, config, options) {
|
|
@@ -8,9 +8,8 @@ class MySQLPlugin extends DatabasePlugin {
|
|
|
8
8
|
static get system () { return 'mysql' }
|
|
9
9
|
|
|
10
10
|
start (payload) {
|
|
11
|
-
const service =
|
|
12
|
-
|
|
13
|
-
this.startSpan(`${this.system}.query`, {
|
|
11
|
+
const service = this.serviceName(this.config, payload.conf, this.system)
|
|
12
|
+
this.startSpan(this.operationName(), {
|
|
14
13
|
service,
|
|
15
14
|
resource: payload.sql,
|
|
16
15
|
type: 'sql',
|
|
@@ -27,12 +26,4 @@ class MySQLPlugin extends DatabasePlugin {
|
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
function getServiceName (config, dbConfig) {
|
|
31
|
-
if (typeof config.service === 'function') {
|
|
32
|
-
return config.service(dbConfig)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return config.service
|
|
36
|
-
}
|
|
37
|
-
|
|
38
29
|
module.exports = MySQLPlugin
|
|
@@ -9,8 +9,8 @@ class TediousPlugin extends DatabasePlugin {
|
|
|
9
9
|
static get system () { return 'mssql' }
|
|
10
10
|
|
|
11
11
|
start ({ queryOrProcedure, connectionConfig }) {
|
|
12
|
-
this.startSpan(
|
|
13
|
-
service: this.config.
|
|
12
|
+
this.startSpan(this.operationName(), {
|
|
13
|
+
service: this.serviceName(this.config, this.system),
|
|
14
14
|
resource: queryOrProcedure,
|
|
15
15
|
type: 'sql',
|
|
16
16
|
kind: 'client',
|
|
@@ -4,9 +4,12 @@ module.exports = {
|
|
|
4
4
|
'COMMAND_INJECTION_ANALYZER': require('./command-injection-analyzer'),
|
|
5
5
|
'INSECURE_COOKIE_ANALYZER': require('./insecure-cookie-analyzer'),
|
|
6
6
|
'LDAP_ANALYZER': require('./ldap-injection-analyzer'),
|
|
7
|
+
'NO_HTTPONLY_COOKIE_ANALYZER': require('./no-httponly-cookie-analyzer'),
|
|
8
|
+
'NO_SAMESITE_COOKIE_ANALYZER': require('./no-samesite-cookie-analyzer'),
|
|
7
9
|
'PATH_TRAVERSAL_ANALYZER': require('./path-traversal-analyzer'),
|
|
8
10
|
'SQL_INJECTION_ANALYZER': require('./sql-injection-analyzer'),
|
|
9
11
|
'SSRF': require('./ssrf-analyzer'),
|
|
12
|
+
'UNVALIDATED_REDIRECT_ANALYZER': require('./unvalidated-redirect-analyzer'),
|
|
10
13
|
'WEAK_CIPHER_ANALYZER': require('./weak-cipher-analyzer'),
|
|
11
14
|
'WEAK_HASH_ANALYZER': require('./weak-hash-analyzer')
|
|
12
15
|
}
|