newrelic 12.6.0 → 12.7.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,60 +1,107 @@
1
- ### v12.6.0 (2024-10-30)
2
-
3
- #### Features
4
-
5
- * Added ARN and provider to Lambda segments ([#2674](https://github.com/newrelic/node-newrelic/pull/2674)) ([a23294c](https://github.com/newrelic/node-newrelic/commit/a23294c2d2cc665de5df1a0f3c9099dedbfbb896))
6
- * Added IAST configurations for scan scheduling and restrictions ([#2645](https://github.com/newrelic/node-newrelic/pull/2645)) ([13a627a](https://github.com/newrelic/node-newrelic/commit/13a627a1a1529dd8f8c93d0b9f582457c019a63e))
7
-
8
- #### Documentation
9
-
10
- * Updated compatibility report ([#2673](https://github.com/newrelic/node-newrelic/pull/2673)) ([e4d0503](https://github.com/newrelic/node-newrelic/commit/e4d0503934f7de45d3cdb6dbb4640a66cf8d8421))
11
-
12
- #### Miscellaneous chores
13
-
14
- * Replaced static openssl cert usage with in-process cert ([#2671](https://github.com/newrelic/node-newrelic/pull/2671)) ([72872f4](https://github.com/newrelic/node-newrelic/commit/72872f4313fd9bc6d2b358a735dc76b9cda1a489))
15
-
16
- ### v12.5.2 (2024-10-23)
17
-
18
- #### Features
19
-
20
- * Updated shim/when instrumentation to use tracer to run in context ([#2642](https://github.com/newrelic/node-newrelic/pull/2642)) ([1a80ad5](https://github.com/newrelic/node-newrelic/commit/1a80ad56a6d502182a0db368f40443467f7943df))
21
-
22
- #### Bug fixes
23
-
24
- * Fixed amqplib instrumentation via ESM ([#2668](https://github.com/newrelic/node-newrelic/pull/2668)) ([a36deba](https://github.com/newrelic/node-newrelic/commit/a36deba7ba7b46c4947fcb83db0a4f97bd4c0bf1))
25
-
26
- #### Documentation
27
-
28
- * Remove SECURITY.md ([#2633](https://github.com/newrelic/node-newrelic/pull/2633)) ([41002cd](https://github.com/newrelic/node-newrelic/commit/41002cd1c423c378bfbe024ebe7dae03d02d2949))
29
- * Updated compatibility report ([#2670](https://github.com/newrelic/node-newrelic/pull/2670)) ([281c0fa](https://github.com/newrelic/node-newrelic/commit/281c0fa3be096a0ef3eef25b0f51df7ae8bf50bf))
30
- * Updated match custom-assertion jsdoc ([#2636](https://github.com/newrelic/node-newrelic/pull/2636)) ([c37abe5](https://github.com/newrelic/node-newrelic/commit/c37abe5eb4528493bb3950e376bf780d6cd29023))
31
-
32
- #### Miscellaneous chores
33
-
34
- * Upgraded `import-in-the-middle` to work around a bug introduced in 1.11.1 ([#2618](https://github.com/newrelic/node-newrelic/pull/2618)) ([9ad476a](https://github.com/newrelic/node-newrelic/commit/9ad476a765eee472f510239b4265d10f0a50c666))
35
-
36
- #### Tests
37
-
38
- * Migrated `aws-sdk-v2` and `aws-sdk-v3` tests to `node:test` ([#2620](https://github.com/newrelic/node-newrelic/pull/2620)) ([e0dc015](https://github.com/newrelic/node-newrelic/commit/e0dc01571087c3d53434d2d21d77206592137b66))
39
- * Migrated `test/unit/shim` to `node:test` ([#2599](https://github.com/newrelic/node-newrelic/pull/2599)) ([8d1acff](https://github.com/newrelic/node-newrelic/commit/8d1acffabf29ba6e0b5e20a675b87a81f893fc0a))
40
- * Migrated `test/versioned/amqplib` to `node:test` ([#2612](https://github.com/newrelic/node-newrelic/pull/2612)) ([7bdada6](https://github.com/newrelic/node-newrelic/commit/7bdada678c18997c268cf19c56262b870bae5673))
41
- * Migrated `test/versioned/express` to `node:test` ([#2609](https://github.com/newrelic/node-newrelic/pull/2609)) ([bd2f1a5](https://github.com/newrelic/node-newrelic/commit/bd2f1a53f8e03810e3c0aa5d042b6b256ec7346b))
42
- * Migrated bluebird versioned tests to `node:test` ([#2635](https://github.com/newrelic/node-newrelic/pull/2635)) ([6e28fad](https://github.com/newrelic/node-newrelic/commit/6e28fad70390ffaf4df7ccbc96c88f79bb5d2fe2))
43
- * Migrated last group of unit tests to `node:test` ([#2624](https://github.com/newrelic/node-newrelic/pull/2624)) ([386f546](https://github.com/newrelic/node-newrelic/commit/386f54682128d0dda8ad073a57cd45109c927fe1))
44
- * Migrated unit tests to `node:test` ([#2623](https://github.com/newrelic/node-newrelic/pull/2623)) ([86231b7](https://github.com/newrelic/node-newrelic/commit/86231b7dec5bc5807ae26a88a7b8f2ff1535d9c4))
45
- * Updated tests that relied on `tspl` by awating the `plan.completed` instead of calling `end` to avoid flaky tests ([#2610](https://github.com/newrelic/node-newrelic/pull/2610)) ([935ac14](https://github.com/newrelic/node-newrelic/commit/935ac14dbff7d11e797d290fb24a0d791ac9a61a))
46
- * Updated tests that used the context manager directly and instead use the tracer to access the segment context ([#2643](https://github.com/newrelic/node-newrelic/pull/2643)) ([b917b3e](https://github.com/newrelic/node-newrelic/commit/b917b3ea9416eaf64bf365f6f46a0d4eafdfc437))
47
- * Updated the mininum version of pg-native in pg-esm tests to align with the pg tests ([#2616](https://github.com/newrelic/node-newrelic/pull/2616)) ([16be714](https://github.com/newrelic/node-newrelic/commit/16be71404dcea903f3f7b7d4d238cc0a416d7b79))
48
- * Migrated `bunyan`, `pino`, and `winston` tests to `node:test` ([#2634](https://github.com/newrelic/node-newrelic/pull/2634)) ([69c1ab8](https://github.com/newrelic/node-newrelic/commit/69c1ab8951f8cd405986e879399dff716f839a78))
49
- * Migrated `fastify` tests to `node:test` ([#2632](https://github.com/newrelic/node-newrelic/pull/2632)) ([b522477](https://github.com/newrelic/node-newrelic/commit/b522477168c2049b12bcfd39ae485f9e5374f724))
50
- * Migrated block of unit tests to `node:test` ([#2607](https://github.com/newrelic/node-newrelic/pull/2607)) ([e33807b](https://github.com/newrelic/node-newrelic/commit/e33807b817852bb7cdc93c9b171250df17a3b867))
51
- * Migrated block of unit tests to `node:test` ([#2604](https://github.com/newrelic/node-newrelic/pull/2604)) ([cd90ce1](https://github.com/newrelic/node-newrelic/commit/cd90ce11908edc4376a704153f44d4f3ddfb6866))
52
- * Migrated block of unit tests to `node:test` ([#2593](https://github.com/newrelic/node-newrelic/pull/2593)) ([6d4d49e](https://github.com/newrelic/node-newrelic/commit/6d4d49e075d8c4c687d4730b65aa39177e384ce5))
53
-
54
- #### Continuous integration
55
-
56
- * Added delay to site extension publishing to wait for NPM ([#2665](https://github.com/newrelic/node-newrelic/pull/2665)) ([e412020](https://github.com/newrelic/node-newrelic/commit/e412020865bab187d8c7d274cdc6973946286a1f))
57
-
1
+ ### v12.7.0 (2024-11-11)
2
+
3
+ #### Features
4
+
5
+ * Added `cloud.resource_id` attribute to dynamo spans ([#2701](https://github.com/newrelic/node-newrelic/pull/2701)) ([904f41b](https://github.com/newrelic/node-newrelic/commit/904f41b26637394a24aa13f31ff94b100ae6d090))
6
+ * Enhance Proxy Request Handling to Display Actual External URLs ([#2698](https://github.com/newrelic/node-newrelic/pull/2698)) ([3ef7bbe](https://github.com/newrelic/node-newrelic/commit/3ef7bbe595860234c021a02235e6fd0615da5f69))
7
+ * Thanks for the contribution @mstarzec386
8
+
9
+ #### Documentation
10
+
11
+ * Updated compatibility report ([#2712](https://github.com/newrelic/node-newrelic/pull/2712)) ([82f0e98](https://github.com/newrelic/node-newrelic/commit/82f0e9806c88d14cba2e0cdf47593e036107bd7d)) ([#2699](https://github.com/newrelic/node-newrelic/pull/2699)) ([4432c42](https://github.com/newrelic/node-newrelic/commit/4432c4215d68cc79333ee3828f1ecd55476c63d8))
12
+
13
+ #### Miscellaneous chores
14
+
15
+ * Added a benchmark script for our sql parser ([#2708](https://github.com/newrelic/node-newrelic/pull/2708)) ([9b6de68](https://github.com/newrelic/node-newrelic/commit/9b6de6852747230b87a9873faffba6e5b39669f3))
16
+ * Updated express-esm, generic-pool, grpc, & grpc-esm tests to node:test ([#2702](https://github.com/newrelic/node-newrelic/pull/2702)) ([a229bbf](https://github.com/newrelic/node-newrelic/commit/a229bbf0dd92c43fb2da077d8dce831b84c0c972))
17
+
18
+ #### Tests
19
+
20
+ * Migrated `mysql` and `mysql2` versioned tests to `node:test` ([#2711](https://github.com/newrelic/node-newrelic/pull/2711)) ([fc767e0](https://github.com/newrelic/node-newrelic/commit/fc767e08d8b546d14c53c07bc2cfe65f3fb55368))
21
+
22
+ ### v12.6.1 (2024-11-07)
23
+
24
+ #### Features
25
+
26
+ * added `cloud.aws.account_id` to default config ([#2691](https://github.com/newrelic/node-newrelic/pull/2691)) ([0ccee8e](https://github.com/newrelic/node-newrelic/commit/0ccee8e471b5568a36a5ef755f83f0da513548c8))
27
+
28
+ #### Bug fixes
29
+
30
+ * Fixed issue parsing docker container id ([#2705](https://github.com/newrelic/node-newrelic/pull/2705)) ([0c897ab](https://github.com/newrelic/node-newrelic/commit/0c897ab7bea32daf0afbf75e2349f2fad008cc92))
31
+
32
+ #### Documentation
33
+
34
+ * Updated compatibility report ([#2679](https://github.com/newrelic/node-newrelic/pull/2679)) ([3c19cdf](https://github.com/newrelic/node-newrelic/commit/3c19cdfed751dfa20ebba471a6cdd320f0610d95))
35
+
36
+ #### Miscellaneous chores
37
+
38
+ * Moved recorders to `lib/metrics/recorders` ([#2666](https://github.com/newrelic/node-newrelic/pull/2666)) ([d8dfe84](https://github.com/newrelic/node-newrelic/commit/d8dfe843aebf275bda6d5c857cfe263039bc1a83))
39
+
40
+ #### Tests
41
+
42
+ * Fixed file extensions for aws-sdk v2 and v3 versioned tests to reflect they have been migrated to `node:test` ([#2687](https://github.com/newrelic/node-newrelic/pull/2687)) ([4ec09ba](https://github.com/newrelic/node-newrelic/commit/4ec09ba34a825fa9decdc2d854eec6d24ee37ac4))
43
+ * Migrated elasticsearch and esm-package versioned tests to `node:test` ([#2680](https://github.com/newrelic/node-newrelic/pull/2680)) ([0e0c2b2](https://github.com/newrelic/node-newrelic/commit/0e0c2b2f15e2179def4e67741fc988b7d16248d7))
44
+ * Updated cls and connect tests to node:test ([#2676](https://github.com/newrelic/node-newrelic/pull/2676)) ([1e74434](https://github.com/newrelic/node-newrelic/commit/1e74434efd21c13199ad12af837129d251136c76))
45
+ * Reorganized custom assertions and improved test reporter ([#2700](https://github.com/newrelic/node-newrelic/pull/2700)) ([9e98b18](https://github.com/newrelic/node-newrelic/commit/9e98b18b0f2768df9f75348975bebe904418a4a2))
46
+ * Updated cassandra-driver tests to node:test ([#2678](https://github.com/newrelic/node-newrelic/pull/2678)) ([bd4f7ff](https://github.com/newrelic/node-newrelic/commit/bd4f7ff9df2cd1057e21a6ba3e28aac9fe02ecc6))
47
+
48
+ ### v12.6.0 (2024-10-30)
49
+
50
+ #### Features
51
+
52
+ * Added ARN and provider to Lambda segments ([#2674](https://github.com/newrelic/node-newrelic/pull/2674)) ([a23294c](https://github.com/newrelic/node-newrelic/commit/a23294c2d2cc665de5df1a0f3c9099dedbfbb896))
53
+ * Added IAST configurations for scan scheduling and restrictions ([#2645](https://github.com/newrelic/node-newrelic/pull/2645)) ([13a627a](https://github.com/newrelic/node-newrelic/commit/13a627a1a1529dd8f8c93d0b9f582457c019a63e))
54
+
55
+ #### Documentation
56
+
57
+ * Updated compatibility report ([#2673](https://github.com/newrelic/node-newrelic/pull/2673)) ([e4d0503](https://github.com/newrelic/node-newrelic/commit/e4d0503934f7de45d3cdb6dbb4640a66cf8d8421))
58
+
59
+ #### Miscellaneous chores
60
+
61
+ * Replaced static openssl cert usage with in-process cert ([#2671](https://github.com/newrelic/node-newrelic/pull/2671)) ([72872f4](https://github.com/newrelic/node-newrelic/commit/72872f4313fd9bc6d2b358a735dc76b9cda1a489))
62
+
63
+ ### v12.5.2 (2024-10-23)
64
+
65
+ #### Features
66
+
67
+ * Updated shim/when instrumentation to use tracer to run in context ([#2642](https://github.com/newrelic/node-newrelic/pull/2642)) ([1a80ad5](https://github.com/newrelic/node-newrelic/commit/1a80ad56a6d502182a0db368f40443467f7943df))
68
+
69
+ #### Bug fixes
70
+
71
+ * Fixed amqplib instrumentation via ESM ([#2668](https://github.com/newrelic/node-newrelic/pull/2668)) ([a36deba](https://github.com/newrelic/node-newrelic/commit/a36deba7ba7b46c4947fcb83db0a4f97bd4c0bf1))
72
+
73
+ #### Documentation
74
+
75
+ * Remove SECURITY.md ([#2633](https://github.com/newrelic/node-newrelic/pull/2633)) ([41002cd](https://github.com/newrelic/node-newrelic/commit/41002cd1c423c378bfbe024ebe7dae03d02d2949))
76
+ * Updated compatibility report ([#2670](https://github.com/newrelic/node-newrelic/pull/2670)) ([281c0fa](https://github.com/newrelic/node-newrelic/commit/281c0fa3be096a0ef3eef25b0f51df7ae8bf50bf))
77
+ * Updated match custom-assertion jsdoc ([#2636](https://github.com/newrelic/node-newrelic/pull/2636)) ([c37abe5](https://github.com/newrelic/node-newrelic/commit/c37abe5eb4528493bb3950e376bf780d6cd29023))
78
+
79
+ #### Miscellaneous chores
80
+
81
+ * Upgraded `import-in-the-middle` to work around a bug introduced in 1.11.1 ([#2618](https://github.com/newrelic/node-newrelic/pull/2618)) ([9ad476a](https://github.com/newrelic/node-newrelic/commit/9ad476a765eee472f510239b4265d10f0a50c666))
82
+
83
+ #### Tests
84
+
85
+ * Migrated `aws-sdk-v2` and `aws-sdk-v3` tests to `node:test` ([#2620](https://github.com/newrelic/node-newrelic/pull/2620)) ([e0dc015](https://github.com/newrelic/node-newrelic/commit/e0dc01571087c3d53434d2d21d77206592137b66))
86
+ * Migrated `test/unit/shim` to `node:test` ([#2599](https://github.com/newrelic/node-newrelic/pull/2599)) ([8d1acff](https://github.com/newrelic/node-newrelic/commit/8d1acffabf29ba6e0b5e20a675b87a81f893fc0a))
87
+ * Migrated `test/versioned/amqplib` to `node:test` ([#2612](https://github.com/newrelic/node-newrelic/pull/2612)) ([7bdada6](https://github.com/newrelic/node-newrelic/commit/7bdada678c18997c268cf19c56262b870bae5673))
88
+ * Migrated `test/versioned/express` to `node:test` ([#2609](https://github.com/newrelic/node-newrelic/pull/2609)) ([bd2f1a5](https://github.com/newrelic/node-newrelic/commit/bd2f1a53f8e03810e3c0aa5d042b6b256ec7346b))
89
+ * Migrated bluebird versioned tests to `node:test` ([#2635](https://github.com/newrelic/node-newrelic/pull/2635)) ([6e28fad](https://github.com/newrelic/node-newrelic/commit/6e28fad70390ffaf4df7ccbc96c88f79bb5d2fe2))
90
+ * Migrated last group of unit tests to `node:test` ([#2624](https://github.com/newrelic/node-newrelic/pull/2624)) ([386f546](https://github.com/newrelic/node-newrelic/commit/386f54682128d0dda8ad073a57cd45109c927fe1))
91
+ * Migrated unit tests to `node:test` ([#2623](https://github.com/newrelic/node-newrelic/pull/2623)) ([86231b7](https://github.com/newrelic/node-newrelic/commit/86231b7dec5bc5807ae26a88a7b8f2ff1535d9c4))
92
+ * Updated tests that relied on `tspl` by awating the `plan.completed` instead of calling `end` to avoid flaky tests ([#2610](https://github.com/newrelic/node-newrelic/pull/2610)) ([935ac14](https://github.com/newrelic/node-newrelic/commit/935ac14dbff7d11e797d290fb24a0d791ac9a61a))
93
+ * Updated tests that used the context manager directly and instead use the tracer to access the segment context ([#2643](https://github.com/newrelic/node-newrelic/pull/2643)) ([b917b3e](https://github.com/newrelic/node-newrelic/commit/b917b3ea9416eaf64bf365f6f46a0d4eafdfc437))
94
+ * Updated the mininum version of pg-native in pg-esm tests to align with the pg tests ([#2616](https://github.com/newrelic/node-newrelic/pull/2616)) ([16be714](https://github.com/newrelic/node-newrelic/commit/16be71404dcea903f3f7b7d4d238cc0a416d7b79))
95
+ * Migrated `bunyan`, `pino`, and `winston` tests to `node:test` ([#2634](https://github.com/newrelic/node-newrelic/pull/2634)) ([69c1ab8](https://github.com/newrelic/node-newrelic/commit/69c1ab8951f8cd405986e879399dff716f839a78))
96
+ * Migrated `fastify` tests to `node:test` ([#2632](https://github.com/newrelic/node-newrelic/pull/2632)) ([b522477](https://github.com/newrelic/node-newrelic/commit/b522477168c2049b12bcfd39ae485f9e5374f724))
97
+ * Migrated block of unit tests to `node:test` ([#2607](https://github.com/newrelic/node-newrelic/pull/2607)) ([e33807b](https://github.com/newrelic/node-newrelic/commit/e33807b817852bb7cdc93c9b171250df17a3b867))
98
+ * Migrated block of unit tests to `node:test` ([#2604](https://github.com/newrelic/node-newrelic/pull/2604)) ([cd90ce1](https://github.com/newrelic/node-newrelic/commit/cd90ce11908edc4376a704153f44d4f3ddfb6866))
99
+ * Migrated block of unit tests to `node:test` ([#2593](https://github.com/newrelic/node-newrelic/pull/2593)) ([6d4d49e](https://github.com/newrelic/node-newrelic/commit/6d4d49e075d8c4c687d4730b65aa39177e384ce5))
100
+
101
+ #### Continuous integration
102
+
103
+ * Added delay to site extension publishing to wait for NPM ([#2665](https://github.com/newrelic/node-newrelic/pull/2665)) ([e412020](https://github.com/newrelic/node-newrelic/commit/e412020865bab187d8c7d274cdc6973946286a1f))
104
+
58
105
  ### v12.5.1 (2024-09-23)
59
106
 
60
107
  #### Bug fixes
@@ -413,6 +413,17 @@ defaultConfig.definition = () => ({
413
413
  default: false
414
414
  }
415
415
  },
416
+ cloud: {
417
+ aws: {
418
+ /**
419
+ * The AWS account ID for the AWS account associated with this app.
420
+ */
421
+ account_id: {
422
+ formatter: int,
423
+ default: null
424
+ }
425
+ }
426
+ },
416
427
  /**
417
428
  * Options regarding collecting system information. Used for system
418
429
  * utilization based pricing scheme.
@@ -5,9 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const { DB, ALL } = require('../metrics/names')
9
- const { DESTINATIONS } = require('../config/attribute-filter')
10
-
11
8
  function ParsedStatement(type, operation, collection, raw) {
12
9
  this.type = type
13
10
  this.operation = operation
@@ -21,55 +18,4 @@ function ParsedStatement(type, operation, collection, raw) {
21
18
  }
22
19
  }
23
20
 
24
- ParsedStatement.prototype.recordMetrics = function recordMetrics(segment, scope) {
25
- const duration = segment.getDurationInMillis()
26
- const exclusive = segment.getExclusiveDurationInMillis()
27
- const transaction = segment.transaction
28
- const type = transaction.isWeb() ? DB.WEB : DB.OTHER
29
- const thisTypeSlash = this.type + '/'
30
- const operation = DB.OPERATION + '/' + thisTypeSlash + this.operation
31
-
32
- // Note, an operation metric should _always_ be created even if the action was
33
- // a statement. This is part of the spec.
34
-
35
- // Rollups
36
- transaction.measure(operation, null, duration, exclusive)
37
- transaction.measure(DB.PREFIX + type, null, duration, exclusive)
38
- transaction.measure(DB.PREFIX + thisTypeSlash + type, null, duration, exclusive)
39
- transaction.measure(DB.PREFIX + thisTypeSlash + ALL, null, duration, exclusive)
40
- transaction.measure(DB.ALL, null, duration, exclusive)
41
-
42
- // If we can parse the SQL statement, create a 'statement' metric, and use it
43
- // as the scoped metric for transaction breakdowns. Otherwise, skip the
44
- // 'statement' metric and use the 'operation' metric as the scoped metric for
45
- // transaction breakdowns.
46
- let collection
47
- if (this.collection) {
48
- collection = DB.STATEMENT + '/' + thisTypeSlash + this.collection + '/' + this.operation
49
- transaction.measure(collection, null, duration, exclusive)
50
- if (scope) {
51
- transaction.measure(collection, scope, duration, exclusive)
52
- }
53
- } else if (scope) {
54
- transaction.measure(operation, scope, duration, exclusive)
55
- }
56
-
57
- // This recorder is side-effectful Because we are depending on the recorder
58
- // setting the transaction name, recorders must always be run before generating
59
- // the final transaction trace
60
- segment.name = collection || operation
61
-
62
- // Datastore instance metrics.
63
- const attributes = segment.attributes.get(DESTINATIONS.TRANS_SEGMENT)
64
- if (attributes.host && attributes.port_path_or_id) {
65
- const instanceName =
66
- DB.INSTANCE + '/' + thisTypeSlash + attributes.host + '/' + attributes.port_path_or_id
67
- transaction.measure(instanceName, null, duration, exclusive)
68
- }
69
-
70
- if (this.raw) {
71
- transaction.agent.queries.add(segment, this.type.toLowerCase(), this.raw, this.trace)
72
- }
73
- }
74
-
75
21
  module.exports = ParsedStatement
@@ -72,21 +72,66 @@ function dynamoMiddleware(shim, config, next, context) {
72
72
  }
73
73
  }
74
74
 
75
- const dynamoMiddlewareConfig = {
76
- middleware: dynamoMiddleware,
77
- init(shim) {
78
- shim.setDatastore(shim.DYNAMODB)
79
- return true
80
- },
81
- type: InstrumentationDescriptor.TYPE_DATASTORE,
82
- config: {
83
- name: 'NewRelicDynamoMiddleware',
84
- step: 'initialize',
85
- priority: 'high',
86
- override: true
75
+ /**
76
+ * Wraps the deserialize middleware step to add the
77
+ * cloud.resource_id segment attributes for the AWS command
78
+ *
79
+ * @param {Shim} shim
80
+ * @param {Object} config AWS command configuration
81
+ * @param {function} next next function in middleware chain
82
+ * @returns {function}
83
+ */
84
+ function resourceIdMiddlerware(shim, config, next) {
85
+ return async function wrappedResourceIdMiddlerware(args) {
86
+ let region
87
+ try {
88
+ region = await config.region()
89
+ const segment = shim.getSegment()
90
+
91
+ const accountId = shim.agent.config.cloud.aws.account_id
92
+
93
+ if (accountId) {
94
+ const attributes = segment.getAttributes()
95
+ segment.addAttribute(
96
+ 'cloud.resource_id',
97
+ `arn:aws:dynamodb:${region}:${accountId}:table/${attributes.collection}`
98
+ )
99
+ }
100
+ } catch (err) {
101
+ shim.logger.debug(err, 'Failed to add AWS cloud resource id to segment')
102
+ }
103
+
104
+ return next(args)
87
105
  }
88
106
  }
89
107
 
108
+ const dynamoMiddlewareConfig = [
109
+ {
110
+ middleware: dynamoMiddleware,
111
+ init(shim) {
112
+ shim.setDatastore(shim.DYNAMODB)
113
+ return true
114
+ },
115
+ type: InstrumentationDescriptor.TYPE_DATASTORE,
116
+ config: {
117
+ name: 'NewRelicDynamoMiddleware',
118
+ step: 'initialize',
119
+ priority: 'high',
120
+ override: true
121
+ }
122
+ },
123
+ {
124
+ middleware: resourceIdMiddlerware,
125
+ type: InstrumentationDescriptor.TYPE_GENERIC,
126
+ config: {
127
+ name: 'NewRelicCloudResource',
128
+ step: 'deserialize',
129
+ priority: 'low',
130
+ override: true
131
+ }
132
+ }
133
+ ]
134
+
90
135
  module.exports = {
91
136
  dynamoMiddlewareConfig
92
137
  }
@@ -17,8 +17,8 @@ const middlewareByClient = {
17
17
  BedrockRuntime: [...middlewareConfig, bedrockMiddlewareConfig],
18
18
  SNS: [...middlewareConfig, snsMiddlewareConfig],
19
19
  SQS: [...middlewareConfig, sqsMiddlewareConfig],
20
- DynamoDB: [...middlewareConfig, dynamoMiddlewareConfig],
21
- DynamoDBDocument: [...middlewareConfig, dynamoMiddlewareConfig]
20
+ DynamoDB: [...middlewareConfig, ...dynamoMiddlewareConfig],
21
+ DynamoDBDocument: [...middlewareConfig, ...dynamoMiddlewareConfig]
22
22
  }
23
23
 
24
24
  module.exports = function instrumentSmithyClient(shim, smithyClientExport) {
@@ -15,6 +15,7 @@ const copy = require('../../util/copy')
15
15
  const symbols = require('../../symbols')
16
16
  const http = require('http')
17
17
  const synthetics = require('../../synthetics')
18
+ const { URL } = require('node:url')
18
19
 
19
20
  const NAMES = require('../../metrics/names')
20
21
  const DEFAULT_HOST = 'localhost'
@@ -93,6 +94,27 @@ function extractHostPort(opts) {
93
94
  return { host, hostname, port }
94
95
  }
95
96
 
97
+ /**
98
+ * Extracts the host, hostname, and port from HTTP request options when using a proxy
99
+ *
100
+ * @param {object} opts HTTP request options
101
+ * @returns {object|null} { host, hostname, port } if proxy request is detected, or null otherwise.
102
+ */
103
+ function extractHostPortViaProxy(opts) {
104
+ const pathname = opts.pathname || opts.path
105
+
106
+ if (pathname && (pathname.startsWith('https://') || pathname.startsWith('http://'))) {
107
+ const url = new URL(pathname)
108
+ return {
109
+ host: url.host,
110
+ hostname: url.hostname,
111
+ port: url.port || url.protocol === 'https:' ? '443' : '80'
112
+ }
113
+ }
114
+
115
+ return null
116
+ }
117
+
96
118
  /**
97
119
  * Instruments an outbound HTTP request.
98
120
  *
@@ -103,7 +125,9 @@ function extractHostPort(opts) {
103
125
  */
104
126
  module.exports = function instrumentOutbound(agent, opts, makeRequest) {
105
127
  opts = parseOpts(opts)
106
- const { host, hostname, port } = extractHostPort(opts)
128
+
129
+ const viaProxy = extractHostPortViaProxy(opts)
130
+ const { host, hostname, port } = viaProxy ? viaProxy : extractHostPort(opts)
107
131
 
108
132
  if (!hostname || port < 1) {
109
133
  logger.warn('Invalid host name (%s) or port (%s) for outbound request.', hostname, port)
@@ -127,7 +127,7 @@ function wrapResponse(shim, response) {
127
127
  if (!shim.isFunction(cb)) {
128
128
  ++cbIdx
129
129
  cb = function defaultRenderCB(err, str) {
130
- // https://github.com/expressjs/express/blob/4.x/lib/response.js#L961-L962
130
+ // https://github.com/expressjs/express/blob/4.x/lib/response.js#L961-L962
131
131
  if (err) {
132
132
  return res.req.next(err)
133
133
  }
@@ -0,0 +1,62 @@
1
+ /*
2
+ * Copyright 2024 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const metrics = require('../names')
9
+
10
+ /**
11
+ * Records all the metrics required for database operations.
12
+ *
13
+ * - `recordOperationMetrics(segment [, scope])`
14
+ *
15
+ * @private
16
+ * @this DatastoreShim
17
+ * @implements {MetricFunction}
18
+ * @param {TraceSegment} segment - The segment being recorded.
19
+ * @param {string} [scope] - The scope of the segment.
20
+ * @see DatastoreShim#recordOperation
21
+ * @see MetricFunction
22
+ */
23
+ function recordOperationMetrics(segment, scope) {
24
+ if (!segment) {
25
+ return
26
+ }
27
+
28
+ const duration = segment.getDurationInMillis()
29
+ const exclusive = segment.getExclusiveDurationInMillis()
30
+ const transaction = segment.transaction
31
+ const type = transaction.isWeb() ? 'allWeb' : 'allOther'
32
+ const operation = segment.name
33
+
34
+ if (scope) {
35
+ transaction.measure(operation, scope, duration, exclusive)
36
+ }
37
+
38
+ transaction.measure(operation, null, duration, exclusive)
39
+ transaction.measure(metrics.DB.PREFIX + type, null, duration, exclusive)
40
+ transaction.measure(metrics.DB.ALL, null, duration, exclusive)
41
+ transaction.measure(this._metrics.ALL, null, duration, exclusive)
42
+ transaction.measure(
43
+ metrics.DB.PREFIX + this._metrics.PREFIX + '/' + type,
44
+ null,
45
+ duration,
46
+ exclusive
47
+ )
48
+
49
+ const attributes = segment.getAttributes()
50
+ if (attributes.host && attributes.port_path_or_id) {
51
+ const instanceName = [
52
+ metrics.DB.INSTANCE,
53
+ this._metrics.PREFIX,
54
+ attributes.host,
55
+ attributes.port_path_or_id
56
+ ].join('/')
57
+
58
+ transaction.measure(instanceName, null, duration, exclusive)
59
+ }
60
+ }
61
+
62
+ module.exports = recordOperationMetrics
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Copyright 2024 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ const { DB, ALL } = require('../names')
9
+ const { DESTINATIONS } = require('../../config/attribute-filter')
10
+
11
+ /**
12
+ * @this ParsedStatement
13
+ * @param {TraceSegment} segment - The segment being recorded.
14
+ * @param {string} [scope] - The scope of the segment.
15
+ */
16
+
17
+ function recordQueryMetrics(segment, scope) {
18
+ const duration = segment.getDurationInMillis()
19
+ const exclusive = segment.getExclusiveDurationInMillis()
20
+ const transaction = segment.transaction
21
+ const type = transaction.isWeb() ? DB.WEB : DB.OTHER
22
+ const thisTypeSlash = this.type + '/'
23
+ const operation = DB.OPERATION + '/' + thisTypeSlash + this.operation
24
+
25
+ // Note, an operation metric should _always_ be created even if the action was
26
+ // a statement. This is part of the spec.
27
+
28
+ // Rollups
29
+ transaction.measure(operation, null, duration, exclusive)
30
+ transaction.measure(DB.PREFIX + type, null, duration, exclusive)
31
+ transaction.measure(DB.PREFIX + thisTypeSlash + type, null, duration, exclusive)
32
+ transaction.measure(DB.PREFIX + thisTypeSlash + ALL, null, duration, exclusive)
33
+ transaction.measure(DB.ALL, null, duration, exclusive)
34
+
35
+ // If we can parse the SQL statement, create a 'statement' metric, and use it
36
+ // as the scoped metric for transaction breakdowns. Otherwise, skip the
37
+ // 'statement' metric and use the 'operation' metric as the scoped metric for
38
+ // transaction breakdowns.
39
+ let collection
40
+ if (this.collection) {
41
+ collection = DB.STATEMENT + '/' + thisTypeSlash + this.collection + '/' + this.operation
42
+ transaction.measure(collection, null, duration, exclusive)
43
+ if (scope) {
44
+ transaction.measure(collection, scope, duration, exclusive)
45
+ }
46
+ } else if (scope) {
47
+ transaction.measure(operation, scope, duration, exclusive)
48
+ }
49
+
50
+ // This recorder is side-effectful Because we are depending on the recorder
51
+ // setting the transaction name, recorders must always be run before generating
52
+ // the final transaction trace
53
+ segment.name = collection || operation
54
+
55
+ // Datastore instance metrics.
56
+ const attributes = segment.attributes.get(DESTINATIONS.TRANS_SEGMENT)
57
+ if (attributes.host && attributes.port_path_or_id) {
58
+ const instanceName =
59
+ DB.INSTANCE + '/' + thisTypeSlash + attributes.host + '/' + attributes.port_path_or_id
60
+ transaction.measure(instanceName, null, duration, exclusive)
61
+ }
62
+
63
+ if (this.raw) {
64
+ segment.transaction.agent.queries.add(segment, this.type.toLowerCase(), this.raw, this.trace)
65
+ }
66
+ }
67
+
68
+ module.exports = recordQueryMetrics
@@ -0,0 +1,29 @@
1
+ /*
2
+ * Copyright 2024 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+
6
+ 'use strict'
7
+
8
+ /**
9
+ * Creates a recorder for middleware metrics.
10
+ *
11
+ * @private
12
+ * @param {object} _shim instance of shim
13
+ * @param {string} metricName name of metric
14
+ * @returns {Function} recorder for middleware
15
+ */
16
+ function makeMiddlewareRecorder(_shim, metricName) {
17
+ return function middlewareMetricRecorder(segment, scope) {
18
+ const duration = segment.getDurationInMillis()
19
+ const exclusive = segment.getExclusiveDurationInMillis()
20
+ const transaction = segment.transaction
21
+
22
+ if (scope) {
23
+ transaction.measure(metricName, scope, duration, exclusive)
24
+ }
25
+ transaction.measure(metricName, null, duration, exclusive)
26
+ }
27
+ }
28
+
29
+ module.exports = makeMiddlewareRecorder
@@ -15,7 +15,9 @@ const Shim = require('./shim')
15
15
  const urltils = require('../util/urltils')
16
16
  const util = require('util')
17
17
  const specs = require('./specs')
18
+ const recordOperationMetrics = require('../../lib/metrics/recorders/database-operation')
18
19
  const { DatastoreParameters } = specs.params
20
+ const recordQueryMetrics = require('../../lib/metrics/recorders/database')
19
21
 
20
22
  /**
21
23
  * An enumeration of well-known datastores so that new instrumentations can use
@@ -284,7 +286,7 @@ function recordOperation(nodule, properties, opSpec) {
284
286
  if (!segDesc?.name?.startsWith(shim._metrics.OPERATION)) {
285
287
  segDesc.name = shim._metrics.OPERATION + segDesc.name
286
288
  }
287
- segDesc.recorder = _recordOperationMetrics.bind(shim)
289
+ segDesc.recorder = recordOperationMetrics.bind(shim)
288
290
  }
289
291
 
290
292
  return segDesc
@@ -567,7 +569,7 @@ function _recordQuery(suffix, nodule, properties, querySpec) {
567
569
  const name = (parsed.collection || 'other') + '/' + parsed.operation + suffix
568
570
  shim.logger.trace('Found and parsed query %s -> %s', parsed.type, name)
569
571
  segDesc.name = shim._metrics.STATEMENT + name
570
- segDesc.recorder = _recordQueryMetrics.bind(null, parsed)
572
+ segDesc.recorder = recordQueryMetrics.bind(parsed)
571
573
  }
572
574
 
573
575
  return segDesc
@@ -598,72 +600,6 @@ function _getSpec({ spec, shim, fn, fnName, args }) {
598
600
  return dsSpec
599
601
  }
600
602
 
601
- /**
602
- * Records all query metrics when a segment is active
603
- *
604
- * @private
605
- * @param {ParsedStatement} parsed instance of ParsedStatement
606
- * @param {TraceSegment} segment active segment
607
- * @param {string} scope scope of metrics if it exists
608
- */
609
- function _recordQueryMetrics(parsed, segment, scope) {
610
- if (segment) {
611
- parsed.recordMetrics(segment, scope)
612
- }
613
- }
614
-
615
- /**
616
- * Records all the metrics required for database operations.
617
- *
618
- * - `_recordOperationMetrics(segment [, scope])`
619
- *
620
- * @private
621
- * @this DatastoreShim
622
- * @implements {MetricFunction}
623
- * @param {TraceSegment} segment - The segment being recorded.
624
- * @param {string} [scope] - The scope of the segment.
625
- * @see DatastoreShim#recordOperation
626
- * @see MetricFunction
627
- */
628
- function _recordOperationMetrics(segment, scope) {
629
- if (!segment) {
630
- return
631
- }
632
-
633
- const duration = segment.getDurationInMillis()
634
- const exclusive = segment.getExclusiveDurationInMillis()
635
- const transaction = segment.transaction
636
- const type = transaction.isWeb() ? 'allWeb' : 'allOther'
637
- const operation = segment.name
638
-
639
- if (scope) {
640
- transaction.measure(operation, scope, duration, exclusive)
641
- }
642
-
643
- transaction.measure(operation, null, duration, exclusive)
644
- transaction.measure(metrics.DB.PREFIX + type, null, duration, exclusive)
645
- transaction.measure(metrics.DB.ALL, null, duration, exclusive)
646
- transaction.measure(this._metrics.ALL, null, duration, exclusive)
647
- transaction.measure(
648
- metrics.DB.PREFIX + this._metrics.PREFIX + '/' + type,
649
- null,
650
- duration,
651
- exclusive
652
- )
653
-
654
- const attributes = segment.getAttributes()
655
- if (attributes.host && attributes.port_path_or_id) {
656
- const instanceName = [
657
- metrics.DB.INSTANCE,
658
- this._metrics.PREFIX,
659
- attributes.host,
660
- attributes.port_path_or_id
661
- ].join('/')
662
-
663
- transaction.measure(instanceName, null, duration, exclusive)
664
- }
665
- }
666
-
667
603
  /**
668
604
  * Extracts the query string from the arguments according to the given spec.
669
605
  *
@@ -13,6 +13,7 @@ const {
13
13
  } = require('./common')
14
14
  const { assignCLMSymbol } = require('../../util/code-level-metrics')
15
15
  const { RecorderSpec } = require('../specs')
16
+ const makeMiddlewareRecorder = require('../../metrics/recorders/middleware')
16
17
 
17
18
  const MIDDLEWARE_TYPE_DETAILS = {
18
19
  APPLICATION: { name: 'Mounted App: ', path: true, record: false },
@@ -88,7 +89,7 @@ function constructRecorder({ txInfo, typeDetails, shim, metricName }) {
88
89
  let recorder = null
89
90
  if (typeDetails.record) {
90
91
  const stackPath = txInfo.transaction.nameState.getPath() || ''
91
- recorder = _makeMiddlewareRecorder(shim, metricName + '/' + stackPath)
92
+ recorder = makeMiddlewareRecorder(shim, metricName + '/' + stackPath)
92
93
  }
93
94
  return recorder
94
95
  }
@@ -325,27 +326,6 @@ module.exports._recordMiddleware = function _recordMiddleware(shim, middleware,
325
326
  )
326
327
  }
327
328
 
328
- /**
329
- * Creates a recorder for middleware metrics.
330
- *
331
- * @private
332
- * @param {object} _shim instance of shim
333
- * @param {string} metricName name of metric
334
- * @returns {Function} recorder for middleware
335
- */
336
- function _makeMiddlewareRecorder(_shim, metricName) {
337
- return function middlewareMetricRecorder(segment, scope) {
338
- const duration = segment.getDurationInMillis()
339
- const exclusive = segment.getExclusiveDurationInMillis()
340
- const transaction = segment.transaction
341
-
342
- if (scope) {
343
- transaction.measure(metricName, scope, duration, exclusive)
344
- }
345
- transaction.measure(metricName, null, duration, exclusive)
346
- }
347
- }
348
-
349
329
  /**
350
330
  * Wrap the `next` middleware function and push on our name state if we find it. We only want to
351
331
  * push the name state if there is a next so that we can safely remove it
@@ -116,11 +116,27 @@ function fetchDockerVendorInfo(agent, callback, logger = log) {
116
116
  logger.debug(
117
117
  `${CGROUPS_V2_PATH} not found, trying to parse container id from ${CGROUPS_V1_PATH}`
118
118
  )
119
- findCGroupsV1(callback)
119
+ findCGroupsV1(callback, logger)
120
120
  return
121
121
  }
122
122
 
123
- parseCGroupsV2(data, callback)
123
+ parseCGroupsV2(
124
+ data,
125
+ (_, v2Data) => {
126
+ if (v2Data !== null) {
127
+ // We found a valid Docker identifier in the v2 file, so we are going
128
+ // to prioritize it.
129
+ return callback(null, v2Data)
130
+ }
131
+
132
+ // For some reason, we have a /proc/self/mountinfo but it does not have
133
+ // any Docker information in it (that we have detected). So we will
134
+ // fall back to trying the cgroups v1 file.
135
+ logger.debug(`Attempting to fall back to cgroups v1 parsing.`)
136
+ findCGroupsV1(callback, logger)
137
+ },
138
+ logger
139
+ )
124
140
  })
125
141
  }
126
142
 
@@ -136,6 +152,7 @@ function parseCGroupsV2(data, callback, logger = log) {
136
152
  const containerLine = new RegExp('/docker/containers/([0-9a-f]{64})/')
137
153
  const line = containerLine.exec(data)
138
154
  if (line) {
155
+ logger.debug(`Found docker id from cgroups v2: ${line[1]}`)
139
156
  callback(null, { id: line[1] })
140
157
  } else {
141
158
  logger.debug(`Found ${CGROUPS_V2_PATH} but failed to parse Docker container id.`)
@@ -169,7 +186,8 @@ function findCGroupsV1(callback, logger = log) {
169
186
  })
170
187
 
171
188
  if (id) {
172
- vendorInfo = { id: id }
189
+ vendorInfo = { id }
190
+ logger.debug(`Found docker id from cgroups v1: ${id}`)
173
191
  callback(null, vendorInfo)
174
192
  } else {
175
193
  logger.debug('No matching cpu group found.')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "newrelic",
3
- "version": "12.6.0",
3
+ "version": "12.7.0",
4
4
  "author": "New Relic Node.js agent team <nodejs@newrelic.com>",
5
5
  "license": "Apache-2.0",
6
6
  "contributors": [