newrelic 9.5.0 → 9.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 +14 -0
- package/api.js +2 -0
- package/bin/test-naming-rules.js +1 -1
- package/esm-loader.mjs +1 -3
- package/index.js +6 -5
- package/lib/adaptive-sampler.js +1 -2
- package/lib/agent.js +2 -0
- package/lib/aggregators/event-aggregator.js +2 -2
- package/lib/attributes.js +2 -4
- package/lib/collector/api.js +20 -12
- package/lib/collector/facts.js +1 -3
- package/lib/collector/parse-response.js +3 -1
- package/lib/collector/remote-method.js +10 -10
- package/lib/config/attribute-filter.js +14 -16
- package/lib/config/default.js +544 -286
- package/lib/config/formatters.js +108 -0
- package/lib/config/harvest-config-validator.js +3 -5
- package/lib/config/index.js +74 -93
- package/lib/environment.js +6 -5
- package/lib/errors/error-collector.js +6 -3
- package/lib/errors/helper.js +10 -18
- package/lib/errors/index.js +12 -6
- package/lib/grpc/connection.js +12 -5
- package/lib/header-attributes.js +4 -2
- package/lib/header-processing.js +2 -2
- package/lib/instrumentation/@hapi/hapi.js +231 -1
- package/lib/instrumentation/{vision.js → @hapi/vision.js} +0 -0
- package/lib/instrumentation/@node-redis/client.js +2 -0
- package/lib/instrumentation/amqplib.js +2 -0
- package/lib/instrumentation/core/async_hooks.js +3 -4
- package/lib/instrumentation/core/globals.js +12 -10
- package/lib/instrumentation/core/http-outbound.js +17 -17
- package/lib/instrumentation/core/http.js +16 -27
- package/lib/instrumentation/core/timers.js +5 -1
- package/lib/instrumentation/fastify.js +1 -3
- package/lib/instrumentation/grpc-js/grpc.js +14 -3
- package/lib/instrumentation/memcached.js +5 -0
- package/lib/instrumentation/mongodb/common.js +3 -0
- package/lib/instrumentation/mongodb/v2-mongo.js +6 -3
- package/lib/instrumentation/mongodb.js +1 -1
- package/lib/instrumentation/mysql/mysql.js +6 -5
- package/lib/instrumentation/nr-winston-transport.js +3 -4
- package/lib/instrumentation/promise.js +22 -18
- package/lib/instrumentation/redis.js +2 -0
- package/lib/instrumentation/undici.js +12 -15
- package/lib/instrumentations.js +1 -1
- package/lib/metrics/mapper.js +2 -3
- package/lib/metrics/metric-aggregator.js +1 -3
- package/lib/metrics/names.js +19 -15
- package/lib/metrics/normalizer/rule.js +6 -7
- package/lib/metrics/normalizer/tx_segment.js +3 -2
- package/lib/metrics/normalizer.js +5 -3
- package/lib/parse-proc-cpuinfo.js +11 -6
- package/lib/serverless/api-gateway.js +3 -4
- package/lib/serverless/aws-lambda.js +3 -3
- package/lib/shim/conglomerate-shim.js +2 -3
- package/lib/shim/constants.js +1 -16
- package/lib/shim/datastore-shim.js +24 -105
- package/lib/shim/index.js +7 -0
- package/lib/shim/message-shim.js +2 -0
- package/lib/shim/promise-shim.js +66 -59
- package/lib/shim/shim.js +44 -89
- package/lib/shim/transaction-shim.js +1 -1
- package/lib/shim/webframework-shim.js +4 -8
- package/lib/shimmer.js +29 -23
- package/lib/spans/map-to-streaming-type.js +0 -2
- package/lib/spans/span-context.js +2 -0
- package/lib/spans/span-event-aggregator.js +2 -2
- package/lib/spans/span-event.js +2 -2
- package/lib/spans/span-streamer.js +4 -0
- package/lib/spans/streaming-span-event-aggregator.js +2 -4
- package/lib/spans/streaming-span-event.js +3 -2
- package/lib/symbols.js +26 -0
- package/lib/system-info.js +4 -7
- package/lib/timer.js +8 -6
- package/lib/transaction/dt-payload.js +4 -3
- package/lib/transaction/handle.js +12 -2
- package/lib/transaction/index.js +19 -18
- package/lib/transaction/name-state.js +17 -2
- package/lib/transaction/trace/aggregator.js +4 -12
- package/lib/transaction/trace/index.js +7 -5
- package/lib/transaction/trace/segment.js +6 -11
- package/lib/transaction/tracecontext.js +10 -6
- package/lib/transaction/tracer/index.js +35 -43
- package/lib/transaction/transaction-event-aggregator.js +1 -3
- package/lib/util/arity.js +4 -9
- package/lib/util/attribute-types.js +1 -2
- package/lib/util/byte-limit.js +1 -3
- package/lib/util/cat.js +16 -13
- package/lib/util/codec.js +0 -2
- package/lib/util/copy.js +1 -2
- package/lib/util/deep-equal.js +7 -0
- package/lib/util/flatten.js +4 -6
- package/lib/util/hashes.js +1 -3
- package/lib/util/process-version.js +2 -3
- package/lib/util/properties.js +2 -51
- package/lib/util/stream-sink.js +2 -0
- package/lib/util/urltils.js +4 -10
- package/newrelic.js +1 -1
- package/package.json +2 -1
- package/lib/config/env.js +0 -294
- package/lib/instrumentation/hapi/hapi.js +0 -207
- package/lib/instrumentation/hapi/shared.js +0 -28
- package/lib/instrumentation/hapi.js +0 -254
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2022 New Relic Corporation. All rights reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict'
|
|
7
|
+
const formatters = module.exports
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Splits a string by a ',' and trims whitespace
|
|
11
|
+
*
|
|
12
|
+
* @param {string} val config setting
|
|
13
|
+
* @param {Array}
|
|
14
|
+
*/
|
|
15
|
+
formatters.array = function array(val) {
|
|
16
|
+
return val.split(',').map((k) => k.trim())
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parses a config setting as an int
|
|
21
|
+
*
|
|
22
|
+
* @param {string} val config setting
|
|
23
|
+
* @returns {int}
|
|
24
|
+
*/
|
|
25
|
+
formatters.int = function int(val) {
|
|
26
|
+
return parseInt(val, 10)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Parses a config setting as a float
|
|
31
|
+
*
|
|
32
|
+
* @param {string} val config setting
|
|
33
|
+
* @returns {float}
|
|
34
|
+
*/
|
|
35
|
+
formatters.float = function float(val) {
|
|
36
|
+
return parseFloat(val, 10)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parses a config setting as a boolean
|
|
41
|
+
*
|
|
42
|
+
* @param {string} val config setting
|
|
43
|
+
* @param setting
|
|
44
|
+
* @returns {boolean}
|
|
45
|
+
*/
|
|
46
|
+
formatters.boolean = function boolean(setting) {
|
|
47
|
+
if (setting == null) {
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const normalized = setting.toString().toLowerCase()
|
|
52
|
+
switch (normalized) {
|
|
53
|
+
case 'false':
|
|
54
|
+
case 'f':
|
|
55
|
+
case 'no':
|
|
56
|
+
case 'n':
|
|
57
|
+
case 'disabled':
|
|
58
|
+
case '0':
|
|
59
|
+
return false
|
|
60
|
+
|
|
61
|
+
default:
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Parses a config setting as an object
|
|
68
|
+
*
|
|
69
|
+
* @param {string} val config setting
|
|
70
|
+
* @param {logger} logger agent logger instance
|
|
71
|
+
* @returns {object}
|
|
72
|
+
*/
|
|
73
|
+
formatters.object = function object(val, logger) {
|
|
74
|
+
try {
|
|
75
|
+
return JSON.parse(val)
|
|
76
|
+
} catch (error) {
|
|
77
|
+
logger.error('New Relic configurator could not deserialize object:')
|
|
78
|
+
logger.error(error.stack)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Parse a config setting as a collection with 1 object
|
|
84
|
+
*
|
|
85
|
+
* @param {string} val config setting
|
|
86
|
+
* @param {logger} logger agent logger instance
|
|
87
|
+
* @returns {Array}
|
|
88
|
+
*/
|
|
89
|
+
formatters.objectList = function objectList(val, logger) {
|
|
90
|
+
try {
|
|
91
|
+
return JSON.parse('[' + val + ']')
|
|
92
|
+
} catch (error) {
|
|
93
|
+
logger.error('New Relic configurator could not deserialize object list:')
|
|
94
|
+
logger.error(error.stack)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Checks if a value is within an allow list. If not it assigns
|
|
100
|
+
* the first element in allow list as default
|
|
101
|
+
*
|
|
102
|
+
* @param {Array} list allowable values
|
|
103
|
+
* @param {string} val config setting
|
|
104
|
+
* @returns {string}
|
|
105
|
+
*/
|
|
106
|
+
formatters.allowList = function allowList(list, val) {
|
|
107
|
+
return list.includes(val) ? val : list[0]
|
|
108
|
+
}
|
|
@@ -12,17 +12,15 @@ function isValidHarvestConfig(harvestConfig) {
|
|
|
12
12
|
|
|
13
13
|
const harvestLimits = harvestConfig.harvest_limits
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
return (
|
|
16
16
|
isValidHarvestValue(harvestConfig.report_period_ms) &&
|
|
17
17
|
harvestLimits != null &&
|
|
18
18
|
Object.keys(harvestLimits).length > 0
|
|
19
|
-
|
|
20
|
-
return isValid
|
|
19
|
+
)
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
function isValidHarvestValue(value) {
|
|
24
|
-
|
|
25
|
-
return !!isValid
|
|
23
|
+
return !!(value != null && value >= 0)
|
|
26
24
|
}
|
|
27
25
|
|
|
28
26
|
module.exports = {
|
package/lib/config/index.js
CHANGED
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
+
/* eslint sonarjs/cognitive-complexity: ["error", 29] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
|
+
/* eslint sonarjs/max-switch-cases: ["error", 36] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
10
|
+
|
|
8
11
|
const AttributeFilter = require('./attribute-filter')
|
|
9
12
|
const CollectorResponse = require('../collector/response')
|
|
10
13
|
const copy = require('../util/copy')
|
|
11
|
-
const defaultConfig = require('./default')
|
|
14
|
+
const { config: defaultConfig, definition, setNestedKey } = require('./default')
|
|
12
15
|
const EventEmitter = require('events').EventEmitter
|
|
13
16
|
const featureFlag = require('../feature_flags')
|
|
14
17
|
const flatten = require('../util/flatten')
|
|
@@ -22,6 +25,8 @@ const util = require('util')
|
|
|
22
25
|
const MergeServerConfig = require('./merge-server-config')
|
|
23
26
|
const harvestConfigValidator = require('./harvest-config-validator')
|
|
24
27
|
const mergeServerConfig = new MergeServerConfig()
|
|
28
|
+
const { boolean: isTruthular } = require('./formatters')
|
|
29
|
+
const configDefinition = definition()
|
|
25
30
|
|
|
26
31
|
/**
|
|
27
32
|
* CONSTANTS -- we gotta lotta 'em
|
|
@@ -33,11 +38,11 @@ const BASE_CONFIG_PATH = require.resolve('../../newrelic')
|
|
|
33
38
|
const HAS_ARBITRARY_KEYS = new Set(['ignore_messages', 'expected_messages', 'labels'])
|
|
34
39
|
|
|
35
40
|
const LASP_MAP = require('./lasp').LASP_MAP
|
|
36
|
-
const ENV = require('./env')
|
|
37
41
|
const HSM = require('./hsm')
|
|
38
42
|
const REMOVE_BEFORE_SEND = new Set(['attributeFilter'])
|
|
43
|
+
const SSL_WARNING = 'SSL config key can no longer be disabled, not updating.'
|
|
39
44
|
|
|
40
|
-
const exists = fs.existsSync
|
|
45
|
+
const exists = fs.existsSync
|
|
41
46
|
let logger = null // Lazy-loaded in `initialize`.
|
|
42
47
|
let _configInstance = null
|
|
43
48
|
|
|
@@ -56,35 +61,6 @@ const getConfigFileLocations = () =>
|
|
|
56
61
|
: undefined
|
|
57
62
|
].filter(Boolean)
|
|
58
63
|
|
|
59
|
-
function isTruthular(setting) {
|
|
60
|
-
if (setting == null) {
|
|
61
|
-
return false
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const normalized = setting.toString().toLowerCase()
|
|
65
|
-
switch (normalized) {
|
|
66
|
-
case 'false':
|
|
67
|
-
case 'f':
|
|
68
|
-
case 'no':
|
|
69
|
-
case 'n':
|
|
70
|
-
case 'disabled':
|
|
71
|
-
case '0':
|
|
72
|
-
return false
|
|
73
|
-
|
|
74
|
-
default:
|
|
75
|
-
return true
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function fromObjectList(setting) {
|
|
80
|
-
try {
|
|
81
|
-
return JSON.parse('[' + setting + ']')
|
|
82
|
-
} catch (error) {
|
|
83
|
-
logger.error('New Relic configurator could not deserialize object list:')
|
|
84
|
-
logger.error(error.stack)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
64
|
function _findConfigFile() {
|
|
89
65
|
const configFileCandidates = getConfigFileLocations().reduce((files, configPath) => {
|
|
90
66
|
const configFiles = getConfigFileNames().map((filename) =>
|
|
@@ -145,11 +121,6 @@ function Config(config) {
|
|
|
145
121
|
this.collect_errors = true
|
|
146
122
|
this.collect_span_events = true
|
|
147
123
|
|
|
148
|
-
// override options for utilization stats
|
|
149
|
-
this.utilization.logical_processors = null
|
|
150
|
-
this.utilization.total_ram_mib = null
|
|
151
|
-
this.utilization.billing_hostname = null
|
|
152
|
-
|
|
153
124
|
this.browser_monitoring.loader = 'rum'
|
|
154
125
|
this.browser_monitoring.loader_version = ''
|
|
155
126
|
|
|
@@ -338,7 +309,7 @@ Config.prototype._fromServer = function _fromServer(params, key) {
|
|
|
338
309
|
|
|
339
310
|
case 'ssl':
|
|
340
311
|
if (!isTruthular(params.ssl)) {
|
|
341
|
-
logger.warn(
|
|
312
|
+
logger.warn(SSL_WARNING)
|
|
342
313
|
}
|
|
343
314
|
break
|
|
344
315
|
|
|
@@ -996,7 +967,7 @@ Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrar
|
|
|
996
967
|
}
|
|
997
968
|
|
|
998
969
|
if (key === 'ssl' && !isTruthular(external.ssl)) {
|
|
999
|
-
logger.warn(
|
|
970
|
+
logger.warn(SSL_WARNING)
|
|
1000
971
|
return
|
|
1001
972
|
}
|
|
1002
973
|
|
|
@@ -1057,66 +1028,76 @@ Config.prototype._featureFlagsFromEnv = function _featureFlagsFromEnv() {
|
|
|
1057
1028
|
}
|
|
1058
1029
|
|
|
1059
1030
|
/**
|
|
1060
|
-
*
|
|
1061
|
-
* environment variable names, overriding any configuration values that are
|
|
1062
|
-
* found in the environment. Operates purely via side effects.
|
|
1031
|
+
* Creates an env var mapper from the configuration path value
|
|
1063
1032
|
*
|
|
1064
|
-
* @param
|
|
1065
|
-
*
|
|
1066
|
-
* @
|
|
1067
|
-
* never need to set this yourself.
|
|
1068
|
-
* @param metadata
|
|
1069
|
-
* @param data
|
|
1033
|
+
* @param {string} key of configuration value
|
|
1034
|
+
* @param {Array} paths list of leaf nodes leading to configuration value
|
|
1035
|
+
* @returns {string} formatted env var name
|
|
1070
1036
|
*/
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}
|
|
1075
|
-
|
|
1076
|
-
data = this
|
|
1077
|
-
}
|
|
1037
|
+
function deriveEnvVar(key, paths) {
|
|
1038
|
+
let path = paths.join('_')
|
|
1039
|
+
path = path ? `${path}_` : path
|
|
1040
|
+
return `NEW_RELIC_${path.toUpperCase()}${key.toUpperCase()}`
|
|
1041
|
+
}
|
|
1078
1042
|
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1043
|
+
/**
|
|
1044
|
+
* Assigns the value of an env var to its corresponding configuration path
|
|
1045
|
+
*
|
|
1046
|
+
* @param {object} params
|
|
1047
|
+
* @param {object} params.config agent config
|
|
1048
|
+
* @param {string} params.key key to assign value
|
|
1049
|
+
* @param {string} params.envVar name of env var
|
|
1050
|
+
* @param {Function} params.formatter function to coerce env var as they are all strings
|
|
1051
|
+
* @param {Array} params.paths list of leaf nodes leading to the configuration value
|
|
1052
|
+
*/
|
|
1053
|
+
function setFromEnv({ config, key, envVar, formatter, paths }) {
|
|
1054
|
+
const setting = process.env[envVar]
|
|
1055
|
+
if (setting) {
|
|
1056
|
+
const formattedSetting = formatter ? formatter(setting, logger) : setting
|
|
1057
|
+
setNestedKey(config, [...paths, key], formattedSetting)
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1084
1060
|
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1061
|
+
/**
|
|
1062
|
+
* Recursively visit the nodes of the config definition and look for environment variable names, overriding any configuration values that are found.
|
|
1063
|
+
*
|
|
1064
|
+
* @param {object} [config=this] The current level of the configuration object.
|
|
1065
|
+
* @param {object} [data=configDefinition] The current level of the config definition object.
|
|
1066
|
+
* @param {Array} [paths=[]] keeps track of the nested path to properly derive the env var
|
|
1067
|
+
* @param {int} [objectKeys=1] indicator of how many keys exist in current node to know when to remove current node after all keys are processed
|
|
1068
|
+
*/
|
|
1069
|
+
Config.prototype._fromEnvironment = function _fromEnvironment(
|
|
1070
|
+
config = this,
|
|
1071
|
+
data = configDefinition,
|
|
1072
|
+
paths = [],
|
|
1073
|
+
objectKeys = 1
|
|
1074
|
+
) {
|
|
1075
|
+
let keysSeen = 0
|
|
1076
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
1077
|
+
const type = typeof value
|
|
1078
|
+
keysSeen++
|
|
1079
|
+
if (type === 'string') {
|
|
1080
|
+
const envVar = deriveEnvVar(key, paths)
|
|
1081
|
+
setFromEnv({ config, key, envVar, paths })
|
|
1082
|
+
} else if (type === 'object') {
|
|
1083
|
+
if (value.hasOwnProperty('env')) {
|
|
1084
|
+
setFromEnv({ config, key, envVar: value.env, paths, formatter: value.formatter })
|
|
1085
|
+
} else if (value.hasOwnProperty('default')) {
|
|
1086
|
+
const envVar = deriveEnvVar(key, paths)
|
|
1087
|
+
setFromEnv({ config, key, envVar, formatter: value.formatter, paths })
|
|
1088
|
+
} else {
|
|
1089
|
+
paths.push(key)
|
|
1090
|
+
const { length } = Object.keys(value)
|
|
1091
|
+
this._fromEnvironment(config, value, paths, length)
|
|
1116
1092
|
}
|
|
1117
|
-
this._fromEnvironment(node, data[value])
|
|
1118
1093
|
}
|
|
1119
|
-
}
|
|
1094
|
+
})
|
|
1095
|
+
|
|
1096
|
+
// we have traversed every key in current object leaf node, remove wrapping key
|
|
1097
|
+
// to properly derive env vars of future leaf nodes
|
|
1098
|
+
if (keysSeen === objectKeys) {
|
|
1099
|
+
paths.pop()
|
|
1100
|
+
}
|
|
1120
1101
|
}
|
|
1121
1102
|
|
|
1122
1103
|
/**
|
package/lib/environment.js
CHANGED
|
@@ -10,6 +10,7 @@ const { fsPromises } = require('./util/unwrapped-core')
|
|
|
10
10
|
const os = require('os')
|
|
11
11
|
const logger = require('./logger').child({ component: 'environment' })
|
|
12
12
|
const stringify = require('json-stringify-safe')
|
|
13
|
+
const DISPATCHER_VERSION = 'Dispatcher Version'
|
|
13
14
|
|
|
14
15
|
// As of 1.7.0 you can no longer dynamically link v8
|
|
15
16
|
// https://github.com/nodejs/io.js/commit/d726a177ed
|
|
@@ -418,7 +419,7 @@ function refreshSyncOnly() {
|
|
|
418
419
|
// gather persisted settings
|
|
419
420
|
const framework = getSetting('Framework')
|
|
420
421
|
const dispatcher = getSetting('Dispatcher')
|
|
421
|
-
const dispatcherVersion = getSetting(
|
|
422
|
+
const dispatcherVersion = getSetting(DISPATCHER_VERSION)
|
|
422
423
|
|
|
423
424
|
// clearing and rebuilding a global variable
|
|
424
425
|
settings = Object.create(null)
|
|
@@ -437,7 +438,7 @@ function refreshSyncOnly() {
|
|
|
437
438
|
|
|
438
439
|
if (dispatcherVersion.length) {
|
|
439
440
|
dispatcher.forEach(function addDispatchers(d) {
|
|
440
|
-
addSetting(
|
|
441
|
+
addSetting(DISPATCHER_VERSION, d)
|
|
441
442
|
})
|
|
442
443
|
}
|
|
443
444
|
|
|
@@ -503,12 +504,12 @@ module.exports = {
|
|
|
503
504
|
}
|
|
504
505
|
|
|
505
506
|
userSetDispatcher = !!userSet
|
|
506
|
-
clearSetting(
|
|
507
|
+
clearSetting(DISPATCHER_VERSION)
|
|
507
508
|
clearSetting('Dispatcher')
|
|
508
509
|
|
|
509
510
|
// TODO: Decide if this should only happen once for internals as well.
|
|
510
511
|
if (version) {
|
|
511
|
-
addSetting(
|
|
512
|
+
addSetting(DISPATCHER_VERSION, version)
|
|
512
513
|
}
|
|
513
514
|
|
|
514
515
|
addSetting('Dispatcher', dispatcher)
|
|
@@ -520,7 +521,7 @@ module.exports = {
|
|
|
520
521
|
// This method is only used for tests.
|
|
521
522
|
userSetDispatcher = false
|
|
522
523
|
clearSetting('Dispatcher')
|
|
523
|
-
clearSetting(
|
|
524
|
+
clearSetting(DISPATCHER_VERSION)
|
|
524
525
|
},
|
|
525
526
|
listPackages,
|
|
526
527
|
getJSON,
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
+
/* eslint sonarjs/cognitive-complexity: ["error", 25] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
|
+
|
|
8
10
|
const errorsModule = require('./index')
|
|
9
11
|
|
|
10
12
|
const logger = require('../logger').child({ component: 'error_tracer' })
|
|
@@ -112,8 +114,7 @@ class ErrorCollector {
|
|
|
112
114
|
* possible.
|
|
113
115
|
*
|
|
114
116
|
* @param {Transaction} transaction
|
|
115
|
-
*
|
|
116
|
-
* @return {number} The number of unexpected errors
|
|
117
|
+
* @returns {number} The number of unexpected errors
|
|
117
118
|
*/
|
|
118
119
|
onTransactionFinished(transaction) {
|
|
119
120
|
if (!transaction) {
|
|
@@ -226,6 +227,8 @@ class ErrorCollector {
|
|
|
226
227
|
*
|
|
227
228
|
* @param {?Transaction} transaction Transaction associated with the error.
|
|
228
229
|
* @param {Exception} exception The Exception to be traced.
|
|
230
|
+
* @param error
|
|
231
|
+
* @param customAttributes
|
|
229
232
|
*/
|
|
230
233
|
addUserError(transaction, error, customAttributes) {
|
|
231
234
|
if (!error) {
|
|
@@ -260,7 +263,7 @@ class ErrorCollector {
|
|
|
260
263
|
*
|
|
261
264
|
* @param {?Transaction} transaction Transaction associated with the error.
|
|
262
265
|
* @param {?Exception} exception The Exception object to be traced.
|
|
263
|
-
* @
|
|
266
|
+
* @returns {bool} True if the error was collected.
|
|
264
267
|
*/
|
|
265
268
|
collect(transaction, exception) {
|
|
266
269
|
if (!exception) {
|
package/lib/errors/helper.js
CHANGED
|
@@ -21,20 +21,17 @@ module.exports = {
|
|
|
21
21
|
if (!config.error_collector.expected_messages[type]) {
|
|
22
22
|
return false
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return false
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
config.error_collector.expected_messages[type].length > 0 &&
|
|
27
|
+
config.error_collector.expected_messages[type].indexOf(message) !== -1
|
|
28
|
+
)
|
|
30
29
|
},
|
|
31
30
|
isExpectedErrorClass: function isExpectedErrorClass(config, className) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
return false
|
|
31
|
+
return (
|
|
32
|
+
config.error_collector.expected_classes.length > 0 &&
|
|
33
|
+
config.error_collector.expected_classes.indexOf(className) !== -1
|
|
34
|
+
)
|
|
38
35
|
},
|
|
39
36
|
isExpectedException: function isExpectedException(transaction, exception, config, urltils) {
|
|
40
37
|
const { type, message } = this.extractErrorInformation(transaction, exception, config, urltils)
|
|
@@ -123,11 +120,6 @@ module.exports = {
|
|
|
123
120
|
return false
|
|
124
121
|
}
|
|
125
122
|
|
|
126
|
-
|
|
127
|
-
if (-1 !== configIgnoreMessages.indexOf(errorInfo.message)) {
|
|
128
|
-
return true
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return false
|
|
123
|
+
return configIgnoreMessages.length > 0 && configIgnoreMessages.indexOf(errorInfo.message) !== -1
|
|
132
124
|
}
|
|
133
125
|
}
|
package/lib/errors/index.js
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
8
|
+
/* eslint sonarjs/cognitive-complexity: ["error", 22] -- TODO: https://issues.newrelic.com/browse/NEWRELIC-5252 */
|
|
9
|
+
|
|
8
10
|
const DESTINATIONS = require('../config/attribute-filter').DESTINATIONS
|
|
9
11
|
const NAMES = require('../metrics/names')
|
|
10
12
|
const props = require('../util/properties')
|
|
11
13
|
const urltils = require('../util/urltils')
|
|
12
14
|
const errorHelper = require('../errors/helper')
|
|
15
|
+
const ERROR_EXPECTED_PATH = 'error.expected'
|
|
13
16
|
|
|
14
17
|
class Exception {
|
|
15
18
|
constructor({ error, timestamp, customAttributes, agentAttributes }) {
|
|
@@ -101,9 +104,9 @@ function createError(transaction, exception, config) {
|
|
|
101
104
|
}
|
|
102
105
|
}
|
|
103
106
|
|
|
104
|
-
params.intrinsics[
|
|
107
|
+
params.intrinsics[ERROR_EXPECTED_PATH] = false
|
|
105
108
|
if (errorHelper.isExpected(type, message, transaction, config, urltils)) {
|
|
106
|
-
params.intrinsics[
|
|
109
|
+
params.intrinsics[ERROR_EXPECTED_PATH] = true
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
const res = [0, name, message, type, params]
|
|
@@ -116,6 +119,11 @@ function createError(transaction, exception, config) {
|
|
|
116
119
|
/**
|
|
117
120
|
* Creates a structure for error event that is sent to the collector.
|
|
118
121
|
* The error parameter is an output of the createError() function for a given exception.
|
|
122
|
+
*
|
|
123
|
+
* @param transaction
|
|
124
|
+
* @param error
|
|
125
|
+
* @param timestamp
|
|
126
|
+
* @param config
|
|
119
127
|
*/
|
|
120
128
|
function createEvent(transaction, error, timestamp, config) {
|
|
121
129
|
const message = error[2]
|
|
@@ -126,7 +134,7 @@ function createEvent(transaction, error, timestamp, config) {
|
|
|
126
134
|
transaction,
|
|
127
135
|
errorClass,
|
|
128
136
|
message,
|
|
129
|
-
errorParams.intrinsics[
|
|
137
|
+
errorParams.intrinsics[ERROR_EXPECTED_PATH],
|
|
130
138
|
timestamp,
|
|
131
139
|
config
|
|
132
140
|
)
|
|
@@ -136,9 +144,7 @@ function createEvent(transaction, error, timestamp, config) {
|
|
|
136
144
|
const userAttributes = Object.assign(Object.create(null), errorParams.userAttributes)
|
|
137
145
|
const agentAttributes = Object.assign(Object.create(null), errorParams.agentAttributes)
|
|
138
146
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return errorEvent
|
|
147
|
+
return [intrinsicAttributes, userAttributes, agentAttributes]
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
// eslint-disable-next-line max-params
|
package/lib/grpc/connection.js
CHANGED
|
@@ -41,9 +41,9 @@ class GrpcConnection extends EventEmitter {
|
|
|
41
41
|
* Standard property setting/initialization, and sets an initial
|
|
42
42
|
* connection state of disconnected
|
|
43
43
|
*
|
|
44
|
-
* @param {
|
|
44
|
+
* @param {object} traceObserverConfig config item config.infinite_tracing.trace_observer
|
|
45
45
|
* @param {MetricAggregator} metrics metric aggregator, for supportability metrics
|
|
46
|
-
* @param {
|
|
46
|
+
* @param {number} [reconnectDelayMs=15000] number of milliseconds to wait before reconnecting
|
|
47
47
|
* for error states that require a reconnect delay.
|
|
48
48
|
*/
|
|
49
49
|
constructor(traceObserverConfig, metrics, reconnectDelayMs) {
|
|
@@ -97,6 +97,7 @@ class GrpcConnection extends EventEmitter {
|
|
|
97
97
|
*
|
|
98
98
|
* @param {int} state The connection state (See connectionStates above)
|
|
99
99
|
* @param {ClientDuplexStreamImpl} state The GRPC stream, when defined
|
|
100
|
+
* @param stream
|
|
100
101
|
*/
|
|
101
102
|
_setState(state, stream = null) {
|
|
102
103
|
this._state = state
|
|
@@ -146,6 +147,8 @@ class GrpcConnection extends EventEmitter {
|
|
|
146
147
|
*
|
|
147
148
|
* @param {string} licenseKey
|
|
148
149
|
* @param {string} runId
|
|
150
|
+
* @param requestHeadersMap
|
|
151
|
+
* @param env
|
|
149
152
|
*/
|
|
150
153
|
_getMetadata(licenseKey, runId, requestHeadersMap, env) {
|
|
151
154
|
const metadata = new grpc.Metadata()
|
|
@@ -170,6 +173,7 @@ class GrpcConnection extends EventEmitter {
|
|
|
170
173
|
* when appropriate env vars are set
|
|
171
174
|
*
|
|
172
175
|
* @param {Metadata} metadata
|
|
176
|
+
* @param env
|
|
173
177
|
*/
|
|
174
178
|
_setTestMetadata(metadata, env) {
|
|
175
179
|
for (const [key, envVar] of Object.entries(GRPC_TEST_META)) {
|
|
@@ -183,6 +187,7 @@ class GrpcConnection extends EventEmitter {
|
|
|
183
187
|
|
|
184
188
|
/**
|
|
185
189
|
* Disconnects from gRPC endpoint and schedules establishing a new connection.
|
|
190
|
+
*
|
|
186
191
|
* @param {number} reconnectDelayMs number of milliseconds to wait before reconnecting.
|
|
187
192
|
*/
|
|
188
193
|
_reconnect(reconnectDelayMs = 0) {
|
|
@@ -291,6 +296,8 @@ class GrpcConnection extends EventEmitter {
|
|
|
291
296
|
|
|
292
297
|
/**
|
|
293
298
|
* Creates the GRPC credentials needed
|
|
299
|
+
*
|
|
300
|
+
* @param grpcApi
|
|
294
301
|
*/
|
|
295
302
|
_generateCredentials(grpcApi) {
|
|
296
303
|
let certBuffer = null
|
|
@@ -349,6 +356,8 @@ class GrpcConnection extends EventEmitter {
|
|
|
349
356
|
* ChannelImplementation and related objects will stay in memory even after
|
|
350
357
|
* the stream is closed and we do not have a handle to the client. Currently
|
|
351
358
|
* impacting grpc-js@1.2.11 and several earlier versions.
|
|
359
|
+
*
|
|
360
|
+
* @param endpoint
|
|
352
361
|
*/
|
|
353
362
|
_createClient(endpoint) {
|
|
354
363
|
logger.trace('Creating gRPC client for: ', endpoint)
|
|
@@ -360,9 +369,7 @@ class GrpcConnection extends EventEmitter {
|
|
|
360
369
|
const traceApi = protoDescriptor.com.newrelic.trace.v1
|
|
361
370
|
|
|
362
371
|
const credentials = this._generateCredentials(grpc)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
return client
|
|
372
|
+
return new traceApi.IngestService(endpoint, credentials)
|
|
366
373
|
}
|
|
367
374
|
}
|
|
368
375
|
|
package/lib/header-attributes.js
CHANGED
|
@@ -139,7 +139,8 @@ function _collectHeaders(headers, nameMap, prefix, transaction) {
|
|
|
139
139
|
|
|
140
140
|
/**
|
|
141
141
|
* Adds request headers as request.headers.* attributes to the given transaction.
|
|
142
|
-
*
|
|
142
|
+
*
|
|
143
|
+
* @param {Object<string, string>} headers - Request headers to add attributes for.
|
|
143
144
|
* @param {Transaction} transaction - Transaction to add header attributes to.
|
|
144
145
|
*/
|
|
145
146
|
function collectRequestHeaders(headers, transaction) {
|
|
@@ -148,7 +149,8 @@ function collectRequestHeaders(headers, transaction) {
|
|
|
148
149
|
|
|
149
150
|
/**
|
|
150
151
|
* Adds response headers as response.headers.* attributes to the given transaction.
|
|
151
|
-
*
|
|
152
|
+
*
|
|
153
|
+
* @param {Object<string, string>} headers - Response headers to add attributes for.
|
|
152
154
|
* @param {Transaction} transaction - Transaction to add header attributes to.
|
|
153
155
|
*/
|
|
154
156
|
function collectResponseHeaders(headers, transaction) {
|
package/lib/header-processing.js
CHANGED
|
@@ -14,6 +14,7 @@ const CONTENT_LENGTH_REGEX = /^Content-Length$/i
|
|
|
14
14
|
*
|
|
15
15
|
* Queue time is provided by certain providers by stamping the request
|
|
16
16
|
* header with the time the request arrived at the router.
|
|
17
|
+
*
|
|
17
18
|
* @param {*} logger
|
|
18
19
|
* @param {*} requestHeaders
|
|
19
20
|
*/
|
|
@@ -37,8 +38,7 @@ function getQueueTime(logger, requestHeaders) {
|
|
|
37
38
|
return null
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
return convertedQueueTime
|
|
41
|
+
return convertUnit(parsedQueueTime)
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
function convertUnit(time) {
|