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 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
@@ -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.2](https://github.com/newrelic/node-newrelic-aws-sdk/tree/v7.0.2)), distributed under the [Apache-2.0 License](https://github.com/newrelic/node-newrelic-aws-sdk/blob/v7.0.2/LICENSE):
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: './api' }) : initApi({ apiPath: './stub_api' })
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
- maybeAddSyntheticAttributes(transaction, intrinsicAttributes)
750
+ synthetics.assignTransactionAttrs(transaction, intrinsicAttributes)
751
751
 
752
752
  if (this.config.distributed_tracing.enabled) {
753
753
  transaction.addDistributedTraceIntrinsics(intrinsicAttributes)
@@ -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
- maybeAddSyntheticAttributes(transaction, attributes)
233
+ synthetics.assignTransactionAttrs(transaction, attributes)
234
234
 
235
235
  if (transaction.agent.config.distributed_tracing.enabled) {
236
236
  transaction.addDistributedTraceIntrinsics(attributes)
@@ -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
@@ -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
- if (agent.config.encoding_key && transaction.syntheticsHeader) {
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
- const synthHeader = request.headers[NEWRELIC_SYNTHETICS_HEADER]
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
- if (transaction.syntheticsHeader) {
282
- this.setHeader(NEWRELIC_SYNTHETICS_HEADER, transaction.syntheticsHeader)
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
- }