newrelic 12.21.0 → 12.23.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.
Files changed (48) hide show
  1. package/NEWS.md +60 -0
  2. package/THIRD_PARTY_NOTICES.md +54 -6
  3. package/index.js +3 -3
  4. package/lib/agent.js +8 -0
  5. package/lib/config/default.js +35 -1
  6. package/lib/config/index.js +36 -22
  7. package/lib/instrumentation/@hapi/hapi.js +6 -10
  8. package/lib/instrumentation/@hapi/vision.js +3 -3
  9. package/lib/instrumentation/amqplib/amqplib.js +2 -4
  10. package/lib/instrumentation/amqplib/channel.js +3 -4
  11. package/lib/instrumentation/bunyan.js +1 -2
  12. package/lib/instrumentation/cassandra-driver.js +1 -3
  13. package/lib/instrumentation/core/child_process.js +1 -2
  14. package/lib/instrumentation/core/fs.js +2 -3
  15. package/lib/instrumentation/core/inspector.js +1 -2
  16. package/lib/instrumentation/core/net.js +2 -3
  17. package/lib/instrumentation/core/zlib.js +2 -3
  18. package/lib/instrumentation/fastify.js +4 -6
  19. package/lib/instrumentation/grpc-js/grpc.js +3 -8
  20. package/lib/instrumentation/kafkajs/consumer.js +2 -4
  21. package/lib/instrumentation/kafkajs/producer.js +1 -2
  22. package/lib/instrumentation/koa/router-instrumentation.js +2 -2
  23. package/lib/instrumentation/openai.js +120 -7
  24. package/lib/instrumentation/pino/pino.js +2 -2
  25. package/lib/instrumentation/winston.js +3 -6
  26. package/lib/llm-events/aws-bedrock/bedrock-command.js +1 -9
  27. package/lib/llm-events/aws-bedrock/bedrock-response.js +2 -7
  28. package/lib/llm-events/aws-bedrock/chat-completion-message.js +1 -1
  29. package/lib/llm-events/openai/chat-completion-message.js +17 -5
  30. package/lib/llm-events/openai/chat-completion-summary.js +13 -3
  31. package/lib/otel/metrics/bootstrap-metrics.js +117 -0
  32. package/lib/otel/metrics/proxying-exporter.js +75 -0
  33. package/lib/otel/setup.js +1 -1
  34. package/lib/otel/transformation-rules.json +0 -33
  35. package/lib/serverless/aws-lambda.js +6 -6
  36. package/lib/shim/message-shim/subscribe-consume.js +2 -5
  37. package/lib/shim/promise-shim.js +6 -4
  38. package/lib/shim/shim.js +12 -11
  39. package/lib/shim/webframework-shim/middleware-mounter.js +1 -3
  40. package/lib/spans/helpers.js +63 -1
  41. package/lib/spans/span-event-aggregator.js +6 -3
  42. package/lib/spans/span-event.js +10 -4
  43. package/lib/spans/streaming-span-event-aggregator.js +6 -2
  44. package/lib/spans/streaming-span-event.js +10 -4
  45. package/lib/util/code-level-metrics.js +1 -1
  46. package/lib/w3c/tracestate.js +5 -0
  47. package/package.json +4 -3
  48. package/lib/otel/bootstrap-metrics.js +0 -58
package/NEWS.md CHANGED
@@ -1,3 +1,63 @@
1
+ ### v12.23.0 (2025-06-30)
2
+
3
+ #### Features
4
+
5
+ * Added ability to report only on entry and exit spans ([#3184](https://github.com/newrelic/node-newrelic/pull/3184)) ([1f909d3](https://github.com/newrelic/node-newrelic/commit/1f909d389f790733c8787a9db8b0ee71c26bb5ed))
6
+ * Added Node.js 24 support ([#3080](https://github.com/newrelic/node-newrelic/pull/3080)) ([a538c2a](https://github.com/newrelic/node-newrelic/commit/a538c2a5e23b96be40fa3c014e60b912f695423e))
7
+
8
+ #### Documentation
9
+
10
+ * Updated compatibility report ([#3186](https://github.com/newrelic/node-newrelic/pull/3186)) ([5498c15](https://github.com/newrelic/node-newrelic/commit/5498c15bb6cf3329fe50595da46ab4f2b1385170))
11
+
12
+ #### Miscellaneous chores
13
+
14
+ * Fix issues on Node 24 ([#3181](https://github.com/newrelic/node-newrelic/pull/3181)) ([24832df](https://github.com/newrelic/node-newrelic/commit/24832df2984df960a4e44375525a8127a00a637c))
15
+ * Removed force labels on main CI workflow ([#3183](https://github.com/newrelic/node-newrelic/pull/3183)) ([3aaee17](https://github.com/newrelic/node-newrelic/commit/3aaee17586f817ae1a2ab0573570a740bd6397ef))
16
+ * Updated undici tests to unblock CI ([#3185](https://github.com/newrelic/node-newrelic/pull/3185)) ([08261eb](https://github.com/newrelic/node-newrelic/commit/08261ebcdbafdb625a451f4ccec9b0cba7641cc2))
17
+
18
+ #### Continuous integration
19
+
20
+ * Fixed the name of todo colum in add to board reusable workflow ([#3178](https://github.com/newrelic/node-newrelic/pull/3178)) ([f216e0c](https://github.com/newrelic/node-newrelic/commit/f216e0c48adf0291bfa38b3edbb04c9dcc96f92c))
21
+
22
+ ### v12.22.0 (2025-06-24)
23
+
24
+ #### Features
25
+
26
+ * Added `openai` v5 streaming support ([#3148](https://github.com/newrelic/node-newrelic/pull/3148)) ([6e90d41](https://github.com/newrelic/node-newrelic/commit/6e90d41756929bf69b82e190dc39792f97ec6d92))
27
+ * Added support for `openai.responses.create` api ([#3139](https://github.com/newrelic/node-newrelic/pull/3139)) ([a1204b2](https://github.com/newrelic/node-newrelic/commit/a1204b2484f3307eac74e7a370be2fc38061c358))
28
+
29
+ #### Bug fixes
30
+
31
+ * Fixed error logging for undefined tracestate header ([#3170](https://github.com/newrelic/node-newrelic/pull/3170)) ([3c915f5](https://github.com/newrelic/node-newrelic/commit/3c915f5a631b609daa6b87f3018e458945077f65))
32
+
33
+ #### Code refactoring
34
+
35
+ * Updated transformation rules to remove the bespoke rule to appease `@google-cloud/pubsub` < 5.1.0 ([#3151](https://github.com/newrelic/node-newrelic/pull/3151)) ([2d9b4b4](https://github.com/newrelic/node-newrelic/commit/2d9b4b4642e856622175adcfd2e31fa4cdfa7a3a))
36
+
37
+ #### Documentation
38
+
39
+ * Gemini compatibility ([#3134](https://github.com/newrelic/node-newrelic/pull/3134)) ([bbdc531](https://github.com/newrelic/node-newrelic/commit/bbdc531ac59aad7b53f1a98306b6857927b87237))
40
+ * Updated compatibility report ([#3171](https://github.com/newrelic/node-newrelic/pull/3171)) ([f3361e4](https://github.com/newrelic/node-newrelic/commit/f3361e421d67a0015719c3ae91bed64e5d38f317))
41
+
42
+ #### Miscellaneous chores
43
+
44
+ * Added logging of used New Relic environment variables ([#3145](https://github.com/newrelic/node-newrelic/pull/3145)) ([1a9d9f5](https://github.com/newrelic/node-newrelic/commit/1a9d9f53ddce7f373a7ff868b363feacf10e3bd8))
45
+ * Added supportability metrics to OTEL metrics API ([#3164](https://github.com/newrelic/node-newrelic/pull/3164)) ([5312db0](https://github.com/newrelic/node-newrelic/commit/5312db0f7c0b4260dd39691e246625380ea2ed12))
46
+ * Fixed formatting in Slack PR titles ([#3167](https://github.com/newrelic/node-newrelic/pull/3167)) ([847859f](https://github.com/newrelic/node-newrelic/commit/847859f8ece852d4fa511039d2131573d4b1392b))
47
+ * Improved output of pending prs script ([#3160](https://github.com/newrelic/node-newrelic/pull/3160)) ([9bafd77](https://github.com/newrelic/node-newrelic/commit/9bafd7758fc63d7fb5106fe0a28aaa5a626bdf3d))
48
+ * Improved setup of OpenTelemetry metrics API ([#3138](https://github.com/newrelic/node-newrelic/pull/3138)) ([e91592d](https://github.com/newrelic/node-newrelic/commit/e91592d8365a3e2543228526d6959751da7ea5aa))
49
+ * Pinned google/genai to <1.5.0 ([#3154](https://github.com/newrelic/node-newrelic/pull/3154)) ([04b9bde](https://github.com/newrelic/node-newrelic/commit/04b9bdef417d6ce9e9148c9489bbfc28081d5e84))
50
+ * Removed discontinued Bedrock models ([#3158](https://github.com/newrelic/node-newrelic/pull/3158)) ([2c79a31](https://github.com/newrelic/node-newrelic/commit/2c79a312daf31f51f8a270facf1c3a125700e987))
51
+ * Removed usage of `shim.argsToArray` in favor of rest parameters ([#3141](https://github.com/newrelic/node-newrelic/pull/3141)) ([b144d71](https://github.com/newrelic/node-newrelic/commit/b144d712f6e75265dc4be6f82a2fc3977ac1c640))
52
+ * Tweaked nestjs test manifest ([#3152](https://github.com/newrelic/node-newrelic/pull/3152)) ([51b82aa](https://github.com/newrelic/node-newrelic/commit/51b82aa28279e0d5ac8be5f4e6a4274532c76a22))
53
+
54
+ #### Tests
55
+
56
+ * Added JSDoc annotation for benchmark interface ([#3127](https://github.com/newrelic/node-newrelic/pull/3127)) ([77e7e0a](https://github.com/newrelic/node-newrelic/commit/77e7e0a27f719ce14d31636e46600ec7ff881b13))
57
+ * fixed test assertion for langchain openai ([#3169](https://github.com/newrelic/node-newrelic/pull/3169)) ([29ec912](https://github.com/newrelic/node-newrelic/commit/29ec9122fdf9347875b884efa6f6fba9cb32303e))
58
+ * Skips running nest 11+ on node 18 due to dropping support ([#3149](https://github.com/newrelic/node-newrelic/pull/3149)) ([961975b](https://github.com/newrelic/node-newrelic/commit/961975baeb74e46c0e60d96cbd49fb421acd0dfd))
59
+ * unpinned google genai tests ([#3168](https://github.com/newrelic/node-newrelic/pull/3168)) ([cfa7114](https://github.com/newrelic/node-newrelic/commit/cfa71142ba7fb9861a1e7ab835276e7c651b9993))
60
+
1
61
  ### v12.21.0 (2025-06-04)
2
62
 
3
63
  #### Features
@@ -72,6 +72,7 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic
72
72
  * [lint-staged](#lint-staged)
73
73
  * [lockfile-lint](#lockfile-lint)
74
74
  * [nock](#nock)
75
+ * [protobufjs](#protobufjs)
75
76
  * [proxyquire](#proxyquire)
76
77
  * [rimraf](#rimraf)
77
78
  * [self-cert](#self-cert)
@@ -94,7 +95,7 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic
94
95
 
95
96
  ### @grpc/grpc-js
96
97
 
97
- 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):
98
+ This product includes source derived from [@grpc/grpc-js](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js) ([v1.13.4](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/tree/v1.13.4)), distributed under the [Apache-2.0 License](https://github.com/grpc/grpc-node/tree/master/packages/grpc-js/blob/v1.13.4/LICENSE):
98
99
 
99
100
  ```
100
101
  Apache License
@@ -1901,7 +1902,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1901
1902
 
1902
1903
  ### import-in-the-middle
1903
1904
 
1904
- 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):
1905
+ This product includes source derived from [import-in-the-middle](https://github.com/nodejs/import-in-the-middle) ([v1.14.0](https://github.com/nodejs/import-in-the-middle/tree/v1.14.0)), distributed under the [Apache-2.0 License](https://github.com/nodejs/import-in-the-middle/blob/v1.14.0/LICENSE):
1905
1906
 
1906
1907
  ```
1907
1908
  Apache License
@@ -2332,7 +2333,7 @@ SOFTWARE.
2332
2333
 
2333
2334
  ### @aws-sdk/client-s3
2334
2335
 
2335
- This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.810.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.810.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.810.0/LICENSE):
2336
+ This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.821.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.821.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.821.0/LICENSE):
2336
2337
 
2337
2338
  ```
2338
2339
  Apache License
@@ -2541,7 +2542,7 @@ This product includes source derived from [@aws-sdk/client-s3](https://github.co
2541
2542
 
2542
2543
  ### @aws-sdk/s3-request-presigner
2543
2544
 
2544
- This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.810.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.810.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.810.0/LICENSE):
2545
+ This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.821.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.821.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.821.0/LICENSE):
2545
2546
 
2546
2547
  ```
2547
2548
  Apache License
@@ -4369,7 +4370,7 @@ SOFTWARE.
4369
4370
 
4370
4371
  ### eslint-plugin-jsdoc
4371
4372
 
4372
- This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v50.6.17](https://github.com/gajus/eslint-plugin-jsdoc/tree/v50.6.17)), distributed under the [BSD-3-Clause License](https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.6.17/LICENSE):
4373
+ This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v50.7.1](https://github.com/gajus/eslint-plugin-jsdoc/tree/v50.7.1)), distributed under the [BSD-3-Clause License](https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.7.1/LICENSE):
4373
4374
 
4374
4375
  ```
4375
4376
  Copyright (c) 2018, Gajus Kuizinas (http://gajus.com/)
@@ -4401,7 +4402,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4401
4402
 
4402
4403
  ### eslint
4403
4404
 
4404
- 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):
4405
+ This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v9.28.0](https://github.com/eslint/eslint/tree/v9.28.0)), distributed under the [MIT License](https://github.com/eslint/eslint/blob/v9.28.0/LICENSE):
4405
4406
 
4406
4407
  ```
4407
4408
  Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
@@ -5012,6 +5013,53 @@ SOFTWARE.
5012
5013
 
5013
5014
  ```
5014
5015
 
5016
+ ### protobufjs
5017
+
5018
+ This product includes source derived from [protobufjs](https://github.com/protobufjs/protobuf.js) ([v7.5.3](https://github.com/protobufjs/protobuf.js/tree/v7.5.3)), distributed under the [BSD-3-Clause License](https://github.com/protobufjs/protobuf.js/blob/v7.5.3/LICENSE):
5019
+
5020
+ ```
5021
+ This license applies to all parts of protobuf.js except those files
5022
+ either explicitly including or referencing a different license or
5023
+ located in a directory containing a different LICENSE file.
5024
+
5025
+ ---
5026
+
5027
+ Copyright (c) 2016, Daniel Wirtz All rights reserved.
5028
+
5029
+ Redistribution and use in source and binary forms, with or without
5030
+ modification, are permitted provided that the following conditions are
5031
+ met:
5032
+
5033
+ * Redistributions of source code must retain the above copyright
5034
+ notice, this list of conditions and the following disclaimer.
5035
+ * Redistributions in binary form must reproduce the above copyright
5036
+ notice, this list of conditions and the following disclaimer in the
5037
+ documentation and/or other materials provided with the distribution.
5038
+ * Neither the name of its author, nor the names of its contributors
5039
+ may be used to endorse or promote products derived from this software
5040
+ without specific prior written permission.
5041
+
5042
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5043
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5044
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
5045
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
5046
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
5047
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
5048
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
5049
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
5050
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5051
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
5052
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5053
+
5054
+ ---
5055
+
5056
+ Code generated by the command line utilities is owned by the owner
5057
+ of the input file used when generating it. This code is not
5058
+ standalone and requires a support library to be linked with it. This
5059
+ support library is itself covered by the above license.
5060
+
5061
+ ```
5062
+
5015
5063
  ### proxyquire
5016
5064
 
5017
5065
  This product includes source derived from [proxyquire](https://github.com/thlorenz/proxyquire) ([v1.8.0](https://github.com/thlorenz/proxyquire/tree/v1.8.0)), distributed under the [MIT License](https://github.com/thlorenz/proxyquire/blob/v1.8.0/LICENSE):
package/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const HealthReporter = require('./lib/health-reporter')
8
+ const HealthReporter = require('./lib/health-reporter.js')
9
9
 
10
10
  // Record opening times before loading any other files.
11
11
  const preAgentTime = process.uptime()
@@ -64,8 +64,8 @@ function initialize() {
64
64
  throw new Error(message)
65
65
  }
66
66
 
67
- // TODO: Update this check when Node v24 support is added
68
- if (psemver.satisfies('>=23.0.0')) {
67
+ // TODO: Update this check when Node v26 support is added
68
+ if (psemver.satisfies('>=25.0.0')) {
69
69
  logger.warn(
70
70
  'New Relic for Node.js %s has not been tested on Node.js %s. Please ' +
71
71
  'update the agent or downgrade your version of Node.js',
package/lib/agent.js CHANGED
@@ -104,6 +104,14 @@ const DEFAULT_HARVEST_INTERVAL_MS = 60000
104
104
  * @event Agent#harvestStarted
105
105
  */
106
106
 
107
+ /**
108
+ * Indicates that the OpenTelemetry metrics API client has been fully
109
+ * configured and is ready to send metrics to New Relic. This happens
110
+ * subsequent to the {@link Agent#started} event.
111
+ *
112
+ * @event Agent#otelMetricsBootstrapped
113
+ */
114
+
107
115
  /**
108
116
  * Indicates that the agent state has entered the "started" state. That is,
109
117
  * the agent has finished bootstrapping and is collecting and sending data.
@@ -1120,6 +1120,19 @@ defaultConfig.definition = () => ({
1120
1120
  default: false
1121
1121
  },
1122
1122
 
1123
+ /**
1124
+ * Controls whether the agent will generate spans for in-process actions.
1125
+ * When disabled, this will only create spans for entry and exit spans.
1126
+ * entry spans - initial actions for web servers and messsage queue consumption.
1127
+ * exit spans - all outgoing calls to external services(external and database calls)
1128
+ */
1129
+ in_process_spans: {
1130
+ enabled: {
1131
+ formatter: boolean,
1132
+ default: true
1133
+ }
1134
+ },
1135
+
1123
1136
  sampler: {
1124
1137
  /**
1125
1138
  * When set to `always_on`, the sampled flag in the `traceparent` header
@@ -1706,7 +1719,28 @@ defaultConfig.definition = () => ({
1706
1719
  * application entity that is instrumented by the New Relic agent.
1707
1720
  */
1708
1721
  metrics: {
1709
- enabled: { default: false, formatter: boolean }
1722
+ enabled: { default: false, formatter: boolean },
1723
+
1724
+ /**
1725
+ * `exportInterval` defines the number of milliseconds between each
1726
+ * attempt to ship metrics to New Relic. This value must be equal to
1727
+ * or greater than the value of `exportTimeout`.
1728
+ */
1729
+ exportInterval: {
1730
+ default: 60_000,
1731
+ formatter: int
1732
+ },
1733
+
1734
+ /**
1735
+ * `exportTimeout` defines the number of milliseconds an export operation
1736
+ * is allowed in order to successfully complete. If the timeout is
1737
+ * exceeded, it will be reported via the OpenTelemetry diagnostics
1738
+ * API.
1739
+ */
1740
+ exportTimeout: {
1741
+ default: 30_000,
1742
+ formatter: int
1743
+ }
1710
1744
  }
1711
1745
  }
1712
1746
  })
@@ -1143,6 +1143,13 @@ function setFromEnv({ config, key, envVar, formatter, paths }) {
1143
1143
  const setting = process.env[envVar]
1144
1144
  if (setting) {
1145
1145
  const formattedSetting = formatter ? formatter(setting, logger) : setting
1146
+ // `setting` _should_ be a string when reading from the actual process
1147
+ // environment. But we have tests that construct an environment with
1148
+ // non-string values. So we need to convert them before accessing.
1149
+ const prefix = setting.toString().at(0)
1150
+ const suffix = setting.toString().at(-1)
1151
+ const redacted = prefix + '*'.repeat(setting.length) + suffix
1152
+ logger.trace({ env: { [envVar]: redacted } }, 'setting value from environment variable')
1146
1153
  setNestedKey(config, [...paths, key], formattedSetting)
1147
1154
  }
1148
1155
  }
@@ -1162,31 +1169,36 @@ Config.prototype._fromEnvironment = function _fromEnvironment(
1162
1169
  objectKeys = 1
1163
1170
  ) {
1164
1171
  let keysSeen = 0
1165
- Object.entries(data).forEach(([key, value]) => {
1172
+ for (const [key, value] of Object.entries(data)) {
1166
1173
  const type = typeof value
1167
- keysSeen++
1174
+ keysSeen += 1
1175
+
1176
+ if (type !== 'string' && type !== 'object') {
1177
+ continue
1178
+ }
1179
+
1168
1180
  if (type === 'string') {
1169
1181
  const envVar = deriveEnvVar(key, paths)
1170
1182
  setFromEnv({ config, key, envVar, paths })
1171
- } else if (type === 'object') {
1172
- if (Object.prototype.hasOwnProperty.call(value, 'env')) {
1173
- setFromEnv({
1174
- config,
1175
- key,
1176
- envVar: value.env,
1177
- paths,
1178
- formatter: value.formatter
1179
- })
1180
- } else if (Object.prototype.hasOwnProperty.call(value, 'default')) {
1181
- const envVar = deriveEnvVar(key, paths)
1182
- setFromEnv({ config, key, envVar, formatter: value.formatter, paths })
1183
- } else {
1184
- paths.push(key)
1185
- const { length } = Object.keys(value)
1186
- this._fromEnvironment(config, value, paths, length)
1187
- }
1183
+ continue
1188
1184
  }
1189
- })
1185
+
1186
+ if (Object.prototype.hasOwnProperty.call(value, 'env') === true) {
1187
+ const envVar = value.env
1188
+ setFromEnv({ config, key, paths, envVar, formatter: value.formatter })
1189
+ continue
1190
+ }
1191
+
1192
+ if (Object.prototype.hasOwnProperty.call(value, 'default') === true) {
1193
+ const envVar = deriveEnvVar(key, paths)
1194
+ setFromEnv({ config, key, paths, envVar, formatter: value.formatter })
1195
+ continue
1196
+ }
1197
+
1198
+ paths.push(key)
1199
+ const { length } = Object.keys(value)
1200
+ this._fromEnvironment(config, value, paths, length)
1201
+ }
1190
1202
 
1191
1203
  // we have traversed every key in current object leaf node, remove wrapping key
1192
1204
  // to properly derive env vars of future leaf nodes
@@ -1738,16 +1750,18 @@ Config.prototype._warnDeprecations = function _warnDeprecations() {
1738
1750
  * configuration file settings.
1739
1751
  *
1740
1752
  * @param {object} config Optional configuration to be used in place of a config file.
1753
+ * @param root0
1754
+ * @param root0.loggerInstance
1741
1755
  * @returns {object} instantiated configuration object
1742
1756
  */
1743
- function initialize(config) {
1757
+ function initialize(config, { loggerInstance } = {}) {
1744
1758
  /**
1745
1759
  * When the logger is required here, it bootstraps itself and then
1746
1760
  * injects itself into this module's closure via setLogger on the
1747
1761
  * instance of the logger it creates. Logs are queued until config
1748
1762
  * has been loaded to apply logging settings to bootstrapping logs
1749
1763
  */
1750
- logger = require('../logger')
1764
+ logger = loggerInstance ?? require('../logger')
1751
1765
 
1752
1766
  if (config) {
1753
1767
  return new Config(config)
@@ -72,16 +72,14 @@ function serverPostConstructor(shim) {
72
72
 
73
73
  function wrapProtoDecorate(shim, proto) {
74
74
  shim.wrap(proto, 'decorate', function wrapDecorate(shim, original) {
75
- return function wrappedDecorate(type) {
75
+ return function wrappedDecorate(...args) {
76
+ const [type] = args
76
77
  // server.decorate also accepts 'request', 'toolkit', 'server' types,
77
78
  // but we're only concerned with 'handler'
78
79
  if (type !== 'handler') {
79
- return original.apply(this, arguments)
80
+ return original.apply(this, args)
80
81
  }
81
82
 
82
- // Convert arguments to usable array
83
- const args = shim.argsToArray.apply(shim, arguments)
84
-
85
83
  // Wrap the third server.decorate arg, the user-defined handler
86
84
  shim.wrap(args, shim.THIRD, function wrapHandler(shim, fn) {
87
85
  if (typeof fn !== 'function') {
@@ -108,9 +106,7 @@ function wrapProtoDecorate(shim, proto) {
108
106
 
109
107
  function wrapProtoRoute(shim, proto) {
110
108
  shim.wrap(proto, 'route', function wrapRoute(shim, original) {
111
- return function wrappedRoute() {
112
- const args = shim.argsToArray.apply(shim, arguments)
113
-
109
+ return function wrappedRoute(...args) {
114
110
  if (!shim.isObject(args[0])) {
115
111
  return original.apply(this, args)
116
112
  }
@@ -171,8 +167,8 @@ function _wrapRouteHandler(shim, container, path) {
171
167
 
172
168
  function wrapProtoExt(shim, proto) {
173
169
  shim.wrap(proto, 'ext', function wrapExt(shim, original) {
174
- return function wrappedExt(event, method) {
175
- const args = shim.argsToArray.apply(shim, arguments)
170
+ return function wrappedExt(...args) {
171
+ const [event, method] = args
176
172
 
177
173
  if (shim.isArray(event)) {
178
174
  for (let i = 0; i < event.length; i++) {
@@ -31,12 +31,12 @@ module.exports = function initialize(agent, vision, moduleName, shim) {
31
31
  }
32
32
 
33
33
  function wrapDecorate(shim, decorate) {
34
- return function wrappedDecorate(type, name, handler) {
34
+ return function wrappedDecorate(...args) {
35
+ const [type, name, handler] = args
35
36
  if (type !== 'toolkit' || name !== 'view') {
36
- return decorate.apply(this, arguments)
37
+ return decorate.apply(this, args)
37
38
  }
38
39
 
39
- const args = shim.argsToArray.apply(shim, arguments)
40
40
  args[2] = shim.recordRender(handler, new RenderSpec({ promise: true }))
41
41
 
42
42
  return decorate.apply(this, args)
@@ -83,14 +83,12 @@ function instrumentAMQP(shim, amqp, promiseMode) {
83
83
  */
84
84
  function wrapConnect(shim, amqp, promiseMode) {
85
85
  shim.wrap(amqp, 'connect', function wrapConnect(shim, connect) {
86
- return function wrappedConnect() {
87
- const args = shim.argsToArray.apply(shim, arguments)
86
+ return function wrappedConnect(...args) {
88
87
  const [connArgs] = args
89
88
  const params = parseConnectionArgs({ shim, connArgs })
90
89
  const cb = args[args.length - 1]
91
90
  if (!promiseMode) {
92
- args[args.length - 1] = function wrappedCallback() {
93
- const cbArgs = shim.argsToArray.apply(shim, arguments)
91
+ args[args.length - 1] = function wrappedCallback(...cbArgs) {
94
92
  const [, c] = cbArgs
95
93
  c.connection[amqpConnection] = params
96
94
  return cb.apply(this, cbArgs)
@@ -33,16 +33,15 @@ module.exports = function wrapChannel(shim) {
33
33
  return fn
34
34
  }
35
35
 
36
- return function wrappedSendOrEnqueue() {
36
+ return function wrappedSendOrEnqueue(...args) {
37
37
  const segment = shim.getSegment()
38
- const cb = arguments[arguments.length - 1]
38
+ const cb = args[args.length - 1]
39
39
  if (!shim.isFunction(cb) || !segment) {
40
40
  shim.logger.debug({ cb: !!cb, segment: !!segment }, 'Not binding sendOrEnqueue callback')
41
- return fn.apply(this, arguments)
41
+ return fn.apply(this, args)
42
42
  }
43
43
 
44
44
  shim.logger.trace('Binding sendOrEnqueue callback to %s', segment.name)
45
- const args = shim.argsToArray.apply(shim, arguments)
46
45
  args[args.length - 1] = shim.bindSegment(cb, segment)
47
46
  return fn.apply(this, args)
48
47
  }
@@ -82,8 +82,7 @@ module.exports = function instrument(agent, bunyan, _, shim) {
82
82
 
83
83
  if (metricsEnabled || localDecoratingEnabled) {
84
84
  shim.wrap(bunyan.prototype, '_emit', function wrapEmit(_shim, emit) {
85
- return function wrappedEmit() {
86
- const args = shim.argsToArray.apply(shim, arguments)
85
+ return function wrappedEmit(...args) {
87
86
  const rec = args[0]
88
87
 
89
88
  if (metricsEnabled) {
@@ -71,12 +71,10 @@ module.exports = function initialize(_agent, cassandra, _moduleName, shim) {
71
71
  )
72
72
 
73
73
  shim.wrap(RequestExecutionProto, 'start', function wrapStart(shim, start) {
74
- return function wrappedStart() {
74
+ return function wrappedStart(...args) {
75
75
  const parent = shim.getSegment()
76
76
  const self = this
77
77
 
78
- const args = shim.argsToArray.apply(shim, arguments)
79
-
80
78
  /**
81
79
  * In older versions of cassandra-driver, we can't rely on RequestExecution._sendOnConnection,
82
80
  * so instead we use the callback passed to RequestExecution.start as a sort of hook point,
@@ -29,8 +29,7 @@ function initialize(agent, childProcess, moduleName, shim) {
29
29
 
30
30
  function wrapChildProcessClass(shim, childProcessClass) {
31
31
  shim.wrap(childProcessClass.prototype, 'on', function wrapChildProcessClassOn(shim, fn) {
32
- return function wrappedChildProcessOn() {
33
- const args = shim.argsToArray.apply(shim, arguments)
32
+ return function wrappedChildProcessOn(...args) {
34
33
  const cbIndex = args.length - 1
35
34
 
36
35
  const originalListener = args[cbIndex]
@@ -66,13 +66,12 @@ function initialize(agent, fs, moduleName, shim) {
66
66
  })
67
67
 
68
68
  shim.wrap(fs, nonRecordedMethods, function wrapNonRecordedFs(shim, fn) {
69
- return function wrappedNonRecordedFs() {
69
+ return function wrappedNonRecordedFs(...args) {
70
70
  // these are called in tight loops so opting out early
71
71
  if (!shim.getActiveSegment()) {
72
- return fn.apply(this, arguments)
72
+ return fn.apply(this, args)
73
73
  }
74
74
 
75
- const args = shim.argsToArray.apply(shim, arguments)
76
75
  const cbIndex = args.length - 1
77
76
 
78
77
  shim.bindSegment(args, cbIndex)
@@ -14,8 +14,7 @@ function initialize(agent, inspector, name, shim) {
14
14
  }
15
15
 
16
16
  shim.wrap(sessionProto, 'post', function wrapPost(shim, fn) {
17
- return function wrappedPost() {
18
- const args = shim.argsToArray.apply(shim, arguments)
17
+ return function wrappedPost(...args) {
19
18
  shim.bindCallbackSegment(null, args, shim.LAST)
20
19
  return fn.apply(this, args)
21
20
  }
@@ -24,12 +24,11 @@ module.exports = function initialize(agent, net, moduleName, shim) {
24
24
  const serverProto = net.Server.prototype
25
25
 
26
26
  shim.wrap(serverProto, ['listen', 'close'], function wrapNoRecord(shim, fn) {
27
- return function wrappedNoRecord() {
27
+ return function wrappedNoRecord(...args) {
28
28
  if (!shim.getActiveSegment()) {
29
- return fn.apply(this, arguments)
29
+ return fn.apply(this, args)
30
30
  }
31
31
 
32
- const args = shim.argsToArray.apply(shim, arguments)
33
32
  const cbIndex = args.length - 1
34
33
 
35
34
  shim.bindSegment(args, cbIndex)
@@ -32,12 +32,11 @@ function initialize(agent, zlib, moduleName, shim) {
32
32
  }
33
33
 
34
34
  function wrapNoSegment(shim, fn) {
35
- return function wrappedZLibNoSegment() {
35
+ return function wrappedZLibNoSegment(...args) {
36
36
  if (!shim.getActiveSegment()) {
37
- return fn.apply(this, arguments)
37
+ return fn.apply(this, args)
38
38
  }
39
39
 
40
- const args = shim.argsToArray.apply(shim, arguments)
41
40
  const cbIndex = args.length - 1
42
41
 
43
42
  shim.bindSegment(args, cbIndex)
@@ -68,8 +68,7 @@ const setupRouteHandler = (shim, fastify) => {
68
68
  })
69
69
 
70
70
  shim.wrap(fastify, 'addHook', function addWrapHook(shim, fn) {
71
- return function wrappedAddHook() {
72
- const args = shim.argsToArray.apply(shim, arguments)
71
+ return function wrappedAddHook(...args) {
73
72
  const hookName = args[0]
74
73
  if (REQUEST_HOOKS.includes(hookName)) {
75
74
  const middlewareFunction = args[1]
@@ -122,13 +121,12 @@ function setupMiddlewareHandlers(shim, fastify, isv3Plus) {
122
121
  // This style is accomplished leveraging decorators. Both middie (which was built-in in v2)
123
122
  // and fastify-express mount a 'use' function for mounting middleware.
124
123
  shim.wrap(fastify, 'decorate', function wrapDecorate(shim, fn) {
125
- return function wrappedDecorate() {
126
- const name = arguments[0]
124
+ return function wrappedDecorate(...args) {
125
+ const name = args[0]
127
126
  if (name !== 'use') {
128
- return fn.apply(this, arguments)
127
+ return fn.apply(this, args)
129
128
  }
130
129
 
131
- const args = shim.argsToArray.apply(shim, arguments)
132
130
  args[1] = shim.wrapMiddlewareMounter(args[1], mounterSpec)
133
131
 
134
132
  return fn.apply(this, args)
@@ -63,9 +63,7 @@ function wrapStart(shim, original) {
63
63
 
64
64
  return shim.applySegment(callStart, segment, true, this, arguments)
65
65
 
66
- function callStart() {
67
- const args = shim.argsToArray.apply(shim, arguments)
68
-
66
+ function callStart(...args) {
69
67
  const originalMetadata = args[0]
70
68
  const nrMetadata = originalMetadata.clone()
71
69
 
@@ -138,9 +136,7 @@ function wrapStart(shim, original) {
138
136
  function wrapRegister(shim, original) {
139
137
  const constants = shim.require('./build/src/constants')
140
138
 
141
- return function wrappedRegister() {
142
- const args = shim.argsToArray.apply(shim, arguments)
143
-
139
+ return function wrappedRegister(...args) {
144
140
  const name = args[0]
145
141
  const handler = args[1]
146
142
  const type = args[args.length - 1]
@@ -219,8 +215,7 @@ function wrapRegister(shim, original) {
219
215
  const config = agent.config
220
216
  if (!shim.isWrapped(stream.call.callEventTracker, 'onCallEnd')) {
221
217
  shim.wrap(stream.call.callEventTracker, 'onCallEnd', function onCallEnd(shim, orig) {
222
- return function wrappedOnCallEnd() {
223
- const args = shim.argsToArray.apply(shim, arguments)
218
+ return function wrappedOnCallEnd(...args) {
224
219
  const [{ code: statusCode }] = args
225
220
  transaction.trace.attributes.addAttribute(DESTINATION, 'response.status', statusCode)
226
221
  if (shouldTrackError(statusCode, config)) {
@@ -24,8 +24,7 @@ const SEGMENT_PREFIX = 'kafkajs.Kafka.consumer#'
24
24
  module.exports = wrapConsumer
25
25
 
26
26
  function wrapConsumer(shim, orig) {
27
- return function wrappedConsumer() {
28
- const args = shim.argsToArray.apply(shim, arguments)
27
+ return function wrappedConsumer(...args) {
29
28
  const consumer = orig.apply(this, args)
30
29
  consumer[kafkaCtx] = this[kafkaCtx]
31
30
 
@@ -58,8 +57,7 @@ function wrapConsumer(shim, orig) {
58
57
 
59
58
  function wrapRun(shim, fn) {
60
59
  const agent = shim.agent
61
- return function wrappedRun() {
62
- const runArgs = shim.argsToArray.apply(shim, arguments)
60
+ return function wrappedRun(...runArgs) {
63
61
  const brokers = this[kafkaCtx].brokers
64
62
  if (runArgs?.[0]?.eachBatch) {
65
63
  runArgs[0].eachBatch = shim.wrap(
@@ -14,8 +14,7 @@ const { kafkaCtx } = require('../../symbols')
14
14
  module.exports = nrProducerWrapper
15
15
 
16
16
  function nrProducerWrapper(shim, orig) {
17
- return function nrProducer() {
18
- const params = shim.argsToArray.apply(shim, arguments)
17
+ return function nrProducer(...params) {
19
18
  const producer = orig.apply(this, params)
20
19
  producer[kafkaCtx] = this[kafkaCtx]
21
20