newrelic 12.14.0 → 12.16.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/NEWS.md +96 -43
- package/README.md +36 -31
- package/api.js +2 -0
- package/lib/agent.js +5 -5
- package/lib/context-manager/async-local-context-manager.js +4 -2
- package/lib/context-manager/context.js +15 -48
- package/lib/errors/error-collector.js +3 -2
- package/lib/feature_flags.js +2 -1
- package/lib/instrumentation/kafkajs/consumer.js +1 -1
- package/lib/instrumentation/undici.js +2 -1
- package/lib/otel/attr-reconciler.js +52 -0
- package/lib/otel/constants.js +50 -3
- package/lib/otel/context.js +89 -0
- package/lib/otel/fake-span.js +28 -0
- package/lib/otel/segments/consumer.js +12 -12
- package/lib/otel/segments/database.js +1 -0
- package/lib/otel/segments/http-external.js +33 -3
- package/lib/otel/segments/internal.js +1 -0
- package/lib/otel/segments/producer.js +1 -0
- package/lib/otel/segments/server.js +7 -2
- package/lib/otel/segments/utils.js +30 -0
- package/lib/otel/setup.js +7 -8
- package/lib/otel/span-key-interceptor.js +30 -0
- package/lib/otel/span-processor.js +216 -85
- package/lib/otel/trace-propagator.js +12 -16
- package/lib/serverless/aws-lambda.js +119 -37
- package/lib/shim/message-shim/subscribe-consume.js +0 -1
- package/lib/spans/helpers.js +69 -0
- package/lib/spans/span-event.js +15 -17
- package/lib/spans/streaming-span-event.js +11 -16
- package/lib/{sampler.js → system-metrics-sampler.js} +11 -10
- package/lib/transaction/index.js +12 -53
- package/lib/transaction/trace/segment.js +6 -2
- package/lib/transaction/tracecontext.js +13 -6
- package/lib/transaction/tracer/index.js +18 -2
- package/package.json +1 -1
package/NEWS.md
CHANGED
|
@@ -1,46 +1,99 @@
|
|
|
1
|
-
### v12.
|
|
2
|
-
|
|
3
|
-
#### Features
|
|
4
|
-
|
|
5
|
-
* Added support for
|
|
6
|
-
* Added
|
|
7
|
-
* Added
|
|
8
|
-
|
|
9
|
-
####
|
|
10
|
-
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
####
|
|
32
|
-
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
* Updated
|
|
38
|
-
|
|
39
|
-
####
|
|
40
|
-
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
1
|
+
### v12.16.0 (2025-03-17)
|
|
2
|
+
|
|
3
|
+
#### Features
|
|
4
|
+
|
|
5
|
+
* Added support for response streaming Lambda functions ([#2981](https://github.com/newrelic/node-newrelic/pull/2981)) ([61dbbf9](https://github.com/newrelic/node-newrelic/commit/61dbbf9b4a6cf69f5378387fc9c17c31671e9da4))
|
|
6
|
+
* Added AWS entity linking segment attributes for otel bridge ([#2978](https://github.com/newrelic/node-newrelic/pull/2978)) ([6bf1ccc](https://github.com/newrelic/node-newrelic/commit/6bf1ccc657a955b4064a7a3a473bf24948d4ff56))
|
|
7
|
+
* Added error handling on transactions for otel spans ([#2985](https://github.com/newrelic/node-newrelic/pull/2985)) ([4e61e09](https://github.com/newrelic/node-newrelic/commit/4e61e0935394744345c39f6b581ee86e66d0f82c))
|
|
8
|
+
|
|
9
|
+
#### Code refactoring
|
|
10
|
+
|
|
11
|
+
* Updated span event generation to assign the appropriate `span.kind` based on the segment name ([#2976](https://github.com/newrelic/node-newrelic/pull/2976)) ([697b17e](https://github.com/newrelic/node-newrelic/commit/697b17e0553111aa494d08bc33eb7043cdfa8ca6))
|
|
12
|
+
|
|
13
|
+
#### Documentation
|
|
14
|
+
|
|
15
|
+
* Updated compatibility report ([#2988](https://github.com/newrelic/node-newrelic/pull/2988)) ([ed17a6d](https://github.com/newrelic/node-newrelic/commit/ed17a6df1152a8e54cb8c8570fec0015990a4247)
|
|
16
|
+
|
|
17
|
+
#### Miscellaneous chores
|
|
18
|
+
|
|
19
|
+
* Clarified supported next.js middleware versions in docs ([#2984](https://github.com/newrelic/node-newrelic/pull/2984)) ([15cb454](https://github.com/newrelic/node-newrelic/commit/15cb454f9cc38ccc22089d62aaeea54713159aa7))
|
|
20
|
+
* Clarified system metrics sampler naming ([#2987](https://github.com/newrelic/node-newrelic/pull/2987)) ([8647d43](https://github.com/newrelic/node-newrelic/commit/8647d43f097d6d3d68a372824d9feb325604be96))
|
|
21
|
+
* Refactored loops to be simpler ([#2990](https://github.com/newrelic/node-newrelic/pull/2990)) ([79fb8e9](https://github.com/newrelic/node-newrelic/commit/79fb8e90802954b617c1c00aecc866aa065aee12))
|
|
22
|
+
* Removed unused transaction method ([#2986](https://github.com/newrelic/node-newrelic/pull/2986)) ([cb4e2f7](https://github.com/newrelic/node-newrelic/commit/cb4e2f7a8b84adb6d744a2083b083c92e306fbd5))
|
|
23
|
+
* Reverted restriction in NestJS versioned tests ([#2979](https://github.com/newrelic/node-newrelic/pull/2979)) ([ffddcab](https://github.com/newrelic/node-newrelic/commit/ffddcab6d77bfc10c0df9cbfa724bc1c8f5fb251))
|
|
24
|
+
|
|
25
|
+
#### Tests
|
|
26
|
+
|
|
27
|
+
* Fixed fastify assertions around span kind while running security agent ([#2983](https://github.com/newrelic/node-newrelic/pull/2983)) ([c641645](https://github.com/newrelic/node-newrelic/commit/c6416451f1fa6126b7dfd59f6b9267f9d2188ad0))
|
|
28
|
+
|
|
29
|
+
### v12.15.0 (2025-03-03)
|
|
30
|
+
|
|
31
|
+
#### Features
|
|
32
|
+
|
|
33
|
+
* Allowed undici error reporting to be disabled with feature flag `undici_error_tracking` ([#2956](https://github.com/newrelic/node-newrelic/pull/2956)) ([6278107](https://github.com/newrelic/node-newrelic/commit/6278107727678c8b45769190c6972c33057067e5))
|
|
34
|
+
* Thanks for your contribution @Voziv :tada:
|
|
35
|
+
* Added ability to propagate traceparent and tracestate on incoming server/consumer spans and outgoing client http and producer spans ([#2958](https://github.com/newrelic/node-newrelic/pull/2958)) ([258ad7d](https://github.com/newrelic/node-newrelic/commit/258ad7de7751df59cf6d68334e342f751bb3a934))
|
|
36
|
+
* Added server span transaction naming fallback to the url.path ([#2966](https://github.com/newrelic/node-newrelic/pull/2966)) ([770bf6f](https://github.com/newrelic/node-newrelic/commit/770bf6fd6ce26642e3fe08b2c1557dd826270516))
|
|
37
|
+
* Updated Context class to ensure bi-directional context propagation with opentelemetry bridge ([#2962](https://github.com/newrelic/node-newrelic/pull/2962)) ([dfeec5a](https://github.com/newrelic/node-newrelic/commit/dfeec5a0443723e7f799db4b9ea7bf4aed5b3bcc))
|
|
38
|
+
|
|
39
|
+
#### Code refactoring
|
|
40
|
+
|
|
41
|
+
* Separated context classes for agent in standard and opentelemetry bridge mode ([#2967](https://github.com/newrelic/node-newrelic/pull/2967)) ([d11c071](https://github.com/newrelic/node-newrelic/commit/d11c071be2504ef442e5aa19fed769ca7a20ceb5))
|
|
42
|
+
|
|
43
|
+
#### Documentation
|
|
44
|
+
|
|
45
|
+
* Updated compatibility report ([#2973](https://github.com/newrelic/node-newrelic/pull/2973)) ([7106c81](https://github.com/newrelic/node-newrelic/commit/7106c818b7add3220d256646cd816dee64efb80a))
|
|
46
|
+
|
|
47
|
+
#### Miscellaneous chores
|
|
48
|
+
|
|
49
|
+
* Added consumer attribute reconciliation ([#2957](https://github.com/newrelic/node-newrelic/pull/2957)) ([8943672](https://github.com/newrelic/node-newrelic/commit/894367239e5e8050da0a38347b81d7186cac0a1f))
|
|
50
|
+
* Added http external span attributes ([#2955](https://github.com/newrelic/node-newrelic/pull/2955)) ([ef697a5](https://github.com/newrelic/node-newrelic/commit/ef697a505ee23f5c2fb2bbe306e90561e66d75c1))
|
|
51
|
+
* Limit nestjs to enable successful CI ([#2972](https://github.com/newrelic/node-newrelic/pull/2972)) ([e9699cf](https://github.com/newrelic/node-newrelic/commit/e9699cf31ff758ff79f44c470bc5f11630117f1c))
|
|
52
|
+
* Refactored otel attribute reconciling ([#2964](https://github.com/newrelic/node-newrelic/pull/2964)) ([1b5ed2c](https://github.com/newrelic/node-newrelic/commit/1b5ed2c2f7c78cb413603124757b9b1c3412ab0a))
|
|
53
|
+
|
|
54
|
+
### v12.14.0 (2025-02-18)
|
|
55
|
+
|
|
56
|
+
#### Features
|
|
57
|
+
|
|
58
|
+
* Added support for region-prefixed Bedrock models ([#2947](https://github.com/newrelic/node-newrelic/pull/2947)) ([6acf535](https://github.com/newrelic/node-newrelic/commit/6acf5354d1e7f6786da88c0078699e82a714551d))
|
|
59
|
+
* Added attribute reconciliation for message producer spans ([#2942](https://github.com/newrelic/node-newrelic/pull/2942)) ([a9ba396](https://github.com/newrelic/node-newrelic/commit/a9ba39613c78b89c047ca35a218c2eedbb01e3d2))
|
|
60
|
+
* Added timeslice metrics for synthesized consumer segments ([#2938](https://github.com/newrelic/node-newrelic/pull/2938)) ([acfe953](https://github.com/newrelic/node-newrelic/commit/acfe953cf7a656fafb69104384c72f94ddc13000))
|
|
61
|
+
|
|
62
|
+
#### Bug fixes
|
|
63
|
+
|
|
64
|
+
* Fixed queueing of logs from child loggers ([#2945](https://github.com/newrelic/node-newrelic/pull/2945)) ([888cfe8](https://github.com/newrelic/node-newrelic/commit/888cfe84a1ffaf0287682cc9099a2fa762f7a37f))
|
|
65
|
+
* Fixed undici/fetch instrumentation to properly assign the parent-id portion of the `traceparent` header on outgoing requests to the active http external span id ([#2951](https://github.com/newrelic/node-newrelic/pull/2951)) ([bc714cf](https://github.com/newrelic/node-newrelic/commit/bc714cfa8fe6754abf25eb556b8f804c9982f986))
|
|
66
|
+
* Updated `api.recordLogEvent` to no longer truncate the message key in log event ([#2949](https://github.com/newrelic/node-newrelic/pull/2949)) ([8dd557b](https://github.com/newrelic/node-newrelic/commit/8dd557b4dfca2505b7e9f7f030ab094a6ae8019a))
|
|
67
|
+
* Thanks for your contribution @rChaoz 🎉
|
|
68
|
+
|
|
69
|
+
#### Documentation
|
|
70
|
+
|
|
71
|
+
* Updated compatibility report ([#2948](https://github.com/newrelic/node-newrelic/pull/2948)) ([8e32ed7](https://github.com/newrelic/node-newrelic/commit/8e32ed7d7bc456a0693485e7bdef955c25ead29a))
|
|
72
|
+
|
|
73
|
+
### v12.13.0 (2025-02-12)
|
|
74
|
+
|
|
75
|
+
#### Features
|
|
76
|
+
|
|
77
|
+
* Added timeslice metrics for synthesized server segments ([#2924](https://github.com/newrelic/node-newrelic/pull/2924)) ([f404585](https://github.com/newrelic/node-newrelic/commit/f4045855a1cdbfb74e3217daf8bfa125aa6fe2e4))
|
|
78
|
+
* Added timeslice metrics for synthesized producer segments ([#2939](https://github.com/newrelic/node-newrelic/pull/2939)) ([6832637](https://github.com/newrelic/node-newrelic/commit/68326377dcd23b574abae7c323ff93bc05c525ed))
|
|
79
|
+
* Added timeslice metrics for synthesized database segments ([#2922](https://github.com/newrelic/node-newrelic/pull/2922)) ([8606f78](https://github.com/newrelic/node-newrelic/commit/8606f789772b7651d0c46ad50dad3a1da74e5e9c))
|
|
80
|
+
* Propagate agent root context when opentelemetry `ROOT_CONTEXT` is passed in to trace propagator.([#2940](https://github.com/newrelic/node-newrelic/pull/2940)) ([b85111c](https://github.com/newrelic/node-newrelic/commit/b85111c46797dfbf399faf973e7a3e0ea6bbdc28))
|
|
81
|
+
* Added logic to handle properly naming and ending transactions for server spans.
|
|
82
|
+
* Provided ability to disable instrumentation for core Node.js libraries ([#2927](https://github.com/newrelic/node-newrelic/pull/2927)) ([2d232f1](https://github.com/newrelic/node-newrelic/commit/2d232f16c167e5f84b7b7898a6c5410d9cece55e))
|
|
83
|
+
|
|
84
|
+
#### Bug fixes
|
|
85
|
+
|
|
86
|
+
* Fixed `api.getTraceMetadata` to handle when there is an active transaction but not active segment ([#2944](https://github.com/newrelic/node-newrelic/pull/2944)) ([6db3b4d](https://github.com/newrelic/node-newrelic/commit/6db3b4d53a077a9738dd72d46e1ba1cee0d6af3f))
|
|
87
|
+
|
|
88
|
+
#### Documentation
|
|
89
|
+
|
|
90
|
+
* Updated compatibility report ([#2920](https://github.com/newrelic/node-newrelic/pull/2920)) ([c7ae8be](https://github.com/newrelic/node-newrelic/commit/c7ae8befafa4c91fab6804cd95e20f5a93546ea4))
|
|
91
|
+
|
|
92
|
+
#### Miscellaneous chores
|
|
93
|
+
|
|
94
|
+
* Localized OTEL attribute constants ([#2928](https://github.com/newrelic/node-newrelic/pull/2928)) ([965c41b](https://github.com/newrelic/node-newrelic/commit/965c41b3e64805ac14ae4dd36120b018ec5899f4))
|
|
95
|
+
* Updated import-in-the-middle version ([#2923](https://github.com/newrelic/node-newrelic/pull/2923)) ([aa2781f](https://github.com/newrelic/node-newrelic/commit/aa2781fd9c7bed08d590e33682729a92f21f43a5))
|
|
96
|
+
|
|
44
97
|
### v12.12.0 (2025-02-05)
|
|
45
98
|
|
|
46
99
|
#### Features
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ To use New Relic's Node.js agent entails these three steps, which are described
|
|
|
31
31
|
|
|
32
32
|
3. Now, add your New Relic license key and application/service name to that file:
|
|
33
33
|
|
|
34
|
-
```js
|
|
34
|
+
```js
|
|
35
35
|
/* File: newrelic.js */
|
|
36
36
|
'use strict'
|
|
37
37
|
/**
|
|
@@ -45,30 +45,29 @@ To use New Relic's Node.js agent entails these three steps, which are described
|
|
|
45
45
|
license_key: 'your new relic license key',
|
|
46
46
|
/* ... rest of configuration .. */
|
|
47
47
|
}
|
|
48
|
-
```
|
|
48
|
+
```
|
|
49
49
|
|
|
50
50
|
4. Finally, run your program with the `newrelic` module loaded first by using node's `-r/--require` flag.
|
|
51
51
|
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
```
|
|
52
|
+
```sh
|
|
53
|
+
$ node -r newrelic your-program.js
|
|
54
|
+
```
|
|
55
55
|
|
|
56
|
-
If you cannot control how your program is run, you can load the `newrelic` module _before any other module_ in your program.
|
|
56
|
+
If you cannot control how your program is run, you can load the `newrelic` module _before any other module_ in your program.
|
|
57
57
|
|
|
58
|
-
```js
|
|
58
|
+
```js
|
|
59
59
|
const newrelic = require('newrelic')
|
|
60
60
|
|
|
61
61
|
/* ... the rest of your program ... */
|
|
62
|
-
```
|
|
62
|
+
```
|
|
63
63
|
|
|
64
64
|
## Next.js instrumentation
|
|
65
65
|
**Note**: The minimum supported Next.js version is [12.0.9](https://github.com/vercel/next.js/releases/tag/v12.0.9). If you are using Next.js middleware the minimum supported version is [12.2.0](https://github.com/vercel/next.js/releases/tag/v12.2.0).
|
|
66
66
|
|
|
67
|
-
The New Relic Node.js agent provides instrumentation for Next.js The instrumentation provides telemetry for server-side rendering via [getServerSideProps](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props), [middleware](https://nextjs.org/docs/middleware), and New Relic transaction naming for both page and server requests. It does not provide any instrumentation for actions occurring during build or in client-side code. If you want telemetry data on actions occurring on the client (browser), you can [inject the browser agent](./documentation/nextjs/faqs/browser-agent.md).
|
|
67
|
+
The New Relic Node.js agent provides instrumentation for Next.js The instrumentation provides telemetry for server-side rendering via [`getServerSideProps`](https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props), [middleware](https://nextjs.org/docs/middleware) (limited to Next.js versions [12.2.0](https://github.com/vercel/next.js/releases/tag/v12.2.0) - [13.4.12](https://github.com/vercel/next.js/releases/tag/v13.4.12)), and New Relic transaction naming for both page and server requests. It does not provide any instrumentation for actions occurring during build or in client-side code. If you want telemetry data on actions occurring on the client (browser), you can [inject the browser agent](./documentation/nextjs/faqs/browser-agent.md).
|
|
68
68
|
|
|
69
69
|
Here are documents for more in-depth explanations about [transaction naming](./documentation/nextjs/transactions.md), and [segments/spans](./documentation/nextjs/segments-and-spans.md).
|
|
70
70
|
|
|
71
|
-
|
|
72
71
|
### Setup
|
|
73
72
|
Typically you are running a Next.js app with the `next` cli and you must load the agent via `NODE_OPTIONS`:
|
|
74
73
|
|
|
@@ -102,15 +101,15 @@ The New Relic Node.js agent includes ***_experimental_*** support for ES Modules
|
|
|
102
101
|
|
|
103
102
|
1. If you rely on a configuration file to run the agent, you must rename the file from `newrelic.js` to `newrelic.cjs` so it can be properly loaded. All the contents of the configuration file will behave the same once you rename. See [CommonJS modules in ESM](https://nodejs.org/api/modules.html#enabling) for more details.
|
|
104
103
|
|
|
105
|
-
```sh
|
|
106
|
-
$ mv newrelic.js newrelic.cjs
|
|
107
|
-
```
|
|
104
|
+
```sh
|
|
105
|
+
$ mv newrelic.js newrelic.cjs
|
|
106
|
+
```
|
|
108
107
|
|
|
109
108
|
2. To use the newrelic ESM loader, start your program with node and use the `--experimental-loader` flag and a path to the loader file, like this:
|
|
110
109
|
|
|
111
|
-
```sh
|
|
112
|
-
$ node --experimental-loader newrelic/esm-loader.mjs -r newrelic your-program.js
|
|
113
|
-
```
|
|
110
|
+
```sh
|
|
111
|
+
$ node --experimental-loader newrelic/esm-loader.mjs -r newrelic your-program.js
|
|
112
|
+
```
|
|
114
113
|
|
|
115
114
|
**Note**: Unlike the CommonJS methods listed above, there are no alternatives to running the agent without the `--experimental-loader` flag.
|
|
116
115
|
|
|
@@ -122,11 +121,11 @@ The agent supports adding your own custom instrumentation to ES module applicati
|
|
|
122
121
|
import newrelic from 'newrelic'
|
|
123
122
|
newrelic.instrument({ moduleName: 'parse-json', isEsm: true }, function wrap(shim, parseJson, moduleName) {
|
|
124
123
|
shim.wrap(parseJson.default, function wrapParseJson(shim, orig) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
124
|
+
return function wrappedParseJson() {
|
|
125
|
+
const result = orig.apply(this, arguments)
|
|
126
|
+
result.instrumented = true
|
|
127
|
+
return true
|
|
128
|
+
}
|
|
130
129
|
})
|
|
131
130
|
})
|
|
132
131
|
```
|
|
@@ -151,11 +150,11 @@ For more information on getting started, [check the Node.js docs](https://docs.n
|
|
|
151
150
|
|
|
152
151
|
There are modules that can be installed and configured to accompany the Node.js agent:
|
|
153
152
|
|
|
154
|
-
* [
|
|
153
|
+
* [`@newrelic/apollo-server-plugin`](https://github.com/newrelic/newrelic-node-apollo-server-plugin): New Relic's official Apollo Server plugin for use with the Node.js agent.
|
|
155
154
|
|
|
156
155
|
There are modules included within the Node.js agent to add more instrumentation for 3rd party modules:
|
|
157
156
|
|
|
158
|
-
* [
|
|
157
|
+
* [`@newrelic/native-metrics`](https://github.com/newrelic/node-native-metrics): Provides hooks into the native v8 layer of Node.js to provide metrics to the Node.js agent.
|
|
159
158
|
|
|
160
159
|
## Usage
|
|
161
160
|
|
|
@@ -164,10 +163,10 @@ There are modules included within the Node.js agent to add more instrumentation
|
|
|
164
163
|
The `newrelic` module returns an object with the Node.js agent's API methods attached.
|
|
165
164
|
|
|
166
165
|
```js
|
|
167
|
-
|
|
166
|
+
const newrelic = require('newrelic')
|
|
168
167
|
|
|
169
|
-
|
|
170
|
-
|
|
168
|
+
/* ... */
|
|
169
|
+
newrelic.addCustomAttribute('some-attribute', 'some-value')
|
|
171
170
|
```
|
|
172
171
|
|
|
173
172
|
You can read more about using the API over on the [New Relic documentation](https://docs.newrelic.com/docs/agents/nodejs-agent/api-guides/guide-using-nodejs-agent-api) site.
|
|
@@ -182,12 +181,16 @@ These are the steps to work on core agent features, with more detail below:
|
|
|
182
181
|
|
|
183
182
|
1. [Fork](https://github.com/newrelic/node-newrelic/fork) and clone this GitHub repository:
|
|
184
183
|
|
|
184
|
+
```sh
|
|
185
185
|
$ git clone git@github.com:your-user-name/node-newrelic.git
|
|
186
186
|
$ cd node-newrelic
|
|
187
|
+
```
|
|
187
188
|
|
|
188
189
|
2. Install the project's dependencies:
|
|
189
190
|
|
|
191
|
+
```sh
|
|
190
192
|
$ npm install
|
|
193
|
+
```
|
|
191
194
|
|
|
192
195
|
Then you're all set to start programming.
|
|
193
196
|
|
|
@@ -199,11 +202,13 @@ Then you're all set to start programming.
|
|
|
199
202
|
|
|
200
203
|
Available test suites include:
|
|
201
204
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
205
|
+
```sh
|
|
206
|
+
$ npm run unit
|
|
207
|
+
$ npm run integration
|
|
208
|
+
$ npm run versioned
|
|
209
|
+
$ npm run lint
|
|
210
|
+
$ npm run smoke
|
|
211
|
+
```
|
|
207
212
|
|
|
208
213
|
## Further Reading
|
|
209
214
|
|
package/api.js
CHANGED
|
@@ -992,6 +992,7 @@ API.prototype.startWebTransaction = function startWebTransaction(url, handle) {
|
|
|
992
992
|
transaction: tx,
|
|
993
993
|
parent
|
|
994
994
|
})
|
|
995
|
+
tx.baseSegment.spanKind = 'server'
|
|
995
996
|
const newContext = context.enterSegment({ transaction: tx, segment: tx.baseSegment })
|
|
996
997
|
tx.baseSegment.start()
|
|
997
998
|
|
|
@@ -1101,6 +1102,7 @@ function startBackgroundTransaction(name, group, handle) {
|
|
|
1101
1102
|
parent
|
|
1102
1103
|
})
|
|
1103
1104
|
const newContext = context.enterSegment({ transaction: tx, segment: tx.baseSegment })
|
|
1105
|
+
tx.baseSegment.spanKind = 'server'
|
|
1104
1106
|
tx.baseSegment.partialName = group
|
|
1105
1107
|
tx.baseSegment.start()
|
|
1106
1108
|
|
package/lib/agent.js
CHANGED
|
@@ -21,7 +21,7 @@ const MetricNormalizer = require('./metrics/normalizer')
|
|
|
21
21
|
const MetricAggregator = require('./metrics/metric-aggregator')
|
|
22
22
|
const NAMES = require('./metrics/names')
|
|
23
23
|
const QueryTraceAggregator = require('./db/query-trace-aggregator')
|
|
24
|
-
const
|
|
24
|
+
const systemMetricsSampler = require('./system-metrics-sampler')
|
|
25
25
|
const TransactionTraceAggregator = require('./transaction/trace/aggregator')
|
|
26
26
|
const TransactionEventAggregator = require('./transaction/transaction-event-aggregator')
|
|
27
27
|
const Tracer = require('./transaction/tracer')
|
|
@@ -334,7 +334,7 @@ Agent.prototype.start = function start(callback) {
|
|
|
334
334
|
return process.nextTick(callback)
|
|
335
335
|
}
|
|
336
336
|
|
|
337
|
-
|
|
337
|
+
systemMetricsSampler.start(agent)
|
|
338
338
|
|
|
339
339
|
if (this.config.serverless_mode.enabled) {
|
|
340
340
|
return this._serverlessModeStart(callback)
|
|
@@ -349,7 +349,7 @@ Agent.prototype.start = function start(callback) {
|
|
|
349
349
|
this.healthReporter.setStatus(HealthReporter.STATUS_LICENSE_KEY_MISSING)
|
|
350
350
|
|
|
351
351
|
this.setState('errored')
|
|
352
|
-
|
|
352
|
+
systemMetricsSampler.stop()
|
|
353
353
|
return process.nextTick(function onNextTick() {
|
|
354
354
|
agent.healthReporter.stop(() => {
|
|
355
355
|
callback(new Error('Not starting without license key!'))
|
|
@@ -362,7 +362,7 @@ Agent.prototype.start = function start(callback) {
|
|
|
362
362
|
if (error || response.shouldShutdownRun()) {
|
|
363
363
|
agent.healthReporter.setStatus(HealthReporter.STATUS_CONNECT_ERROR)
|
|
364
364
|
agent.setState('errored')
|
|
365
|
-
|
|
365
|
+
systemMetricsSampler.stop()
|
|
366
366
|
callback(error || new Error('Failed to connect to collector'), response && response.payload)
|
|
367
367
|
return
|
|
368
368
|
}
|
|
@@ -482,7 +482,7 @@ Agent.prototype.stop = function stop(callback) {
|
|
|
482
482
|
|
|
483
483
|
this.harvester.stop()
|
|
484
484
|
|
|
485
|
-
|
|
485
|
+
systemMetricsSampler.stop()
|
|
486
486
|
|
|
487
487
|
this.healthReporter.setStatus(HealthReporter.STATUS_AGENT_SHUTDOWN)
|
|
488
488
|
this.healthReporter.stop(() => {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
const { AsyncLocalStorage } = require('async_hooks')
|
|
9
9
|
const Context = require('./context')
|
|
10
|
+
const OtelContext = require('../otel/context')
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Class for managing state in the agent.
|
|
@@ -18,7 +19,8 @@ const Context = require('./context')
|
|
|
18
19
|
* @class
|
|
19
20
|
*/
|
|
20
21
|
class AsyncLocalContextManager {
|
|
21
|
-
constructor() {
|
|
22
|
+
constructor(isOtelBridgeMode) {
|
|
23
|
+
this.isOtelBridgeMode = isOtelBridgeMode
|
|
22
24
|
this._asyncLocalStorage = new AsyncLocalStorage()
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -28,7 +30,7 @@ class AsyncLocalContextManager {
|
|
|
28
30
|
* @returns {object} The current active context.
|
|
29
31
|
*/
|
|
30
32
|
getContext() {
|
|
31
|
-
return this._asyncLocalStorage.getStore() || new Context()
|
|
33
|
+
return this._asyncLocalStorage.getStore() || (this.isOtelBridgeMode ? new OtelContext() : new Context())
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
/**
|
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
|
-
const { otelSynthesis } = require('../symbols')
|
|
8
7
|
|
|
9
8
|
module.exports = class Context {
|
|
10
|
-
constructor(transaction, segment
|
|
9
|
+
constructor(transaction, segment) {
|
|
11
10
|
this._transaction = transaction
|
|
12
11
|
this._segment = segment
|
|
13
|
-
this._otelCtx = parentContext ? new Map(parentContext) : new Map()
|
|
14
12
|
}
|
|
15
13
|
|
|
16
14
|
get segment() {
|
|
@@ -21,58 +19,27 @@ module.exports = class Context {
|
|
|
21
19
|
return this._transaction
|
|
22
20
|
}
|
|
23
21
|
|
|
24
|
-
enterSegment({ segment, transaction = this._transaction }) {
|
|
25
|
-
return new this.constructor(transaction, segment)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
enterTransaction(transaction) {
|
|
29
|
-
return new this.constructor(transaction, transaction.trace.root)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Required for bridging OTEL data into the agent.
|
|
34
|
-
*
|
|
35
|
-
* @param {string} key Stored entity name to retrieve.
|
|
36
|
-
*
|
|
37
|
-
* @returns {*} The stored value.
|
|
38
|
-
*/
|
|
39
|
-
getValue(key) {
|
|
40
|
-
return this._otelCtx.get(key)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
22
|
/**
|
|
44
|
-
*
|
|
23
|
+
* Constructs a new context from segment about to be bound to context manager
|
|
24
|
+
* along with the current transaction.
|
|
45
25
|
*
|
|
46
|
-
* @param {
|
|
47
|
-
* @param {
|
|
48
|
-
*
|
|
49
|
-
* @returns {
|
|
26
|
+
* @param {object} params to function
|
|
27
|
+
* @param {TraceSegment} params.segment segment to bind to context
|
|
28
|
+
* @param {Transaction} params.transaction active transaction
|
|
29
|
+
* @returns {Context} a newly constructed context
|
|
50
30
|
*/
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (value[otelSynthesis] && value[otelSynthesis].segment && value[otelSynthesis].transaction) {
|
|
55
|
-
const { segment, transaction } = value[otelSynthesis]
|
|
56
|
-
segment.start()
|
|
57
|
-
ctx = new this.constructor(transaction, segment, this._otelCtx)
|
|
58
|
-
} else {
|
|
59
|
-
ctx = new this.constructor(this._transaction, this._segment, this._otelCtx)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
ctx._otelCtx.set(key, value)
|
|
63
|
-
return ctx
|
|
31
|
+
enterSegment({ segment, transaction = this._transaction }) {
|
|
32
|
+
return new this.constructor(transaction, segment)
|
|
64
33
|
}
|
|
65
34
|
|
|
66
35
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* @param {string} key Named value to remove from the store.
|
|
36
|
+
* Constructs a new context from transaction about to be bound to context manager.
|
|
37
|
+
* It uses the trace root segment as the segment in context.
|
|
70
38
|
*
|
|
71
|
-
* @
|
|
39
|
+
* @param {Transaction} transaction transaction to bind to context
|
|
40
|
+
* @returns {Context} a newly constructed context
|
|
72
41
|
*/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
ctx._otelCtx.delete(key)
|
|
76
|
-
return ctx
|
|
42
|
+
enterTransaction(transaction) {
|
|
43
|
+
return new this.constructor(transaction, transaction.trace.root)
|
|
77
44
|
}
|
|
78
45
|
}
|
|
@@ -215,8 +215,9 @@ class ErrorCollector {
|
|
|
215
215
|
* @param {?Transaction} transaction Transaction associated with the error.
|
|
216
216
|
* @param {Error} error The error to be traced.
|
|
217
217
|
* @param {?object} customAttributes Custom attributes associated with the request (optional).
|
|
218
|
+
* @param {object} segment The segment associated with the error (optional). Only used in otel bridge.
|
|
218
219
|
*/
|
|
219
|
-
add(transaction, error, customAttributes) {
|
|
220
|
+
add(transaction, error, customAttributes, segment) {
|
|
220
221
|
if (!error) {
|
|
221
222
|
return
|
|
222
223
|
}
|
|
@@ -236,7 +237,7 @@ class ErrorCollector {
|
|
|
236
237
|
const exception = new Exception({ error, timestamp, customAttributes })
|
|
237
238
|
|
|
238
239
|
if (transaction) {
|
|
239
|
-
transaction.addException(exception)
|
|
240
|
+
transaction.addException(exception, segment)
|
|
240
241
|
} else {
|
|
241
242
|
this.collect(transaction, exception)
|
|
242
243
|
}
|
package/lib/feature_flags.js
CHANGED
|
@@ -14,7 +14,8 @@ exports.prerelease = {
|
|
|
14
14
|
promise_segments: false,
|
|
15
15
|
reverse_naming_rules: false,
|
|
16
16
|
unresolved_promise_cleanup: true,
|
|
17
|
-
kafkajs_instrumentation: false
|
|
17
|
+
kafkajs_instrumentation: false,
|
|
18
|
+
undici_error_tracking: true
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
// flags that are no longer used for released features
|
|
@@ -192,6 +192,7 @@ function requestHeadersHook(shim, { request, response }) {
|
|
|
192
192
|
* @param {Error} params.error error from undici request
|
|
193
193
|
*/
|
|
194
194
|
function endAndRestoreSegment(shim, { request, error }) {
|
|
195
|
+
const { config } = shim.agent
|
|
195
196
|
const activeSegment = request[symbols.segment]
|
|
196
197
|
const parentSegment = request[symbols.parentSegment]
|
|
197
198
|
const tx = request[symbols.transaction]
|
|
@@ -199,7 +200,7 @@ function endAndRestoreSegment(shim, { request, error }) {
|
|
|
199
200
|
activeSegment.end()
|
|
200
201
|
}
|
|
201
202
|
|
|
202
|
-
if (error && tx) {
|
|
203
|
+
if (error && tx && config.feature_flag.undici_error_tracking === true) {
|
|
203
204
|
handleError(shim, tx, error)
|
|
204
205
|
}
|
|
205
206
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
|
|
8
|
+
const urltils = require('../util/urltils')
|
|
9
|
+
const constants = require('./constants')
|
|
10
|
+
|
|
11
|
+
const hostKeys = [
|
|
12
|
+
constants.ATTR_NET_HOST_NAME,
|
|
13
|
+
constants.ATTR_NET_PEER_NAME,
|
|
14
|
+
constants.ATTR_SERVER_ADDRESS
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
class AttributeReconciler {
|
|
18
|
+
#agent
|
|
19
|
+
|
|
20
|
+
constructor({ agent }) {
|
|
21
|
+
this.#agent = agent
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#resolveHost(hostname) {
|
|
25
|
+
if (urltils.isLocalhost(hostname)) {
|
|
26
|
+
return this.#agent.config.getHostnameSafe(hostname)
|
|
27
|
+
}
|
|
28
|
+
return hostname
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#isHostnameKey(key) {
|
|
32
|
+
return hostKeys.includes(key)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
reconcile({ segment, otelSpan, mapper = {} }) {
|
|
36
|
+
for (const [key, srcValue] of Object.entries(otelSpan.attributes)) {
|
|
37
|
+
let value = srcValue
|
|
38
|
+
|
|
39
|
+
if (this.#isHostnameKey(key) === true) {
|
|
40
|
+
value = this.#resolveHost(srcValue)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (Object.prototype.hasOwnProperty.call(mapper, key) === true) {
|
|
44
|
+
mapper[key](value)
|
|
45
|
+
} else {
|
|
46
|
+
segment.addAttribute(key, value)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = AttributeReconciler
|