newrelic 12.7.0 → 12.8.1
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 +75 -0
- package/README.md +2 -2
- package/THIRD_PARTY_NOTICES.md +13 -42
- package/lib/agent.js +35 -27
- package/lib/aggregators/log-aggregator.js +13 -1
- package/lib/collector/facts.js +1 -2
- package/lib/config/default.js +16 -0
- package/lib/config/index.js +30 -0
- package/lib/instrumentation/mysql/mysql.js +93 -40
- package/lib/instrumentation/nr-winston-transport.js +1 -1
- package/lib/instrumentation/pino/pino.js +2 -15
- package/lib/llm-events/aws-bedrock/bedrock-command.js +13 -4
- package/lib/metrics/names.js +2 -1
- package/lib/serverless/api-gateway.js +72 -37
- package/lib/util/application-logging.js +58 -0
- package/lib/util/label-parser.js +7 -6
- package/package.json +3 -4
package/NEWS.md
CHANGED
|
@@ -1,3 +1,78 @@
|
|
|
1
|
+
### v12.8.1 (2024-12-04)
|
|
2
|
+
|
|
3
|
+
#### Bug fixes
|
|
4
|
+
|
|
5
|
+
* Fixed matching for ALB and API Gateway (v1 & v2) events for Lambda ([#2780](https://github.com/newrelic/node-newrelic/pull/2780)) ([2f1a6c6](https://github.com/newrelic/node-newrelic/commit/2f1a6c6dc6e4408c62b074d71a95b67cc0926785))
|
|
6
|
+
* Updated `mysql2` instrumentation to work with 3.11.5+ ([#2811](https://github.com/newrelic/node-newrelic/pull/2811)) ([3ec4fee](https://github.com/newrelic/node-newrelic/commit/3ec4fee486c6f609426deddb7cee8372e4dc1192))
|
|
7
|
+
|
|
8
|
+
#### Documentation
|
|
9
|
+
|
|
10
|
+
* Fixed changelog to group the labels in logs work ([#2776](https://github.com/newrelic/node-newrelic/pull/2776)) ([04271da](https://github.com/newrelic/node-newrelic/commit/04271dae2306f54d885aa723eebc3041edee2575))
|
|
11
|
+
* Fixed links to next.js apps ([#2812](https://github.com/newrelic/node-newrelic/pull/2812)) ([834440c](https://github.com/newrelic/node-newrelic/commit/834440caee017fe632b354d20112c3016587064b))
|
|
12
|
+
* Updated compatibility report ([#2809](https://github.com/newrelic/node-newrelic/pull/2809)) ([fc1fbda](https://github.com/newrelic/node-newrelic/commit/fc1fbdaf69c82caf4d7933c7fdd4eec395648e63))
|
|
13
|
+
|
|
14
|
+
#### Tests
|
|
15
|
+
|
|
16
|
+
* Migrated `test/integration/api` tests to `node:test` ([#2787](https://github.com/newrelic/node-newrelic/pull/2787)) ([03b01a3](https://github.com/newrelic/node-newrelic/commit/03b01a3bf40c8902c29c772aee4d70af8020ae62))
|
|
17
|
+
* Migrated `test/integration/core` tests to `node:test` ([#2781](https://github.com/newrelic/node-newrelic/pull/2781)) ([36bc0e7](https://github.com/newrelic/node-newrelic/commit/36bc0e7f97f1bbde522031942ec0cc7c1d4c1349))
|
|
18
|
+
* Migrated `test/integration/instrumentation` tests to `node:test` ([#2784](https://github.com/newrelic/node-newrelic/pull/2784)) ([963fb30](https://github.com/newrelic/node-newrelic/commit/963fb30087e1b9a7bf12c4ae71b8252a872e90e5))
|
|
19
|
+
* Migrated `test/integration/transaction` tests to `node:test` ([#2783](https://github.com/newrelic/node-newrelic/pull/2783)) ([68e1a0c](https://github.com/newrelic/node-newrelic/commit/68e1a0c8c529702fafb29a7684f6982b0d3c48cb))
|
|
20
|
+
* Migrated `test/integration/utilization` tests to node `node:test` ([#2794](https://github.com/newrelic/node-newrelic/pull/2794)) ([db237e9](https://github.com/newrelic/node-newrelic/commit/db237e9b8811554472b4f83100b3266ce52dc38b))
|
|
21
|
+
* Migrated `test/smoke/api` tests to `node:test` ([#2772](https://github.com/newrelic/node-newrelic/pull/2772)) ([af3bbcd](https://github.com/newrelic/node-newrelic/commit/af3bbcddd1e9ed28fdea32b2837bf509737181cc))
|
|
22
|
+
* Migrated CAT integration tests to `node:test` ([#2778](https://github.com/newrelic/node-newrelic/pull/2778)) ([bd9df5f](https://github.com/newrelic/node-newrelic/commit/bd9df5f0def633391762a191c16886735cddf9d2))
|
|
23
|
+
* Migrated integration tests at root to `node:test` ([#2803](https://github.com/newrelic/node-newrelic/pull/2803)) ([a7ef080](https://github.com/newrelic/node-newrelic/commit/a7ef080296b79d5fb8d313aa2bd9d474904e0a22))
|
|
24
|
+
* Migrated root smoke tests to `node:test` ([#2771](https://github.com/newrelic/node-newrelic/pull/2771)) ([78f2709](https://github.com/newrelic/node-newrelic/commit/78f2709a24328225f0c3c2392cf0a3b8072a877f))
|
|
25
|
+
* Migrated smoke tests in `test/smoke/agent`, `test/smoke/e2e`, and `test/smoke/index` to `node:test` ([#2774](https://github.com/newrelic/node-newrelic/pull/2774)) ([440a0af](https://github.com/newrelic/node-newrelic/commit/440a0af5545c0585d1bb5036b950f201444566db))
|
|
26
|
+
* Removed `t.diagnostic` as they are better suited as code comments ([#2786](https://github.com/newrelic/node-newrelic/pull/2786)) ([ee24027](https://github.com/newrelic/node-newrelic/commit/ee24027539aa2a6b5c8ab4c49529ff7f4fb8f269))
|
|
27
|
+
* Fixed flaky test on macOS ([#2790](https://github.com/newrelic/node-newrelic/pull/2790)) ([eebf06b](https://github.com/newrelic/node-newrelic/commit/eebf06b16c86cd40402c8d5566e01ca140802b24))
|
|
28
|
+
* Removed reference to `pino` internals ([#2805](https://github.com/newrelic/node-newrelic/pull/2805)) ([0382ee2](https://github.com/newrelic/node-newrelic/commit/0382ee26342546467f2f3b93be1c82d74e9d0123))
|
|
29
|
+
* Restricted `mysql2` version to get CI working ([#2808](https://github.com/newrelic/node-newrelic/pull/2808)) ([ad60ed4](https://github.com/newrelic/node-newrelic/commit/ad60ed4faf69d7c7938d63f335186323327e350f))
|
|
30
|
+
* Updated agent integration tests to `node:test` ([#2782](https://github.com/newrelic/node-newrelic/pull/2782)) ([d556512](https://github.com/newrelic/node-newrelic/commit/d556512ffebe3f38887aae65706dc5f1da4122d8))
|
|
31
|
+
* Updated config integration tests to `node:test` ([#2777](https://github.com/newrelic/node-newrelic/pull/2777)) ([fe8d2df](https://github.com/newrelic/node-newrelic/commit/fe8d2df36ccc7d818bbc7350985034767ca221b5))
|
|
32
|
+
* Updated distributed-tracing integration tests to `node:test` ([#2798](https://github.com/newrelic/node-newrelic/pull/2798)) ([83ad1f3](https://github.com/newrelic/node-newrelic/commit/83ad1f3e72f06211993b5dcbc2a5af4a27b259fe))
|
|
33
|
+
* Updated `grpc` integration tests to `node:test` ([#2789](https://github.com/newrelic/node-newrelic/pull/2789)) ([ea8f743](https://github.com/newrelic/node-newrelic/commit/ea8f743c7ef0d8bad0aa25f77b239ea18da59368))
|
|
34
|
+
* Updated index, issue-2155, and metric integration tests to `node:test` ([#2801](https://github.com/newrelic/node-newrelic/pull/2801)) ([80b55c2](https://github.com/newrelic/node-newrelic/commit/80b55c211aa9712ba79e39b236257583d4ccffd3))
|
|
35
|
+
* Updated `q`, `superagent`, and `when` tests to `node:test` ([#2773](https://github.com/newrelic/node-newrelic/pull/2773)) ([ff2d8d0](https://github.com/newrelic/node-newrelic/commit/ff2d8d02df8f602adbed3e361763ed406b891d21))
|
|
36
|
+
* Updated shimmer, uninstrumented, environment, flatten, and logger integration tests to `node:test` ([#2802](https://github.com/newrelic/node-newrelic/pull/2802)) ([83fd7ee](https://github.com/newrelic/node-newrelic/commit/83fd7ee912f5548b651bfa4c1ad7d7cbbc304092))
|
|
37
|
+
* Added per test file timing to test reporter ([#2785](https://github.com/newrelic/node-newrelic/pull/2785)) ([00d9940](https://github.com/newrelic/node-newrelic/commit/00d994086a228a096aaabb1f7f8af1f2f5ffc954))
|
|
38
|
+
|
|
39
|
+
### v12.8.0 (2024-11-19)
|
|
40
|
+
|
|
41
|
+
#### Features
|
|
42
|
+
|
|
43
|
+
* Added new configuration options to add custom tags (labels) to logs ([#2743](https://github.com/newrelic/node-newrelic/pull/2743)) ([d20c874](https://github.com/newrelic/node-newrelic/commit/d20c874638ebb19f8888003d4402bce17e56360f))
|
|
44
|
+
* With custom tags on logs, platform engineers can easily filter, search, and correlate log data for faster and more efficient troubleshooting, improved performance, and optimized resource utilization. To learn more about this feature see the [documentation](https://docs.newrelic.com/docs/logs/logs-context/custom-tags-agent-forwarder-logs/)
|
|
45
|
+
* To enable set `config.application_logging.forwarding.labels.enabled` to `true` or the environment variable `NEW_RELIC_APPLICATION_LOGGING_FORWARDING_LABELS_ENABLED` to `true` ([#2727](https://github.com/newrelic/node-newrelic/pull/2727)) ([36adb13](https://github.com/newrelic/node-newrelic/commit/36adb13caad41a5df5a5fa9345b9dcb9061db969))
|
|
46
|
+
* To exclude labels that were set on application from logs use `config.application_logging.forwarding.labels.exclude` or the environment variable `NEW_RELIC_APPLICATION_LOGGING_FORWARDING_LABELS_EXCLUDE`
|
|
47
|
+
* Added support for Bedrock Claude 3.5 invoke model user request ([#2721](https://github.com/newrelic/node-newrelic/pull/2721)) ([a901a24](https://github.com/newrelic/node-newrelic/commit/a901a2499e73e0f1142054ead53e7b99df94b201))
|
|
48
|
+
* Moved `entity.guid`, `entity.name`, `entity.type`, and `hostname` to `common.attributes` on logs payload instead of in every log message ([#2736](https://github.com/newrelic/node-newrelic/pull/2736)) ([a7f14de](https://github.com/newrelic/node-newrelic/commit/a7f14def489000ab7492b01155069b1a084eeb36))
|
|
49
|
+
|
|
50
|
+
#### Bug fixes
|
|
51
|
+
|
|
52
|
+
* Corrected expected shape of user input in get Prompt() ([#2741](https://github.com/newrelic/node-newrelic/pull/2741)) ([a8eef8b](https://github.com/newrelic/node-newrelic/commit/a8eef8b0f80ec2b0db5834a722a69f58a32b5676))
|
|
53
|
+
|
|
54
|
+
#### Documentation
|
|
55
|
+
|
|
56
|
+
* Updated compatibility report ([#2755](https://github.com/newrelic/node-newrelic/pull/2755)) ([459a3f1](https://github.com/newrelic/node-newrelic/commit/459a3f19ee080a3a2e560636ce087f9e91bc529e))
|
|
57
|
+
|
|
58
|
+
#### Miscellaneous chores
|
|
59
|
+
|
|
60
|
+
* Fixed test reporter ([#2751](https://github.com/newrelic/node-newrelic/pull/2751)) ([5878ef9](https://github.com/newrelic/node-newrelic/commit/5878ef9844fd56038d08e3b2f8cd9e26ba8c4c92))
|
|
61
|
+
* Improved unit test speed ([#2728](https://github.com/newrelic/node-newrelic/pull/2728)) ([9640030](https://github.com/newrelic/node-newrelic/commit/96400304e451502ce2f09b569b46eaff271fd9ab))
|
|
62
|
+
|
|
63
|
+
#### Tests
|
|
64
|
+
|
|
65
|
+
* Fixed two assertions to work against older versions of `openai` ([#2726](https://github.com/newrelic/node-newrelic/pull/2726)) ([8996fc3](https://github.com/newrelic/node-newrelic/commit/8996fc3538735d7ad2d447bc7c4221b08c6c2be5))
|
|
66
|
+
* Migrated `ioredis`, `prisma` and `undici` versioned tests to `node:test` ([#2746](https://github.com/newrelic/node-newrelic/pull/2746)) ([449ae03](https://github.com/newrelic/node-newrelic/commit/449ae03883d2a5e92d11590372993eedc976ab99))
|
|
67
|
+
* Migrated `memcached`, `nestjs`, and `restify` versioned tests to `node:test` ([#2752](https://github.com/newrelic/node-newrelic/pull/2752)) ([653f614](https://github.com/newrelic/node-newrelic/commit/653f61410a0258683ac104cd8b8b2e7ae7c61043))
|
|
68
|
+
* Migrated `nextjs` versioned tests to `node:test` ([#2749](https://github.com/newrelic/node-newrelic/pull/2749)) ([d385af6](https://github.com/newrelic/node-newrelic/commit/d385af69c84a5425cee9ff19eaeadcba9e63a761))
|
|
69
|
+
* Migrated `redis` versioned tests to `node:test` ([#2725](https://github.com/newrelic/node-newrelic/pull/2725)) ([9752827](https://github.com/newrelic/node-newrelic/commit/97528270c70ecaac9161f4eb0cc78ffcc482be36))
|
|
70
|
+
* Updated `hapi` tests to `node:test` ([#2722](https://github.com/newrelic/node-newrelic/pull/2722)) ([636899b](https://github.com/newrelic/node-newrelic/commit/636899b487e196572a3bc0970e7338d0c9f113cf))
|
|
71
|
+
* Updated `kafkajs`, `langchain`, & `openai` tests to `node:test` ([#2723](https://github.com/newrelic/node-newrelic/pull/2723)) ([b6e4c5d](https://github.com/newrelic/node-newrelic/commit/b6e4c5d4c59032a615fea6d12623a881a6211917))
|
|
72
|
+
* Updated `koa` tests to `node:test` ([#2744](https://github.com/newrelic/node-newrelic/pull/2744)) ([86c22a4](https://github.com/newrelic/node-newrelic/commit/86c22a4813ec5a63ae8bd04f7d9d013979ac34ed))
|
|
73
|
+
* Updated `mongodb` tests to `node:test` ([#2738](https://github.com/newrelic/node-newrelic/pull/2738)) ([295e7e6](https://github.com/newrelic/node-newrelic/commit/295e7e6441b7220022ce4fcaaf33054945a678b0))
|
|
74
|
+
* Updated `pg` and `pg-esm` tests to `node:test` ([#2750](https://github.com/newrelic/node-newrelic/pull/2750)) ([40aea36](https://github.com/newrelic/node-newrelic/commit/40aea36320d15b201800431268be2c3d4c794a7b))
|
|
75
|
+
|
|
1
76
|
### v12.7.0 (2024-11-11)
|
|
2
77
|
|
|
3
78
|
#### Features
|
package/README.md
CHANGED
|
@@ -81,8 +81,8 @@ If you are having trouble getting the `newrelic` package to instrument Next.js,
|
|
|
81
81
|
### Next.js example projects
|
|
82
82
|
The following example applications show how to load the `newrelic` instrumentation, inject browser agent, and handle errors:
|
|
83
83
|
|
|
84
|
-
* [Pages Router example](https://github.com/newrelic/newrelic-node-examples/tree/
|
|
85
|
-
* [App Router example](https://github.com/newrelic/newrelic-node-examples/tree/
|
|
84
|
+
* [Pages Router example](https://github.com/newrelic/newrelic-node-examples/tree/9415503f3bd78fa5d87a7214596d51c946199474/nextjs/nextjs-legacy)
|
|
85
|
+
* [App Router example](https://github.com/newrelic/newrelic-node-examples/tree/9415503f3bd78fa5d87a7214596d51c946199474/nextjs/nextjs-app-router)
|
|
86
86
|
|
|
87
87
|
### Custom Next.js servers
|
|
88
88
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -75,7 +75,6 @@ code, the source code can be found at [https://github.com/newrelic/node-newrelic
|
|
|
75
75
|
* [sinon](#sinon)
|
|
76
76
|
* [superagent](#superagent)
|
|
77
77
|
* [tap](#tap)
|
|
78
|
-
* [temp](#temp)
|
|
79
78
|
|
|
80
79
|
**[optionalDependencies](#optionalDependencies)**
|
|
81
80
|
|
|
@@ -1042,7 +1041,7 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
1042
1041
|
|
|
1043
1042
|
### winston-transport
|
|
1044
1043
|
|
|
1045
|
-
This product includes source derived from [winston-transport](https://github.com/winstonjs/winston-transport) ([v4.
|
|
1044
|
+
This product includes source derived from [winston-transport](https://github.com/winstonjs/winston-transport) ([v4.7.1](https://github.com/winstonjs/winston-transport/tree/v4.7.1)), distributed under the [MIT License](https://github.com/winstonjs/winston-transport/blob/v4.7.1/LICENSE):
|
|
1046
1045
|
|
|
1047
1046
|
```
|
|
1048
1047
|
The MIT License (MIT)
|
|
@@ -1075,7 +1074,7 @@ SOFTWARE.
|
|
|
1075
1074
|
|
|
1076
1075
|
### @aws-sdk/client-s3
|
|
1077
1076
|
|
|
1078
|
-
This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.
|
|
1077
|
+
This product includes source derived from [@aws-sdk/client-s3](https://github.com/aws/aws-sdk-js-v3) ([v3.621.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.621.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.621.0/LICENSE):
|
|
1079
1078
|
|
|
1080
1079
|
```
|
|
1081
1080
|
Apache License
|
|
@@ -1284,7 +1283,7 @@ This product includes source derived from [@aws-sdk/client-s3](https://github.co
|
|
|
1284
1283
|
|
|
1285
1284
|
### @aws-sdk/s3-request-presigner
|
|
1286
1285
|
|
|
1287
|
-
This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.
|
|
1286
|
+
This product includes source derived from [@aws-sdk/s3-request-presigner](https://github.com/aws/aws-sdk-js-v3) ([v3.621.0](https://github.com/aws/aws-sdk-js-v3/tree/v3.621.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js-v3/blob/v3.621.0/LICENSE):
|
|
1288
1287
|
|
|
1289
1288
|
```
|
|
1290
1289
|
Apache License
|
|
@@ -1493,7 +1492,7 @@ This product includes source derived from [@aws-sdk/s3-request-presigner](https:
|
|
|
1493
1492
|
|
|
1494
1493
|
### @koa/router
|
|
1495
1494
|
|
|
1496
|
-
This product includes source derived from [@koa/router](https://github.com/koajs/router) ([v12.0.
|
|
1495
|
+
This product includes source derived from [@koa/router](https://github.com/koajs/router) ([v12.0.1](https://github.com/koajs/router/tree/v12.0.1)), distributed under the [MIT License](https://github.com/koajs/router/blob/v12.0.1/LICENSE):
|
|
1497
1496
|
|
|
1498
1497
|
```
|
|
1499
1498
|
The MIT License (MIT)
|
|
@@ -2207,7 +2206,7 @@ THE SOFTWARE.
|
|
|
2207
2206
|
|
|
2208
2207
|
### @slack/bolt
|
|
2209
2208
|
|
|
2210
|
-
This product includes source derived from [@slack/bolt](https://github.com/slackapi/bolt) ([v3.
|
|
2209
|
+
This product includes source derived from [@slack/bolt](https://github.com/slackapi/bolt) ([v3.19.0](https://github.com/slackapi/bolt/tree/v3.19.0)), distributed under the [MIT License](https://github.com/slackapi/bolt/blob/v3.19.0/LICENSE):
|
|
2211
2210
|
|
|
2212
2211
|
```
|
|
2213
2212
|
The MIT License (MIT)
|
|
@@ -2684,7 +2683,7 @@ SOFTWARE.
|
|
|
2684
2683
|
|
|
2685
2684
|
### async
|
|
2686
2685
|
|
|
2687
|
-
This product includes source derived from [async](https://github.com/caolan/async) ([v3.2.
|
|
2686
|
+
This product includes source derived from [async](https://github.com/caolan/async) ([v3.2.5](https://github.com/caolan/async/tree/v3.2.5)), distributed under the [MIT License](https://github.com/caolan/async/blob/v3.2.5/LICENSE):
|
|
2688
2687
|
|
|
2689
2688
|
```
|
|
2690
2689
|
Copyright (c) 2010-2018 Caolan McMahon
|
|
@@ -2711,7 +2710,7 @@ THE SOFTWARE.
|
|
|
2711
2710
|
|
|
2712
2711
|
### aws-sdk
|
|
2713
2712
|
|
|
2714
|
-
This product includes source derived from [aws-sdk](https://github.com/aws/aws-sdk-js) ([v2.
|
|
2713
|
+
This product includes source derived from [aws-sdk](https://github.com/aws/aws-sdk-js) ([v2.1665.0](https://github.com/aws/aws-sdk-js/tree/v2.1665.0)), distributed under the [Apache-2.0 License](https://github.com/aws/aws-sdk-js/blob/v2.1665.0/LICENSE.txt):
|
|
2715
2714
|
|
|
2716
2715
|
```
|
|
2717
2716
|
|
|
@@ -2921,7 +2920,7 @@ This product includes source derived from [aws-sdk](https://github.com/aws/aws-s
|
|
|
2921
2920
|
|
|
2922
2921
|
### borp
|
|
2923
2922
|
|
|
2924
|
-
This product includes source derived from [borp](https://github.com/mcollina/borp) ([v0.
|
|
2923
|
+
This product includes source derived from [borp](https://github.com/mcollina/borp) ([v0.19.0](https://github.com/mcollina/borp/tree/v0.19.0)), distributed under the [MIT License](https://github.com/mcollina/borp/blob/v0.19.0/LICENSE):
|
|
2925
2924
|
|
|
2926
2925
|
```
|
|
2927
2926
|
MIT License
|
|
@@ -3139,7 +3138,7 @@ THE SOFTWARE.
|
|
|
3139
3138
|
|
|
3140
3139
|
### eslint-plugin-jsdoc
|
|
3141
3140
|
|
|
3142
|
-
This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v48.
|
|
3141
|
+
This product includes source derived from [eslint-plugin-jsdoc](https://github.com/gajus/eslint-plugin-jsdoc) ([v48.10.2](https://github.com/gajus/eslint-plugin-jsdoc/tree/v48.10.2)), distributed under the [BSD-3-Clause License](https://github.com/gajus/eslint-plugin-jsdoc/blob/v48.10.2/LICENSE):
|
|
3143
3142
|
|
|
3144
3143
|
```
|
|
3145
3144
|
Copyright (c) 2018, Gajus Kuizinas (http://gajus.com/)
|
|
@@ -3344,7 +3343,7 @@ Library.
|
|
|
3344
3343
|
|
|
3345
3344
|
### eslint
|
|
3346
3345
|
|
|
3347
|
-
This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v8.57.
|
|
3346
|
+
This product includes source derived from [eslint](https://github.com/eslint/eslint) ([v8.57.0](https://github.com/eslint/eslint/tree/v8.57.0)), distributed under the [MIT License](https://github.com/eslint/eslint/blob/v8.57.0/LICENSE):
|
|
3348
3347
|
|
|
3349
3348
|
```
|
|
3350
3349
|
Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
@@ -3371,7 +3370,7 @@ THE SOFTWARE.
|
|
|
3371
3370
|
|
|
3372
3371
|
### express
|
|
3373
3372
|
|
|
3374
|
-
This product includes source derived from [express](https://github.com/expressjs/express) ([v4.
|
|
3373
|
+
This product includes source derived from [express](https://github.com/expressjs/express) ([v4.19.2](https://github.com/expressjs/express/tree/v4.19.2)), distributed under the [MIT License](https://github.com/expressjs/express/blob/v4.19.2/LICENSE):
|
|
3375
3374
|
|
|
3376
3375
|
```
|
|
3377
3376
|
(The MIT License)
|
|
@@ -3507,7 +3506,7 @@ SOFTWARE.
|
|
|
3507
3506
|
|
|
3508
3507
|
### jsdoc
|
|
3509
3508
|
|
|
3510
|
-
This product includes source derived from [jsdoc](https://github.com/jsdoc/jsdoc) ([v4.0.
|
|
3509
|
+
This product includes source derived from [jsdoc](https://github.com/jsdoc/jsdoc) ([v4.0.3](https://github.com/jsdoc/jsdoc/tree/v4.0.3)), distributed under the [Apache-2.0 License](https://github.com/jsdoc/jsdoc/blob/v4.0.3/LICENSE.md):
|
|
3511
3510
|
|
|
3512
3511
|
```
|
|
3513
3512
|
# License
|
|
@@ -4002,7 +4001,7 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
4002
4001
|
|
|
4003
4002
|
### self-cert
|
|
4004
4003
|
|
|
4005
|
-
This product includes source derived from [self-cert](https://github.com/jsumners/self-cert) ([v2.0.
|
|
4004
|
+
This product includes source derived from [self-cert](https://github.com/jsumners/self-cert) ([v2.0.0](https://github.com/jsumners/self-cert/tree/v2.0.0)), distributed under the [MIT License](https://github.com/jsumners/self-cert/blob/v2.0.0/Readme.md):
|
|
4006
4005
|
|
|
4007
4006
|
```
|
|
4008
4007
|
MIT License
|
|
@@ -4132,34 +4131,6 @@ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
4132
4131
|
|
|
4133
4132
|
```
|
|
4134
4133
|
|
|
4135
|
-
### temp
|
|
4136
|
-
|
|
4137
|
-
This product includes source derived from [temp](https://github.com/bruce/node-temp) ([v0.8.4](https://github.com/bruce/node-temp/tree/v0.8.4)), distributed under the [MIT License](https://github.com/bruce/node-temp/blob/v0.8.4/LICENSE):
|
|
4138
|
-
|
|
4139
|
-
```
|
|
4140
|
-
The MIT License (MIT)
|
|
4141
|
-
|
|
4142
|
-
Copyright (c) 2010-2014 Bruce Williams
|
|
4143
|
-
|
|
4144
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4145
|
-
this software and associated documentation files (the "Software"), to deal in
|
|
4146
|
-
the Software without restriction, including without limitation the rights to
|
|
4147
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
4148
|
-
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
4149
|
-
subject to the following conditions:
|
|
4150
|
-
|
|
4151
|
-
The above copyright notice and this permission notice shall be included in all
|
|
4152
|
-
copies or substantial portions of the Software.
|
|
4153
|
-
|
|
4154
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
4155
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
4156
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
4157
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
4158
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
4159
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
4160
|
-
|
|
4161
|
-
```
|
|
4162
|
-
|
|
4163
4134
|
|
|
4164
4135
|
## optionalDependencies
|
|
4165
4136
|
|
package/lib/agent.js
CHANGED
|
@@ -40,6 +40,7 @@ const {
|
|
|
40
40
|
} = require('./util/attributes')
|
|
41
41
|
const synthetics = require('./synthetics')
|
|
42
42
|
const Harvester = require('./harvester')
|
|
43
|
+
const { createFeatureUsageMetrics } = require('./util/application-logging')
|
|
43
44
|
|
|
44
45
|
// Map of valid states to whether or not data collection is valid
|
|
45
46
|
const STATES = {
|
|
@@ -405,7 +406,7 @@ Agent.prototype.startStreaming = function startStreaming() {
|
|
|
405
406
|
*/
|
|
406
407
|
Agent.prototype.onConnect = function onConnect(shouldImmediatelyHarvest, callback) {
|
|
407
408
|
this.harvester.update(this.config)
|
|
408
|
-
|
|
409
|
+
createFeatureUsageMetrics(this)
|
|
409
410
|
|
|
410
411
|
if (this.config.certificates && this.config.certificates.length > 0) {
|
|
411
412
|
this.metrics.getOrCreateMetric(NAMES.FEATURES.CERTIFICATES).incrementCallCount()
|
|
@@ -821,6 +822,8 @@ Agent.prototype._listenForConfigChanges = function _listenForConfigChanges() {
|
|
|
821
822
|
* This method returns an object with the following keys/data:
|
|
822
823
|
* - `trace.id`: The current trace ID
|
|
823
824
|
* - `span.id`: The current span ID
|
|
825
|
+
*
|
|
826
|
+
* If `excludeServiceLinks` is false it will also include the following:
|
|
824
827
|
* - `entity.name`: The application name specified in the connect request as
|
|
825
828
|
* app_name. If multiple application names are specified this will only be
|
|
826
829
|
* the first name
|
|
@@ -830,17 +833,14 @@ Agent.prototype._listenForConfigChanges = function _listenForConfigChanges() {
|
|
|
830
833
|
* utilization.full_hostname. If utilization.full_hostname is null or empty,
|
|
831
834
|
* this will be the hostname specified in the connect request as host.
|
|
832
835
|
*
|
|
836
|
+
* @param {boolean} excludeServiceLinks flag to indicate if you should include `entity.guid`, `entity.type`, `entity.name` and `hostname` from linking metadata
|
|
833
837
|
* @returns {object} The LinkingMetadata object with the data above
|
|
834
838
|
*/
|
|
835
|
-
Agent.prototype.getLinkingMetadata = function getLinkingMetadata() {
|
|
839
|
+
Agent.prototype.getLinkingMetadata = function getLinkingMetadata(excludeServiceLinks = false) {
|
|
836
840
|
const segment = this.tracer.getSegment()
|
|
837
841
|
const config = this.config
|
|
838
842
|
|
|
839
|
-
const linkingMetadata = {
|
|
840
|
-
'entity.name': config.applications()[0],
|
|
841
|
-
'entity.type': 'SERVICE',
|
|
842
|
-
'hostname': config.getHostnameSafe()
|
|
843
|
-
}
|
|
843
|
+
const linkingMetadata = {}
|
|
844
844
|
|
|
845
845
|
if (config.distributed_tracing.enabled && segment) {
|
|
846
846
|
linkingMetadata['trace.id'] = segment.transaction.traceId
|
|
@@ -852,10 +852,37 @@ Agent.prototype.getLinkingMetadata = function getLinkingMetadata() {
|
|
|
852
852
|
logger.debug('getLinkingMetadata with no active transaction')
|
|
853
853
|
}
|
|
854
854
|
|
|
855
|
+
if (!excludeServiceLinks) {
|
|
856
|
+
this.getServiceLinkingMetadata(linkingMetadata)
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
return linkingMetadata
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* This methods returns an object with the following keys/data:
|
|
864
|
+
* - `entity.name`: The application name specified in the connect request as
|
|
865
|
+
* app_name. If multiple application names are specified this will only be
|
|
866
|
+
* the first name
|
|
867
|
+
* - `entity.type`: The string "SERVICE"
|
|
868
|
+
* - `entity.guid`: The entity ID returned in the connect reply as entity_guid
|
|
869
|
+
* - `hostname`: The hostname as specified in the connect request as
|
|
870
|
+
* utilization.full_hostname. If utilization.full_hostname is null or empty,
|
|
871
|
+
* this will be the hostname specified in the connect request as host.
|
|
872
|
+
*
|
|
873
|
+
* @param {object} linkingMetadata object to add service linking keys
|
|
874
|
+
* @returns {object} with service linking metadata
|
|
875
|
+
*/
|
|
876
|
+
Agent.prototype.getServiceLinkingMetadata = function getServiceLinkingMetadata(
|
|
877
|
+
linkingMetadata = {}
|
|
878
|
+
) {
|
|
879
|
+
const config = this.config
|
|
855
880
|
if (config.entity_guid) {
|
|
856
881
|
linkingMetadata['entity.guid'] = config.entity_guid
|
|
857
882
|
}
|
|
858
|
-
|
|
883
|
+
linkingMetadata['entity.name'] = config.applications()[0]
|
|
884
|
+
linkingMetadata['entity.type'] = 'SERVICE'
|
|
885
|
+
linkingMetadata.hostname = config.getHostnameSafe()
|
|
859
886
|
return linkingMetadata
|
|
860
887
|
}
|
|
861
888
|
|
|
@@ -927,23 +954,4 @@ function generateEventHarvestSupportMetrics(agent, harvestConfig) {
|
|
|
927
954
|
}
|
|
928
955
|
}
|
|
929
956
|
|
|
930
|
-
/**
|
|
931
|
-
* Increments the call counts of application logging supportability metrics
|
|
932
|
-
* on every connect cycle
|
|
933
|
-
*
|
|
934
|
-
* @param {object} agent Instantiation of Node.js agent
|
|
935
|
-
*/
|
|
936
|
-
function generateLoggingSupportMetrics(agent) {
|
|
937
|
-
const loggingConfig = agent.config.application_logging
|
|
938
|
-
const logNames = NAMES.LOGGING
|
|
939
|
-
|
|
940
|
-
const configKeys = ['metrics', 'forwarding', 'local_decorating']
|
|
941
|
-
configKeys.forEach((configValue) => {
|
|
942
|
-
const configFlag =
|
|
943
|
-
loggingConfig.enabled && loggingConfig[`${configValue}`].enabled ? 'enabled' : 'disabled'
|
|
944
|
-
const metricName = logNames[`${configValue.toUpperCase()}`]
|
|
945
|
-
agent.metrics.getOrCreateMetric(`${metricName}${configFlag}`).incrementCallCount()
|
|
946
|
-
})
|
|
947
|
-
}
|
|
948
|
-
|
|
949
957
|
module.exports = Agent
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
8
|
const logger = require('../logger').child({ component: 'logs_aggregator' })
|
|
9
|
+
const { isLogLabelingEnabled } = require('../../lib/util/application-logging')
|
|
9
10
|
const EventAggregator = require('./event-aggregator')
|
|
10
11
|
|
|
11
12
|
const NAMES = require('../metrics/names')
|
|
@@ -56,7 +57,18 @@ class LogAggregator extends EventAggregator {
|
|
|
56
57
|
return
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
let commonAttrs = this.agent.getServiceLinkingMetadata()
|
|
61
|
+
|
|
62
|
+
if (isLogLabelingEnabled(this.agent.config)) {
|
|
63
|
+
commonAttrs = { ...commonAttrs, ...this.agent.config.loggingLabels }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return [
|
|
67
|
+
{
|
|
68
|
+
common: { attributes: commonAttrs },
|
|
69
|
+
logs: formattedLogs
|
|
70
|
+
}
|
|
71
|
+
]
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
add(logLine) {
|
package/lib/collector/facts.js
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
const fetchSystemInfo = require('../system-info')
|
|
9
9
|
const defaultLogger = require('../logger').child({ component: 'facts' })
|
|
10
10
|
const os = require('os')
|
|
11
|
-
const parseLabels = require('../util/label-parser')
|
|
12
11
|
|
|
13
12
|
module.exports = facts
|
|
14
13
|
|
|
@@ -49,7 +48,7 @@ async function facts(agent, callback, { logger = defaultLogger } = {}) {
|
|
|
49
48
|
environment: environment,
|
|
50
49
|
settings: agent.config.publicSettings(),
|
|
51
50
|
high_security: agent.config.high_security,
|
|
52
|
-
labels:
|
|
51
|
+
labels: agent.config.parsedLabels,
|
|
53
52
|
metadata: Object.keys(process.env).reduce((obj, key) => {
|
|
54
53
|
if (key.startsWith('NEW_RELIC_METADATA_')) {
|
|
55
54
|
obj[key] = process.env[key]
|
package/lib/config/default.js
CHANGED
|
@@ -1185,6 +1185,22 @@ defaultConfig.definition = () => ({
|
|
|
1185
1185
|
max_samples_stored: {
|
|
1186
1186
|
formatter: int,
|
|
1187
1187
|
default: 10000
|
|
1188
|
+
},
|
|
1189
|
+
labels: {
|
|
1190
|
+
/**
|
|
1191
|
+
* If `true`, the agent attaches labels to log records.
|
|
1192
|
+
*/
|
|
1193
|
+
enabled: {
|
|
1194
|
+
formatter: boolean,
|
|
1195
|
+
default: false
|
|
1196
|
+
},
|
|
1197
|
+
/**
|
|
1198
|
+
* A case-insensitive array containing the labels to exclude from log records.
|
|
1199
|
+
*/
|
|
1200
|
+
exclude: {
|
|
1201
|
+
formatter: array,
|
|
1202
|
+
default: []
|
|
1203
|
+
}
|
|
1188
1204
|
}
|
|
1189
1205
|
},
|
|
1190
1206
|
metrics: {
|
package/lib/config/index.js
CHANGED
|
@@ -24,6 +24,7 @@ const harvestConfigValidator = require('./harvest-config-validator')
|
|
|
24
24
|
const mergeServerConfig = new MergeServerConfig()
|
|
25
25
|
const { boolean: isTruthular } = require('./formatters')
|
|
26
26
|
const configDefinition = definition()
|
|
27
|
+
const parseLabels = require('../util/label-parser')
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* CONSTANTS -- we gotta lotta 'em
|
|
@@ -195,9 +196,38 @@ function Config(config) {
|
|
|
195
196
|
|
|
196
197
|
// 9. Set instance attribute filter using updated context
|
|
197
198
|
this.attributeFilter = new AttributeFilter(this)
|
|
199
|
+
|
|
200
|
+
// 10. Setup labels for both `collector/facts` and application logging
|
|
201
|
+
this.parsedLabels = parseLabels(this.labels, logger)
|
|
202
|
+
this.loggingLabels = this._setApplicationLoggingLabels()
|
|
198
203
|
}
|
|
199
204
|
util.inherits(Config, EventEmitter)
|
|
200
205
|
|
|
206
|
+
/**
|
|
207
|
+
* Compares the labels list to the application logging excluded label list and removes any labels that need to be excluded.
|
|
208
|
+
* Then prefixing each label with "tags."
|
|
209
|
+
*
|
|
210
|
+
* assigns labels to `config.loggingLabels`
|
|
211
|
+
*/
|
|
212
|
+
Config.prototype._setApplicationLoggingLabels = function setApplicationLoggingLabels() {
|
|
213
|
+
if (this.application_logging.forwarding.labels.enabled === false) {
|
|
214
|
+
return
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
this.application_logging.forwarding.labels.exclude =
|
|
218
|
+
this.application_logging.forwarding.labels.exclude.map((k) => k.toLowerCase())
|
|
219
|
+
|
|
220
|
+
return this.parsedLabels.reduce((filteredLabels, label) => {
|
|
221
|
+
if (
|
|
222
|
+
!this.application_logging.forwarding.labels.exclude.includes(label.label_type.toLowerCase())
|
|
223
|
+
) {
|
|
224
|
+
filteredLabels[`tags.${label.label_type}`] = label.label_value
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return filteredLabels
|
|
228
|
+
}, {})
|
|
229
|
+
}
|
|
230
|
+
|
|
201
231
|
/**
|
|
202
232
|
* Because this module and logger depend on each other, the logger needs
|
|
203
233
|
* a way to inject the actual logger instance once it's constructed.
|
|
@@ -11,63 +11,116 @@ const symbols = require('../../symbols')
|
|
|
11
11
|
const { QuerySpec } = require('../../shim/specs')
|
|
12
12
|
const DatastoreParameters = require('../../shim/specs/params/datastore')
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Used to instrument `mysql` and `mysql2` packages
|
|
16
|
+
* the `mysql2/promise` instrumentation is below in `promiseInitialize`
|
|
17
|
+
*
|
|
18
|
+
* @param {Shim} shim instance of shim
|
|
19
|
+
* @param {object} mysql package to instrument
|
|
20
|
+
*/
|
|
14
21
|
function callbackInitialize(shim, mysql) {
|
|
15
22
|
shim.setDatastore(shim.MYSQL)
|
|
16
23
|
shim[symbols.wrappedPoolConnection] = false
|
|
17
24
|
|
|
18
25
|
shim.wrapReturn(mysql, 'createConnection', wrapCreateConnection)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
shim.wrapReturn(mysql, 'createPool', wrapCreatePool)
|
|
27
|
+
shim.wrapReturn(mysql, 'createPoolCluster', wrapCreatePoolCluster)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Used to instrument `mysql2/promise`
|
|
32
|
+
*
|
|
33
|
+
* @param {Shim} shim instance of shim
|
|
34
|
+
* @param {object} mysql2 package to instrument
|
|
35
|
+
*/
|
|
36
|
+
function promiseInitialize(shim, mysql2) {
|
|
37
|
+
shim.setDatastore(shim.MYSQL)
|
|
38
|
+
shim[symbols.wrappedPoolConnection] = false
|
|
39
|
+
shim.wrap(
|
|
40
|
+
mysql2,
|
|
41
|
+
'createConnection',
|
|
42
|
+
function wrapPromiseCreateConnection(shim, createConnection) {
|
|
43
|
+
return async function wrappedPromiseCreateConnection() {
|
|
44
|
+
const promiseConnection = await createConnection.apply(this, arguments)
|
|
45
|
+
wrapCreateConnection(
|
|
46
|
+
shim,
|
|
47
|
+
createConnection,
|
|
48
|
+
'createConnection',
|
|
49
|
+
promiseConnection.connection
|
|
50
|
+
)
|
|
51
|
+
return promiseConnection
|
|
52
|
+
}
|
|
28
53
|
}
|
|
29
|
-
|
|
54
|
+
)
|
|
30
55
|
|
|
31
|
-
shim.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
56
|
+
shim.wrap(mysql2, 'createPool', function wrapPromiseCreatePool(shim, createPool) {
|
|
57
|
+
return async function wrappedPromiseCreatePool() {
|
|
58
|
+
const promisePool = await createPool.apply(this, arguments)
|
|
59
|
+
wrapCreatePool(shim, createPool, 'createPool', promisePool.pool)
|
|
60
|
+
return promisePool
|
|
35
61
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
shim.wrap(
|
|
65
|
+
mysql2,
|
|
66
|
+
'createPoolCluster',
|
|
67
|
+
function wrapPromiseCreatePoolCluster(shim, createPoolCluster) {
|
|
68
|
+
return async function wrappedPromiseCreatePoolCluster() {
|
|
69
|
+
const promisePoolCluster = await createPoolCluster.apply(this, arguments)
|
|
70
|
+
wrapCreatePoolCluster(
|
|
71
|
+
shim,
|
|
72
|
+
createPoolCluster,
|
|
73
|
+
'createPoolCluster',
|
|
74
|
+
promisePoolCluster.poolCluster
|
|
75
|
+
)
|
|
76
|
+
return promisePoolCluster
|
|
77
|
+
}
|
|
39
78
|
}
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function wrapCreateConnection(shim, fn, fnName, connection) {
|
|
83
|
+
if (shim[symbols.unwrapConnection]) {
|
|
84
|
+
return
|
|
40
85
|
}
|
|
86
|
+
shim.logger.debug('Wrapping Connection#query')
|
|
87
|
+
if (wrapQueryable(shim, connection, false)) {
|
|
88
|
+
const connProto = Object.getPrototypeOf(connection)
|
|
89
|
+
connProto[symbols.storeDatabase] = true
|
|
90
|
+
shim[symbols.unwrapConnection] = true
|
|
91
|
+
}
|
|
92
|
+
}
|
|
41
93
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (poolNamespace[symbols.clusterOf]) {
|
|
52
|
-
return
|
|
53
|
-
}
|
|
94
|
+
function wrapCreatePool(shim, fn, fnName, pool) {
|
|
95
|
+
if (shim[symbols.unwrapPool]) {
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
shim.logger.debug('Wrapping Pool#query and Pool#getConnection')
|
|
99
|
+
if (wrapQueryable(shim, pool, true) && wrapGetConnection(shim, pool)) {
|
|
100
|
+
shim[symbols.unwrapPool] = true
|
|
101
|
+
}
|
|
102
|
+
}
|
|
54
103
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
104
|
+
function wrapCreatePoolCluster(shim, fn, fnName, poolCluster) {
|
|
105
|
+
if (shim[symbols.createPoolCluster]) {
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
shim.logger.debug('Wrapping PoolCluster#of')
|
|
109
|
+
const proto = Object.getPrototypeOf(poolCluster)
|
|
110
|
+
shim.wrapReturn(proto, 'of', wrapPoolClusterOf)
|
|
111
|
+
function wrapPoolClusterOf(shim, of, _n, poolNamespace) {
|
|
112
|
+
if (poolNamespace[symbols.clusterOf]) {
|
|
113
|
+
return
|
|
58
114
|
}
|
|
59
115
|
|
|
60
|
-
shim
|
|
61
|
-
|
|
62
|
-
shim[symbols.createPoolCluster] = true
|
|
116
|
+
if (wrapGetConnection(shim, poolNamespace) && wrapQueryable(shim, poolNamespace, false)) {
|
|
117
|
+
poolNamespace[symbols.clusterOf] = true
|
|
63
118
|
}
|
|
64
119
|
}
|
|
65
|
-
}
|
|
66
120
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
callbackInitialize(shim, callbackAPI)
|
|
121
|
+
shim.logger.debug('Wrapping PoolCluster#getConnection')
|
|
122
|
+
if (wrapGetConnection(shim, poolCluster)) {
|
|
123
|
+
shim[symbols.createPoolCluster] = true
|
|
71
124
|
}
|
|
72
125
|
}
|
|
73
126
|
|
|
@@ -35,7 +35,7 @@ class NrTransport extends TransportStream {
|
|
|
35
35
|
* @param {Function} callback callback to invoke once we are done
|
|
36
36
|
*/
|
|
37
37
|
log(logLine, callback) {
|
|
38
|
-
const metadata = this.agent.getLinkingMetadata()
|
|
38
|
+
const metadata = this.agent.getLinkingMetadata(true)
|
|
39
39
|
const formattedLine = reformatLogLine(logLine, metadata)
|
|
40
40
|
this.agent.logs.add(formattedLine)
|
|
41
41
|
callback()
|
|
@@ -45,7 +45,6 @@ module.exports = function instrument(shim, tools) {
|
|
|
45
45
|
* @param {object} params.tools exported `pino/lib/tools`
|
|
46
46
|
*/
|
|
47
47
|
function wrapAsJson({ shim, tools }) {
|
|
48
|
-
const symbols = shim.require('./lib/symbols')
|
|
49
48
|
const { agent } = shim
|
|
50
49
|
const { config, metrics } = agent
|
|
51
50
|
|
|
@@ -88,12 +87,10 @@ function wrapAsJson({ shim, tools }) {
|
|
|
88
87
|
const logLine = asJson.apply(this, args)
|
|
89
88
|
|
|
90
89
|
if (isLogForwardingEnabled(config, agent)) {
|
|
91
|
-
const chindings = this[symbols.chindingsSym]
|
|
92
90
|
const formatLogLine = reformatLogLine({
|
|
93
91
|
msg: useMergeObj === true ? args[0].msg : args[1],
|
|
94
92
|
logLine,
|
|
95
93
|
agent,
|
|
96
|
-
chindings,
|
|
97
94
|
level,
|
|
98
95
|
logger: shim.logger
|
|
99
96
|
})
|
|
@@ -114,22 +111,12 @@ function wrapAsJson({ shim, tools }) {
|
|
|
114
111
|
* @param {object} params.logLine log line
|
|
115
112
|
* @param {string} params.msg message of log line
|
|
116
113
|
* @param {object} params.agent instance of agent
|
|
117
|
-
* @param {string} params.chindings serialized string of all common log line data
|
|
118
114
|
* @param {string} params.level log level
|
|
119
115
|
* @param {object} params.logger instance of agent logger
|
|
120
116
|
* @returns {function} wrapped log formatter function
|
|
121
117
|
*/
|
|
122
|
-
function reformatLogLine({ logLine, msg, agent,
|
|
123
|
-
const metadata = agent.getLinkingMetadata()
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* pino adds this already for us at times
|
|
127
|
-
* since asJson manually constructs the json string,
|
|
128
|
-
* it will have hostname twice if we do not delete ours.
|
|
129
|
-
*/
|
|
130
|
-
if (chindings.includes('hostname')) {
|
|
131
|
-
delete metadata.hostname
|
|
132
|
-
}
|
|
118
|
+
function reformatLogLine({ logLine, msg, agent, level, logger }) {
|
|
119
|
+
const metadata = agent.getLinkingMetadata(true)
|
|
133
120
|
|
|
134
121
|
const agentMeta = Object.assign({}, { timestamp: Date.now() }, metadata)
|
|
135
122
|
// eslint-disable-next-line eqeqeq
|
|
@@ -84,10 +84,19 @@ class BedrockCommand {
|
|
|
84
84
|
) {
|
|
85
85
|
result = this.#body.prompt
|
|
86
86
|
} else if (this.isClaude3() === true) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
const collected = []
|
|
88
|
+
for (const message of this.#body?.messages) {
|
|
89
|
+
if (message?.role === 'assistant') {
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
if (typeof message?.content === 'string') {
|
|
93
|
+
collected.push(message?.content)
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
const mappedMsgObj = message?.content.map((msgContent) => msgContent.text)
|
|
97
|
+
collected.push(mappedMsgObj)
|
|
98
|
+
}
|
|
99
|
+
result = collected.join(' ')
|
|
91
100
|
}
|
|
92
101
|
return result
|
|
93
102
|
}
|
package/lib/metrics/names.js
CHANGED
|
@@ -337,7 +337,8 @@ const LOGGING = {
|
|
|
337
337
|
SENT: `${LOGGING_FORWARDING_PREFIX}/Sent`,
|
|
338
338
|
FORWARDING: `${LOGGING_FORWARDING_PREFIX}/${NODEJS.PREFIX}`,
|
|
339
339
|
METRICS: `${SUPPORTABILITY.LOGGING}/Metrics/${NODEJS.PREFIX}`,
|
|
340
|
-
LOCAL_DECORATING: `${SUPPORTABILITY.LOGGING}/LocalDecorating/${NODEJS.PREFIX}
|
|
340
|
+
LOCAL_DECORATING: `${SUPPORTABILITY.LOGGING}/LocalDecorating/${NODEJS.PREFIX}`,
|
|
341
|
+
LABELS: `${SUPPORTABILITY.LOGGING}/Labels/${NODEJS.PREFIX}`
|
|
341
342
|
}
|
|
342
343
|
|
|
343
344
|
const KAFKA = {
|
|
@@ -22,7 +22,7 @@ class LambdaProxyWebRequest {
|
|
|
22
22
|
}
|
|
23
23
|
this.method = ''
|
|
24
24
|
|
|
25
|
-
if (isGatewayV1Event(event) === true) {
|
|
25
|
+
if (isGatewayV1Event(event) === true || isAlbEvent(event) === true) {
|
|
26
26
|
this.url.path = event.path
|
|
27
27
|
this.method = event.httpMethod
|
|
28
28
|
} else if (isGatewayV2Event(event) === true) {
|
|
@@ -54,7 +54,10 @@ class LambdaProxyWebResponse {
|
|
|
54
54
|
* @returns {Object<string, string>} The normalized query string map
|
|
55
55
|
*/
|
|
56
56
|
function normalizeQueryStringParameters(event) {
|
|
57
|
-
if (
|
|
57
|
+
if (
|
|
58
|
+
!event.multiValueQueryStringParameters ||
|
|
59
|
+
Object.keys(event.multiValueQueryStringParameters).length === 0
|
|
60
|
+
) {
|
|
58
61
|
return event.queryStringParameters
|
|
59
62
|
}
|
|
60
63
|
return Object.fromEntries(
|
|
@@ -107,56 +110,87 @@ function normalizeHeaders(event, lowerCaseKey = false) {
|
|
|
107
110
|
* to create a web transaction.
|
|
108
111
|
*/
|
|
109
112
|
function isLambdaProxyEvent(event) {
|
|
110
|
-
return isGatewayV1Event(event) || isGatewayV2Event(event)
|
|
113
|
+
return isGatewayV1Event(event) || isGatewayV2Event(event) || isAlbEvent(event)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Iterates over the minimum signature properties of an event received by this Lambda function
|
|
118
|
+
* to determine if this request is triggered from a proxy (API Gateway V1, V2, ALB) or some other service.
|
|
119
|
+
* If API Gateway, we need to determine which version: V1 and V2 have a lot of overlap, but some signature
|
|
120
|
+
* differences for which we can test.
|
|
121
|
+
*
|
|
122
|
+
* The test is designed to look only at signature properties used by each version, and returns true with the first
|
|
123
|
+
* top-level match. Each test array has only four elements, and each invocation should incur
|
|
124
|
+
* only five comparisons: one match for its matching type, and four comparisons for the non-matching type.
|
|
125
|
+
*
|
|
126
|
+
* API Gateway v2 HTTP: top-level 'rawPath', 'rawQueryString', 'routeKey'. Possibly 'cookies'
|
|
127
|
+
* API Gateway v1 HTTP: top-level 'httpMethod', 'resource'. Possibly 'multiValueHeaders', 'multiValueQueryStringParameters'
|
|
128
|
+
* API Gateway v1 REST same as HTTP, but without top-level `version`
|
|
129
|
+
* ALB: very similar to API Gateway v1, but requestContext contains an elb property
|
|
130
|
+
*
|
|
131
|
+
* In tests, this set of required API Gateway v1 properties has consistently been delivered in event payloads.
|
|
132
|
+
* Similar tests with API Gateway V2 shows that the cookies property is *only* defined if cookies are present.
|
|
133
|
+
* If `cookies` is present as a top-level property, the event is surely triggered by API Gateway V2. Its absence,
|
|
134
|
+
* though, is *not* a certain indicator of v1. As such, it's the last property considered in our test.
|
|
135
|
+
*
|
|
136
|
+
* @param {object} targetEvent The event to inspect.
|
|
137
|
+
* @param {Array} searchFor An array of keys unique to this proxy type
|
|
138
|
+
* @returns {boolean} Whether this event has matches for the keys we're checking
|
|
139
|
+
*/
|
|
140
|
+
function eventHasRequiredKeys(targetEvent, searchFor) {
|
|
141
|
+
const keys = Object.keys(targetEvent)
|
|
142
|
+
for (const el of searchFor) {
|
|
143
|
+
if (keys.indexOf(el) > -1) {
|
|
144
|
+
return true
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return false
|
|
111
148
|
}
|
|
112
149
|
|
|
113
150
|
// See https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
|
|
114
|
-
const
|
|
115
|
-
'body',
|
|
116
|
-
'headers',
|
|
151
|
+
const requiredHttpApiV1Keys = [
|
|
117
152
|
'httpMethod',
|
|
118
|
-
'isBase64Encoded',
|
|
119
|
-
'multiValueHeaders',
|
|
120
|
-
'multiValueQueryStringParameters',
|
|
121
153
|
'path',
|
|
122
|
-
'pathParameters',
|
|
123
|
-
'queryStringParameters',
|
|
124
|
-
'requestContext',
|
|
125
154
|
'resource',
|
|
126
|
-
'
|
|
127
|
-
|
|
155
|
+
'multiValueHeaders',
|
|
156
|
+
'multiValueQueryStringParameters'
|
|
157
|
+
]
|
|
128
158
|
|
|
129
159
|
// See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
|
|
130
|
-
const httpApiV1Keys = [...restApiV1Keys.split(','), 'version'].join(',')
|
|
131
|
-
|
|
132
160
|
function isGatewayV1Event(event) {
|
|
133
|
-
|
|
134
|
-
|
|
161
|
+
if (event?.requestContext?.elb !== undefined) {
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
const hasKeys = eventHasRequiredKeys(event, requiredHttpApiV1Keys)
|
|
165
|
+
if (hasKeys && event?.version === '1.0') {
|
|
135
166
|
return true
|
|
136
167
|
}
|
|
137
|
-
|
|
138
|
-
return
|
|
168
|
+
// Rest API doesn't have version, but we can check on the key matching:
|
|
169
|
+
return hasKeys
|
|
139
170
|
}
|
|
140
171
|
|
|
141
172
|
// See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
|
|
142
|
-
const
|
|
143
|
-
'body',
|
|
144
|
-
'cookies',
|
|
145
|
-
'headers',
|
|
146
|
-
'isBase64Encoded',
|
|
147
|
-
'pathParameters',
|
|
148
|
-
'queryStringParameters',
|
|
149
|
-
'rawPath',
|
|
150
|
-
'rawQueryString',
|
|
151
|
-
'requestContext',
|
|
152
|
-
'routeKey',
|
|
153
|
-
'stageVariables',
|
|
154
|
-
'version'
|
|
155
|
-
].join(',')
|
|
173
|
+
const requiredHttpApiV2Keys = ['rawPath', 'rawQueryString', 'routeKey', 'cookies']
|
|
156
174
|
|
|
157
175
|
function isGatewayV2Event(event) {
|
|
158
|
-
|
|
159
|
-
|
|
176
|
+
if (event?.requestContext?.elb !== undefined) {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
return eventHasRequiredKeys(event, requiredHttpApiV2Keys) && event?.version === '2.0'
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* ALB can act as a proxy for Lambda. Properties have commonalities with API GateWay v1, though ALB-triggered events
|
|
184
|
+
* consistently carry an ARN at requestContext.elb. See
|
|
185
|
+
* https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#receive-event-from-load-balancer
|
|
186
|
+
* and https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html
|
|
187
|
+
*
|
|
188
|
+
* If we check for that property, we can accept variation in other properties.
|
|
189
|
+
* @param {object} event The event property supplied to the Lambda handler
|
|
190
|
+
* @returns {boolean} Whether or not the event was triggered by ALB
|
|
191
|
+
*/
|
|
192
|
+
function isAlbEvent(event) {
|
|
193
|
+
return event?.requestContext?.elb !== undefined
|
|
160
194
|
}
|
|
161
195
|
|
|
162
196
|
/**
|
|
@@ -176,5 +210,6 @@ module.exports = {
|
|
|
176
210
|
isLambdaProxyEvent,
|
|
177
211
|
isValidLambdaProxyResponse,
|
|
178
212
|
isGatewayV1Event,
|
|
179
|
-
isGatewayV2Event
|
|
213
|
+
isGatewayV2Event,
|
|
214
|
+
isAlbEvent
|
|
180
215
|
}
|
|
@@ -75,6 +75,16 @@ utils.isLogForwardingEnabled = function isLogForwardingEnabled(config, agent) {
|
|
|
75
75
|
)
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Checks if application_logging.forwarding.labels is enabled
|
|
80
|
+
*
|
|
81
|
+
* @param {object} config agent config
|
|
82
|
+
* @returns {boolean} is labeling enabled
|
|
83
|
+
*/
|
|
84
|
+
utils.isLogLabelingEnabled = function isLogLabelingEnabled(config) {
|
|
85
|
+
return !!config.application_logging.forwarding.labels.enabled
|
|
86
|
+
}
|
|
87
|
+
|
|
78
88
|
/**
|
|
79
89
|
* Increments both `Logging/lines` and `Logging/lines/<level>` call count
|
|
80
90
|
*
|
|
@@ -108,3 +118,51 @@ function getLogLevel(level) {
|
|
|
108
118
|
}
|
|
109
119
|
return logLevel
|
|
110
120
|
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Increments the enabled/disabled metrics for the top line application logging features:
|
|
124
|
+
* 1. Supportability/Logging/Metrics/Nodejs/<enabled|disabled>
|
|
125
|
+
* 2. Supportability/Logging/Forwarding/Nodejs/<enabled|disabled>
|
|
126
|
+
* 3. Supportability/Logging/LocalDecorating/Nodejs/<enabled|disabled>
|
|
127
|
+
* 4. Supportability/Logging/Labels/Nodejs/<enabled|disabled>
|
|
128
|
+
*
|
|
129
|
+
* Run in `agent.onConnect`
|
|
130
|
+
*
|
|
131
|
+
* @param {Agent} agent instance
|
|
132
|
+
*/
|
|
133
|
+
utils.createFeatureUsageMetrics = function createFeatureUsageMetrics(agent) {
|
|
134
|
+
const { config, metrics } = agent
|
|
135
|
+
const loggingConfig = config.application_logging.enabled
|
|
136
|
+
metrics
|
|
137
|
+
.getOrCreateMetric(
|
|
138
|
+
`${LOGGING.METRICS}${
|
|
139
|
+
loggingConfig && config.application_logging.metrics.enabled ? 'enabled' : 'disabled'
|
|
140
|
+
}`
|
|
141
|
+
)
|
|
142
|
+
.incrementCallCount()
|
|
143
|
+
metrics
|
|
144
|
+
.getOrCreateMetric(
|
|
145
|
+
`${LOGGING.FORWARDING}${
|
|
146
|
+
loggingConfig && config.application_logging.forwarding.enabled ? 'enabled' : 'disabled'
|
|
147
|
+
}`
|
|
148
|
+
)
|
|
149
|
+
.incrementCallCount()
|
|
150
|
+
metrics
|
|
151
|
+
.getOrCreateMetric(
|
|
152
|
+
`${LOGGING.LOCAL_DECORATING}${
|
|
153
|
+
loggingConfig && config.application_logging.local_decorating.enabled
|
|
154
|
+
? 'enabled'
|
|
155
|
+
: 'disabled'
|
|
156
|
+
}`
|
|
157
|
+
)
|
|
158
|
+
.incrementCallCount()
|
|
159
|
+
metrics
|
|
160
|
+
.getOrCreateMetric(
|
|
161
|
+
`${LOGGING.LABELS}${
|
|
162
|
+
loggingConfig && config.application_logging.forwarding.labels.enabled
|
|
163
|
+
? 'enabled'
|
|
164
|
+
: 'disabled'
|
|
165
|
+
}`
|
|
166
|
+
)
|
|
167
|
+
.incrementCallCount()
|
|
168
|
+
}
|
package/lib/util/label-parser.js
CHANGED
|
@@ -11,10 +11,11 @@ module.exports.fromMap = fromMap
|
|
|
11
11
|
|
|
12
12
|
// this creates a copy of trim that can be used with map
|
|
13
13
|
const trim = Function.prototype.call.bind(String.prototype.trim)
|
|
14
|
-
const logger = require('../logger').child({ component: 'label-parser' })
|
|
15
14
|
const stringify = require('json-stringify-safe')
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
// pass in parent logger to avoid circular deps
|
|
17
|
+
function parse(labels, parentLogger) {
|
|
18
|
+
const logger = parentLogger.child({ component: 'label-parser' })
|
|
18
19
|
let results
|
|
19
20
|
|
|
20
21
|
if (!labels) {
|
|
@@ -25,8 +26,8 @@ function parse(labels) {
|
|
|
25
26
|
results = fromMap(labels)
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
results.warnings.forEach(function logWarnings(
|
|
29
|
-
logger.warn(
|
|
29
|
+
results.warnings.forEach(function logWarnings(message) {
|
|
30
|
+
logger.warn(message)
|
|
30
31
|
})
|
|
31
32
|
|
|
32
33
|
return results.labels
|
|
@@ -106,11 +107,11 @@ function fromMap(map) {
|
|
|
106
107
|
try {
|
|
107
108
|
warnings.unshift('Partially Invalid Label Setting: ' + stringify(map))
|
|
108
109
|
} catch (err) {
|
|
109
|
-
|
|
110
|
+
warnings.unshift('Failed to stringify labels: ' + err.message)
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
return { labels
|
|
114
|
+
return { labels, warnings }
|
|
114
115
|
}
|
|
115
116
|
|
|
116
117
|
function truncate(str, max) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "newrelic",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.8.1",
|
|
4
4
|
"author": "New Relic Node.js agent team <nodejs@newrelic.com>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"contributors": [
|
|
@@ -229,7 +229,7 @@
|
|
|
229
229
|
"ajv": "^6.12.6",
|
|
230
230
|
"async": "^3.2.4",
|
|
231
231
|
"aws-sdk": "^2.1604.0",
|
|
232
|
-
"borp": "^0.
|
|
232
|
+
"borp": "^0.19.0",
|
|
233
233
|
"c8": "^8.0.1",
|
|
234
234
|
"clean-jsdoc-theme": "^4.2.18",
|
|
235
235
|
"commander": "^7.0.0",
|
|
@@ -258,8 +258,7 @@
|
|
|
258
258
|
"should": "*",
|
|
259
259
|
"sinon": "^5.1.1",
|
|
260
260
|
"superagent": "^9.0.1",
|
|
261
|
-
"tap": "^16.3.4"
|
|
262
|
-
"temp": "^0.8.1"
|
|
261
|
+
"tap": "^16.3.4"
|
|
263
262
|
},
|
|
264
263
|
"repository": {
|
|
265
264
|
"type": "git",
|