newrelic 12.6.0 → 12.6.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 +83 -57
- package/lib/config/default.js +11 -0
- package/lib/db/parsed-statement.js +0 -54
- package/lib/metrics/recorders/database-operation.js +62 -0
- package/lib/metrics/recorders/database.js +68 -0
- package/lib/metrics/recorders/middleware.js +29 -0
- package/lib/shim/datastore-shim.js +4 -68
- package/lib/shim/webframework-shim/middleware.js +2 -22
- package/lib/utilization/docker-info.js +21 -3
- package/package.json +1 -1
package/NEWS.md
CHANGED
|
@@ -1,60 +1,86 @@
|
|
|
1
|
-
### v12.6.
|
|
2
|
-
|
|
3
|
-
#### Features
|
|
4
|
-
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
* Updated
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
*
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
*
|
|
57
|
-
|
|
1
|
+
### v12.6.1 (2024-11-07)
|
|
2
|
+
|
|
3
|
+
#### Features
|
|
4
|
+
|
|
5
|
+
* 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))
|
|
6
|
+
|
|
7
|
+
#### Bug fixes
|
|
8
|
+
|
|
9
|
+
* Fixed issue parsing docker container id ([#2705](https://github.com/newrelic/node-newrelic/pull/2705)) ([0c897ab](https://github.com/newrelic/node-newrelic/commit/0c897ab7bea32daf0afbf75e2349f2fad008cc92))
|
|
10
|
+
|
|
11
|
+
#### Documentation
|
|
12
|
+
|
|
13
|
+
* Updated compatibility report ([#2679](https://github.com/newrelic/node-newrelic/pull/2679)) ([3c19cdf](https://github.com/newrelic/node-newrelic/commit/3c19cdfed751dfa20ebba471a6cdd320f0610d95))
|
|
14
|
+
|
|
15
|
+
#### Miscellaneous chores
|
|
16
|
+
|
|
17
|
+
* Moved recorders to `lib/metrics/recorders` ([#2666](https://github.com/newrelic/node-newrelic/pull/2666)) ([d8dfe84](https://github.com/newrelic/node-newrelic/commit/d8dfe843aebf275bda6d5c857cfe263039bc1a83))
|
|
18
|
+
|
|
19
|
+
#### Tests
|
|
20
|
+
|
|
21
|
+
* 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))
|
|
22
|
+
* 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))
|
|
23
|
+
* 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))
|
|
24
|
+
* 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))
|
|
25
|
+
* 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))
|
|
26
|
+
|
|
27
|
+
### v12.6.0 (2024-10-30)
|
|
28
|
+
|
|
29
|
+
#### Features
|
|
30
|
+
|
|
31
|
+
* 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))
|
|
32
|
+
* 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))
|
|
33
|
+
|
|
34
|
+
#### Documentation
|
|
35
|
+
|
|
36
|
+
* Updated compatibility report ([#2673](https://github.com/newrelic/node-newrelic/pull/2673)) ([e4d0503](https://github.com/newrelic/node-newrelic/commit/e4d0503934f7de45d3cdb6dbb4640a66cf8d8421))
|
|
37
|
+
|
|
38
|
+
#### Miscellaneous chores
|
|
39
|
+
|
|
40
|
+
* 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))
|
|
41
|
+
|
|
42
|
+
### v12.5.2 (2024-10-23)
|
|
43
|
+
|
|
44
|
+
#### Features
|
|
45
|
+
|
|
46
|
+
* 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))
|
|
47
|
+
|
|
48
|
+
#### Bug fixes
|
|
49
|
+
|
|
50
|
+
* Fixed amqplib instrumentation via ESM ([#2668](https://github.com/newrelic/node-newrelic/pull/2668)) ([a36deba](https://github.com/newrelic/node-newrelic/commit/a36deba7ba7b46c4947fcb83db0a4f97bd4c0bf1))
|
|
51
|
+
|
|
52
|
+
#### Documentation
|
|
53
|
+
|
|
54
|
+
* Remove SECURITY.md ([#2633](https://github.com/newrelic/node-newrelic/pull/2633)) ([41002cd](https://github.com/newrelic/node-newrelic/commit/41002cd1c423c378bfbe024ebe7dae03d02d2949))
|
|
55
|
+
* Updated compatibility report ([#2670](https://github.com/newrelic/node-newrelic/pull/2670)) ([281c0fa](https://github.com/newrelic/node-newrelic/commit/281c0fa3be096a0ef3eef25b0f51df7ae8bf50bf))
|
|
56
|
+
* Updated match custom-assertion jsdoc ([#2636](https://github.com/newrelic/node-newrelic/pull/2636)) ([c37abe5](https://github.com/newrelic/node-newrelic/commit/c37abe5eb4528493bb3950e376bf780d6cd29023))
|
|
57
|
+
|
|
58
|
+
#### Miscellaneous chores
|
|
59
|
+
|
|
60
|
+
* 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))
|
|
61
|
+
|
|
62
|
+
#### Tests
|
|
63
|
+
|
|
64
|
+
* 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))
|
|
65
|
+
* 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))
|
|
66
|
+
* 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))
|
|
67
|
+
* 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))
|
|
68
|
+
* 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))
|
|
69
|
+
* 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))
|
|
70
|
+
* Migrated unit tests to `node:test` ([#2623](https://github.com/newrelic/node-newrelic/pull/2623)) ([86231b7](https://github.com/newrelic/node-newrelic/commit/86231b7dec5bc5807ae26a88a7b8f2ff1535d9c4))
|
|
71
|
+
* 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))
|
|
72
|
+
* 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))
|
|
73
|
+
* 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))
|
|
74
|
+
* 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))
|
|
75
|
+
* Migrated `fastify` tests to `node:test` ([#2632](https://github.com/newrelic/node-newrelic/pull/2632)) ([b522477](https://github.com/newrelic/node-newrelic/commit/b522477168c2049b12bcfd39ae485f9e5374f724))
|
|
76
|
+
* 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))
|
|
77
|
+
* 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))
|
|
78
|
+
* 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))
|
|
79
|
+
|
|
80
|
+
#### Continuous integration
|
|
81
|
+
|
|
82
|
+
* 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))
|
|
83
|
+
|
|
58
84
|
### v12.5.1 (2024-09-23)
|
|
59
85
|
|
|
60
86
|
#### Bug fixes
|
package/lib/config/default.js
CHANGED
|
@@ -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
|
|
@@ -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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
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.')
|