Skip to content

Commit

Permalink
feat(cli): support multiple verbosity levels (#8749)
Browse files Browse the repository at this point in the history
Adds support for a "trace" verbosity level (achieved by passing
`--verbose` or `-v` multiple times); and use this new verbosity for the
AWS SDK logging, which is otherwise a little too present.
  • Loading branch information
RomainMuller authored Jun 26, 2020
1 parent 127547a commit fa4196b
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 26 deletions.
9 changes: 5 additions & 4 deletions packages/aws-cdk/bin/cdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { execProgram } from '../lib/api/cxapp/exec';
import { CdkToolkit } from '../lib/cdk-toolkit';
import { RequireApproval } from '../lib/diff';
import { availableInitLanguages, cliInit, printAvailableTemplates } from '../lib/init';
import { data, debug, error, setVerbose } from '../lib/logging';
import { data, debug, error, setLogLevel } from '../lib/logging';
import { PluginHost } from '../lib/plugin';
import { serializeStructure } from '../lib/serialize';
import { Configuration, Settings } from '../lib/settings';
Expand Down Expand Up @@ -45,7 +45,8 @@ async function parseCommandLineArguments() {
.option('strict', { type: 'boolean', desc: 'Do not construct stacks with warnings' })
.option('ignore-errors', { type: 'boolean', default: false, desc: 'Ignores synthesis errors, which will likely produce an invalid output' })
.option('json', { type: 'boolean', alias: 'j', desc: 'Use JSON output instead of YAML when templates are printed to STDOUT', default: false })
.option('verbose', { type: 'boolean', alias: 'v', desc: 'Show debug logs', default: false })
.option('verbose', { type: 'boolean', alias: 'v', desc: 'Show debug logs (specify multiple times to increase verbosity)', default: false })
.count('verbose')
.option('profile', { type: 'string', desc: 'Use the indicated AWS profile as the default environment', requiresArg: true })
.option('proxy', { type: 'string', desc: 'Use the indicated proxy. Will read from HTTPS_PROXY environment variable if not specified.', requiresArg: true })
.option('ca-bundle-path', { type: 'string', desc: 'Path to CA certificate to use when validating HTTPS requests. Will read from AWS_CA_BUNDLE environment variable if not specified.', requiresArg: true })
Expand Down Expand Up @@ -122,7 +123,7 @@ if (!process.stdout.isTTY) {
async function initCommandLine() {
const argv = await parseCommandLineArguments();
if (argv.verbose) {
setVerbose();
setLogLevel(argv.verbose);
}
debug('CDK toolkit version:', version.DISPLAY_VERSION);
debug('Command line arguments:', argv);
Expand Down Expand Up @@ -203,7 +204,7 @@ async function initCommandLine() {
const cli = new CdkToolkit({
cloudExecutable,
cloudFormation,
verbose: argv.trace || argv.verbose,
verbose: argv.trace || argv.verbose > 0,
ignoreErrors: argv['ignore-errors'],
strict: argv.strict,
configuration,
Expand Down
4 changes: 2 additions & 2 deletions packages/aws-cdk/lib/api/aws-auth/sdk.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as AWS from 'aws-sdk';
import { ConfigurationOptions } from 'aws-sdk/lib/config';
import { debug } from '../../logging';
import { debug, trace } from '../../logging';
import { cached } from '../../util/functions';
import { AccountAccessKeyCache } from './account-cache';
import { Account } from './sdk-provider';
Expand Down Expand Up @@ -60,7 +60,7 @@ export class SDK implements ISDK {
...this.retryOptions,
credentials,
region,
logger: { log: (...messages) => messages.forEach(m => debug('%s', m)) },
logger: { log: (...messages) => messages.forEach(m => trace('%s', m)) },
};
this.currentRegion = region;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as cxapi from '@aws-cdk/cx-api';
import * as aws from 'aws-sdk';
import * as colors from 'colors/safe';
import * as util from 'util';
import { error, isVerbose, setVerbose } from '../../../logging';
import { error, logLevel, LogLevel, setLogLevel } from '../../../logging';
import { RewritableBlock } from '../display';

interface StackActivity {
Expand All @@ -28,13 +28,13 @@ export interface StackActivityMonitorProps {
readonly resourcesTotal?: number;

/**
* Whether 'verbose' was requested in the CLI
* The log level that was requested in the CLI
*
* If verbose is requested, we'll always use the full history printer.
* If verbose or trace is requested, we'll always use the full history printer.
*
* @default - Use value from logging.isVerbose
* @default - Use value from logging.logLevel
*/
readonly verbose?: boolean;
readonly logLevel?: LogLevel;
}

export class StackActivityMonitor {
Expand Down Expand Up @@ -78,7 +78,7 @@ export class StackActivityMonitor {
};

const isWindows = process.platform === 'win32';
const verbose = options.verbose ?? isVerbose;
const verbose = options.logLevel ?? logLevel;
const fancyOutputAvailable = !isWindows && stream.isTTY;

this.printer = fancyOutputAvailable && !verbose
Expand Down Expand Up @@ -479,7 +479,7 @@ export class CurrentActivityPrinter extends ActivityPrinterBase {
*/
public readonly updateSleep: number = 2_000;

private oldVerbose: boolean = false;
private oldLogLevel: LogLevel = LogLevel.DEFAULT;
private block = new RewritableBlock(this.stream);

constructor(props: PrinterProps) {
Expand Down Expand Up @@ -520,12 +520,12 @@ export class CurrentActivityPrinter extends ActivityPrinterBase {
public start() {
// Need to prevent the waiter from printing 'stack not stable' every 5 seconds, it messes
// with the output calculations.
this.oldVerbose = isVerbose;
setVerbose(false);
this.oldLogLevel = logLevel;
setLogLevel(LogLevel.DEFAULT);
}

public stop() {
setVerbose(this.oldVerbose);
setLogLevel(this.oldLogLevel);

// Print failures at the end
const lines = new Array<string>();
Expand Down Expand Up @@ -623,4 +623,4 @@ function shorten(maxWidth: number, p: string) {
}

const TIMESTAMP_WIDTH = 12;
const STATUS_WIDTH = 20;
const STATUS_WIDTH = 20;
22 changes: 18 additions & 4 deletions packages/aws-cdk/lib/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@ const logger = (stream: Writable, styles?: StyleFn[]) => (fmt: string, ...args:
stream.write(str + '\n');
};

export let isVerbose = false;
export let logLevel = LogLevel.DEFAULT;

export function setVerbose(enabled = true) {
isVerbose = enabled;
export function setLogLevel(newLogLevel: LogLevel) {
logLevel = newLogLevel;
}

export function increaseVerbosity() {
logLevel += 1;
}

const _debug = logger(stderr, [colors.gray]);

export const debug = (fmt: string, ...args: any[]) => isVerbose && _debug(fmt, ...args);
export const trace = (fmt: string, ...args: any) => logLevel >= LogLevel.TRACE && _debug(fmt, ...args);
export const debug = (fmt: string, ...args: any[]) => logLevel >= LogLevel.DEBUG && _debug(fmt, ...args);
export const error = logger(stderr, [colors.red]);
export const warning = logger(stderr, [colors.yellow]);
export const success = logger(stderr, [colors.green]);
Expand All @@ -42,3 +47,12 @@ export type LoggerFunction = (fmt: string, ...args: any[]) => void;
export function prefix(prefixString: string, fn: LoggerFunction): LoggerFunction {
return (fmt: string, ...args: any[]) => fn(`%s ${fmt}`, prefixString, ...args);
}

export const enum LogLevel {
/** Not verbose at all */
DEFAULT = 0,
/** Pretty verbose */
DEBUG = 1,
/** Extremely verbose */
TRACE = 2
}
8 changes: 5 additions & 3 deletions packages/aws-cdk/test/api/exec.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ import * as semver from 'semver';
import * as sinon from 'sinon';
import { ImportMock } from 'ts-mock-imports';
import { execProgram } from '../../lib/api/cxapp/exec';
import { setVerbose } from '../../lib/logging';
import { LogLevel, setLogLevel } from '../../lib/logging';
import { Configuration } from '../../lib/settings';
import * as bockfs from '../bockfs';
import { testAssembly } from '../util';
import { mockSpawn } from '../util/mock-child_process';
import { MockSdkProvider } from '../util/mock-sdk';

setVerbose(true);

let sdkProvider: MockSdkProvider;
let config: Configuration;
beforeEach(() => {
setLogLevel(LogLevel.DEBUG);

sdkProvider = new MockSdkProvider();
config = new Configuration();

Expand All @@ -34,6 +34,8 @@ beforeEach(() => {
});

afterEach(() => {
setLogLevel(LogLevel.DEFAULT);

sinon.restore();
bockfs.restore();
});
Expand Down
7 changes: 5 additions & 2 deletions packages/aws-cdk/test/api/sdk-provider.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import * as logging from '../../lib/logging';
import * as bockfs from '../bockfs';

SDKMock.setSDKInstance(AWS);
logging.setVerbose(true);

type AwsCallback<T> = (err: Error | null, val: T) => void;

Expand All @@ -26,6 +25,8 @@ let defaultEnv: cxapi.Environment;
beforeEach(() => {
uid = `(${uuid.v4()})`;

logging.setLogLevel(logging.LogLevel.TRACE);

bockfs({
'/home/me/.bxt/credentials': dedent(`
[default]
Expand Down Expand Up @@ -98,6 +99,8 @@ beforeEach(() => {
});

afterEach(() => {
logging.setLogLevel(logging.LogLevel.DEFAULT);

SDKMock.restore();
bockfs.restore();
});
Expand Down Expand Up @@ -264,4 +267,4 @@ function commonPrefix(a: string, b: string): string {
if (a[i] !== b[i]) { return a.substring(0, i); }
}
return a.substr(N);
}
}

0 comments on commit fa4196b

Please sign in to comment.