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 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
@@ -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.2](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.13.2)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.13.2/LICENSE):
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.13](https://github.com/grpc/grpc-node/tree/v0.7.13)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/blob/v0.7.13/LICENSE):
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.0](https://github.com/newrelic/csec-node-agent/tree/v2.4.0)), distributed under the [UNKNOWN License](https://github.com/newrelic/csec-node-agent/blob/v2.4.0/LICENSE):
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.1](https://github.com/nodejs/import-in-the-middle/tree/v1.13.1)), distributed under the [Apache-2.0 License](https://github.com/nodejs/import-in-the-middle/blob/v1.13.1/LICENSE):
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.3](https://github.com/watson/module-details-from-path/tree/v1.0.3)), distributed under the [MIT License](https://github.com/watson/module-details-from-path/blob/v1.0.3/LICENSE):
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/elastic/require-in-the-middle) ([v7.5.0](https://github.com/elastic/require-in-the-middle/tree/v7.5.0)), distributed under the [MIT License](https://github.com/elastic/require-in-the-middle/blob/v7.5.0/LICENSE):
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-2023, Elasticsearch B.V.
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.6.3](https://github.com/npm/node-semver/tree/v7.6.3)), distributed under the [ISC License](https://github.com/npm/node-semver/blob/v7.6.3/LICENSE):
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.726.1](https://github.com/aws/aws-sdk-js-v3/tree/v3.726.1)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.726.1/LICENSE):
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.726.1](https://github.com/aws/aws-sdk-js-v3/tree/v3.726.1)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.726.1/LICENSE):
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.1](https://github.com/gajus/eslint-plugin-jsdoc/tree/v50.6.1)), distributed under the [BSD-3-Clause License](https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.6.1/LICENSE):
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.18.0](https://github.com/eslint/eslint/tree/v9.18.0)), distributed under the [MIT License](https://github.com/eslint/eslint/blob/v9.18.0/LICENSE):
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) ([v4.21.2](https://github.com/expressjs/express/tree/v4.21.2)), distributed under the [MIT License](https://github.com/expressjs/express/blob/v4.21.2/LICENSE):
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 associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
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 portions of the Software.
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 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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.15.3](https://github.com/koajs/koa/tree/v2.15.3)), distributed under the [MIT License](https://github.com/koajs/koa/blob/v2.15.3/LICENSE):
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.0](https://github.com/lirantal/lockfile-lint/tree/v4.14.0)), distributed under the [Apache-2.0 License](https://github.com/lirantal/lockfile-lint/blob/v4.14.0/LICENSE):
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 associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
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 portions of the Software.
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 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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
- getValue('entity.guid'),
927
- getValue('hostname'),
928
- getValue('trace.id'),
929
- getValue('span.id'),
930
- encodeURIComponent(getValue('entity.name'))
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.trace.root)
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.status) {
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?
@@ -14,6 +14,7 @@ const {
14
14
  module.exports = function initialize(_agent, redis, _moduleName, shim) {
15
15
  const proto = redis?.RedisClient?.prototype
16
16
  if (!proto) {
17
+ shim.logger.warn('Skipping redis instrumentation due to unrecognized module shape')
17
18
  return false
18
19
  }
19
20
 
@@ -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
- this._otelCtx.set(transaction.agent.otelSpanKey, new FakeSpan(segment, transaction))
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
- this._otelCtx.set(transaction.agent.otelSpanKey, new FakeSpan(transaction.trace.root, transaction))
40
- return new this.constructor(transaction, transaction.trace.root, this._otelCtx)
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
  /**
@@ -14,14 +14,14 @@
14
14
  */
15
15
  module.exports = class FakeSpan {
16
16
  constructor(segment, transaction) {
17
- this.segment = segment
18
- this.transaction = transaction
17
+ this.segmentId = segment.id
18
+ this.traceId = transaction.traceId
19
19
  }
20
20
 
21
21
  spanContext() {
22
22
  return {
23
- spanId: this.segment.id,
24
- traceId: this.transaction.traceId,
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
- module.exports = function setupOtel(agent, logger = defaultLogger) {
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
- transaction.trace.segments.add(segment)
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.18.1",
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.3.0",
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",