newrelic 11.6.0 → 11.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 +47 -0
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/index.js +2 -2
- package/lib/agent.js +3 -3
- package/lib/errors/index.js +3 -3
- package/lib/feature_flags.js +2 -1
- package/lib/header-attributes.js +1 -0
- package/lib/instrumentation/core/http-outbound.js +2 -6
- package/lib/instrumentation/core/http.js +4 -122
- package/lib/instrumentation/openai.js +189 -181
- package/lib/instrumentation/pg.js +43 -16
- package/lib/instrumentation/restify.js +19 -4
- package/lib/instrumentation/undici.js +2 -4
- package/lib/instrumentation/winston.js +6 -1
- package/lib/metrics/names.js +8 -1
- package/lib/shimmer.js +56 -4
- package/lib/symbols.js +6 -1
- package/lib/synthetics.js +255 -0
- package/lib/transaction/index.js +4 -5
- package/lib/util/attributes.js +1 -16
- package/lib/util/camel-case.js +26 -0
- package/lib/util/logger.js +1 -1
- package/lib/util/snake-case.js +25 -0
- package/package.json +3 -3
package/NEWS.md
CHANGED
|
@@ -1,3 +1,50 @@
|
|
|
1
|
+
### v11.7.0 (2023-12-14)
|
|
2
|
+
|
|
3
|
+
#### Features
|
|
4
|
+
|
|
5
|
+
* Added deserialized X-NewRelic-Synthetics-Info header to transaction and transaction trace intrinsic attributes ([#1912](https://github.com/newrelic/node-newrelic/pull/1912)) ([7ed64bd](https://github.com/newrelic/node-newrelic/commit/7ed64bd1410d7eed6c4dbf153e0a67754e7bcdef))
|
|
6
|
+
* The attributes in transactions are: `nr.syntheticsType`, `nr.syntheticsInitiator`, and `nr.synthetics<attributeKey(s)>`
|
|
7
|
+
* The attributes in transaction traces are: `synthetics_type`, `synthetics_initiator`, and `synthetics_<attribute_key(s)>`
|
|
8
|
+
* It will also include the `X-NewRelic-Synthetics-Info` header in outgoing http requests
|
|
9
|
+
* Added instrumentation for Restify async handlers ([#1910](https://github.com/newrelic/node-newrelic/pull/1910)) ([1a3f87f](https://github.com/newrelic/node-newrelic/commit/1a3f87ff10dea1c25b35c349550338f327446cb1))
|
|
10
|
+
|
|
11
|
+
#### Bug fixes
|
|
12
|
+
|
|
13
|
+
* Update import-in-the-middle to fix ESM on Node 18.19.0 ([#1906](https://github.com/newrelic/node-newrelic/pull/1906)) ([e9c3748](https://github.com/newrelic/node-newrelic/commit/e9c37487a606d986d3568c11a014f6397f4f379e))
|
|
14
|
+
|
|
15
|
+
#### Code refactoring
|
|
16
|
+
|
|
17
|
+
* change dynamic import to work with bundlers ([#1905](https://github.com/newrelic/node-newrelic/pull/1905)) ([ee81429](https://github.com/newrelic/node-newrelic/commit/ee81429f5c34491392ed79026e6f716c76e2d735))
|
|
18
|
+
|
|
19
|
+
#### Miscellaneous chores
|
|
20
|
+
|
|
21
|
+
* Add AWS Bedrock feature flag ([#1913](https://github.com/newrelic/node-newrelic/pull/1913)) ([91019b0](https://github.com/newrelic/node-newrelic/commit/91019b0a45dcf8399cd8eadbe4e111e72ceab512))
|
|
22
|
+
|
|
23
|
+
#### Continuous integration
|
|
24
|
+
|
|
25
|
+
* removed step in post release process to update an internal system with the latest agent version ([#1909](https://github.com/newrelic/node-newrelic/pull/1909)) ([2080b1f](https://github.com/newrelic/node-newrelic/commit/2080b1fe03e65a4c6aaa073e8e338835c708680d))
|
|
26
|
+
|
|
27
|
+
### v11.6.1 (2023-12-07)
|
|
28
|
+
|
|
29
|
+
#### Bug fixes
|
|
30
|
+
|
|
31
|
+
* **deps:** Updated @newrelic/aws-sdk to 7.0.3 ([#1902](https://github.com/newrelic/node-newrelic/pull/1902)) ([bf22ae5](https://github.com/newrelic/node-newrelic/commit/bf22ae502ee74d5071dc5578cc77c38039e68778))
|
|
32
|
+
* Updated shimmer to handle instrumenting named and default exports of CommonJS modules in ESM ([#1894](https://github.com/newrelic/node-newrelic/pull/1894)) ([9f7979c](https://github.com/newrelic/node-newrelic/commit/9f7979cd41dcb3735e553cbd4837ad455836e3ff))
|
|
33
|
+
|
|
34
|
+
#### Code refactoring
|
|
35
|
+
|
|
36
|
+
* Fixed cognitive complexity violations of openai instrumentation by moving functions outside of the parent function scope ([#1895](https://github.com/newrelic/node-newrelic/pull/1895)) ([31dc717](https://github.com/newrelic/node-newrelic/commit/31dc71797c4798793b1bba8ca15733482ba3e7d6))
|
|
37
|
+
* Updated span names of openai actions to allow AI O11y team to locate relevant spans ([#1896](https://github.com/newrelic/node-newrelic/pull/1896)) ([b7a644d](https://github.com/newrelic/node-newrelic/commit/b7a644d1ef56bf88171fb74868ae78d24745dd19))
|
|
38
|
+
|
|
39
|
+
#### Miscellaneous chores
|
|
40
|
+
|
|
41
|
+
* Improve OpenAI mock server streams ([#1890](https://github.com/newrelic/node-newrelic/pull/1890)) ([d12bfe4](https://github.com/newrelic/node-newrelic/commit/d12bfe45f2c8d01277a1f8186844f0dd3598cbd7))
|
|
42
|
+
|
|
43
|
+
#### Tests
|
|
44
|
+
|
|
45
|
+
* Fix winston-esm versioned tests ([#1898](https://github.com/newrelic/node-newrelic/pull/1898)) ([6e02e57](https://github.com/newrelic/node-newrelic/commit/6e02e57a2b4ed8351e39e5fb8d47e2702bcafde0))
|
|
46
|
+
* pin undici versioned to <6.0.0 on Node 16 ([#1900](https://github.com/newrelic/node-newrelic/pull/1900)) ([9973b24](https://github.com/newrelic/node-newrelic/commit/9973b24067211f5fcc06adae79e02df8f599d735))
|
|
47
|
+
|
|
1
48
|
### v11.6.0 (2023-11-29)
|
|
2
49
|
|
|
3
50
|
#### Features
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -510,7 +510,7 @@ This product includes source derived from [@grpc/proto-loader](https://github.co
|
|
|
510
510
|
|
|
511
511
|
### @newrelic/aws-sdk
|
|
512
512
|
|
|
513
|
-
This product includes source derived from [@newrelic/aws-sdk](https://github.com/newrelic/node-newrelic-aws-sdk) ([v7.0.
|
|
513
|
+
This product includes source derived from [@newrelic/aws-sdk](https://github.com/newrelic/node-newrelic-aws-sdk) ([v7.0.3](https://github.com/newrelic/node-newrelic-aws-sdk/tree/v7.0.3)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-aws-sdk/blob/v7.0.3/LICENSE):
|
|
514
514
|
|
|
515
515
|
```
|
|
516
516
|
Apache License
|
package/index.js
CHANGED
|
@@ -40,7 +40,7 @@ if (require.cache.__NR_cache) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function initApi({ agent, apiPath }) {
|
|
43
|
-
const API = require(apiPath)
|
|
43
|
+
const API = require(`./${apiPath}`)
|
|
44
44
|
|
|
45
45
|
const api = new API(agent)
|
|
46
46
|
require.cache.__NR_cache = module.exports = api
|
|
@@ -115,7 +115,7 @@ function initialize() {
|
|
|
115
115
|
/* eslint-enable no-console */
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
const api = agent ? initApi({ agent, apiPath: '
|
|
118
|
+
const api = agent ? initApi({ agent, apiPath: 'api' }) : initApi({ apiPath: 'stub_api' })
|
|
119
119
|
|
|
120
120
|
// If we loaded an agent, record a startup time for the agent.
|
|
121
121
|
// NOTE: Metrics are recorded in seconds, so divide the value by 1000.
|
package/lib/agent.js
CHANGED
|
@@ -36,9 +36,9 @@ const {
|
|
|
36
36
|
addRequiredCATAttributes,
|
|
37
37
|
maybeAddExtraCATAttributes,
|
|
38
38
|
maybeAddParentAttributes,
|
|
39
|
-
maybeAddQueueAttributes
|
|
40
|
-
maybeAddSyntheticAttributes
|
|
39
|
+
maybeAddQueueAttributes
|
|
41
40
|
} = require('./util/attributes')
|
|
41
|
+
const synthetics = require('./synthetics')
|
|
42
42
|
|
|
43
43
|
// Map of valid states to whether or not data collection is valid
|
|
44
44
|
const STATES = {
|
|
@@ -747,7 +747,7 @@ function _addIntrinsicAttrsFromTransaction(transaction) {
|
|
|
747
747
|
maybeAddQueueAttributes(transaction, intrinsicAttributes)
|
|
748
748
|
maybeAddExternalAttributes(transaction, intrinsicAttributes)
|
|
749
749
|
maybeAddDatabaseAttributes(transaction, intrinsicAttributes)
|
|
750
|
-
|
|
750
|
+
synthetics.assignTransactionAttrs(transaction, intrinsicAttributes)
|
|
751
751
|
|
|
752
752
|
if (this.config.distributed_tracing.enabled) {
|
|
753
753
|
transaction.addDistributedTraceIntrinsics(intrinsicAttributes)
|
package/lib/errors/index.js
CHANGED
|
@@ -13,9 +13,9 @@ const errorHelper = require('../errors/helper')
|
|
|
13
13
|
const {
|
|
14
14
|
maybeAddQueueAttributes,
|
|
15
15
|
maybeAddExternalAttributes,
|
|
16
|
-
maybeAddDatabaseAttributes
|
|
17
|
-
maybeAddSyntheticAttributes
|
|
16
|
+
maybeAddDatabaseAttributes
|
|
18
17
|
} = require('../util/attributes')
|
|
18
|
+
const synthetics = require('../synthetics')
|
|
19
19
|
const Transaction = require('../transaction')
|
|
20
20
|
const ERROR_EXPECTED_PATH = 'error.expected'
|
|
21
21
|
|
|
@@ -230,7 +230,7 @@ function _getErrorEventIntrinsicAttrs(transaction, errorClass, message, expected
|
|
|
230
230
|
maybeAddQueueAttributes(transaction, attributes)
|
|
231
231
|
maybeAddExternalAttributes(transaction, attributes)
|
|
232
232
|
maybeAddDatabaseAttributes(transaction, attributes)
|
|
233
|
-
|
|
233
|
+
synthetics.assignTransactionAttrs(transaction, attributes)
|
|
234
234
|
|
|
235
235
|
if (transaction.agent.config.distributed_tracing.enabled) {
|
|
236
236
|
transaction.addDistributedTraceIntrinsics(attributes)
|
package/lib/feature_flags.js
CHANGED
|
@@ -12,7 +12,8 @@ exports.prerelease = {
|
|
|
12
12
|
reverse_naming_rules: false,
|
|
13
13
|
undici_async_tracking: true,
|
|
14
14
|
unresolved_promise_cleanup: true,
|
|
15
|
-
legacy_context_manager: false
|
|
15
|
+
legacy_context_manager: false,
|
|
16
|
+
aws_bedrock_instrumentation: false
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
// flags that are no longer used for released features
|
package/lib/header-attributes.js
CHANGED
|
@@ -60,6 +60,7 @@ const HEADER_ATTR_NAMES = {
|
|
|
60
60
|
'x-newrelic-app-data': 'xNewrelicAppData',
|
|
61
61
|
'x-newrelic-id': 'xNewrelicId',
|
|
62
62
|
'x-newrelic-synthetics': 'xNewrelicSynthetics',
|
|
63
|
+
'x-newrelic-synthetics-info': 'xNewrelicSyntheticsInfo',
|
|
63
64
|
'x-newrelic-transaction': 'xNewrelicTransaction',
|
|
64
65
|
'x-powered-by': 'xPoweredBy',
|
|
65
66
|
'x-queue-start': 'xQueueStart',
|
|
@@ -14,6 +14,7 @@ const url = require('url')
|
|
|
14
14
|
const copy = require('../../util/copy')
|
|
15
15
|
const symbols = require('../../symbols')
|
|
16
16
|
const http = require('http')
|
|
17
|
+
const synthetics = require('../../synthetics')
|
|
17
18
|
|
|
18
19
|
const NAMES = require('../../metrics/names')
|
|
19
20
|
|
|
@@ -21,8 +22,6 @@ const DEFAULT_HOST = 'localhost'
|
|
|
21
22
|
const DEFAULT_HTTP_PORT = 80
|
|
22
23
|
const DEFAULT_SSL_PORT = 443
|
|
23
24
|
|
|
24
|
-
const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
|
|
25
|
-
|
|
26
25
|
/**
|
|
27
26
|
* Determines the default port to 80 if protocol is undefined or http:
|
|
28
27
|
* Otherwise it assigns it as 443
|
|
@@ -139,10 +138,7 @@ function instrumentRequest(agent, opts, makeRequest, hostname, segment) {
|
|
|
139
138
|
const transaction = segment.transaction
|
|
140
139
|
const outboundHeaders = Object.create(null)
|
|
141
140
|
|
|
142
|
-
|
|
143
|
-
outboundHeaders[NEWRELIC_SYNTHETICS_HEADER] = transaction.syntheticsHeader
|
|
144
|
-
}
|
|
145
|
-
|
|
141
|
+
synthetics.assignHeadersToOutgoingRequest(agent.config, transaction, outboundHeaders)
|
|
146
142
|
maybeAddDtCatHeaders(agent, transaction, outboundHeaders, opts?.headers)
|
|
147
143
|
opts.headers = assignOutgoingHeaders(opts.headers, outboundHeaders)
|
|
148
144
|
|
|
@@ -10,26 +10,19 @@
|
|
|
10
10
|
const shimmer = require('../../shimmer')
|
|
11
11
|
const logger = require('../../logger').child({ component: 'http' })
|
|
12
12
|
const recordWeb = require('../../metrics/recorders/http')
|
|
13
|
-
const hashes = require('../../util/hashes')
|
|
14
13
|
const cat = require('../../util/cat')
|
|
15
14
|
const instrumentOutbound = require('./http-outbound')
|
|
16
15
|
const url = require('url')
|
|
17
16
|
const urltils = require('../../util/urltils')
|
|
18
17
|
const headerAttributes = require('../../header-attributes')
|
|
19
18
|
const headerProcessing = require('../../header-processing')
|
|
19
|
+
const synthetics = require('../../synthetics')
|
|
20
20
|
|
|
21
21
|
const NAMES = require('../../metrics/names')
|
|
22
22
|
const DESTS = require('../../config/attribute-filter').DESTINATIONS
|
|
23
23
|
|
|
24
24
|
const symbols = require('../../symbols')
|
|
25
25
|
|
|
26
|
-
/*
|
|
27
|
-
*
|
|
28
|
-
* CONSTANTS
|
|
29
|
-
*
|
|
30
|
-
*/
|
|
31
|
-
const NEWRELIC_SYNTHETICS_HEADER = 'x-newrelic-synthetics'
|
|
32
|
-
|
|
33
26
|
// For incoming requests this instrumentation functions by wrapping
|
|
34
27
|
// `http.createServer` and `http.Server#addListener`. The former merely sets the
|
|
35
28
|
// agent dispatcher to 'http' and the latter wraps any event handlers bound to
|
|
@@ -119,16 +112,7 @@ function wrapEmitWithTransaction(agent, emit, isHTTPS) {
|
|
|
119
112
|
transaction.queueTime = Date.now() - queueTimeStamp
|
|
120
113
|
}
|
|
121
114
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
if (synthHeader && agent.config.trusted_account_ids && agent.config.encoding_key) {
|
|
125
|
-
handleSyntheticsHeader(
|
|
126
|
-
synthHeader,
|
|
127
|
-
agent.config.encoding_key,
|
|
128
|
-
agent.config.trusted_account_ids,
|
|
129
|
-
transaction
|
|
130
|
-
)
|
|
131
|
-
}
|
|
115
|
+
synthetics.assignHeadersToTransaction(agent.config, transaction, request.headers)
|
|
132
116
|
|
|
133
117
|
if (agent.config.distributed_tracing.enabled) {
|
|
134
118
|
// Node http headers are automatically lowercase
|
|
@@ -278,9 +262,8 @@ function wrapWriteHead(agent, writeHead) {
|
|
|
278
262
|
logger.trace('No transaction - not adding response CAT headers')
|
|
279
263
|
return writeHead.apply(this, arguments)
|
|
280
264
|
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
}
|
|
265
|
+
|
|
266
|
+
synthetics.assignHeadersToResponse(this, transaction)
|
|
284
267
|
|
|
285
268
|
if (!transaction.incomingCatId) {
|
|
286
269
|
logger.trace('No incoming CAT ID - not adding response CAT headers')
|
|
@@ -487,104 +470,3 @@ module.exports = function initialize(agent, http, moduleName) {
|
|
|
487
470
|
}
|
|
488
471
|
)
|
|
489
472
|
}
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Take the X-NewRelic-Synthetics header and apply any appropriate data to the
|
|
493
|
-
* transaction for later use. This is the gate keeper for attributes being
|
|
494
|
-
* added onto the transaction object for synthetics.
|
|
495
|
-
*
|
|
496
|
-
* @param {string} header - The raw X-NewRelic-Synthetics header
|
|
497
|
-
* @param {string} encKey - Encoding key handed down from the server
|
|
498
|
-
* @param {Array.<number>} trustedIds - Array of accounts to trust the header from.
|
|
499
|
-
* @param {object} transaction - Where the synthetics data is attached to.
|
|
500
|
-
*/
|
|
501
|
-
function handleSyntheticsHeader(header, encKey, trustedIds, transaction) {
|
|
502
|
-
const synthData = parseSyntheticsHeader(header, encKey, trustedIds)
|
|
503
|
-
if (!synthData) {
|
|
504
|
-
return
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
transaction.syntheticsData = synthData
|
|
508
|
-
transaction.syntheticsHeader = header
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/**
|
|
512
|
-
* Parse out and verify the the pieces of the X-NewRelic-Synthetics header.
|
|
513
|
-
*
|
|
514
|
-
* @param {string} header - The raw X-NewRelic-Synthetics header
|
|
515
|
-
* @param {string} encKey - Encoding key handed down from the server
|
|
516
|
-
* @param {Array.<number>} trustedIds - Array of accounts to trust the header from.
|
|
517
|
-
* @returns {object | null} - On successful parse and verification an object of
|
|
518
|
-
* synthetics data is returned, otherwise null is
|
|
519
|
-
* returned.
|
|
520
|
-
*/
|
|
521
|
-
function parseSyntheticsHeader(header, encKey, trustedIds) {
|
|
522
|
-
// Eagerly declare this object because we know what it should look like and
|
|
523
|
-
// can use that for header verification.
|
|
524
|
-
const parsedData = {
|
|
525
|
-
version: null,
|
|
526
|
-
accountId: null,
|
|
527
|
-
resourceId: null,
|
|
528
|
-
jobId: null,
|
|
529
|
-
monitorId: null
|
|
530
|
-
}
|
|
531
|
-
let synthData = null
|
|
532
|
-
try {
|
|
533
|
-
synthData = JSON.parse(hashes.deobfuscateNameUsingKey(header, encKey))
|
|
534
|
-
} catch (e) {
|
|
535
|
-
logger.trace(e, 'Got unparsable synthetics header: %s', header)
|
|
536
|
-
return
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
if (!Array.isArray(synthData)) {
|
|
540
|
-
logger.trace('Synthetics data is not an array: %s (%s)', synthData, typeof synthData)
|
|
541
|
-
return
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
if (synthData.length < Object.keys(parsedData).length) {
|
|
545
|
-
logger.trace(
|
|
546
|
-
'Synthetics header length is %s, expected at least %s',
|
|
547
|
-
synthData.length,
|
|
548
|
-
Object.keys(parsedData).length
|
|
549
|
-
)
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
parsedData.version = synthData[0]
|
|
553
|
-
if (parsedData.version !== 1) {
|
|
554
|
-
logger.trace('Synthetics header version is not 1, got: %s (%s)', parsedData.version, synthData)
|
|
555
|
-
return
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
parsedData.accountId = synthData[1]
|
|
559
|
-
if (parsedData.accountId) {
|
|
560
|
-
if (trustedIds.indexOf(parsedData.accountId) === -1) {
|
|
561
|
-
logger.trace(
|
|
562
|
-
'Synthetics header account ID is not in trusted account IDs: %s (%s)',
|
|
563
|
-
parsedData.accountId,
|
|
564
|
-
trustedIds
|
|
565
|
-
)
|
|
566
|
-
return
|
|
567
|
-
}
|
|
568
|
-
} else {
|
|
569
|
-
logger.trace('Synthetics header account ID missing.')
|
|
570
|
-
return
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
parsedData.resourceId = synthData[2]
|
|
574
|
-
if (!parsedData.resourceId) {
|
|
575
|
-
logger.trace('Synthetics resource ID is missing.')
|
|
576
|
-
return
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
parsedData.jobId = synthData[3]
|
|
580
|
-
if (!parsedData.jobId) {
|
|
581
|
-
logger.trace('Synthetics job ID is missing.')
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
parsedData.monitorId = synthData[4]
|
|
585
|
-
if (!parsedData.monitorId) {
|
|
586
|
-
logger.trace('Synthetics monitor ID is missing.')
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
return parsedData
|
|
590
|
-
}
|