From 7db177d1814985485bb8262940e43f24a240f221 Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Mon, 18 May 2020 15:37:18 -0700 Subject: [PATCH] feat(dev-infra): create logging utils with support for defined logging levels (#37192) Creates common logging functions at different levels. Allows for providing logging statements which are actually printed to the console based on the LOG_LEVEL environment variable. PR Close #37192 --- dev-infra/utils/BUILD.bazel | 1 + dev-infra/utils/console.ts | 92 +++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/dev-infra/utils/BUILD.bazel b/dev-infra/utils/BUILD.bazel index 48b015feeb..062f2080af 100644 --- a/dev-infra/utils/BUILD.bazel +++ b/dev-infra/utils/BUILD.bazel @@ -10,6 +10,7 @@ ts_library( "@npm//@types/inquirer", "@npm//@types/node", "@npm//@types/shelljs", + "@npm//chalk", "@npm//shelljs", "@npm//tslib", "@npm//typed-graphqlify", diff --git a/dev-infra/utils/console.ts b/dev-infra/utils/console.ts index f6ca0c9d9e..78bfb6dc81 100644 --- a/dev-infra/utils/console.ts +++ b/dev-infra/utils/console.ts @@ -6,8 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ +import chalk from 'chalk'; import {prompt} from 'inquirer'; + +/** Reexport of chalk colors for convenient access. */ +export const red: typeof chalk = chalk.red; +export const green: typeof chalk = chalk.green; +export const yellow: typeof chalk = chalk.yellow; + /** Prompts the user with a confirmation question and a specified message. */ export async function promptConfirm(message: string, defaultValue = false): Promise { return (await prompt<{result: boolean}>({ @@ -18,3 +25,88 @@ export async function promptConfirm(message: string, defaultValue = false): Prom })) .result; } + +/** + * Supported levels for logging functions. + * + * Levels are mapped to numbers to represent a hierarchy of logging levels. + */ +export enum LOG_LEVELS { + SILENT = 0, + ERROR = 1, + WARN = 2, + LOG = 3, + INFO = 4, + DEBUG = 5, +} + +/** Default log level for the tool. */ +export const DEFAULT_LOG_LEVEL = LOG_LEVELS.INFO; + +/** Write to the console for at INFO logging level */ +export function info(...text: string[]): void; +export function info(color: typeof chalk, ...text: string[]): void; +export function info(color: typeof chalk|string, ...text: string[]) { + runConsoleCommand(console.info, LOG_LEVELS.INFO, color, ...text); +} + +/** Write to the console for at ERROR logging level */ +export function error(...text: string[]): void; +export function error(color: typeof chalk, ...text: string[]): void; +export function error(color: typeof chalk|string, ...text: string[]) { + runConsoleCommand(console.error, LOG_LEVELS.ERROR, color, ...text); +} + +/** Write to the console for at DEBUG logging level */ +export function debug(...text: string[]): void; +export function debug(color: typeof chalk, ...text: string[]): void; +export function debug(color: typeof chalk|string, ...text: string[]) { + runConsoleCommand(console.debug, LOG_LEVELS.DEBUG, color, ...text); +} + +/** Write to the console for at LOG logging level */ +export function log(...text: string[]): void; +export function log(color: typeof chalk, ...text: string[]): void; +export function log(color: typeof chalk|string, ...text: string[]) { + // tslint:disable-next-line: no-console + runConsoleCommand(console.log, LOG_LEVELS.LOG, color, ...text); +} + +/** Write to the console for at WARN logging level */ +export function warn(...text: string[]): void; +export function warn(color: typeof chalk, ...text: string[]): void; +export function warn(color: typeof chalk|string, ...text: string[]) { + runConsoleCommand(console.warn, LOG_LEVELS.WARN, color, ...text); +} + +/** + * Run the console command provided, if the environments logging level greater than the + * provided logging level. + */ +function runConsoleCommand( + command: Function, logLevel: LOG_LEVELS, color: typeof chalk|string, ...text: string[]) { + if (getLogLevel() >= logLevel) { + if (typeof color === 'function') { + text = text.map(entry => color(entry)); + } else { + text = [color as string, ...text]; + } + for (const textEntry of text) { + command(textEntry); + } + } +} + +/** + * Retrieve the log level from environment variables, if the value found + * based on the LOG_LEVEL environment variable is undefined, return the default + * logging level. + */ +function getLogLevel() { + const logLevelEnvValue: any = (process.env[`LOG_LEVEL`] || '').toUpperCase(); + const logLevel = LOG_LEVELS[logLevelEnvValue]; + if (logLevel === undefined) { + return DEFAULT_LOG_LEVEL; + } + return logLevel; +}