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.
- package/NEWS.md +42 -18
- package/THIRD_PARTY_NOTICES.md +203 -2
- package/api.js +155 -103
- package/lib/agent.js +29 -82
- package/lib/collector/api.js +234 -201
- package/lib/config/attribute-filter.js +35 -25
- package/lib/config/default.js +45 -19
- package/lib/config/index.js +260 -199
- package/lib/environment.js +16 -12
- package/lib/errors/error-collector.js +124 -55
- package/lib/errors/index.js +59 -49
- package/lib/instrumentation/@hapi/hapi.js +56 -50
- package/lib/instrumentation/@node-redis/client.js +50 -41
- package/lib/instrumentation/amqplib.js +116 -151
- package/lib/instrumentation/core/{async_hooks.js → async-hooks.js} +26 -11
- package/lib/instrumentation/core/globals.js +1 -1
- package/lib/instrumentation/core/http-outbound.js +193 -78
- package/lib/instrumentation/core/timers.js +106 -59
- package/lib/instrumentation/grpc-js/grpc.js +20 -23
- package/lib/instrumentation/mongodb/common.js +87 -85
- package/lib/instrumentation/redis.js +112 -90
- package/lib/instrumentation/undici.js +204 -192
- package/lib/instrumentation/{when.js → when/constants.js} +13 -10
- package/lib/instrumentation/when/contextualizer.js +168 -0
- package/lib/instrumentation/when/index.js +354 -0
- package/lib/instrumentation/when/nr-hooks.js +15 -0
- package/lib/instrumentations.js +1 -1
- package/lib/shim/shim.js +2 -0
- package/lib/shim/webframework-shim.js +19 -0
- package/lib/symbols.js +1 -0
- package/lib/system-info.js +240 -163
- package/lib/util/async-each-limit.js +30 -0
- package/lib/util/attributes.js +159 -0
- package/lib/util/code-level-metrics.js +58 -0
- package/lib/util/deep-equal.js +11 -144
- package/package.json +5 -4
- package/lib/instrumentation/promise.js +0 -572
package/lib/config/index.js
CHANGED
|
@@ -5,9 +5,6 @@
|
|
|
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
|
-
|
|
11
8
|
const AttributeFilter = require('./attribute-filter')
|
|
12
9
|
const CollectorResponse = require('../collector/response')
|
|
13
10
|
const copy = require('../util/copy')
|
|
@@ -41,6 +38,7 @@ const LASP_MAP = require('./lasp').LASP_MAP
|
|
|
41
38
|
const HSM = require('./hsm')
|
|
42
39
|
const REMOVE_BEFORE_SEND = new Set(['attributeFilter'])
|
|
43
40
|
const SSL_WARNING = 'SSL config key can no longer be disabled, not updating.'
|
|
41
|
+
const SERVERLESS_DT_KEYS = ['account_id', 'primary_application_id', 'trusted_account_key']
|
|
44
42
|
|
|
45
43
|
const exists = fs.existsSync
|
|
46
44
|
let logger = null // Lazy-loaded in `initialize`.
|
|
@@ -200,7 +198,7 @@ Config.prototype.mergeServerConfig = mergeServerConfig
|
|
|
200
198
|
* recognized, unsupported, and unknown parameters.
|
|
201
199
|
*
|
|
202
200
|
* @param {object} json The config blob sent by New Relic.
|
|
203
|
-
* @param recursion
|
|
201
|
+
* @param {boolean} recursion flag indicating coming from server side config
|
|
204
202
|
*/
|
|
205
203
|
Config.prototype.onConnect = function onConnect(json, recursion) {
|
|
206
204
|
json = json || Object.create(null)
|
|
@@ -233,6 +231,49 @@ Config.prototype._getMostSecure = function getMostSecure(key, currentVal, newVal
|
|
|
233
231
|
return filter(currentVal, newVal)
|
|
234
232
|
}
|
|
235
233
|
|
|
234
|
+
/**
|
|
235
|
+
* Helper that checks if value from server is false
|
|
236
|
+
* then updates the corresponding configuration enabled flag.
|
|
237
|
+
* We never allow server-side config to enable a feature but you can disable
|
|
238
|
+
*
|
|
239
|
+
* @param {*} serverValue value from server
|
|
240
|
+
* @param {string} key within configuration to disable its enabled flag
|
|
241
|
+
*/
|
|
242
|
+
Config.prototype._disableOption = function _disableOption(serverValue, key) {
|
|
243
|
+
if (serverValue === false) {
|
|
244
|
+
this[key].enabled = false
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Updates harvest_limits for event_harvest_config if they are valid values
|
|
250
|
+
*
|
|
251
|
+
* @param {object} serverConfig harvest config from server
|
|
252
|
+
* @param {string} key value from server side config that stores the event harvest config
|
|
253
|
+
*/
|
|
254
|
+
Config.prototype._updateHarvestConfig = function _updateHarvestConfig(serverConfig, key) {
|
|
255
|
+
const val = serverConfig[key]
|
|
256
|
+
const isValidConfig = harvestConfigValidator.isValidHarvestConfig(val)
|
|
257
|
+
if (!isValidConfig) {
|
|
258
|
+
this.emit(key, null)
|
|
259
|
+
return
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
logger.info('Valid event_harvest_config received. Updating harvest cycles.', val)
|
|
263
|
+
const limits = Object.keys(val.harvest_limits).reduce((acc, k) => {
|
|
264
|
+
const v = val.harvest_limits[k]
|
|
265
|
+
if (harvestConfigValidator.isValidHarvestValue(v)) {
|
|
266
|
+
acc[k] = v
|
|
267
|
+
} else {
|
|
268
|
+
logger.info(`Omitting limit for ${k} due to invalid value ${v}`)
|
|
269
|
+
}
|
|
270
|
+
return acc
|
|
271
|
+
}, {})
|
|
272
|
+
val.harvest_limits = limits
|
|
273
|
+
this[key] = val
|
|
274
|
+
this.emit(key, val)
|
|
275
|
+
}
|
|
276
|
+
|
|
236
277
|
/**
|
|
237
278
|
* The guts of the logic about how to deal with server-side configuration.
|
|
238
279
|
*
|
|
@@ -240,6 +281,7 @@ Config.prototype._getMostSecure = function getMostSecure(key, currentVal, newVal
|
|
|
240
281
|
* @param {string} key The particular configuration parameter to set.
|
|
241
282
|
*/
|
|
242
283
|
Config.prototype._fromServer = function _fromServer(params, key) {
|
|
284
|
+
/* eslint-disable-next-line sonarjs/max-switch-cases */
|
|
243
285
|
switch (key) {
|
|
244
286
|
// handled by the connection
|
|
245
287
|
case 'messages':
|
|
@@ -318,49 +360,19 @@ Config.prototype._fromServer = function _fromServer(params, key) {
|
|
|
318
360
|
this._updateIfChanged(params, key)
|
|
319
361
|
break
|
|
320
362
|
case 'event_harvest_config':
|
|
321
|
-
|
|
322
|
-
const isValidConfig = harvestConfigValidator.isValidHarvestConfig(val)
|
|
323
|
-
if (!isValidConfig) {
|
|
324
|
-
this.emit(key, null)
|
|
325
|
-
break
|
|
326
|
-
}
|
|
327
|
-
logger.info('Valid event_harvest_config received. Updating harvest cycles.', val)
|
|
328
|
-
const limits = Object.keys(val.harvest_limits).reduce((acc, k) => {
|
|
329
|
-
const v = val.harvest_limits[k]
|
|
330
|
-
if (harvestConfigValidator.isValidHarvestValue(v)) {
|
|
331
|
-
acc[k] = v
|
|
332
|
-
} else {
|
|
333
|
-
logger.info(`Omitting limit for ${k} due to invalid value ${v}`)
|
|
334
|
-
}
|
|
335
|
-
return acc
|
|
336
|
-
}, {})
|
|
337
|
-
val.harvest_limits = limits
|
|
338
|
-
this[key] = val
|
|
339
|
-
this.emit(key, val)
|
|
363
|
+
this._updateHarvestConfig(params, key)
|
|
340
364
|
break
|
|
341
365
|
|
|
342
366
|
case 'collect_analytics_events':
|
|
343
|
-
|
|
344
|
-
// but we allow the server to disable
|
|
345
|
-
if (params.collect_analytics_events === false) {
|
|
346
|
-
this.transaction_events.enabled = false
|
|
347
|
-
}
|
|
367
|
+
this._disableOption(params.collect_analytics_events, 'transaction_events')
|
|
348
368
|
break
|
|
349
369
|
|
|
350
370
|
case 'collect_custom_events':
|
|
351
|
-
|
|
352
|
-
// but we allow the server to disable
|
|
353
|
-
if (params.collect_custom_events === false) {
|
|
354
|
-
this.custom_insights_events.enabled = false
|
|
355
|
-
}
|
|
371
|
+
this._disableOption(params.collect_custom_events, 'custom_insights_events')
|
|
356
372
|
break
|
|
357
373
|
|
|
358
374
|
case 'collect_span_events':
|
|
359
|
-
|
|
360
|
-
// but we allow the server to disable
|
|
361
|
-
if (params.collect_span_events === false) {
|
|
362
|
-
this.span_events.enabled = false
|
|
363
|
-
}
|
|
375
|
+
this._disableOption(params.collect_span_events, 'span_events')
|
|
364
376
|
break
|
|
365
377
|
|
|
366
378
|
case 'allow_all_headers':
|
|
@@ -930,6 +942,8 @@ function getHostnameSafe() {
|
|
|
930
942
|
|
|
931
943
|
/**
|
|
932
944
|
* Ensure that the apps names are always returned as a list.
|
|
945
|
+
*
|
|
946
|
+
* @returns {Array} list of applications
|
|
933
947
|
*/
|
|
934
948
|
Config.prototype.applications = function applications() {
|
|
935
949
|
const apps = this.app_name
|
|
@@ -950,7 +964,7 @@ Config.prototype.applications = function applications() {
|
|
|
950
964
|
*
|
|
951
965
|
* @param {object} external The configuration being loaded.
|
|
952
966
|
* @param {object} internal Whichever chunk of the config being overridden.
|
|
953
|
-
* @param arbitrary
|
|
967
|
+
* @param {boolean} arbitrary flag indicating if it is in the HAS_ARBITRARY_KEYS set
|
|
954
968
|
*/
|
|
955
969
|
Config.prototype._fromPassed = function _fromPassed(external, internal, arbitrary) {
|
|
956
970
|
if (!external) {
|
|
@@ -1035,15 +1049,15 @@ Config.prototype._featureFlagsFromEnv = function _featureFlagsFromEnv() {
|
|
|
1035
1049
|
* @returns {string} formatted env var name
|
|
1036
1050
|
*/
|
|
1037
1051
|
function deriveEnvVar(key, paths) {
|
|
1038
|
-
let
|
|
1039
|
-
|
|
1040
|
-
return `NEW_RELIC_${
|
|
1052
|
+
let configPath = paths.join('_')
|
|
1053
|
+
configPath = configPath ? `${configPath}_` : configPath
|
|
1054
|
+
return `NEW_RELIC_${configPath.toUpperCase()}${key.toUpperCase()}`
|
|
1041
1055
|
}
|
|
1042
1056
|
|
|
1043
1057
|
/**
|
|
1044
1058
|
* Assigns the value of an env var to its corresponding configuration path
|
|
1045
1059
|
*
|
|
1046
|
-
* @param {object} params
|
|
1060
|
+
* @param {object} params object passed to fn
|
|
1047
1061
|
* @param {object} params.config agent config
|
|
1048
1062
|
* @param {string} params.key key to assign value
|
|
1049
1063
|
* @param {string} params.envVar name of env var
|
|
@@ -1064,7 +1078,7 @@ function setFromEnv({ config, key, envVar, formatter, paths }) {
|
|
|
1064
1078
|
* @param {object} [config=this] The current level of the configuration object.
|
|
1065
1079
|
* @param {object} [data=configDefinition] The current level of the config definition object.
|
|
1066
1080
|
* @param {Array} [paths=[]] keeps track of the nested path to properly derive the env var
|
|
1067
|
-
* @param {
|
|
1081
|
+
* @param {number} [objectKeys=1] indicator of how many keys exist in current node to know when to remove current node after all keys are processed
|
|
1068
1082
|
*/
|
|
1069
1083
|
Config.prototype._fromEnvironment = function _fromEnvironment(
|
|
1070
1084
|
config = this,
|
|
@@ -1101,144 +1115,131 @@ Config.prototype._fromEnvironment = function _fromEnvironment(
|
|
|
1101
1115
|
}
|
|
1102
1116
|
|
|
1103
1117
|
/**
|
|
1104
|
-
*
|
|
1105
|
-
* environment variable.
|
|
1118
|
+
* Disables `logging.enabled` if not set in configuration file or environment variable.
|
|
1106
1119
|
*
|
|
1107
1120
|
* @param {*} inputConfig configuration passed to the Config constructor
|
|
1108
|
-
* @returns {
|
|
1121
|
+
* @returns {void}
|
|
1109
1122
|
*/
|
|
1110
|
-
Config.prototype.
|
|
1111
|
-
const inputEnabled = inputConfig
|
|
1123
|
+
Config.prototype._serverlessLogging = function _serverlessLogging(inputConfig) {
|
|
1124
|
+
const inputEnabled = inputConfig?.logging?.enabled
|
|
1112
1125
|
const envEnabled = process.env.NEW_RELIC_LOG_ENABLED
|
|
1113
1126
|
|
|
1114
|
-
|
|
1127
|
+
if (inputEnabled === undefined && envEnabled === undefined) {
|
|
1128
|
+
this.logging.enabled = false
|
|
1129
|
+
|
|
1130
|
+
logger.info(
|
|
1131
|
+
'Logging is disabled by default when serverless_mode is enabled. ' +
|
|
1132
|
+
'If desired, enable logging via config file or environment variable and ' +
|
|
1133
|
+
'set filepath to a valid path for current environment, stdout or stderr.'
|
|
1134
|
+
)
|
|
1135
|
+
}
|
|
1115
1136
|
}
|
|
1116
1137
|
|
|
1117
1138
|
/**
|
|
1118
1139
|
* Returns true if native-metrics has been manually enabled via configuration
|
|
1119
|
-
* file or
|
|
1140
|
+
* file or environment variable
|
|
1120
1141
|
*
|
|
1121
1142
|
* @param {*} inputConfig configuration pass to the Config constructor
|
|
1122
|
-
* @returns {
|
|
1143
|
+
* @returns {void}
|
|
1123
1144
|
*/
|
|
1124
|
-
Config.prototype.
|
|
1125
|
-
const inputEnabled =
|
|
1126
|
-
inputConfig &&
|
|
1127
|
-
inputConfig.plugins &&
|
|
1128
|
-
inputConfig.plugins.native_metrics &&
|
|
1129
|
-
inputConfig.plugins.native_metrics.enabled
|
|
1145
|
+
Config.prototype._serverlessNativeMetrics = function _serverlessNativeMetrics(inputConfig) {
|
|
1146
|
+
const inputEnabled = inputConfig?.plugins?.native_metrics?.enabled
|
|
1130
1147
|
const envEnabled = process.env.NEW_RELIC_NATIVE_METRICS_ENABLED
|
|
1131
1148
|
|
|
1132
|
-
|
|
1149
|
+
if (
|
|
1150
|
+
(inputEnabled !== undefined || envEnabled !== undefined) &&
|
|
1151
|
+
this.plugins.native_metrics.enabled
|
|
1152
|
+
) {
|
|
1153
|
+
logger.info(
|
|
1154
|
+
'Enabling the native-metrics module when in serverless mode may greatly ' +
|
|
1155
|
+
'increase cold-start times. Given the limited benefit of the VM metrics' +
|
|
1156
|
+
'and general lack of control in a serverless environment, we do not ' +
|
|
1157
|
+
'recommend this trade-off.'
|
|
1158
|
+
)
|
|
1159
|
+
} else {
|
|
1160
|
+
this.plugins.native_metrics.enabled = false
|
|
1161
|
+
|
|
1162
|
+
logger.info(
|
|
1163
|
+
'The native-metrics module is disabled by default when serverless_mode ' +
|
|
1164
|
+
'is enabled. If desired, enable the native-metrics module via config file ' +
|
|
1165
|
+
'or environment variable.'
|
|
1166
|
+
)
|
|
1167
|
+
}
|
|
1133
1168
|
}
|
|
1134
1169
|
|
|
1135
1170
|
/**
|
|
1136
|
-
*
|
|
1137
|
-
*
|
|
1171
|
+
* Application name is not currently leveraged by our Lambda product (March 2021).
|
|
1172
|
+
* Defaulting the name removes burden on customers to set while avoiding
|
|
1173
|
+
* breaking should it be used in the future.
|
|
1138
1174
|
*
|
|
1139
|
-
* @
|
|
1140
|
-
* @returns {boolean}
|
|
1175
|
+
* @returns {void}
|
|
1141
1176
|
*/
|
|
1142
|
-
Config.prototype.
|
|
1143
|
-
|
|
1144
|
-
|
|
1177
|
+
Config.prototype._serverlessAppName = function _serverlessAppName() {
|
|
1178
|
+
if (!this.app_name || this.app_name.length === 0) {
|
|
1179
|
+
const namingSource = process.env.AWS_LAMBDA_FUNCTION_NAME
|
|
1180
|
+
? 'process.env.AWS_LAMBDA_FUNCTION_NAME'
|
|
1181
|
+
: 'DEFAULT'
|
|
1145
1182
|
|
|
1146
|
-
|
|
1183
|
+
const name = process.env.AWS_LAMBDA_FUNCTION_NAME || 'Serverless Application'
|
|
1184
|
+
this.app_name = [name]
|
|
1147
1185
|
|
|
1148
|
-
|
|
1186
|
+
logger.info("Auto-naming serverless application to ['%s'] from: %s", name, namingSource)
|
|
1187
|
+
}
|
|
1149
1188
|
}
|
|
1150
1189
|
|
|
1151
1190
|
/**
|
|
1152
|
-
*
|
|
1153
|
-
* - disables cross_application_tracer.enabled if set
|
|
1154
|
-
* - defaults logging to disabled
|
|
1155
|
-
* - verifies data specific to running DT is defined either in config file of env vars
|
|
1156
|
-
*
|
|
1157
|
-
* @param {*} inputConfig configuration passed to the Config constructor
|
|
1191
|
+
* Disables CAT in serverless mode
|
|
1158
1192
|
*/
|
|
1159
|
-
Config.prototype.
|
|
1160
|
-
if (this.
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const namingSource = process.env.AWS_LAMBDA_FUNCTION_NAME
|
|
1166
|
-
? 'process.env.AWS_LAMBDA_FUNCTION_NAME'
|
|
1167
|
-
: 'DEFAULT'
|
|
1168
|
-
|
|
1169
|
-
const name = process.env.AWS_LAMBDA_FUNCTION_NAME || 'Serverless Application'
|
|
1170
|
-
this.app_name = [name]
|
|
1171
|
-
|
|
1172
|
-
logger.info("Auto-naming serverless application to ['%s'] from: %s", name, namingSource)
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
// Explicitly disable old CAT in serverless_mode
|
|
1176
|
-
if (this.cross_application_tracer.enabled) {
|
|
1177
|
-
this.cross_application_tracer.enabled = false
|
|
1178
|
-
logger.info('Cross application tracing is explicitly disabled in serverless_mode.')
|
|
1179
|
-
}
|
|
1180
|
-
|
|
1181
|
-
if (this.infinite_tracing.trace_observer.host) {
|
|
1182
|
-
this.infinite_tracing.trace_observer.host = ''
|
|
1183
|
-
this.infinite_tracing.trace_observer.port = ''
|
|
1184
|
-
logger.info('Infinite tracing is explicitly disabled in serverless_mode.')
|
|
1185
|
-
}
|
|
1186
|
-
|
|
1187
|
-
if (!this._loggingManuallySet(inputConfig)) {
|
|
1188
|
-
this.logging.enabled = false
|
|
1189
|
-
|
|
1190
|
-
logger.info(
|
|
1191
|
-
'Logging is disabled by default when serverless_mode is enabled. ' +
|
|
1192
|
-
'If desired, enable logging via config file or environment variable and ' +
|
|
1193
|
-
'set filepath to a valid path for current environment, stdout or stderr.'
|
|
1194
|
-
)
|
|
1195
|
-
}
|
|
1193
|
+
Config.prototype._serverlessCAT = function _serverlessCAT() {
|
|
1194
|
+
if (this.cross_application_tracer.enabled) {
|
|
1195
|
+
this.cross_application_tracer.enabled = false
|
|
1196
|
+
logger.info('Cross application tracing is explicitly disabled in serverless_mode.')
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1196
1199
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
} else {
|
|
1205
|
-
this.plugins.native_metrics.enabled = false
|
|
1200
|
+
Config.prototype._serverlessInfiniteTracing = function _serverlessInfiniteTracing() {
|
|
1201
|
+
if (this.infinite_tracing.trace_observer.host) {
|
|
1202
|
+
this.infinite_tracing.trace_observer.host = ''
|
|
1203
|
+
this.infinite_tracing.trace_observer.port = ''
|
|
1204
|
+
logger.info('Infinite tracing is explicitly disabled in serverless_mode.')
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1206
1207
|
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1208
|
+
/**
|
|
1209
|
+
* Disables DT if account_id is not set.
|
|
1210
|
+
* Otherwise it will set trusted_account_key and primary_application_id accordingly.
|
|
1211
|
+
*
|
|
1212
|
+
* @returns {void}
|
|
1213
|
+
*/
|
|
1214
|
+
Config.prototype._serverlessDT = function _serverlessDT() {
|
|
1215
|
+
if (!this.account_id) {
|
|
1216
|
+
if (this.distributed_tracing.enabled) {
|
|
1217
|
+
logger.warn(
|
|
1218
|
+
'Using distributed tracing in serverless mode requires account_id be ' +
|
|
1219
|
+
'defined, either in your newrelic.js file or via environment variables. ' +
|
|
1220
|
+
'Disabling distributed tracing.'
|
|
1211
1221
|
)
|
|
1222
|
+
this.distributed_tracing.enabled = false
|
|
1212
1223
|
}
|
|
1213
|
-
|
|
1214
|
-
if (!this._DTManuallySet(inputConfig)) {
|
|
1215
|
-
this.distributed_tracing.enabled = true
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
if (!this.account_id) {
|
|
1219
|
-
if (this.distributed_tracing.enabled) {
|
|
1220
|
-
logger.warn(
|
|
1221
|
-
'Using distributed tracing in serverless mode requires account_id be ' +
|
|
1222
|
-
'defined, either in your newrelic.js file or via environment variables. ' +
|
|
1223
|
-
'Disabling distributed tracing.'
|
|
1224
|
-
)
|
|
1225
|
-
this.distributed_tracing.enabled = false
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
return
|
|
1229
|
-
}
|
|
1224
|
+
} else {
|
|
1230
1225
|
// default trusted_account_key to account_id
|
|
1231
1226
|
this.trusted_account_key = this.trusted_account_key || this.account_id
|
|
1232
1227
|
|
|
1233
1228
|
// Not required in serverless mode but must default to Unknown to function.
|
|
1234
1229
|
this.primary_application_id = this.primary_application_id || 'Unknown'
|
|
1235
|
-
|
|
1236
|
-
return
|
|
1237
1230
|
}
|
|
1231
|
+
}
|
|
1238
1232
|
|
|
1239
|
-
|
|
1233
|
+
/**
|
|
1234
|
+
* In serverless mode we allow defer auth to the downstream serverless entities.
|
|
1235
|
+
* This means we set account_id, primary_application_id, and trusted_account_key in configuration.
|
|
1236
|
+
* This function sets all those to null because this.serverles_mode.enabled is falsey.
|
|
1237
|
+
*
|
|
1238
|
+
* @returns {void}
|
|
1239
|
+
*/
|
|
1240
|
+
Config.prototype._preventServerlessDT = function _preventServerlessDT() {
|
|
1240
1241
|
// Don't allow DT config settings to be set if serverless_mode is disabled
|
|
1241
|
-
|
|
1242
|
+
SERVERLESS_DT_KEYS.forEach((key) => {
|
|
1242
1243
|
if (this[key]) {
|
|
1243
1244
|
logger.warn(
|
|
1244
1245
|
key +
|
|
@@ -1250,6 +1251,27 @@ Config.prototype._enforceServerless = function _enforceServerless(inputConfig) {
|
|
|
1250
1251
|
})
|
|
1251
1252
|
}
|
|
1252
1253
|
|
|
1254
|
+
/**
|
|
1255
|
+
* Enforces config rules specific to running in serverless_mode:
|
|
1256
|
+
* - disables cross_application_tracer.enabled if set
|
|
1257
|
+
* - defaults logging to disabled
|
|
1258
|
+
* - verifies data specific to running DT is defined either in config file of env vars
|
|
1259
|
+
*
|
|
1260
|
+
* @param {*} inputConfig configuration passed to the Config constructor
|
|
1261
|
+
*/
|
|
1262
|
+
Config.prototype._enforceServerless = function _enforceServerless(inputConfig) {
|
|
1263
|
+
if (this.serverless_mode.enabled) {
|
|
1264
|
+
this._serverlessAppName()
|
|
1265
|
+
this._serverlessCAT()
|
|
1266
|
+
this._serverlessInfiniteTracing()
|
|
1267
|
+
this._serverlessLogging(inputConfig)
|
|
1268
|
+
this._serverlessNativeMetrics(inputConfig)
|
|
1269
|
+
this._serverlessDT(inputConfig)
|
|
1270
|
+
} else {
|
|
1271
|
+
this._preventServerlessDT()
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1253
1275
|
/**
|
|
1254
1276
|
* Depending on how the status codes are set, they could be strings, which
|
|
1255
1277
|
* makes strict equality testing / indexOf fail. To keep things cheap, parse
|
|
@@ -1290,43 +1312,57 @@ Config.prototype._canonicalize = function _canonicalize() {
|
|
|
1290
1312
|
}
|
|
1291
1313
|
}
|
|
1292
1314
|
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
const upper = parseInt(split[1], 10)
|
|
1307
|
-
if (Number.isNaN(lower) || Number.isNaN(upper)) {
|
|
1308
|
-
logger.warn('Range must contain two numbers %s', range)
|
|
1309
|
-
return parsed
|
|
1310
|
-
}
|
|
1311
|
-
if (lower > upper) {
|
|
1312
|
-
logger.warn('Range must start with lower bound %s', range)
|
|
1313
|
-
} else if (lower < 0 || upper > 1000) {
|
|
1314
|
-
logger.warn('Range must be between 0 and 1000 %s', range)
|
|
1315
|
-
} else {
|
|
1316
|
-
// success
|
|
1317
|
-
for (let i = lower; i <= upper; i++) {
|
|
1318
|
-
parsed.push(i)
|
|
1319
|
-
}
|
|
1320
|
-
}
|
|
1315
|
+
/**
|
|
1316
|
+
* Splits a range of status codes. It will not
|
|
1317
|
+
* allow negative values, non-numbers, or numbers above 1000.
|
|
1318
|
+
*
|
|
1319
|
+
* @param {string} range range of status codes 400-421
|
|
1320
|
+
* @param {Array} parsed list of parsed codes
|
|
1321
|
+
* @returns {Array} adds to the cleansed list of status codes
|
|
1322
|
+
* by removing any ranges and adds as elements
|
|
1323
|
+
*/
|
|
1324
|
+
function _parseRange(range, parsed) {
|
|
1325
|
+
const split = range.split('-')
|
|
1326
|
+
if (split.length !== 2) {
|
|
1327
|
+
logger.warn('Failed to parse range %s', range)
|
|
1321
1328
|
return parsed
|
|
1322
1329
|
}
|
|
1330
|
+
if (split[0] === '') {
|
|
1331
|
+
// catch negative code. ex. -7
|
|
1332
|
+
return parsed.push(parseInt(range, 10))
|
|
1333
|
+
}
|
|
1334
|
+
const lower = parseInt(split[0], 10)
|
|
1335
|
+
const upper = parseInt(split[1], 10)
|
|
1336
|
+
if (Number.isNaN(lower) || Number.isNaN(upper)) {
|
|
1337
|
+
logger.warn('Range must contain two numbers %s', range)
|
|
1338
|
+
return parsed
|
|
1339
|
+
}
|
|
1340
|
+
if (lower > upper) {
|
|
1341
|
+
logger.warn('Range must start with lower bound %s', range)
|
|
1342
|
+
} else if (lower < 0 || upper > 1000) {
|
|
1343
|
+
logger.warn('Range must be between 0 and 1000 %s', range)
|
|
1344
|
+
} else {
|
|
1345
|
+
// success
|
|
1346
|
+
for (let i = lower; i <= upper; i++) {
|
|
1347
|
+
parsed.push(i)
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
return parsed
|
|
1351
|
+
}
|
|
1323
1352
|
|
|
1353
|
+
/**
|
|
1354
|
+
* Parses a list of status codes. It can also
|
|
1355
|
+
* parse a range of status codes
|
|
1356
|
+
*
|
|
1357
|
+
* @param {Array} codes list of status codes
|
|
1358
|
+
* @returns {Array} cleansed list of status codes
|
|
1359
|
+
*/
|
|
1360
|
+
function _parseCodes(codes) {
|
|
1324
1361
|
const parsedCodes = []
|
|
1325
1362
|
for (let i = 0; i < codes.length; i++) {
|
|
1326
1363
|
const code = codes[i]
|
|
1327
|
-
|
|
1328
1364
|
if (typeof code === 'string' && code.indexOf('-') !== -1) {
|
|
1329
|
-
|
|
1365
|
+
_parseRange(code, parsedCodes)
|
|
1330
1366
|
} else {
|
|
1331
1367
|
const parsedCode = parseInt(code, 10)
|
|
1332
1368
|
if (!Number.isNaN(parsedCode)) {
|
|
@@ -1376,30 +1412,29 @@ Config.prototype._applyHighSecurity = function _applyHighSecurity() {
|
|
|
1376
1412
|
}
|
|
1377
1413
|
|
|
1378
1414
|
/**
|
|
1379
|
-
*
|
|
1380
|
-
* by the agent, if LASP-enabled. Responds with an error to shut down
|
|
1381
|
-
* the agent if necessary.
|
|
1415
|
+
* Sends a response to collector for LASP application
|
|
1382
1416
|
*
|
|
1383
|
-
* @param {
|
|
1384
|
-
* @
|
|
1385
|
-
* @returns {CollectorResponse} The result of the processing, with the known
|
|
1386
|
-
* policies as the response payload.
|
|
1417
|
+
* @param {Array} keys keys from a LASP policy
|
|
1418
|
+
* @returns {CollectorResponse} creates CollectorResponse with either preserve or shutdown
|
|
1387
1419
|
*/
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
if (!config.security_policies_token) {
|
|
1393
|
-
if (keys.length) {
|
|
1394
|
-
logger.error(
|
|
1395
|
-
'The agent received one or more unexpected security policies and will shut down.'
|
|
1396
|
-
)
|
|
1397
|
-
return CollectorResponse.fatal(null)
|
|
1398
|
-
}
|
|
1399
|
-
return CollectorResponse.success(null)
|
|
1420
|
+
function _laspReponse(keys) {
|
|
1421
|
+
if (keys.length) {
|
|
1422
|
+
logger.error('The agent received one or more unexpected security policies and will shut down.')
|
|
1423
|
+
return CollectorResponse.fatal(null)
|
|
1400
1424
|
}
|
|
1425
|
+
return CollectorResponse.success(null)
|
|
1426
|
+
}
|
|
1401
1427
|
|
|
1402
|
-
|
|
1428
|
+
/**
|
|
1429
|
+
* Applies the server side LASP policies to a local configuration object
|
|
1430
|
+
*
|
|
1431
|
+
* @param agent
|
|
1432
|
+
* @param {object} policies server side LASP policy
|
|
1433
|
+
* @returns {object} { missingRequired, finalPolicies } list of missing required fields and finalized LASP policy
|
|
1434
|
+
*/
|
|
1435
|
+
Config.prototype._buildLaspPolicy = function _buildLaspPolicy(agent, policies) {
|
|
1436
|
+
const config = this
|
|
1437
|
+
const keys = Object.keys(policies)
|
|
1403
1438
|
const missingRequired = []
|
|
1404
1439
|
|
|
1405
1440
|
const finalPolicies = keys.reduce(function applyPolicy(obj, name) {
|
|
@@ -1451,6 +1486,29 @@ Config.prototype.applyLasp = function applyLasp(agent, policies) {
|
|
|
1451
1486
|
return obj
|
|
1452
1487
|
}, Object.create(null))
|
|
1453
1488
|
|
|
1489
|
+
return { missingRequired, finalPolicies }
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
/**
|
|
1493
|
+
* Checks policies received from preconnect against those expected
|
|
1494
|
+
* by the agent, if LASP-enabled. Responds with an error to shut down
|
|
1495
|
+
* the agent if necessary.
|
|
1496
|
+
*
|
|
1497
|
+
* @param agent
|
|
1498
|
+
* @param {object} policies lasp policy
|
|
1499
|
+
* @returns {CollectorResponse} The result of the processing, with the known
|
|
1500
|
+
* policies as the response payload.
|
|
1501
|
+
*/
|
|
1502
|
+
Config.prototype.applyLasp = function applyLasp(agent, policies) {
|
|
1503
|
+
const keys = Object.keys(policies)
|
|
1504
|
+
|
|
1505
|
+
if (!this.security_policies_token) {
|
|
1506
|
+
return _laspReponse(keys)
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
const { finalPolicies, missingRequired } = this._buildLaspPolicy(agent, policies)
|
|
1510
|
+
|
|
1511
|
+
const missingLASP = []
|
|
1454
1512
|
Object.keys(LASP_MAP).forEach(function checkPolicy(name) {
|
|
1455
1513
|
if (!policies[name]) {
|
|
1456
1514
|
// agent is expecting a policy that was not sent from server -- fail
|
|
@@ -1511,7 +1569,7 @@ function redactValue(value) {
|
|
|
1511
1569
|
* Get a JSONifiable object containing all settings we want to report to the
|
|
1512
1570
|
* collector and store in the environment_values table.
|
|
1513
1571
|
*
|
|
1514
|
-
* @returns
|
|
1572
|
+
* @returns {object} containing simple key-value pairs of settings
|
|
1515
1573
|
*/
|
|
1516
1574
|
Config.prototype.publicSettings = function publicSettings() {
|
|
1517
1575
|
let settings = Object.create(null)
|
|
@@ -1586,8 +1644,8 @@ Config.prototype._warnDeprecations = function _warnDeprecations() {
|
|
|
1586
1644
|
* the environment variables will override their corresponding
|
|
1587
1645
|
* configuration file settings.
|
|
1588
1646
|
*
|
|
1589
|
-
* @param {object} config Optional configuration to be used in place of a
|
|
1590
|
-
*
|
|
1647
|
+
* @param {object} config Optional configuration to be used in place of a config file.
|
|
1648
|
+
* @returns {object} instantiated configuration object
|
|
1591
1649
|
*/
|
|
1592
1650
|
function initialize(config) {
|
|
1593
1651
|
/**
|
|
@@ -1660,7 +1718,8 @@ function initialize(config) {
|
|
|
1660
1718
|
/**
|
|
1661
1719
|
* This helper function creates an empty configuration object
|
|
1662
1720
|
*
|
|
1663
|
-
* @param config
|
|
1721
|
+
* @param {object} config current configuration object to overwrite
|
|
1722
|
+
* @returns {object} config new config object
|
|
1664
1723
|
*/
|
|
1665
1724
|
function createNewConfigObject(config) {
|
|
1666
1725
|
config = new Config(Object.create(null))
|
|
@@ -1674,6 +1733,8 @@ function createNewConfigObject(config) {
|
|
|
1674
1733
|
* This function honors the singleton nature of this module while allowing
|
|
1675
1734
|
* consumers to just request an instance without having to worry if one was
|
|
1676
1735
|
* already created.
|
|
1736
|
+
*
|
|
1737
|
+
* @returns {object} initialized configuration object
|
|
1677
1738
|
*/
|
|
1678
1739
|
function getOrCreateInstance() {
|
|
1679
1740
|
if (_configInstance === null) {
|