|
| 1 | +// This is an exact copy of the file `packages/aws-cdk/lib/logging.ts` from 2024-11-29 |
| 2 | +// https://github.com/aws/aws-cdk/blob/81cde0e2e1f83f80273d14724d5518cc20dc5a80/packages/aws-cdk/lib/logging.ts |
| 3 | +// After this we started refactoring the file and functionality changed significantly. |
| 4 | +// In order to preserver backwards-compatibly for users with unsanctioned usage of this file, |
| 5 | +// we keep a copy of the original version around. |
| 6 | +// See https://github.com/aws/aws-cdk/pull/33021 for more information. |
| 7 | + |
| 8 | +import { Writable } from 'stream'; |
| 9 | +import * as util from 'util'; |
| 10 | +import * as chalk from 'chalk'; |
| 11 | + |
| 12 | +type StyleFn = (str: string) => string; |
| 13 | +const { stdout, stderr } = process; |
| 14 | + |
| 15 | +type WritableFactory = () => Writable; |
| 16 | + |
| 17 | +export async function withCorkedLogging<A>(block: () => Promise<A>): Promise<A> { |
| 18 | + corkLogging(); |
| 19 | + try { |
| 20 | + return await block(); |
| 21 | + } finally { |
| 22 | + uncorkLogging(); |
| 23 | + } |
| 24 | +} |
| 25 | + |
| 26 | +let CORK_COUNTER = 0; |
| 27 | +const logBuffer: [Writable, string][] = []; |
| 28 | + |
| 29 | +function corked() { |
| 30 | + return CORK_COUNTER !== 0; |
| 31 | +} |
| 32 | + |
| 33 | +function corkLogging() { |
| 34 | + CORK_COUNTER += 1; |
| 35 | +} |
| 36 | + |
| 37 | +function uncorkLogging() { |
| 38 | + CORK_COUNTER -= 1; |
| 39 | + if (!corked()) { |
| 40 | + logBuffer.forEach(([stream, str]) => stream.write(str + '\n')); |
| 41 | + logBuffer.splice(0); |
| 42 | + } |
| 43 | +} |
| 44 | + |
| 45 | +const logger = (stream: Writable | WritableFactory, styles?: StyleFn[], timestamp?: boolean) => (fmt: string, ...args: unknown[]) => { |
| 46 | + const ts = timestamp ? `[${formatTime(new Date())}] ` : ''; |
| 47 | + |
| 48 | + let str = ts + util.format(fmt, ...args); |
| 49 | + if (styles && styles.length) { |
| 50 | + str = styles.reduce((a, style) => style(a), str); |
| 51 | + } |
| 52 | + |
| 53 | + const realStream = typeof stream === 'function' ? stream() : stream; |
| 54 | + |
| 55 | + // Logger is currently corked, so we store the message to be printed |
| 56 | + // later when we are uncorked. |
| 57 | + if (corked()) { |
| 58 | + logBuffer.push([realStream, str]); |
| 59 | + return; |
| 60 | + } |
| 61 | + |
| 62 | + realStream.write(str + '\n'); |
| 63 | +}; |
| 64 | + |
| 65 | +function formatTime(d: Date) { |
| 66 | + return `${lpad(d.getHours(), 2)}:${lpad(d.getMinutes(), 2)}:${lpad(d.getSeconds(), 2)}`; |
| 67 | + |
| 68 | + function lpad(x: any, w: number) { |
| 69 | + const s = `${x}`; |
| 70 | + return '0'.repeat(Math.max(w - s.length, 0)) + s; |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +export enum LogLevel { |
| 75 | + /** Not verbose at all */ |
| 76 | + DEFAULT = 0, |
| 77 | + /** Pretty verbose */ |
| 78 | + DEBUG = 1, |
| 79 | + /** Extremely verbose */ |
| 80 | + TRACE = 2, |
| 81 | +} |
| 82 | + |
| 83 | +export let logLevel = LogLevel.DEFAULT; |
| 84 | +export let CI = false; |
| 85 | + |
| 86 | +export function setLogLevel(newLogLevel: LogLevel) { |
| 87 | + logLevel = newLogLevel; |
| 88 | +} |
| 89 | + |
| 90 | +export function setCI(newCI: boolean) { |
| 91 | + CI = newCI; |
| 92 | +} |
| 93 | + |
| 94 | +export function increaseVerbosity() { |
| 95 | + logLevel += 1; |
| 96 | +} |
| 97 | + |
| 98 | +const stream = () => CI ? stdout : stderr; |
| 99 | +const _debug = logger(stream, [chalk.gray], true); |
| 100 | + |
| 101 | +export const trace = (fmt: string, ...args: unknown[]) => logLevel >= LogLevel.TRACE && _debug(fmt, ...args); |
| 102 | +export const debug = (fmt: string, ...args: unknown[]) => logLevel >= LogLevel.DEBUG && _debug(fmt, ...args); |
| 103 | +export const error = logger(stderr, [chalk.red]); |
| 104 | +export const warning = logger(stream, [chalk.yellow]); |
| 105 | +export const success = logger(stream, [chalk.green]); |
| 106 | +export const highlight = logger(stream, [chalk.bold]); |
| 107 | +export const print = logger(stream); |
| 108 | +export const data = logger(stdout); |
| 109 | + |
| 110 | +export type LoggerFunction = (fmt: string, ...args: unknown[]) => void; |
| 111 | + |
| 112 | +/** |
| 113 | + * Create a logger output that features a constant prefix string. |
| 114 | + * |
| 115 | + * @param prefixString the prefix string to be appended before any log entry. |
| 116 | + * @param fn the logger function to be used (typically one of the other functions in this module) |
| 117 | + * |
| 118 | + * @returns a new LoggerFunction. |
| 119 | + */ |
| 120 | +export function prefix(prefixString: string, fn: LoggerFunction): LoggerFunction { |
| 121 | + return (fmt: string, ...args: any[]) => fn(`%s ${fmt}`, prefixString, ...args); |
| 122 | +} |
0 commit comments