newrelic 9.7.0 → 9.7.2

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 (37) hide show
  1. package/NEWS.md +42 -18
  2. package/THIRD_PARTY_NOTICES.md +203 -2
  3. package/api.js +155 -103
  4. package/lib/agent.js +29 -82
  5. package/lib/collector/api.js +234 -201
  6. package/lib/config/attribute-filter.js +35 -25
  7. package/lib/config/default.js +45 -19
  8. package/lib/config/index.js +260 -199
  9. package/lib/environment.js +16 -12
  10. package/lib/errors/error-collector.js +124 -55
  11. package/lib/errors/index.js +59 -49
  12. package/lib/instrumentation/@hapi/hapi.js +56 -50
  13. package/lib/instrumentation/@node-redis/client.js +50 -41
  14. package/lib/instrumentation/amqplib.js +116 -151
  15. package/lib/instrumentation/core/{async_hooks.js → async-hooks.js} +26 -11
  16. package/lib/instrumentation/core/globals.js +1 -1
  17. package/lib/instrumentation/core/http-outbound.js +193 -78
  18. package/lib/instrumentation/core/timers.js +106 -59
  19. package/lib/instrumentation/grpc-js/grpc.js +20 -23
  20. package/lib/instrumentation/mongodb/common.js +87 -85
  21. package/lib/instrumentation/redis.js +112 -90
  22. package/lib/instrumentation/undici.js +204 -192
  23. package/lib/instrumentation/{when.js → when/constants.js} +13 -10
  24. package/lib/instrumentation/when/contextualizer.js +168 -0
  25. package/lib/instrumentation/when/index.js +354 -0
  26. package/lib/instrumentation/when/nr-hooks.js +15 -0
  27. package/lib/instrumentations.js +1 -1
  28. package/lib/shim/shim.js +2 -0
  29. package/lib/shim/webframework-shim.js +19 -0
  30. package/lib/symbols.js +1 -0
  31. package/lib/system-info.js +240 -163
  32. package/lib/util/async-each-limit.js +30 -0
  33. package/lib/util/attributes.js +159 -0
  34. package/lib/util/code-level-metrics.js +58 -0
  35. package/lib/util/deep-equal.js +11 -144
  36. package/package.json +5 -4
  37. package/lib/instrumentation/promise.js +0 -572
@@ -5,8 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- /* eslint sonarjs/cognitive-complexity: ["error", 16] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
9
-
10
8
  const NO_MATCH = -Infinity
11
9
  const EXACT_MATCH = Infinity
12
10
  const DESTINATIONS = {
@@ -54,7 +52,7 @@ exports.DESTINATIONS = DESTINATIONS
54
52
  *
55
53
  * @class
56
54
  * @private
57
- * @param {Config} config - The configuration object for the agent.
55
+ * @param {object} config - The configuration object for the agent.
58
56
  */
59
57
  function AttributeFilter(config) {
60
58
  this.config = config
@@ -152,6 +150,7 @@ AttributeFilter.prototype._filter = function _filter(scope, destinations, key) {
152
150
 
153
151
  // Check for a cached result for this key.
154
152
  let result = this._cache[destName][key]
153
+
155
154
  if (result === undefined) {
156
155
  if (globalInclude === null) {
157
156
  globalInclude = _matchRules(this._rules.global.include, key)
@@ -166,13 +165,7 @@ AttributeFilter.prototype._filter = function _filter(scope, destinations, key) {
166
165
  }
167
166
  }
168
167
 
169
- if (result === NO_MATCH) {
170
- // No match, no-op.
171
- } else if (result) {
172
- destinations |= destId // Positive match, add it in.
173
- } else {
174
- destinations &= ~destId // Negative match, remove it.
175
- }
168
+ destinations = _updateDestinations(destinations, destId, result)
176
169
  }
177
170
 
178
171
  return destinations
@@ -209,12 +202,12 @@ AttributeFilter.prototype.update = function update() {
209
202
  /**
210
203
  * Applies the global and destination rules to this key.
211
204
  *
212
- * @param globalInclude
213
- * @param globalExclude
214
- * @param destConfig
215
- * @param key
216
205
  * @private
217
- * @returns {bool|number} True if this key is explicitly included, false if it is
206
+ * @param {number} globalInclude Global inclusion match
207
+ * @param {number} globalExclude Global exclusion match
208
+ * @param {object} destConfig Destination specific include/exclude rules
209
+ * @param {string} key The attribute name
210
+ * @returns {boolean|number} True if this key is explicitly included, false if it is
218
211
  * explicitly excluded, or `NO_MATCH` if no rule applies.
219
212
  */
220
213
  function _doTest(globalInclude, globalExclude, destConfig, key) {
@@ -259,16 +252,14 @@ function _doTest(globalInclude, globalExclude, destConfig, key) {
259
252
  /**
260
253
  * Tests the given key against the given rule set.
261
254
  *
262
- * @private
263
- *
264
255
  * This method assumes that the rule set is sorted from best possible match to
265
256
  * least possible match. Unsorted lists may result in a lesser score being given
266
257
  * to the value.
267
258
  *
268
- * @param {array.<string>} rules - The set of rules to match against.
259
+ * @private
260
+ * @param {Array.<string>} rules - The set of rules to match against.
269
261
  * @param {string} key - The name of the attribute to look for.
270
- *
271
- * @return {number} The strength of the match, from `0` for no-match to `Infinity`
262
+ * @returns {number} The strength of the match, from `0` for no-match to `Infinity`
272
263
  * for exact matches.
273
264
  */
274
265
  function _matchRules(rules, key) {
@@ -322,13 +313,11 @@ function _importRules(rules) {
322
313
  /**
323
314
  * Converts an array of attribute rules into a regular expression string.
324
315
  *
325
- * @private
326
- *
327
316
  * `["foo.bar", "foo.bang"]` becomes "(?:foo\.(?:bar|bang))"
328
317
  *
329
- * @param {array.<string>} rules - The set of rules compose into a regex.
330
- *
331
- * @return {string} The rules composed into a single regular expression string.
318
+ * @private
319
+ * @param {Array.<string>} rules - The set of rules compose into a regex.
320
+ * @returns {string} The rules composed into a single regular expression string.
332
321
  */
333
322
  function _convertRulesToRegex(rules) {
334
323
  return (
@@ -416,3 +405,24 @@ function _convertRulesToRegex(rules) {
416
405
  ')'
417
406
  ) // Step 5) Merge all the regex strings into one.
418
407
  }
408
+
409
+ /**
410
+ * Helper method for updating our list of destinations
411
+ *
412
+ * @private
413
+ * @param {object} destinations list of destination ids
414
+ * @param {string} id destination id
415
+ * @param {boolean} result whether or not we found a match
416
+ * @returns {object} potentially modified list of destinations
417
+ */
418
+ function _updateDestinations(destinations, id, result) {
419
+ if (result === NO_MATCH) {
420
+ // No match, no-op.
421
+ } else if (result) {
422
+ destinations |= id // Positive match, add it in.
423
+ } else {
424
+ destinations &= ~id // Negative match, remove it.
425
+ }
426
+
427
+ return destinations
428
+ }
@@ -5,8 +5,6 @@
5
5
 
6
6
  'use strict'
7
7
 
8
- /* eslint sonarjs/cognitive-complexity: ["error", 17] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252*/
9
-
10
8
  const defaultConfig = module.exports
11
9
  const { array, int, float, boolean, object, objectList, allowList } = require('./formatters')
12
10
 
@@ -20,6 +18,8 @@ const { array, int, float, boolean, object, objectList, allowList } = require('.
20
18
  * an override if the env var does not follow our standard convention. We should not have
21
19
  * to add any more overrides as all new configuration values should follow the convention of
22
20
  * `NEW_RELIC_PATH_TO_CONFIG_KEY`
21
+ *
22
+ * @returns {object} configuration definition
23
23
  */
24
24
  defaultConfig.definition = () => ({
25
25
  newrelic_home: {
@@ -438,7 +438,7 @@ defaultConfig.definition = () => ({
438
438
  * This flag dictates whether the agent attempts to read files
439
439
  * to get info about the container the process is running in.
440
440
  *
441
- * @env NEW_RELIC_UTILIZATION_DETECT_DOCKER
441
+ * env NEW_RELIC_UTILIZATION_DETECT_DOCKER
442
442
  */
443
443
  detect_docker: {
444
444
  formatter: boolean,
@@ -547,7 +547,7 @@ defaultConfig.definition = () => ({
547
547
  * slow trace aggregator if no slow transactions have been recorded for the
548
548
  * last 5 harvest cycles, restarting the aggregation process.
549
549
  *
550
- * @env NEW_RELIC_TRACER_TOP_N
550
+ * env NEW_RELIC_TRACER_TOP_N
551
551
  */
552
552
  top_n: {
553
553
  formatter: int,
@@ -604,7 +604,7 @@ defaultConfig.definition = () => ({
604
604
  *
605
605
  * By default, socket.io long-polling is ignored.
606
606
  *
607
- * @env NEW_RELIC_IGNORING_RULES
607
+ * env NEW_RELIC_IGNORING_RULES
608
608
  */
609
609
  ignore: {
610
610
  formatter: array,
@@ -762,7 +762,7 @@ defaultConfig.definition = () => ({
762
762
  * Prefix of attributes to exclude in transaction events.
763
763
  * Allows * as wildcard at end.
764
764
  *
765
- * @env NEW_RELIC_TRANSACTION_EVENTS_ATTRIBUTES_EXCLUDE
765
+ * env NEW_RELIC_TRANSACTION_EVENTS_ATTRIBUTES_EXCLUDE
766
766
  */
767
767
  exclude: {
768
768
  formatter: array,
@@ -772,7 +772,7 @@ defaultConfig.definition = () => ({
772
772
  * Prefix of attributes to include in transaction events.
773
773
  * Allows * as wildcard at end.
774
774
  *
775
- * @env NEW_RELIC_TRANSACTION_EVENTS_ATTRIBUTES_INCLUDE
775
+ * env NEW_RELIC_TRANSACTION_EVENTS_ATTRIBUTES_INCLUDE
776
776
  */
777
777
  include: {
778
778
  formatter: array,
@@ -895,7 +895,7 @@ defaultConfig.definition = () => ({
895
895
  * Sets the maximum number of slow query samples that will be collected in a
896
896
  * single harvest cycle.
897
897
  *
898
- * @env NEW_RELIC_MAX_SQL_SAMPLES
898
+ * env NEW_RELIC_MAX_SQL_SAMPLES
899
899
  */
900
900
  max_samples: {
901
901
  formatter: int,
@@ -906,9 +906,11 @@ defaultConfig.definition = () => ({
906
906
  /**
907
907
  * Controls behavior of datastore instance metrics.
908
908
  *
909
+ * @property {object} instance_reporting container around enabling flag
909
910
  * @property {boolean} [instance_reporting.enabled=true]
910
911
  * Enables reporting the host and port/path/id of database servers. Default
911
912
  * is `true`.
913
+ * @property {object} database_name_reporting container around enabling flag
912
914
  * @property {boolean} [database_name_reporting.enabled=true]
913
915
  * Enables reporting of database/schema names. Default is `true`.
914
916
  */
@@ -1076,6 +1078,7 @@ defaultConfig.definition = () => ({
1076
1078
  /**
1077
1079
  * Controls behavior of message broker tracing.
1078
1080
  *
1081
+ * @property {object} segment_parameters property around enabling flag
1079
1082
  * @property {boolean} [segment_parameters.enabled=true]
1080
1083
  * Enables reporting parameters on message broker segments.
1081
1084
  */
@@ -1189,17 +1192,29 @@ defaultConfig.definition = () => ({
1189
1192
  * disallow the use of New Relic's server-side configuration for agents.
1190
1193
  * To do so, set this to true.
1191
1194
  *
1192
- * @env NEW_RELIC_IGNORE_SERVER_SIDE_CONFIG
1195
+ * env NEW_RELIC_IGNORE_SERVER_SIDE_CONFIG
1193
1196
  */
1194
1197
  ignore_server_configuration: {
1195
1198
  formatter: boolean,
1196
1199
  default: false,
1197
1200
  env: 'NEW_RELIC_IGNORE_SERVER_SIDE_CONFIG'
1201
+ },
1202
+
1203
+ /**
1204
+ * Toggles whether to capture code.* attributes on spans
1205
+ */
1206
+ code_level_metrics: {
1207
+ enabled: {
1208
+ formatter: boolean,
1209
+ default: false
1210
+ }
1198
1211
  }
1199
1212
  })
1200
1213
 
1201
1214
  /**
1202
1215
  * Creates a new default config
1216
+ *
1217
+ * @returns {object} default configuration object
1203
1218
  */
1204
1219
  defaultConfig.config = () => {
1205
1220
  const config = Object.create(null)
@@ -1223,19 +1238,12 @@ function buildConfig(definition, config, paths = [], objectKeys = 1) {
1223
1238
  const type = typeof value
1224
1239
  keysSeen++
1225
1240
  if (type === 'string') {
1226
- if (paths.length) {
1227
- setNestedKey(conf, [...paths, key], value)
1228
- } else {
1229
- conf[key] = value
1230
- }
1241
+ assignConfigValue({ config: conf, key, value, paths })
1231
1242
  } else if (type === 'object') {
1232
1243
  if (value.hasOwnProperty('default')) {
1233
- if (paths.length) {
1234
- setNestedKey(conf, [...paths, key], value.default)
1235
- } else {
1236
- conf[key] = value.default
1237
- }
1244
+ assignConfigValue({ config: conf, key, value: value.default, paths })
1238
1245
  } else {
1246
+ // add the current leaf node key to the paths and recurse through function again
1239
1247
  const { length } = Object.keys(value)
1240
1248
  paths.push(key)
1241
1249
  buildConfig(definition[key], conf, paths, length)
@@ -1252,6 +1260,24 @@ function buildConfig(definition, config, paths = [], objectKeys = 1) {
1252
1260
  }
1253
1261
  }
1254
1262
 
1263
+ /**
1264
+ * Assigns a value to a configuration option. In the case of a nested key
1265
+ * it will properly build the structure leading to the value
1266
+ *
1267
+ * @param {object} params args to fn
1268
+ * @param {object} params.config object that is used to construct the agent config
1269
+ * @param {string} params.key name of the configuration option
1270
+ * @param {string} params.value value the configuration option
1271
+ * @param {Array} [params.paths=[]] an array to capture the leaf node keys to properly assign defaults for nested objects
1272
+ */
1273
+ function assignConfigValue({ config, key, value, paths }) {
1274
+ if (paths.length) {
1275
+ setNestedKey(config, [...paths, key], value)
1276
+ } else {
1277
+ config[key] = value
1278
+ }
1279
+ }
1280
+
1255
1281
  /**
1256
1282
  * Properly sets the value of a nested key by creating the shells of empty parents
1257
1283
  *