newrelic 13.19.2 → 14.0.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.
Files changed (111) hide show
  1. package/NEWS.md +115 -0
  2. package/THIRD_PARTY_NOTICES.md +82 -345
  3. package/api.js +85 -0
  4. package/lib/agent.js +12 -9
  5. package/lib/attributes.js +1 -2
  6. package/lib/collector/api.js +2 -20
  7. package/lib/collector/http-agents.js +4 -1
  8. package/lib/collector/remote-method.js +3 -1
  9. package/lib/config/default.js +43 -21
  10. package/lib/config/index.js +20 -190
  11. package/lib/context-manager/async-local-context-manager.js +3 -9
  12. package/lib/db/statement-matcher.js +1 -1
  13. package/lib/errors/index.js +0 -2
  14. package/lib/instrumentation/@prisma/client.js +12 -2
  15. package/lib/instrumentation/core/domain.js +2 -13
  16. package/lib/instrumentation/core/globals.js +0 -1
  17. package/lib/instrumentation/core/http-outbound.js +14 -31
  18. package/lib/instrumentation/core/http.js +17 -70
  19. package/lib/instrumentation/core/http2.js +2 -11
  20. package/lib/instrumentation/koa/nr-hooks.js +0 -12
  21. package/lib/instrumentations.js +0 -4
  22. package/lib/llm-events/ai-agent.js +28 -0
  23. package/lib/llm-events/google-genai/chat-completion-message.js +6 -3
  24. package/lib/message-broker-description.js +29 -12
  25. package/lib/metrics/names.js +14 -8
  26. package/lib/metrics/recorders/apollo-resolver.js +40 -0
  27. package/lib/metrics/recorders/http.js +0 -2
  28. package/lib/metrics/recorders/http_external.js +1 -25
  29. package/lib/shim/message-shim/index.js +4 -4
  30. package/lib/shim/shim.js +2 -40
  31. package/lib/shim/transaction-shim.js +10 -130
  32. package/lib/subscriber-configs.js +5 -0
  33. package/lib/subscribers/amqplib/consume.js +1 -1
  34. package/lib/subscribers/apollo-server/config.js +52 -0
  35. package/lib/subscribers/apollo-server/constants.js +49 -0
  36. package/lib/subscribers/apollo-server/request.js +355 -0
  37. package/lib/subscribers/apollo-server/resolve.js +242 -0
  38. package/lib/subscribers/aws-sdk/config.js +41 -3
  39. package/lib/subscribers/aws-sdk/core-send.js +16 -0
  40. package/lib/subscribers/aws-sdk/middleware/bedrock/index.js +3 -4
  41. package/lib/subscribers/aws-sdk/middleware/dynamodb/index.js +2 -3
  42. package/lib/subscribers/aws-sdk/middleware/nr-specific/attributes.js +2 -2
  43. package/lib/subscribers/aws-sdk/middleware/nr-specific/headers.js +3 -3
  44. package/lib/subscribers/aws-sdk/middleware/sns/index.js +3 -4
  45. package/lib/subscribers/aws-sdk/middleware/sqs/index.js +11 -15
  46. package/lib/subscribers/aws-sdk/utils/attach-headers.js +1 -1
  47. package/lib/subscribers/azure-functions/azure-handler-base.js +138 -0
  48. package/lib/subscribers/azure-functions/background-handler.js +29 -0
  49. package/lib/subscribers/azure-functions/config.js +44 -0
  50. package/lib/subscribers/azure-functions/http-handler.js +58 -0
  51. package/lib/subscribers/azure-functions/index.js +74 -0
  52. package/lib/subscribers/azure-functions/logger.js +72 -0
  53. package/lib/subscribers/base.js +8 -29
  54. package/lib/subscribers/bluebird/config.js +1 -1
  55. package/lib/subscribers/bluebird/instrumentation.js +3 -7
  56. package/lib/subscribers/cassandra-driver/config.js +5 -5
  57. package/lib/subscribers/connect/config.js +42 -0
  58. package/lib/subscribers/connect/use.js +31 -0
  59. package/lib/subscribers/dc-base.js +45 -4
  60. package/lib/subscribers/fastify/config.js +2 -2
  61. package/lib/subscribers/fastify/index.js +1 -1
  62. package/lib/subscribers/google-adk/agent-run-async.js +118 -0
  63. package/lib/subscribers/google-adk/config.js +59 -0
  64. package/lib/subscribers/google-adk/tool-run-async.js +87 -0
  65. package/lib/subscribers/grpcjs/client.js +3 -12
  66. package/lib/subscribers/grpcjs/server.js +2 -2
  67. package/lib/subscribers/kafkajs/client-constructor.js +349 -0
  68. package/lib/subscribers/kafkajs/config.js +25 -0
  69. package/lib/subscribers/kafkajs/utils/record-data-metrics.js +48 -0
  70. package/lib/subscribers/kafkajs/utils/record-linking-metrics.js +30 -0
  71. package/lib/{instrumentation/kafkajs → subscribers/kafkajs/utils}/record-method-metric.js +3 -2
  72. package/lib/subscribers/langgraph/graph-stream.js +2 -1
  73. package/lib/subscribers/message-consumer-tools.js +161 -0
  74. package/lib/subscribers/message-consumer.js +43 -61
  75. package/lib/subscribers/message-producer.js +2 -3
  76. package/lib/subscribers/middleware-wrapper.js +7 -7
  77. package/lib/subscribers/mysql/config.js +1 -33
  78. package/lib/subscribers/mysql/connection-query.js +72 -3
  79. package/lib/subscribers/mysql/pool-get-connection.js +0 -1
  80. package/lib/subscribers/mysql2/config.js +14 -56
  81. package/lib/subscribers/mysql2/connection-execute.js +2 -2
  82. package/lib/subscribers/mysql2/pool-get-connection.js +0 -2
  83. package/lib/subscribers/nestjs/config.js +1 -1
  84. package/lib/subscribers/undici/index.js +6 -31
  85. package/lib/symbols.js +1 -0
  86. package/lib/transaction/index.js +16 -82
  87. package/lib/transaction/trace/index.js +148 -67
  88. package/lib/transaction/trace/segment-tree.js +7 -15
  89. package/lib/transaction/trace/segment.js +24 -28
  90. package/lib/transaction/tracer/index.js +71 -29
  91. package/lib/util/attributes.js +1 -70
  92. package/lib/util/hashes.js +0 -30
  93. package/lib/util/logger.js +1 -1
  94. package/package.json +19 -25
  95. package/lib/config/lasp.js +0 -106
  96. package/lib/instrumentation/@azure/functions.js +0 -323
  97. package/lib/instrumentation/connect.js +0 -83
  98. package/lib/instrumentation/fastify/spec-builders.js +0 -103
  99. package/lib/instrumentation/fastify.js +0 -100
  100. package/lib/instrumentation/kafkajs/consumer.js +0 -145
  101. package/lib/instrumentation/kafkajs/index.js +0 -34
  102. package/lib/instrumentation/kafkajs/producer.js +0 -83
  103. package/lib/instrumentation/kafkajs/record-linking-metrics.js +0 -17
  104. package/lib/instrumentation/kafkajs.js +0 -7
  105. package/lib/instrumentation/koa/route-instrumentation.js +0 -31
  106. package/lib/subscribers/mysql/pool-namespace-query.js +0 -19
  107. package/lib/subscribers/mysql/pool-query.js +0 -41
  108. package/lib/subscribers/mysql2/pool-namespace-query.js +0 -19
  109. package/lib/subscribers/mysql2/pool-query.js +0 -19
  110. package/lib/transaction/trace/exclusive-time-calculator.js +0 -143
  111. package/lib/util/cat.js +0 -305
package/api.js CHANGED
@@ -1977,4 +1977,89 @@ API.prototype.withLlmCustomAttributes = function withLlmCustomAttributes(context
1977
1977
  return transaction._llmContextManager.run(fullContext, callback)
1978
1978
  }
1979
1979
 
1980
+ /**
1981
+ * Function for adding a custom callback to generate custom attributes on apollo server operation segments.
1982
+ *
1983
+ * Provided functions must be synchronous and return an object of custom attribute key/values.
1984
+ * The arguments provided to callback are: `requestContext`, which is the apollo server `requestContext`.
1985
+ *
1986
+ *
1987
+ * @param {Function} callback - callback function to generate custom attributes on apollo operation segments
1988
+ * @example
1989
+ * function customOperationAttributes(requestContext) {
1990
+ * return {
1991
+ * clientName: requestContext.request.http.headers.get('graphql-client-name')
1992
+ * }
1993
+ * }
1994
+ *
1995
+ * newrelic.setApolloOperationAttributesCallback(customOperationAttributes)
1996
+ */
1997
+ API.prototype.setApolloOperationAttributesCallback = function setApolloOperationAttributesCallback(callback) {
1998
+ const self = this
1999
+ const metric = this.agent.metrics.getOrCreateMetric(
2000
+ NAMES.SUPPORTABILITY.API + '/setApolloOperationAttributesCallback'
2001
+ )
2002
+ metric.incrementCallCount()
2003
+
2004
+ if (!this.shim.isFunction(callback) || this.shim.isAsyncFunction(callback)) {
2005
+ logger.warn(
2006
+ 'Apollo operation attributes callback must be a synchronous function, custom operation attributes will not be added.'
2007
+ )
2008
+ return
2009
+ }
2010
+
2011
+ this.agent.customCallbacks.apollo.operationCallback = function wrappedOperationAttributesCb(requestContext) {
2012
+ const result = callback(requestContext)
2013
+ self.addCustomAttributes(result)
2014
+ }
2015
+ }
2016
+
2017
+ /**
2018
+ * Function for adding a custom callback to generate custom attributes on apollo server resolver segments.
2019
+ *
2020
+ * Provided functions must be synchronous and return an object of custom attribute key/values.
2021
+ * The arguments provided to callback are:
2022
+ *
2023
+ * ```
2024
+ * {
2025
+ * source: object,
2026
+ * args: array,
2027
+ * contextValue: object,
2028
+ * info: object
2029
+ * }
2030
+ * ```
2031
+ *
2032
+ * @param {Function} callback - callback function to generate custom attributes on apollo operation segments
2033
+ * @example
2034
+ * function customResolverAttributes({ source, args, contextValue, info }}) {
2035
+ * return {
2036
+ * allArgs: Object.keys(args).join(','),
2037
+ * returnType: info.returnType.name,
2038
+ * sourceBranch: source?.branch
2039
+ * stage: contextValue.event.requestContext.stage
2040
+ * }
2041
+ * }
2042
+ *
2043
+ * newrelic.setApolloResolverAttributesCallback(customResolverAttributes)
2044
+ */
2045
+ API.prototype.setApolloResolverAttributesCallback = function setApolloResolverAttributesCallback(callback) {
2046
+ const self = this
2047
+ const metric = this.agent.metrics.getOrCreateMetric(
2048
+ NAMES.SUPPORTABILITY.API + '/setApolloResolverAttributesCallback'
2049
+ )
2050
+ metric.incrementCallCount()
2051
+
2052
+ if (!this.shim.isFunction(callback) || this.shim.isAsyncFunction(callback)) {
2053
+ logger.warn(
2054
+ 'Apollo resolver attributes callback must be a synchronous function, custom resolver attributes will not be added.'
2055
+ )
2056
+ return
2057
+ }
2058
+
2059
+ this.agent.customCallbacks.apollo.resolverCallback = function wrappedResolverAttributesCb(args) {
2060
+ const result = callback(args)
2061
+ self.addCustomAttributes(result)
2062
+ }
2063
+ }
2064
+
1980
2065
  module.exports = API
package/lib/agent.js CHANGED
@@ -31,8 +31,6 @@ const createSpanEventAggregator = require('./spans/create-span-event-aggregator'
31
31
  const {
32
32
  maybeAddDatabaseAttributes,
33
33
  maybeAddExternalAttributes,
34
- addRequiredCATAttributes,
35
- maybeAddExtraCATAttributes,
36
34
  maybeAddParentAttributes,
37
35
  maybeAddQueueAttributes
38
36
  } = require('./util/attributes')
@@ -321,6 +319,18 @@ function Agent(config) {
321
319
  this._listenForConfigChanges()
322
320
 
323
321
  this.initCounters()
322
+ // Set up data structure to store user defined callbacks for various features
323
+ this.customCallbacks = {
324
+ apollo: {
325
+ // defined with `api.setApolloOperationAttributesCallback`
326
+ // it is called to add custom attributes to the operation segments
327
+ operationCallback: null,
328
+ // defined with `api.setApolloResolverAttributesCallback`
329
+ // it is called to add custom attributes to the resolver segments
330
+ resolverCallback: null
331
+ }
332
+ }
333
+ // TODO: move to `this.customCallbacks`
324
334
  this.llm = {}
325
335
 
326
336
  // Finally, add listeners for the agent's own events.
@@ -751,13 +761,6 @@ function _addIntrinsicAttrsFromTransaction(transaction) {
751
761
  if (this.config.distributed_tracing.enabled) {
752
762
  transaction.addDistributedTraceIntrinsics(intrinsicAttributes)
753
763
  maybeAddParentAttributes(transaction, intrinsicAttributes)
754
- } else if (
755
- this.config.cross_application_tracer.enabled &&
756
- !transaction.invalidIncomingExternalTransaction &&
757
- (transaction.referringTransactionGuid || transaction.includesOutboundRequests())
758
- ) {
759
- addRequiredCATAttributes(transaction, intrinsicAttributes, this.config)
760
- maybeAddExtraCATAttributes(transaction, intrinsicAttributes, this.config)
761
764
  }
762
765
 
763
766
  return intrinsicAttributes
package/lib/attributes.js CHANGED
@@ -102,8 +102,7 @@ class Attributes {
102
102
  }
103
103
 
104
104
  /**
105
- * Clears instance attributes. Used for enforcing updated LASP
106
- * settings on connect.
105
+ * Clears instance attributes.
107
106
  */
108
107
  reset() {
109
108
  this.attributes = Object.create(null)
@@ -296,10 +296,6 @@ CollectorAPI.prototype._login = function _login(callback) {
296
296
  const agent = this._agent
297
297
 
298
298
  const preconnectData = { high_security: agent.config.high_security }
299
- if (agent.config.security_policies_token) {
300
- preconnectData.security_policies_token = agent.config.security_policies_token
301
- }
302
-
303
299
  const payload = [preconnectData]
304
300
 
305
301
  this._methods.preconnect.invoke(payload, this._onPreConnect.bind(this, callback))
@@ -312,7 +308,6 @@ CollectorAPI.prototype._login = function _login(callback) {
312
308
  * @returns {void}
313
309
  */
314
310
  CollectorAPI.prototype._onPreConnect = function _onPreConnect(callback, error, response) {
315
- const agent = this._agent
316
311
  if (error || !SUCCESS.has(response.status)) {
317
312
  callback(error, response)
318
313
  return
@@ -320,16 +315,7 @@ CollectorAPI.prototype._onPreConnect = function _onPreConnect(callback, error, r
320
315
 
321
316
  const res = response.payload || Object.create(null)
322
317
  this._handlePreConnectResponse(res)
323
-
324
- const policies = res.security_policies || Object.create(null)
325
-
326
- const laspResponse = agent.config.applyLasp(agent, policies)
327
- if (laspResponse.shouldShutdownRun()) {
328
- callback(null, laspResponse)
329
- return
330
- }
331
-
332
- this._getFacts(laspResponse.payload, callback)
318
+ this._getFacts(callback)
333
319
  }
334
320
 
335
321
  /**
@@ -372,15 +358,11 @@ CollectorAPI.prototype._handlePreConnectResponse = function _handlePreConnectRes
372
358
  }
373
359
  }
374
360
 
375
- CollectorAPI.prototype._getFacts = function _getFacts(lasp, callback) {
361
+ CollectorAPI.prototype._getFacts = function _getFacts(callback) {
376
362
  const agent = this._agent
377
363
  const self = this
378
364
 
379
365
  facts(agent, function getEnvDict(environmentDict) {
380
- if (lasp) {
381
- environmentDict.security_policies = lasp
382
- }
383
-
384
366
  // The collector really likes arrays.
385
367
  // In fact, it kind of insists on them.
386
368
  const environment = [environmentDict]
@@ -5,7 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- const { HttpsProxyAgent } = require('https-proxy-agent')
9
8
  const logger = require('../logger').child({ component: 'http-agent' })
10
9
  const https = require('https')
11
10
 
@@ -64,6 +63,10 @@ exports.proxyAgent = function proxyAgent(config) {
64
63
  }
65
64
 
66
65
  logger.info(`using proxy: ${proxyUrl}`)
66
+ // lazy-load `https-proxy-agent` as it is ESM
67
+ // if required at top it would not allow us to instrument
68
+ // the core `node:http` correctly.
69
+ const { HttpsProxyAgent } = require('https-proxy-agent')
67
70
  agentProxyWithKeepAlive = new HttpsProxyAgent(proxyUrl, proxyOpts)
68
71
  return agentProxyWithKeepAlive
69
72
  }
@@ -354,7 +354,9 @@ RemoteMethod.prototype._path = function _path({ redactLicenseKey } = {}) {
354
354
  const query = {
355
355
  marshal_format: 'json',
356
356
  protocol_version: this._protocolVersion,
357
- license_key: redactLicenseKey ? 'REDACTED' : this._config.license_key,
357
+ license_key: redactLicenseKey
358
+ ? this._config.redacted_license_key
359
+ : this._config.license_key,
358
360
  method: this.name
359
361
  }
360
362
 
@@ -43,12 +43,6 @@ defaultConfig.definition = () => {
43
43
  * The user's license key. Must be set by per-app configuration file.
44
44
  */
45
45
  license_key: '',
46
- /**
47
- *
48
- * Enables/Disables security policies. Paste your security policies
49
- * token from the New Relic Admin below.
50
- */
51
- security_policies_token: '',
52
46
  /**
53
47
  * Hostname for the New Relic collector proxy.
54
48
  *
@@ -1140,7 +1134,7 @@ defaultConfig.definition = () => {
1140
1134
  */
1141
1135
  exclude_newrelic_header: {
1142
1136
  formatter: boolean,
1143
- default: false
1137
+ default: true
1144
1138
  },
1145
1139
 
1146
1140
  sampler: {
@@ -1175,20 +1169,6 @@ defaultConfig.definition = () => {
1175
1169
  }
1176
1170
  },
1177
1171
 
1178
- /**
1179
- * Controls the use of cross-application tracing.
1180
- *
1181
- * @property {boolean} [enabled=false]
1182
- * Enables tracing transactions across multiple applications. Default is `false`.
1183
- * This feature has been deprecated in favor of Distributed Tracing (DT).
1184
- * To fully enable this feature, you must also disable DT in your configuration.
1185
- */
1186
- cross_application_tracer: {
1187
- enabled: {
1188
- formatter: boolean,
1189
- default: false
1190
- }
1191
- },
1192
1172
  /**
1193
1173
  * Controls behavior of message broker tracing.
1194
1174
  *
@@ -1782,6 +1762,48 @@ defaultConfig.definition = () => {
1782
1762
  formatter: int
1783
1763
  }
1784
1764
  }
1765
+ },
1766
+
1767
+ /**
1768
+ * Stanza for customizing behavior for apollo server instrumentation
1769
+ */
1770
+ apollo_server: {
1771
+ /**
1772
+ * Enable capture of timing of fields resolved with the GraphQLScalarType return type. This may be desired when performing time intensive calculations to return a scalar value. This is not recommended for queries that return a large number of pre-calculated scalar fields.
1773
+ * NOTE: query/mutation resolvers will always be captured even if returning a scalar type.
1774
+ */
1775
+ scalars: {
1776
+ formatter: boolean,
1777
+ default: false
1778
+ },
1779
+ /**
1780
+ * Enable capture of timings for an [IntrospectionQuery](https://www.graphql-js.org/api-v16/utilities/#introspectionquery)
1781
+ */
1782
+ introspection_queries: {
1783
+ formatter: boolean,
1784
+ default: false
1785
+ },
1786
+ /**
1787
+ * Enable capture of timings for a [Service Definition query](https://www.apollographql.com/docs/federation/federation-spec/#fetch-service-capabilities) received from an Apollo Federated Gateway Server.
1788
+ */
1789
+ service_definition_queries: {
1790
+ formatter: boolean,
1791
+ default: false
1792
+ },
1793
+ /**
1794
+ * Enable capture of timings for a [Health Check query](https://www.apollographql.com/docs/federation/api/apollo-gateway/#servicehealthcheck) received from an Apollo Federated Gateway Server.
1795
+ */
1796
+ health_check_queries: {
1797
+ formatter: boolean,
1798
+ default: false
1799
+ },
1800
+ /**
1801
+ * Enable capture of metrics for every field and resolver argument seen for an Apollo query. This is intended to be used to check for any unused fields in your graphql schema.
1802
+ */
1803
+ field_metrics: {
1804
+ formatter: boolean,
1805
+ default: false
1806
+ }
1785
1807
  }
1786
1808
  }
1787
1809
  }
@@ -6,14 +6,12 @@
6
6
  'use strict'
7
7
 
8
8
  const AttributeFilter = require('./attribute-filter')
9
- const CollectorResponse = require('../collector/response')
10
9
  const copy = require('../util/copy')
11
10
  const { config: defaultConfig, definition, setNestedKey } = require('./default')
12
11
  const EventEmitter = require('events').EventEmitter
13
12
  const featureFlag = require('../feature_flags')
14
13
  const flatten = require('../util/flatten')
15
14
  const fs = require('../util/unwrapped-core').fs
16
- const hashes = require('../util/hashes')
17
15
  const os = require('os')
18
16
  const parseKey = require('../collector/key-parser').parseKey
19
17
  const path = require('path')
@@ -35,7 +33,6 @@ const DEFAULT_MAX_PAYLOAD_SIZE_IN_BYTES = 1_000_000
35
33
  const BASE_CONFIG_PATH = require.resolve('../../newrelic')
36
34
  const HAS_ARBITRARY_KEYS = new Set(['ignore_messages', 'expected_messages', 'labels'])
37
35
 
38
- const LASP_MAP = require('./lasp').LASP_MAP
39
36
  const HSM = require('./hsm')
40
37
  const REMOVE_BEFORE_SEND = new Set(['attributeFilter'])
41
38
  const SSL_WARNING = 'SSL config key can no longer be disabled, not updating.'
@@ -118,9 +115,7 @@ function Config(config) {
118
115
  this.account_id = null
119
116
  this.application_id = null
120
117
  this.web_transactions_apdex = Object.create(null)
121
- this.cross_process_id = null
122
118
  this.encoding_key = null
123
- this.obfuscatedId = null
124
119
  this.primary_application_id = null
125
120
  this.trusted_account_ids = null
126
121
  this.trusted_account_key = null
@@ -185,14 +180,6 @@ function Config(config) {
185
180
 
186
181
  // 8. apply high security overrides
187
182
  if (this.high_security) {
188
- if (this.security_policies_token) {
189
- throw new Error(
190
- 'Security Policies and High Security Mode cannot both be present ' +
191
- 'in the agent configuration. If Security Policies have been set ' +
192
- 'for your account, please ensure the security_policies_token is ' +
193
- 'set but high_security is disabled (default).'
194
- )
195
- }
196
183
  this._applyHighSecurity()
197
184
  }
198
185
 
@@ -284,22 +271,9 @@ Config.prototype.onConnect = function onConnect(json, recursion) {
284
271
  this._fromServer(json, key)
285
272
  }
286
273
 
287
- this._warnDeprecations()
288
-
289
274
  this.emit('change', this)
290
275
  }
291
276
 
292
- Config.prototype._getMostSecure = function getMostSecure(key, currentVal, newVal) {
293
- const filter = LASP_MAP[key] && LASP_MAP[key].filter
294
- if (!this.security_policies_token || !filter) {
295
- // If we aren't applying something vetted by security policies we
296
- // just return the new value.
297
- return newVal
298
- }
299
- // Return the most secure if we have a filter to apply
300
- return filter(currentVal, newVal)
301
- }
302
-
303
277
  /**
304
278
  * Helper that checks if value from server is false
305
279
  * then updates the corresponding configuration enabled flag.
@@ -389,12 +363,8 @@ Config.prototype._fromServer = function _fromServer(params, key) {
389
363
  break
390
364
 
391
365
  // always accept these settings
392
- case 'cross_process_id':
393
366
  case 'encoding_key':
394
367
  this._alwaysUpdateIfChanged(params, key)
395
- if (this.cross_process_id && this.encoding_key) {
396
- this.obfuscatedId = hashes.obfuscateNameUsingKey(this.cross_process_id, this.encoding_key)
397
- }
398
368
  break
399
369
 
400
370
  // always accept these settings
@@ -476,12 +446,6 @@ Config.prototype._fromServer = function _fromServer(params, key) {
476
446
  break
477
447
 
478
448
  //
479
- // Cross Application Tracer
480
- //
481
- case 'cross_application_tracer.enabled':
482
- this._updateNestedIfChanged(params, this.cross_application_tracer, key, 'enabled')
483
- break
484
- //
485
449
  // Error Collector
486
450
  //
487
451
  case 'error_collector.enabled':
@@ -1335,16 +1299,6 @@ Config.prototype._serverlessAppName = function _serverlessAppName() {
1335
1299
  }
1336
1300
  }
1337
1301
 
1338
- /**
1339
- * Disables CAT in serverless mode
1340
- */
1341
- Config.prototype._serverlessCAT = function _serverlessCAT() {
1342
- if (this.cross_application_tracer.enabled) {
1343
- this.cross_application_tracer.enabled = false
1344
- logger.info('Cross application tracing is explicitly disabled in serverless_mode.')
1345
- }
1346
- }
1347
-
1348
1302
  Config.prototype._serverlessInfiniteTracing = function _serverlessInfiniteTracing() {
1349
1303
  if (this.infinite_tracing.trace_observer.host) {
1350
1304
  this.infinite_tracing.trace_observer.host = ''
@@ -1401,7 +1355,6 @@ Config.prototype._preventServerlessDT = function _preventServerlessDT() {
1401
1355
 
1402
1356
  /**
1403
1357
  * Enforces config rules specific to running in serverless_mode:
1404
- * - disables cross_application_tracer.enabled if set
1405
1358
  * - defaults logging to disabled
1406
1359
  * - verifies data specific to running DT is defined either in config file of env vars
1407
1360
  *
@@ -1410,7 +1363,6 @@ Config.prototype._preventServerlessDT = function _preventServerlessDT() {
1410
1363
  Config.prototype._enforceServerless = function _enforceServerless(inputConfig) {
1411
1364
  if (this.serverless_mode.enabled) {
1412
1365
  this._serverlessAppName()
1413
- this._serverlessCAT()
1414
1366
  this._serverlessInfiniteTracing()
1415
1367
  this._serverlessLogging(inputConfig)
1416
1368
  this._serverlessNativeMetrics(inputConfig)
@@ -1470,6 +1422,8 @@ Config.prototype._canonicalize = function _canonicalize() {
1470
1422
  if (this.license_key) {
1471
1423
  this.license_key = this.license_key.trim()
1472
1424
  }
1425
+
1426
+ this.redacted_license_key = redactLicenseKey(this.license_key)
1473
1427
  }
1474
1428
 
1475
1429
  /**
@@ -1573,135 +1527,6 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
1573
1527
  }
1574
1528
  }
1575
1529
 
1576
- /**
1577
- * Sends a response to collector for LASP application
1578
- *
1579
- * @param {Array} keys keys from a LASP policy
1580
- * @returns {CollectorResponse} creates CollectorResponse with either preserve or shutdown
1581
- */
1582
- function _laspResponse(keys) {
1583
- if (keys.length) {
1584
- logger.error('The agent received one or more unexpected security policies and will shut down.')
1585
- return CollectorResponse.fatal(null)
1586
- }
1587
- return CollectorResponse.success(null)
1588
- }
1589
-
1590
- /**
1591
- * Applies the server side LASP policies to a local configuration object
1592
- *
1593
- * @param {Agent} agent Agent instance
1594
- * @param {object} policies server side LASP policy
1595
- * @returns {object} { missingRequired, finalPolicies } list of missing required fields and finalized LASP policy
1596
- */
1597
- Config.prototype._buildLaspPolicy = function _buildLaspPolicy(agent, policies) {
1598
- const config = this
1599
- const keys = Object.keys(policies)
1600
- const missingRequired = []
1601
-
1602
- const finalPolicies = keys.reduce(function applyPolicy(obj, name) {
1603
- const policy = policies[name]
1604
- const localMapping = LASP_MAP[name]
1605
-
1606
- if (!localMapping) {
1607
- if (!policy.required) {
1608
- // policy is not implemented in agent -- don't send to connect
1609
- return obj
1610
- }
1611
- // policy is required but does not exist in agent -- fail
1612
- missingRequired.push(name)
1613
- } else {
1614
- const splitConfigName = localMapping.path.split('.')
1615
- let settingBlock = config[splitConfigName[0]]
1616
- // pull out the configuration subsection that the option lives in
1617
- for (let i = 1; i < splitConfigName.length - 1; ++i) {
1618
- settingBlock = settingBlock[splitConfigName[i]]
1619
- }
1620
- const valueName = splitConfigName[splitConfigName.length - 1]
1621
- const localVal = settingBlock[valueName]
1622
-
1623
- // Indexes into "allowed values" based on "enabled" setting
1624
- // to retrieve proper mapping.
1625
- const policyValues = localMapping.allowedValues
1626
- const policyValue = policyValues[policy.enabled ? 1 : 0]
1627
-
1628
- // get the most secure setting between local config and the policy
1629
- const finalValue = (settingBlock[valueName] = config._getMostSecure(
1630
- name,
1631
- localVal,
1632
- policyValue
1633
- ))
1634
- policy.enabled = policyValues.indexOf(finalValue) === 1
1635
- obj[name] = policy
1636
-
1637
- if (!policy.enabled && localMapping.applyAdditionalSettings) {
1638
- localMapping.applyAdditionalSettings(config)
1639
- }
1640
-
1641
- if (finalValue !== localVal) {
1642
- // finalValue is more secure than original local val,
1643
- // so drop corresponding data
1644
- localMapping.clearData(agent)
1645
- }
1646
- }
1647
-
1648
- return obj
1649
- }, Object.create(null))
1650
-
1651
- return { missingRequired, finalPolicies }
1652
- }
1653
-
1654
- /**
1655
- * Checks policies received from preconnect against those expected
1656
- * by the agent, if LASP-enabled. Responds with an error to shut down
1657
- * the agent if necessary.
1658
- *
1659
- * @param {Agent} agent Agent instance
1660
- * @param {object} policies lasp policy
1661
- * @returns {CollectorResponse} The result of the processing, with the known
1662
- * policies as the response payload.
1663
- */
1664
- Config.prototype.applyLasp = function applyLasp(agent, policies) {
1665
- const keys = Object.keys(policies)
1666
-
1667
- if (!this.security_policies_token) {
1668
- return _laspResponse(keys)
1669
- }
1670
-
1671
- const { finalPolicies, missingRequired } = this._buildLaspPolicy(agent, policies)
1672
-
1673
- const missingLASP = []
1674
- for (const name of Object.keys(LASP_MAP)) {
1675
- if (!policies[name]) {
1676
- // agent is expecting a policy that was not sent from server -- fail
1677
- missingLASP.push(name)
1678
- }
1679
- }
1680
-
1681
- let fatalMessage = null
1682
- if (missingLASP.length) {
1683
- fatalMessage =
1684
- 'The agent did not receive one or more security policies that it ' +
1685
- 'expected and will shut down: ' +
1686
- missingLASP.join(', ') +
1687
- '.'
1688
- } else if (missingRequired.length) {
1689
- fatalMessage =
1690
- 'The agent received one or more required security policies that it ' +
1691
- 'does not recognize and will shut down: ' +
1692
- missingRequired.join(', ') +
1693
- '. Please check if a newer agent version supports these policies ' +
1694
- 'or contact support.'
1695
- }
1696
-
1697
- if (fatalMessage) {
1698
- logger.error(fatalMessage)
1699
- return CollectorResponse.fatal(null)
1700
- }
1701
-
1702
- return CollectorResponse.success(finalPolicies)
1703
- }
1704
-
1705
1530
  Config.prototype.validateFlags = function validateFlags() {
1706
1531
  for (const key of Object.keys(this.feature_flag)) {
1707
1532
  if (featureFlag.released.indexOf(key) > -1) {
@@ -1727,6 +1552,24 @@ function redactValue(value) {
1727
1552
  return result
1728
1553
  }
1729
1554
 
1555
+ /**
1556
+ * Redact a license key, preserving its original length.
1557
+ * The first 10 characters remain visible; the rest are replaced with '*'.
1558
+ * Keys of 10 or fewer characters are fully redacted.
1559
+ *
1560
+ * @param {string} key the license key to redact
1561
+ * @returns {string} the redacted key
1562
+ */
1563
+ function redactLicenseKey(key) {
1564
+ if (!key) {
1565
+ return ''
1566
+ }
1567
+ if (key.length <= 10) {
1568
+ return '*'.repeat(key.length)
1569
+ }
1570
+ return key.substring(0, 10) + '*'.repeat(key.length - 10)
1571
+ }
1572
+
1730
1573
  /**
1731
1574
  * Get a JSONifiable object containing all settings we want to report to the
1732
1575
  * collector and store in the environment_values table.
@@ -1774,19 +1617,6 @@ Config.prototype.getAggregatorConfig = function getAggregatorConfig(method) {
1774
1617
  }
1775
1618
  }
1776
1619
 
1777
- Config.prototype._warnDeprecations = function _warnDeprecations() {
1778
- // DT overrides CAT so only warn when CAT is actually used.
1779
- if (this.cross_application_tracer.enabled && !this.distributed_tracing.enabled) {
1780
- const deprecationWarning = [
1781
- '[Deprecation Warning]: Cross Application Tracing (CAT) has been deprecated and will be ',
1782
- 'removed in a future major release. CAT has been replaced by Distributed Tracing (DT). ',
1783
- 'Enable DT by setting distributed_tracing: { enabled: true }.'
1784
- ].join('')
1785
-
1786
- logger.infoOnce('Deprecation:CAT', deprecationWarning)
1787
- }
1788
- }
1789
-
1790
1620
  /**
1791
1621
  * Create a configuration, either from a configuration file or the node
1792
1622
  * process's environment.
@@ -35,7 +35,7 @@ class AsyncLocalContextManager {
35
35
 
36
36
  /**
37
37
  * Set a new active context. Not bound to function execution.
38
- * The AsyncLocalStorage method is considered experimental
38
+ * **Note**: Should only be used in tests
39
39
  *
40
40
  * @param {object} newContext The context to set as active.
41
41
  */
@@ -53,14 +53,8 @@ class AsyncLocalContextManager {
53
53
  * @param {Array<*>} [args] Optional arguments object or args array to invoke the callback with.
54
54
  * @returns {*} Returns the value returned by the callback function.
55
55
  */
56
- runInContext(context, callback, cbThis, args) {
57
- const toInvoke = cbThis ? callback.bind(cbThis) : callback
58
-
59
- if (args) {
60
- return this._asyncLocalStorage.run(context, toInvoke, ...args)
61
- }
62
-
63
- return this._asyncLocalStorage.run(context, toInvoke)
56
+ runInContext(context, callback, cbThis, args = []) {
57
+ return this._asyncLocalStorage.run(context, Reflect.apply, callback, cbThis, args)
64
58
  }
65
59
  }
66
60
 
@@ -28,7 +28,7 @@ StatementMatcher.prototype.getParsedStatement = function getParsedStatement(sql)
28
28
  // If the cleaner can match this collection, pull out the cleaned up names
29
29
  // from there. The spec doesn't want the database names in the collection
30
30
  // name, but for legacy reasons we keep it.
31
- // TODO: Either update the spec (and CATs) to accept database name in the
31
+ // TODO: Either update the spec to accept database name in the
32
32
  // collection name or remove it here.
33
33
  const cleanerMatch = CLEANER.exec(collection)
34
34
  if (cleanerMatch && cleanerMatch[4]) {
@@ -293,8 +293,6 @@ function _getErrorEventIntrinsicAttrs(transaction, errorClass, message, expected
293
293
 
294
294
  if (transaction.agent.config.distributed_tracing.enabled) {
295
295
  transaction.addDistributedTraceIntrinsics(attributes)
296
- } else {
297
- attributes['nr.referringTransactionGuid'] = transaction.referringTransactionGuid
298
296
  }
299
297
 
300
298
  attributes['nr.transactionGuid'] = transaction.id