newrelic 12.18.1 → 12.19.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 +34 -0
- package/THIRD_PARTY_NOTICES.md +41 -22
- package/lib/agent.js +5 -15
- package/lib/context-manager/context.js +1 -1
- package/lib/instrumentation/@azure/functions.js +10 -4
- package/lib/instrumentation/core/http.js +6 -0
- package/lib/instrumentation/redis.js +1 -0
- package/lib/otel/context.js +7 -3
- package/lib/otel/fake-span.js +4 -4
- package/lib/otel/sampler.js +32 -0
- package/lib/otel/segments/consumer.js +6 -0
- package/lib/otel/segments/server.js +6 -0
- package/lib/otel/setup.js +19 -1
- package/lib/shimmer.js +3 -2
- package/lib/transaction/tracer/index.js +4 -1
- package/package.json +3 -2
package/NEWS.md
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
### v12.19.0 (2025-05-20)
|
|
2
|
+
|
|
3
|
+
#### Features
|
|
4
|
+
|
|
5
|
+
* Added Azure Function HTTP streaming support ([#3070](https://github.com/newrelic/node-newrelic/pull/3070)) ([9865e1c](https://github.com/newrelic/node-newrelic/commit/9865e1c4d47c2a41fef20f83eb810eee8559bea2))
|
|
6
|
+
|
|
7
|
+
#### Code refactoring
|
|
8
|
+
|
|
9
|
+
* Added check to only set a FakeSpan if `transaction.agent.otelSpanKey` exists ([#3071](https://github.com/newrelic/node-newrelic/pull/3071)) ([b0c1ac1](https://github.com/newrelic/node-newrelic/commit/b0c1ac141be17e4aa1d845a810e60743dc08863d))
|
|
10
|
+
|
|
11
|
+
#### Documentation
|
|
12
|
+
|
|
13
|
+
* Updated compatibility report ([#3074](https://github.com/newrelic/node-newrelic/pull/3074)) ([7dc9aad](https://github.com/newrelic/node-newrelic/commit/7dc9aad20a1cf201de9dd946913daab8e3d23e54))
|
|
14
|
+
|
|
15
|
+
#### Miscellaneous chores
|
|
16
|
+
|
|
17
|
+
* Fixed `redis` legacy test suite ([#3077](https://github.com/newrelic/node-newrelic/pull/3077)) ([ec39925](https://github.com/newrelic/node-newrelic/commit/ec399254d277e36e1120dcf43542819f1ce8d475))
|
|
18
|
+
* Updated security agent ([#3098](https://github.com/newrelic/node-newrelic/pull/3098)) ([48ed8cb](https://github.com/newrelic/node-newrelic/commit/48ed8cb53f5331966bb39065f1b157754a51414e))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
#### Tests
|
|
22
|
+
|
|
23
|
+
* Added cross agent otel bridge tests ([#3057](https://github.com/newrelic/node-newrelic/pull/3057)) ([1526bed](https://github.com/newrelic/node-newrelic/commit/1526bed9cf0f99481cf26ded2ebd43a0fcd720ae))
|
|
24
|
+
|
|
25
|
+
### v12.18.2 (2025-04-30)
|
|
26
|
+
|
|
27
|
+
#### Bug fixes
|
|
28
|
+
|
|
29
|
+
* Updated `createSegment` to stop adding segments to trace when `max_trace_segments` is exceeded ([#3056](https://github.com/newrelic/node-newrelic/pull/3056)) ([8f3336e](https://github.com/newrelic/node-newrelic/commit/8f3336e98ac9f7d4ad0ded3a061774fd68053e76))
|
|
30
|
+
|
|
31
|
+
#### Documentation
|
|
32
|
+
|
|
33
|
+
* Updated compatibility report ([#3065](https://github.com/newrelic/node-newrelic/pull/3065)) ([#3063](https://github.com/newrelic/node-newrelic/pull/3063))
|
|
34
|
+
|
|
1
35
|
### v12.18.1 (2025-04-29)
|
|
2
36
|
|
|
3
37
|
#### Bug fixes
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -91,7 +91,7 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic
|
|
|
91
91
|
|
|
92
92
|
### @grpc/grpc-js
|
|
93
93
|
|
|
94
|
-
This product includes source derived from [@grpc/grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) ([v1.13.
|
|
94
|
+
This product includes source derived from [@grpc/grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) ([v1.13.3](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.13.3)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.13.3/LICENSE):
|
|
95
95
|
|
|
96
96
|
```
|
|
97
97
|
Apache License
|
|
@@ -300,7 +300,7 @@ This product includes source derived from [@grpc/grpc-js](https://github.com/grp
|
|
|
300
300
|
|
|
301
301
|
### @grpc/proto-loader
|
|
302
302
|
|
|
303
|
-
This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.7.
|
|
303
|
+
This product includes source derived from [@grpc/proto-loader](https://github.com/grpc/grpc-node) ([v0.7.15](https://github.com/grpc/grpc-node/tree/v0.7.15)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.7.15/LICENSE):
|
|
304
304
|
|
|
305
305
|
```
|
|
306
306
|
Apache License
|
|
@@ -509,7 +509,7 @@ This product includes source derived from [@grpc/proto-loader](https://github.co
|
|
|
509
509
|
|
|
510
510
|
### @newrelic/security-agent
|
|
511
511
|
|
|
512
|
-
This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v2.4.
|
|
512
|
+
This product includes source derived from [@newrelic/security-agent](https://github.com/newrelic/csec-node-agent) ([v2.4.1](https://github.com/newrelic/csec-node-agent/tree/v2.4.1)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v2.4.1/LICENSE):
|
|
513
513
|
|
|
514
514
|
```
|
|
515
515
|
## New Relic Software License v1.0
|
|
@@ -1271,7 +1271,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
1271
1271
|
|
|
1272
1272
|
### import-in-the-middle
|
|
1273
1273
|
|
|
1274
|
-
This product includes source derived from [import-in-the-middle](https://github.com/nodejs/import-in-the-middle) ([v1.13.
|
|
1274
|
+
This product includes source derived from [import-in-the-middle](https://github.com/nodejs/import-in-the-middle) ([v1.13.2](https://github.com/nodejs/import-in-the-middle/tree/v1.13.2)), distributed under the [Apache-2.0 License](https://github.com/nodejs/import-in-the-middle/blob/v1.13.2/LICENSE):
|
|
1275
1275
|
|
|
1276
1276
|
```
|
|
1277
1277
|
Apache License
|
|
@@ -1531,12 +1531,12 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
1531
1531
|
|
|
1532
1532
|
### module-details-from-path
|
|
1533
1533
|
|
|
1534
|
-
This product includes source derived from [module-details-from-path](https://github.com/watson/module-details-from-path) ([v1.0.
|
|
1534
|
+
This product includes source derived from [module-details-from-path](https://github.com/watson/module-details-from-path) ([v1.0.4](https://github.com/watson/module-details-from-path/tree/v1.0.4)), distributed under the [MIT License](https://github.com/watson/module-details-from-path/blob/v1.0.4/LICENSE):
|
|
1535
1535
|
|
|
1536
1536
|
```
|
|
1537
1537
|
The MIT License (MIT)
|
|
1538
1538
|
|
|
1539
|
-
Copyright (c) 2016 Thomas Watson Steen
|
|
1539
|
+
Copyright (c) 2016-2025 Thomas Watson Steen
|
|
1540
1540
|
|
|
1541
1541
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1542
1542
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1615,13 +1615,14 @@ IN THE SOFTWARE.
|
|
|
1615
1615
|
|
|
1616
1616
|
### require-in-the-middle
|
|
1617
1617
|
|
|
1618
|
-
This product includes source derived from [require-in-the-middle](https://github.com/
|
|
1618
|
+
This product includes source derived from [require-in-the-middle](https://github.com/nodejs/require-in-the-middle) ([v7.5.2](https://github.com/nodejs/require-in-the-middle/tree/v7.5.2)), distributed under the [MIT License](https://github.com/nodejs/require-in-the-middle/blob/v7.5.2/LICENSE):
|
|
1619
1619
|
|
|
1620
1620
|
```
|
|
1621
1621
|
The MIT License (MIT)
|
|
1622
1622
|
|
|
1623
1623
|
Copyright (c) 2016-2019, Thomas Watson Steen
|
|
1624
|
-
Copyright (c) 2019-
|
|
1624
|
+
Copyright (c) 2019-2025, Elasticsearch B.V.
|
|
1625
|
+
Copyright (c) 2025+, require-in-the-middle contributors
|
|
1625
1626
|
|
|
1626
1627
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
1627
1628
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -1645,7 +1646,7 @@ SOFTWARE.
|
|
|
1645
1646
|
|
|
1646
1647
|
### semver
|
|
1647
1648
|
|
|
1648
|
-
This product includes source derived from [semver](https://github.com/npm/node-semver) ([v7.
|
|
1649
|
+
This product includes source derived from [semver](https://github.com/npm/node-semver) ([v7.7.2](https://github.com/npm/node-semver/tree/v7.7.2)), distributed under the [ISC License](https://github.com/npm/node-semver/blob/v7.7.2/LICENSE):
|
|
1649
1650
|
|
|
1650
1651
|
```
|
|
1651
1652
|
The ISC License
|
|
@@ -1701,7 +1702,7 @@ SOFTWARE.
|
|
|
1701
1702
|
|
|
1702
1703
|
### @aws-sdk/client-s3
|
|
1703
1704
|
|
|
1704
|
-
This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.
|
|
1705
|
+
This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.808.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.808.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.808.0/LICENSE):
|
|
1705
1706
|
|
|
1706
1707
|
```
|
|
1707
1708
|
Apache License
|
|
@@ -1910,7 +1911,7 @@ This product includes source derived from [@aws-sdk/client-s3](https://github.co
|
|
|
1910
1911
|
|
|
1911
1912
|
### @aws-sdk/s3-request-presigner
|
|
1912
1913
|
|
|
1913
|
-
This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.
|
|
1914
|
+
This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.808.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.808.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.808.0/LICENSE):
|
|
1914
1915
|
|
|
1915
1916
|
```
|
|
1916
1917
|
Apache License
|
|
@@ -3738,7 +3739,7 @@ SOFTWARE.
|
|
|
3738
3739
|
|
|
3739
3740
|
### eslint-plugin-jsdoc
|
|
3740
3741
|
|
|
3741
|
-
This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v50.6.
|
|
3742
|
+
This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v50.6.14](https://github.com/gajus/eslint-plugin-jsdoc/tree/v50.6.14)), distributed under the [BSD-3-Clause License](https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.6.14/LICENSE):
|
|
3742
3743
|
|
|
3743
3744
|
```
|
|
3744
3745
|
Copyright (c) 2018, Gajus Kuizinas (http://gajus.com/)
|
|
@@ -3770,7 +3771,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
3770
3771
|
|
|
3771
3772
|
### eslint
|
|
3772
3773
|
|
|
3773
|
-
This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v9.
|
|
3774
|
+
This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v9.26.0](https://github.com/eslint/eslint/tree/v9.26.0)), distributed under the [MIT License](https://github.com/eslint/eslint/blob/v9.26.0/LICENSE):
|
|
3774
3775
|
|
|
3775
3776
|
```
|
|
3776
3777
|
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
@@ -3797,7 +3798,7 @@ THE SOFTWARE.
|
|
|
3797
3798
|
|
|
3798
3799
|
### express
|
|
3799
3800
|
|
|
3800
|
-
This product includes source derived from [express](https://github.com/expressjs/express) ([
|
|
3801
|
+
This product includes source derived from [express](https://github.com/expressjs/express) ([v5.1.0](https://github.com/expressjs/express/tree/v5.1.0)), distributed under the [MIT License](https://github.com/expressjs/express/blob/v5.1.0/LICENSE):
|
|
3801
3802
|
|
|
3802
3803
|
```
|
|
3803
3804
|
(The MIT License)
|
|
@@ -4050,11 +4051,20 @@ MIT License
|
|
|
4050
4051
|
|
|
4051
4052
|
Copyright (c) <year> <copyright holders>
|
|
4052
4053
|
|
|
4053
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
4054
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
4055
|
+
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
|
4056
|
+
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
4057
|
+
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
|
4058
|
+
following conditions:
|
|
4054
4059
|
|
|
4055
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
4060
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
4061
|
+
portions of the Software.
|
|
4056
4062
|
|
|
4057
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
4063
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
4064
|
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
|
4065
|
+
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
4066
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
4067
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
4058
4068
|
```
|
|
4059
4069
|
|
|
4060
4070
|
### koa-router
|
|
@@ -4088,7 +4098,7 @@ THE SOFTWARE.
|
|
|
4088
4098
|
|
|
4089
4099
|
### koa
|
|
4090
4100
|
|
|
4091
|
-
This product includes source derived from [koa](https://github.com/koajs/koa) ([v2.
|
|
4101
|
+
This product includes source derived from [koa](https://github.com/koajs/koa) ([v2.16.1](https://github.com/koajs/koa/tree/v2.16.1)), distributed under the [MIT License](https://github.com/koajs/koa/blob/v2.16.1/LICENSE):
|
|
4092
4102
|
|
|
4093
4103
|
```
|
|
4094
4104
|
(The MIT License)
|
|
@@ -4147,7 +4157,7 @@ SOFTWARE.
|
|
|
4147
4157
|
|
|
4148
4158
|
### lockfile-lint
|
|
4149
4159
|
|
|
4150
|
-
This product includes source derived from [lockfile-lint](https://github.com/lirantal/lockfile-lint) ([v4.14.
|
|
4160
|
+
This product includes source derived from [lockfile-lint](https://github.com/lirantal/lockfile-lint) ([v4.14.1](https://github.com/lirantal/lockfile-lint/tree/v4.14.1)), distributed under the [Apache-2.0 License](https://github.com/lirantal/lockfile-lint/blob/v4.14.1/LICENSE):
|
|
4151
4161
|
|
|
4152
4162
|
```
|
|
4153
4163
|
|
|
@@ -4435,11 +4445,20 @@ MIT License
|
|
|
4435
4445
|
|
|
4436
4446
|
Copyright (c) <year> <copyright holders>
|
|
4437
4447
|
|
|
4438
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
4448
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
4449
|
+
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
|
4450
|
+
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
4451
|
+
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
|
4452
|
+
following conditions:
|
|
4439
4453
|
|
|
4440
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
4454
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
4455
|
+
portions of the Software.
|
|
4441
4456
|
|
|
4442
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
4457
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|
4458
|
+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
|
4459
|
+
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
4460
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
4461
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
4443
4462
|
```
|
|
4444
4463
|
|
|
4445
4464
|
### should
|
package/lib/agent.js
CHANGED
|
@@ -923,24 +923,14 @@ Agent.prototype.getServiceLinkingMetadata = function getServiceLinkingMetadata(
|
|
|
923
923
|
Agent.prototype.getNRLinkingMetadata = function getNRLinkingMetadata() {
|
|
924
924
|
const metadata = this.getLinkingMetadata()
|
|
925
925
|
const nrLinkingMeta = [
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
encodeURIComponent(
|
|
926
|
+
metadata['entity.guid'] ?? '',
|
|
927
|
+
metadata['hostname'] ?? '',
|
|
928
|
+
metadata['trace.id'] ?? '',
|
|
929
|
+
metadata['span.id'] ?? '',
|
|
930
|
+
encodeURIComponent(metadata['entity.name'] ?? '')
|
|
931
931
|
]
|
|
932
932
|
|
|
933
933
|
return ` NR-LINKING|${nrLinkingMeta.join('|')}|`
|
|
934
|
-
|
|
935
|
-
/**
|
|
936
|
-
* Retries value for a given key but defaults to `` if falsey
|
|
937
|
-
*
|
|
938
|
-
* @param {string} key in linking metadata
|
|
939
|
-
* @returns {string} Metadata value or empty string
|
|
940
|
-
*/
|
|
941
|
-
function getValue(key) {
|
|
942
|
-
return metadata[key] || ''
|
|
943
|
-
}
|
|
944
934
|
}
|
|
945
935
|
|
|
946
936
|
function generateEventHarvestSupportMetrics(agent, harvestConfig) {
|
|
@@ -40,6 +40,6 @@ module.exports = class Context {
|
|
|
40
40
|
* @returns {Context} a newly constructed context
|
|
41
41
|
*/
|
|
42
42
|
enterTransaction(transaction) {
|
|
43
|
-
return new this.constructor(transaction, transaction
|
|
43
|
+
return new this.constructor(transaction, transaction?.trace?.root)
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -9,6 +9,7 @@ const defaultLogger = require('../../logger').child({ component: 'azure-function
|
|
|
9
9
|
const urltils = require('../../util/urltils')
|
|
10
10
|
const headerProcessing = require('../../header-processing')
|
|
11
11
|
const synthetics = require('../../synthetics')
|
|
12
|
+
const { Transform } = require('node:stream')
|
|
12
13
|
|
|
13
14
|
const backgroundRecorder = require('../../metrics/recorders/other.js')
|
|
14
15
|
const recordWeb = require('../../metrics/recorders/http')
|
|
@@ -134,24 +135,29 @@ function wrapAzureHttpMethods(shim, appMethod) {
|
|
|
134
135
|
|
|
135
136
|
const newContext = ctx.enterSegment({ segment })
|
|
136
137
|
const boundHandler = tracer.bindFunction(handler, newContext)
|
|
137
|
-
|
|
138
138
|
const result = await boundHandler(...args)
|
|
139
|
+
|
|
139
140
|
// Responses should have a shape as described at:
|
|
140
141
|
// https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node?tabs=javascript%2Cwindows%2Cazure-cli&pivots=nodejs-model-v4#http-response
|
|
141
|
-
if (result
|
|
142
|
+
if (result?.status) {
|
|
142
143
|
tx.trace.attributes.addAttribute(
|
|
143
144
|
DESTS.TRANS_COMMON,
|
|
144
145
|
'http.statusCode',
|
|
145
146
|
result.status
|
|
146
147
|
)
|
|
147
148
|
}
|
|
148
|
-
|
|
149
149
|
if (coldStart === true) {
|
|
150
150
|
tx.trace.attributes.addAttribute(DESTS.TRANS_COMMON, 'faas.coldStart', true)
|
|
151
151
|
coldStart = false
|
|
152
152
|
}
|
|
153
|
+
if (result?.body instanceof Transform) {
|
|
154
|
+
result.body.on('close', () => {
|
|
155
|
+
tx.end()
|
|
156
|
+
})
|
|
157
|
+
} else {
|
|
158
|
+
tx.end()
|
|
159
|
+
}
|
|
153
160
|
|
|
154
|
-
tx.end()
|
|
155
161
|
return result
|
|
156
162
|
})
|
|
157
163
|
|
|
@@ -167,6 +167,7 @@ function instrumentedFinish(segment, transaction) {
|
|
|
167
167
|
|
|
168
168
|
// Naming must happen before the segment and transaction are ended,
|
|
169
169
|
// because metrics recording depends on naming's side effects.
|
|
170
|
+
|
|
170
171
|
transaction.finalizeNameFromUri(transaction.parsedUrl, this.statusCode)
|
|
171
172
|
|
|
172
173
|
if (this) {
|
|
@@ -444,6 +445,11 @@ module.exports = function initialize(agent, http, moduleName) {
|
|
|
444
445
|
return false
|
|
445
446
|
}
|
|
446
447
|
|
|
448
|
+
if (process.env.FUNCTIONS_WORKER_RUNTIME) {
|
|
449
|
+
logger.debug('In azure functions environment, disabling core http instrumentation in favor of @azure/functions')
|
|
450
|
+
return false
|
|
451
|
+
}
|
|
452
|
+
|
|
447
453
|
const IS_HTTPS = moduleName === 'https'
|
|
448
454
|
|
|
449
455
|
// FIXME: will this ever not be called?
|
package/lib/otel/context.js
CHANGED
|
@@ -24,7 +24,9 @@ module.exports = class OtelContext extends Context {
|
|
|
24
24
|
* @returns {OtelContext} a newly constructed context
|
|
25
25
|
*/
|
|
26
26
|
enterSegment({ segment, transaction = this._transaction }) {
|
|
27
|
-
|
|
27
|
+
if (transaction?.agent?.otelSpanKey) {
|
|
28
|
+
this._otelCtx.set(transaction.agent.otelSpanKey, new FakeSpan(segment, transaction))
|
|
29
|
+
}
|
|
28
30
|
return new this.constructor(transaction, segment, this._otelCtx)
|
|
29
31
|
}
|
|
30
32
|
|
|
@@ -36,8 +38,10 @@ module.exports = class OtelContext extends Context {
|
|
|
36
38
|
* @returns {OtelContext} a newly constructed context
|
|
37
39
|
*/
|
|
38
40
|
enterTransaction(transaction) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
if (transaction?.agent?.otelSpanKey) {
|
|
42
|
+
this._otelCtx.set(transaction.agent.otelSpanKey, new FakeSpan(transaction.trace.root, transaction))
|
|
43
|
+
}
|
|
44
|
+
return new this.constructor(transaction, transaction?.trace?.root, this._otelCtx)
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
/**
|
package/lib/otel/fake-span.js
CHANGED
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
*/
|
|
15
15
|
module.exports = class FakeSpan {
|
|
16
16
|
constructor(segment, transaction) {
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
17
|
+
this.segmentId = segment.id
|
|
18
|
+
this.traceId = transaction.traceId
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
spanContext() {
|
|
22
22
|
return {
|
|
23
|
-
spanId: this.
|
|
24
|
-
traceId: this.
|
|
23
|
+
spanId: this.segmentId,
|
|
24
|
+
traceId: this.traceId,
|
|
25
25
|
traceFlags: 1
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const { SamplingDecision } = require('@opentelemetry/sdk-trace-base')
|
|
8
|
+
const { trace, SpanKind } = require('@opentelemetry/api')
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Basic sampler that just checks if there is an active transaction.
|
|
12
|
+
* If not, it falls back to checking if it is a server of consumer span
|
|
13
|
+
* or `isRemote` exists on the parent span context.
|
|
14
|
+
*/
|
|
15
|
+
module.exports = class NrSampler {
|
|
16
|
+
shouldSample(context, _traceId, _spanName, spanKind) {
|
|
17
|
+
if (context?.transaction?.isActive()) {
|
|
18
|
+
return { decision: SamplingDecision.RECORD_AND_SAMPLED }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const parentContext = trace.getSpanContext(context)
|
|
22
|
+
if (parentContext?.isRemote || spanKind === SpanKind.SERVER || spanKind === SpanKind.CONSUMER) {
|
|
23
|
+
return { decision: SamplingDecision.RECORD_AND_SAMPLED }
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return { decision: SamplingDecision.NOT_RECORD }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
toString() {
|
|
30
|
+
return 'NrSampler'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -12,12 +12,18 @@ const recorder = require('../../metrics/recorders/message-transaction')
|
|
|
12
12
|
const { TYPES } = Transaction
|
|
13
13
|
const { propagateTraceContext } = require('./utils')
|
|
14
14
|
const { msgAttr } = require('../attr-mapping/messaging')
|
|
15
|
+
const createInternalSegment = require('./internal')
|
|
15
16
|
|
|
16
17
|
const {
|
|
17
18
|
UNKNOWN
|
|
18
19
|
} = require('../constants')
|
|
19
20
|
|
|
20
21
|
function createConsumerSegment(agent, otelSpan) {
|
|
22
|
+
const activeTx = agent.tracer.getTransaction()
|
|
23
|
+
// tx already exists do not create a new transaction
|
|
24
|
+
if (activeTx) {
|
|
25
|
+
return createInternalSegment(agent, otelSpan)
|
|
26
|
+
}
|
|
21
27
|
const spanContext = otelSpan.spanContext()
|
|
22
28
|
const transaction = new Transaction(agent, spanContext?.traceId)
|
|
23
29
|
transaction.type = TYPES.MESSAGE
|
|
@@ -14,8 +14,14 @@ const { propagateTraceContext } = require('./utils')
|
|
|
14
14
|
const { httpAttr } = require('../attr-mapping/http')
|
|
15
15
|
const DESTINATION = Transaction.DESTINATIONS.TRANS_COMMON
|
|
16
16
|
const { UNKNOWN } = require('../constants')
|
|
17
|
+
const createInternalSegment = require('./internal')
|
|
17
18
|
|
|
18
19
|
module.exports = function createServerSegment(agent, otelSpan) {
|
|
20
|
+
const activeTx = agent.tracer.getTransaction()
|
|
21
|
+
// tx already exists do not create a new transaction
|
|
22
|
+
if (activeTx) {
|
|
23
|
+
return createInternalSegment(agent, otelSpan)
|
|
24
|
+
}
|
|
19
25
|
const spanContext = otelSpan.spanContext()
|
|
20
26
|
const transaction = new Transaction(agent, spanContext?.traceId)
|
|
21
27
|
transaction.type = 'web'
|
package/lib/otel/setup.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
const opentelemetry = require('@opentelemetry/api')
|
|
8
8
|
const { BasicTracerProvider } = require('@opentelemetry/sdk-trace-base')
|
|
9
9
|
const NrSpanProcessor = require('./span-processor')
|
|
10
|
+
const NrSampler = require('./sampler')
|
|
10
11
|
const ContextManager = require('./context-manager')
|
|
11
12
|
const defaultLogger = require('../logger').child({ component: 'opentelemetry-bridge' })
|
|
12
13
|
const createOtelLogger = require('./logger')
|
|
@@ -14,7 +15,7 @@ const TracePropagator = require('./trace-propagator')
|
|
|
14
15
|
|
|
15
16
|
const interceptSpanKey = require('./span-key-interceptor')
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
function setupOtel(agent, logger = defaultLogger) {
|
|
18
19
|
if (agent.config.feature_flag.opentelemetry_bridge !== true) {
|
|
19
20
|
logger.warn(
|
|
20
21
|
'`feature_flag.opentelemetry_bridge` is not enabled, skipping setup of opentelemetry-bridge'
|
|
@@ -25,6 +26,7 @@ module.exports = function setupOtel(agent, logger = defaultLogger) {
|
|
|
25
26
|
createOtelLogger(logger, agent.config)
|
|
26
27
|
|
|
27
28
|
opentelemetry.trace.setGlobalTracerProvider(new BasicTracerProvider({
|
|
29
|
+
sampler: new NrSampler(),
|
|
28
30
|
spanProcessors: [new NrSpanProcessor(agent)],
|
|
29
31
|
generalLimits: {
|
|
30
32
|
attributeValueLengthLimit: 4095
|
|
@@ -39,3 +41,19 @@ module.exports = function setupOtel(agent, logger = defaultLogger) {
|
|
|
39
41
|
.getOrCreateMetric('Supportability/Nodejs/OpenTelemetryBridge/Setup')
|
|
40
42
|
.incrementCallCount()
|
|
41
43
|
}
|
|
44
|
+
|
|
45
|
+
function teardownOtel(agent) {
|
|
46
|
+
if (agent?.config?.feature_flag?.opentelemetry_bridge !== true) {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
opentelemetry.trace.disable()
|
|
51
|
+
opentelemetry.context.disable()
|
|
52
|
+
opentelemetry.propagation.disable()
|
|
53
|
+
opentelemetry.diag.disable()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = {
|
|
57
|
+
setupOtel,
|
|
58
|
+
teardownOtel
|
|
59
|
+
}
|
package/lib/shimmer.js
CHANGED
|
@@ -23,7 +23,7 @@ let pkgsToHook = []
|
|
|
23
23
|
const NAMES = require('./metrics/names')
|
|
24
24
|
const symbols = require('./symbols')
|
|
25
25
|
const { unsubscribe } = require('./instrumentation/undici')
|
|
26
|
-
const setupOtel = require('./otel/setup')
|
|
26
|
+
const { setupOtel, teardownOtel } = require('./otel/setup')
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Unwrapping is only likely to be used by test code, and is a fairly drastic
|
|
@@ -317,7 +317,7 @@ const shimmer = (module.exports = {
|
|
|
317
317
|
})
|
|
318
318
|
},
|
|
319
319
|
|
|
320
|
-
removeHooks() {
|
|
320
|
+
removeHooks(agent) {
|
|
321
321
|
if (this._ritm) {
|
|
322
322
|
this._ritm.unhook()
|
|
323
323
|
this._ritm = null
|
|
@@ -329,6 +329,7 @@ const shimmer = (module.exports = {
|
|
|
329
329
|
}
|
|
330
330
|
|
|
331
331
|
pkgsToHook = []
|
|
332
|
+
teardownOtel(agent)
|
|
332
333
|
unsubscribe()
|
|
333
334
|
},
|
|
334
335
|
|
|
@@ -135,7 +135,10 @@ function createSegment({ id, name, recorder, parent, transaction }) {
|
|
|
135
135
|
if (recorder) {
|
|
136
136
|
transaction.addRecorder(recorder.bind(null, segment))
|
|
137
137
|
}
|
|
138
|
-
|
|
138
|
+
|
|
139
|
+
if (collect) {
|
|
140
|
+
transaction.trace.segments.add(segment)
|
|
141
|
+
}
|
|
139
142
|
|
|
140
143
|
return segment
|
|
141
144
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newrelic",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.19.0",
|
|
4
4
|
"author": "New Relic Node.js agent team <nodejs@newrelic.com>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"contributors": [
|
|
@@ -170,6 +170,7 @@
|
|
|
170
170
|
"public-docs": "jsdoc -c ./jsdoc-conf.jsonc",
|
|
171
171
|
"publish-docs": "./bin/publish-docs.sh",
|
|
172
172
|
"services": "DOCKER_PLATFORM=linux/$(uname -m) docker compose up -d --wait",
|
|
173
|
+
"services:start": "npm run services",
|
|
173
174
|
"services:stop": "docker compose down",
|
|
174
175
|
"smoke": "time borp --timeout 180000 --reporter ./test/lib/test-reporter.mjs 'test/smoke/**/*.{test,tap}.js'",
|
|
175
176
|
"sub-install": "node test/bin/install_sub_deps",
|
|
@@ -202,7 +203,7 @@
|
|
|
202
203
|
"dependencies": {
|
|
203
204
|
"@grpc/grpc-js": "^1.13.2",
|
|
204
205
|
"@grpc/proto-loader": "^0.7.5",
|
|
205
|
-
"@newrelic/security-agent": "^2.
|
|
206
|
+
"@newrelic/security-agent": "^2.4.2",
|
|
206
207
|
"@opentelemetry/api": "^1.9.0",
|
|
207
208
|
"@opentelemetry/core": "^2.0.0",
|
|
208
209
|
"@opentelemetry/sdk-trace-base": "^2.0.0",
|