refactor(CLI): Configure processing flow debug logs

This commit is contained in:
Mariusz Nowak 2022-03-18 13:38:19 +01:00 committed by Piotr Grzesik
parent 6a1f083ac8
commit 7af0c8cb07

View File

@ -12,6 +12,8 @@ require('graceful-fs').gracefulify(require('fs'));
require('@serverless/utils/log-reporters/node');
const { log, progress, isInteractive: isInteractiveTerminal } = require('@serverless/utils/log');
const processLog = log.get('process');
const handleError = require('../lib/cli/handle-error');
const {
storeLocally: storeTelemetryLocally,
@ -39,6 +41,7 @@ const keepAliveTimer = setTimeout(() => {}, 60 * 60 * 1000);
let processSpanPromise;
let hasBeenFinalized = false;
const finalize = async ({ error, shouldBeSync, telemetryData, shouldSendTelemetry } = {}) => {
processLog.debug('finalize %o', { error, shouldBeSync, telemetryData, shouldSendTelemetry });
if (hasBeenFinalized) {
if (error) {
// Programmer error in finalize handling, ensure to expose
@ -84,6 +87,7 @@ processSpanPromise = (async () => {
require('signal-exit/signals').forEach((signal) => {
process.once(signal, () => {
processLog.debug('exit signal %s', signal);
// If there's another listener (e.g. we're in deamon context or reading stdin input)
// then let the other listener decide how process will exit
const isOtherSigintListener = Boolean(process.listenerCount(signal));
@ -121,6 +125,7 @@ processSpanPromise = (async () => {
const resolveInput = require('../lib/cli/resolve-input');
let commands;
processLog.debug('resolve CLI input (no service schema)');
// Parse args against schemas of commands which do not require to be run in service context
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/no-service')
@ -128,6 +133,7 @@ processSpanPromise = (async () => {
// If version number request, show it and abort
if (options.version) {
processLog.debug('render version');
await require('../lib/cli/render-version')();
await finalize();
return;
@ -179,6 +185,7 @@ processSpanPromise = (async () => {
// Parse args again, taking acounnt schema of service-specific flags
// as they may influence configuration resolution
processLog.debug('resolve CLI input (service schema)');
resolveInput.clear();
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/service')
@ -186,12 +193,16 @@ processSpanPromise = (async () => {
isInteractiveSetup = !isHelpRequest && command === '';
processLog.debug('resolve eventual service configuration');
const resolveConfigurationPath = require('../lib/cli/resolve-configuration-path');
const readConfiguration = require('../lib/configuration/read');
const resolveProviderName = require('../lib/configuration/resolve-provider-name');
// Resolve eventual service configuration path
configurationPath = await resolveConfigurationPath();
if (configurationPath) {
processLog.debug('service configuration found at %s', configurationPath);
} else processLog.debug('no service configuration found');
// If service configuration file is found, load its content
configuration = configurationPath
@ -209,10 +220,12 @@ processSpanPromise = (async () => {
: null;
if (configuration) {
processLog.debug('service configuration file successfully parsed');
serviceDir = process.cwd();
// IIFE for maintenance convenience
await (async () => {
processLog.debug('resolve variables meta');
const resolveVariablesMeta = require('../lib/configuration/variables/resolve-meta');
variablesMeta = resolveVariablesMeta(configuration);
@ -242,8 +255,8 @@ processSpanPromise = (async () => {
if (!commandSchema && providerName === 'aws') {
// If command was not recognized in previous resolution phases
// parse args again also against schemas commands which require AWS service context
processLog.debug('resolve CLI input (AWS service schema)');
resolveInput.clear();
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/aws-service')
));
@ -251,6 +264,7 @@ processSpanPromise = (async () => {
let envVarNamesNeededForDotenvResolution;
if (variablesMeta.size) {
processLog.debug('resolve variables in core properties');
// Some properties are configured with variables
// Resolve eventual variables in `provider.stage` and `useDotEnv`
@ -297,12 +311,14 @@ processSpanPromise = (async () => {
// If command was not recognized in previous resolution phases
// Parse args again also against schemas of commands which work in context of an AWS
// service
processLog.debug('resolve CLI input (AWS service schema)');
resolveInput.clear();
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/aws-service')
));
if (commandSchema) {
processLog.debug('resolve variables in core properties #2');
resolverConfiguration.options = filterSupportedOptions(options, {
commandSchema,
providerName,
@ -330,6 +346,7 @@ processSpanPromise = (async () => {
// Assume "env" source fulfilled for `provider.stage` and `useDotenv` resolution.
// To pick eventual resolution conflict, track what env variables were reported
// misssing when applying this resolution
processLog.debug('resolve variables in stage related properties');
const envSource = require('../lib/configuration/variables/sources/env');
envSource.missingEnvVariables.clear();
await resolveVariables({
@ -377,6 +394,7 @@ processSpanPromise = (async () => {
}
}
if (!isPropertyResolved(variablesMeta, 'provider\0name')) {
processLog.debug('resolve variables in "provider.name"');
await resolveVariables(resolverConfiguration);
if (
eventuallyReportVariableResolutionErrors(
@ -401,6 +419,7 @@ processSpanPromise = (async () => {
return;
}
if (!commandSchema && providerName === 'aws') {
processLog.debug('resolve CLI input (AWS service schema)');
resolveInput.clear();
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/aws-service')
@ -415,11 +434,13 @@ processSpanPromise = (async () => {
}
if (isHelpRequest || commands[0] === 'plugin') {
processLog.debug('resolve variables in "plugins"');
// We do not need full config resolved, we just need to know what
// provider is service setup with, and with what eventual plugins Framework is extended
// as that influences what CLI commands and options could be used,
resolverConfiguration.propertyPathsToResolve.add('plugins');
} else {
processLog.debug('resolve variables in all properties');
delete resolverConfiguration.propertyPathsToResolve;
}
@ -453,6 +474,7 @@ processSpanPromise = (async () => {
// Ensure to have full AWS commands schema loaded if we're in context of AWS provider
// It's not the case if not AWS service specific command was resolved
if (configuration && resolveProviderName(configuration) === 'aws') {
processLog.debug('resolve CLI input (AWS service schema)');
resolveInput.clear();
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/aws-service')
@ -460,6 +482,8 @@ processSpanPromise = (async () => {
}
} else {
// In non-service context we recognize all AWS service commands
processLog.debug('parsing of configuration file failed');
processLog.debug('resolve CLI input (AWS service schema)');
resolveInput.clear();
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/aws-service')
@ -481,6 +505,7 @@ processSpanPromise = (async () => {
if (!isHelpRequest) {
if (isStandaloneCommand) {
processLog.debug('run standalone commmand');
if (configuration) require('../lib/cli/ensure-supported-command')(configuration);
await require(`../commands/${commands.join('-')}`)({
configuration,
@ -499,6 +524,7 @@ processSpanPromise = (async () => {
);
}
if (!configuration) {
processLog.debug('run interative onboarding');
const interactiveContext = await require('../lib/cli/interactive-setup')({
configuration,
serviceDir,
@ -518,6 +544,7 @@ processSpanPromise = (async () => {
}
}
processLog.debug('construct Serverless instance');
serverless = new Serverless({
configuration,
serviceDir,
@ -531,6 +558,7 @@ processSpanPromise = (async () => {
try {
serverless.onExitPromise = processSpanPromise;
serverless.invocationId = uuid.v4();
processLog.debug('initialize Serverless instance');
await serverless.init();
// IIFE for maintanance convenience
@ -542,6 +570,7 @@ processSpanPromise = (async () => {
// might have defined extra commands and options
if (serverless.pluginManager.externalPlugins.size) {
processLog.debug('resolve CLI input (+ plugins schema)');
const commandsSchema = require('../lib/cli/commands-schema/resolve-final')(
serverless.pluginManager.externalPlugins,
{ providerName: providerName || 'aws', configuration }
@ -557,6 +586,7 @@ processSpanPromise = (async () => {
}
if (!providerName && !hasFinalCommandSchema) {
// Invalid configuration, ensure to recognize all AWS commands
processLog.debug('resolve CLI input (AWS service schema)');
resolveInput.clear();
({ command, commands, options, isHelpRequest, commandSchema } = resolveInput(
require('../lib/cli/commands-schema/aws-service')
@ -600,6 +630,7 @@ processSpanPromise = (async () => {
// Register AWS provider specific variable sources
if (providerName === 'aws') {
// Pre-resolve to eventually pick not yet resolved AWS auth related properties
processLog.debug('resolve variables');
await resolveVariables(resolverConfiguration);
if (!variablesMeta.size) return;
if (
@ -648,6 +679,7 @@ processSpanPromise = (async () => {
);
// Having all source resolvers configured, resolve variables
processLog.debug('resolve all variables');
await resolveVariables(resolverConfiguration);
if (!variablesMeta.size) return;
if (
@ -684,8 +716,10 @@ processSpanPromise = (async () => {
if (isHelpRequest && serverless.pluginManager.externalPlugins) {
// Show help
processLog.debug('render help');
require('../lib/cli/render-help')(serverless.pluginManager.externalPlugins);
} else if (isInteractiveSetup) {
processLog.debug('run interactive onboarding');
const interactiveContext = await require('../lib/cli/interactive-setup')({
configuration,
serverless,
@ -701,6 +735,7 @@ processSpanPromise = (async () => {
serverless = interactiveContext.serverless;
}
} else {
processLog.debug('run Serverless instance');
// Run command
await serverless.run();
}
@ -713,6 +748,7 @@ processSpanPromise = (async () => {
await processBackendNotificationRequest(backendNotificationRequest);
}
} catch (error) {
processLog.debug('handle error');
// If Dashboard Plugin, capture error
const dashboardPlugin = serverless.pluginManager.dashboardPlugin;
const dashboardErrorHandler = _.get(dashboardPlugin, 'enterprise.errorHandler');