@contrast/agentify
Advanced tools
Comparing version 1.26.0 to 1.27.0
@@ -22,3 +22,2 @@ /* | ||
preStartupValidation, | ||
postConfigValidation, | ||
} = require('./utils'); | ||
@@ -93,3 +92,4 @@ const { IntentionalError } = require('@contrast/common'); | ||
} else { | ||
// for 'esm' we load esm-hooks support, which will install lastly | ||
// for 'esm' we load esm-hooks support, which installs last | ||
// eslint-disable-next-line node/no-unsupported-features/es-syntax | ||
const { default: esmHooks } = await import('@contrast/esm-hooks/lib/index.mjs'); | ||
@@ -140,35 +140,72 @@ esmHooks(core); | ||
require('@contrast/core/lib/messages')(core); | ||
require('@contrast/config')(core); | ||
const modules = [ | ||
{ name: 'messages', spec: '@contrast/core/lib/messages' }, | ||
{ name: 'config', spec: '@contrast/config' }, | ||
{ name: 'logger', spec: '@contrast/logger', default: true }, | ||
// call all configValidation functions here | ||
{ name: 'agent-info', spec: '@contrast/core/lib/agent-info' }, | ||
{ name: 'system-info', spec: '@contrast/core/lib/system-info' }, | ||
{ name: 'app-info', spec: '@contrast/core/lib/app-info' }, | ||
// was check for appInfo errors length and throw if found | ||
{ name: 'sensitive-data-masking', spec: '@contrast/core/lib/sensitive-data-masking' }, | ||
{ name: 'is-agent-path', spec: '@contrast/core/lib/is-agent-path' }, | ||
{ name: 'dep-hooks', spec: '@contrast/dep-hooks' }, | ||
{ name: 'patcher', spec: '@contrast/patcher' }, | ||
{ name: 'capture-stacktrace', spec: '@contrast/core/lib/capture-stacktrace' }, | ||
{ name: 'rewriter', spec: '@contrast/rewriter' }, | ||
{ name: 'contrast-methods', spec: '@contrast/core/lib/contrast-methods' }, | ||
{ name: 'scopes', spec: '@contrast/scopes' }, | ||
{ name: 'deadzones', spec: '@contrast/deadzones' }, | ||
{ name: 'reporter', spec: '@contrast/reporter', default: true }, | ||
{ name: 'instrumentation', spec: '@contrast/instrumentation' }, | ||
{ name: 'metrics', spec: '@contrast/metrics' }, | ||
require('@contrast/logger').default(core); | ||
// compose additional local services | ||
{ name: 'heap-snapshots', spec: './heap-snapshots' }, | ||
{ name: 'sources', spec: './sources' }, | ||
{ name: 'function-hooks', spec: './function-hooks' }, | ||
{ name: 'log-diagnostic-files', spec: './log-diagnostic-files' }, | ||
{ name: 'rewrite-hooks', spec: './rewrite-hooks' }, | ||
]; | ||
// validate the config now that the logger has been installed | ||
postConfigValidation(core); | ||
// collect validators for each module that has them. | ||
// | ||
// the pattern for supplying a validator for a module is to put a validators.js file | ||
// in the same directory as the module's index.js file. the validators.js file should | ||
// export an object with a property for each validator it implements. | ||
// | ||
// the module-loading for-loop defines the implemented validators. | ||
// start with agentify, which is a special case because it's not in the list | ||
// modules to be loaded. | ||
const validators = { agentify: require('./validators') }; | ||
for (const { name, spec } of modules) { | ||
try { | ||
// if any module has files in a directory other than /lib then... | ||
const v = require(`${spec}/lib/validators.js`); | ||
validators[name] = v; | ||
} catch (e) { | ||
// if e.code !== 'MODULE_NOT_FOUND' consider logging. | ||
// no validators for this module. | ||
} | ||
} | ||
require('@contrast/core/lib/agent-info')(core); | ||
require('@contrast/core/lib/system-info')(core); | ||
require('@contrast/core/lib/app-info')(core); | ||
if (core.appInfo._errors?.length) { | ||
throw core.appInfo._errors[0]; | ||
// now load each module and, if a validator is available, run it. | ||
for (const { name, spec, default: isDefault } of modules) { | ||
// typescript inserts a default export for esm modules. | ||
let mod = require(spec); | ||
if (isDefault) { | ||
mod = mod.default; | ||
} | ||
mod(core); | ||
// perform any validations that can take place now that this module is loaded. | ||
if (name === 'logger') { | ||
// note that this runs the "config" validation. it does this so that | ||
// the logger is available for any validation errors. | ||
for (const v in validators) { | ||
validators[v]?.config && validators[v].config(core); | ||
} | ||
} // else if (name === 'other-validation-name') {...} | ||
} | ||
require('@contrast/core/lib/sensitive-data-masking')(core); | ||
require('@contrast/core/lib/is-agent-path')(core); | ||
require('@contrast/dep-hooks')(core); | ||
require('@contrast/patcher')(core); | ||
require('@contrast/core/lib/capture-stacktrace')(core); | ||
require('@contrast/rewriter')(core); // merge contrast-methods? | ||
require('@contrast/core/lib/contrast-methods')(core); // can we remove dependency on patcher? | ||
require('@contrast/scopes')(core); | ||
require('@contrast/deadzones')(core); | ||
require('@contrast/reporter').default(core); | ||
require('@contrast/instrumentation')(core); | ||
require('@contrast/metrics')(core); | ||
// compose additional local services | ||
require('./heap-snapshots')(core); | ||
require('./sources')(core); | ||
require('./function-hooks')(core); | ||
require('./log-diagnostic-files')(core); // this doesn't really belong in agentify | ||
require('./rewrite-hooks')(core); | ||
} catch (err) { | ||
@@ -180,2 +217,4 @@ // TODO: Consider proper UNINSTALLATION and normal startup w/o agent | ||
// IntentionalError is used when the agent is disabled by config. We want | ||
// to abort the installation but not issue any messages. | ||
if (!(err instanceof IntentionalError)) { | ||
@@ -182,0 +221,0 @@ if (core.logger) { |
@@ -48,3 +48,2 @@ /* | ||
wrap: true, | ||
trim: false, | ||
}; | ||
@@ -63,3 +62,3 @@ | ||
if (core.config.agent.node.rewrite.cache.enable) { | ||
core.rewriter.cache.write(filename, result); | ||
core.rewriter.cache.writeSync(filename, result); | ||
} | ||
@@ -66,0 +65,0 @@ |
@@ -21,3 +21,3 @@ /* | ||
const semver = require('semver'); | ||
const { IntentionalError } = require('@contrast/common'); | ||
const { | ||
@@ -134,75 +134,2 @@ engines: { | ||
/** | ||
* Check that the config contains the minimum required settings. Issue appropriate | ||
* error messages. | ||
* @throws IntentionalError | ||
*/ | ||
function postConfigValidation(core) { | ||
// find out if any required settings are missing. | ||
const missingRequiredSettings = []; | ||
// these are only required if the API is enabled. if api.enable is false, it | ||
// had to be set by the user because it defaults to true. | ||
if (core.config.getEffectiveValue('api.enable')) { | ||
for (const setting of ['api.api_key', 'api.service_key', 'api.user_name']) { | ||
if (!core.config.getEffectiveValue(setting)) { | ||
missingRequiredSettings.push(setting); | ||
} | ||
} | ||
} | ||
// v4 accepted `-c` or `--configFile` option in argv, but v5 does not. so if | ||
// something that looks like a config flag is present on the command line, we | ||
// log it. the worst case is that it's a false positive; if that's a problem | ||
// we can make it an info level, but the goal here is for the user to see it | ||
// without having to contact customer support and rerun their test at a more | ||
// verbose log level. | ||
const configFlag = getConfigFlag(process.argv); | ||
if (configFlag) { | ||
const msg = `Command line config flag present: ${configFlag[0]} ${configFlag[1]}`; | ||
if (core.logger) { | ||
core.logger.warn(msg); | ||
} else { | ||
console.warn(msg); | ||
} | ||
} | ||
if (missingRequiredSettings.length) { | ||
const reason = `Missing required settings: ${missingRequiredSettings.join(', ')}`; | ||
const finalMsg = 'A configuration error prevents the Contrast agent from starting.'; | ||
if (core.logger) { | ||
core.logger.error({ reason }, finalMsg); | ||
} else { | ||
console.error(reason, finalMsg); | ||
} | ||
throw new IntentionalError(finalMsg); | ||
} | ||
// now check for serious errors, like file not readable, file format is wrong, etc. | ||
// that were captured when building the config. | ||
if (core.config._errors?.length) { | ||
throw core.config._errors[0]; | ||
} | ||
// finally, was it disabled? | ||
if (!core.config.enable) { | ||
const errorMessage = 'Contrast agent disabled by configuration (enable: false)'; | ||
throw new IntentionalError(errorMessage); | ||
} | ||
} | ||
function getConfigFlag(argv) { | ||
for (let i = 0; i < argv.length - 1; i++) { | ||
if (argv[i] === '-c' || argv[i] === '--configFile') { | ||
// should this check to see if the name looks like a contrast config file? | ||
// let's not because that seems false-negative prone. | ||
// if the next arg is another flag, then this isn't a contrast config flag | ||
if (!argv[i + 1].startsWith('-') && argv[i + 1].toLowerCase().includes('contrast')) { | ||
return argv.slice(i, i + 2); | ||
} | ||
} | ||
} | ||
return undefined; | ||
} | ||
/** | ||
* Validates custom `installOrder` options. We currently need the reporter component | ||
@@ -229,4 +156,2 @@ * to install first in order to onboard and get effective settings and mode values. | ||
preStartupValidation, | ||
postConfigValidation, | ||
getConfigFlag, | ||
}; |
{ | ||
"name": "@contrast/agentify", | ||
"version": "1.26.0", | ||
"version": "1.27.0", | ||
"description": "Configures Contrast agent services and instrumentation within an application", | ||
@@ -20,15 +20,15 @@ "license": "SEE LICENSE IN LICENSE", | ||
"dependencies": { | ||
"@contrast/common": "1.21.1", | ||
"@contrast/config": "1.28.1", | ||
"@contrast/core": "1.32.1", | ||
"@contrast/deadzones": "1.2.1", | ||
"@contrast/common": "1.21.2", | ||
"@contrast/config": "1.28.2", | ||
"@contrast/core": "1.32.2", | ||
"@contrast/deadzones": "1.2.2", | ||
"@contrast/dep-hooks": "1.3.3", | ||
"@contrast/esm-hooks": "2.6.1", | ||
"@contrast/esm-hooks": "2.6.2", | ||
"@contrast/find-package-json": "^1.1.0", | ||
"@contrast/instrumentation": "1.9.0", | ||
"@contrast/logger": "1.8.3", | ||
"@contrast/metrics": "1.8.1", | ||
"@contrast/instrumentation": "1.10.0", | ||
"@contrast/logger": "1.8.4", | ||
"@contrast/metrics": "1.8.2", | ||
"@contrast/patcher": "1.7.3", | ||
"@contrast/reporter": "1.27.1", | ||
"@contrast/rewriter": "1.8.1", | ||
"@contrast/reporter": "1.27.2", | ||
"@contrast/rewriter": "1.8.2", | ||
"@contrast/scopes": "1.4.1", | ||
@@ -35,0 +35,0 @@ "semver": "^7.6.0" |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
36020
13
884
8
+ Added@contrast/common@1.21.2(transitive)
+ Added@contrast/config@1.28.2(transitive)
+ Added@contrast/core@1.32.2(transitive)
+ Added@contrast/deadzones@1.2.2(transitive)
+ Added@contrast/esm-hooks@2.6.2(transitive)
+ Added@contrast/instrumentation@1.10.0(transitive)
+ Added@contrast/logger@1.8.4(transitive)
+ Added@contrast/metrics@1.8.2(transitive)
+ Added@contrast/reporter@1.27.2(transitive)
+ Added@contrast/rewriter@1.8.2(transitive)
- Removed@contrast/common@1.21.1(transitive)
- Removed@contrast/config@1.28.1(transitive)
- Removed@contrast/core@1.32.1(transitive)
- Removed@contrast/deadzones@1.2.1(transitive)
- Removed@contrast/esm-hooks@2.6.1(transitive)
- Removed@contrast/instrumentation@1.9.0(transitive)
- Removed@contrast/logger@1.8.3(transitive)
- Removed@contrast/metrics@1.8.1(transitive)
- Removed@contrast/reporter@1.27.1(transitive)
- Removed@contrast/rewriter@1.8.1(transitive)
Updated@contrast/common@1.21.2
Updated@contrast/config@1.28.2
Updated@contrast/core@1.32.2
Updated@contrast/deadzones@1.2.2
Updated@contrast/esm-hooks@2.6.2
Updated@contrast/logger@1.8.4
Updated@contrast/metrics@1.8.2
Updated@contrast/reporter@1.27.2
Updated@contrast/rewriter@1.8.2