From b52e7dc228b2141a22456506ee6bd1df93aa4b77 Mon Sep 17 00:00:00 2001 From: Liang Gong Date: Thu, 19 Sep 2024 15:20:36 -0700 Subject: [PATCH] feat(core): support console annotations (#124) Summary: When dev set the following config, we want stack traces to be printed even if `lowLevel` output is muted (stack traces is output at `lowLevel` for various reasons such as coloring, but semantically it is part of the error output). ``` memlabConfig.muteConfig = { muteError: false, muteWarning: false, muteInfo: true, muteSuccess: true, muteLog: true, muteTable: true, muteTrace: true, muteTopLevel: true, muteHighLevel: true, muteMidLevel: true, muteLowLevel: true, }; memlabConfig.verbose = true; ``` This diff patches the MemLab console output module so that stack traces is still printed when `muteLowLevel` is `true` while `muteError` is `false`. Differential Revision: D63012111 fbshipit-source-id: 535bde1a3e7287a2d5b33c75f48b04f708a44be8 --- packages/core/src/lib/Console.ts | 20 +++++++++++++++++--- packages/core/src/lib/Types.ts | 8 ++++++++ packages/core/src/lib/Utils.ts | 12 +++++++++--- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/packages/core/src/lib/Console.ts b/packages/core/src/lib/Console.ts index bcab4817..4f66c5ee 100644 --- a/packages/core/src/lib/Console.ts +++ b/packages/core/src/lib/Console.ts @@ -16,7 +16,13 @@ import path from 'path'; import readline from 'readline'; import stringWidth from 'string-width'; import {OutputFormat, type MemLabConfig} from './Config'; -import {AnyValue, Nullable, Optional} from './Types'; +import { + AnyValue, + ConsoleOutputAnnotation, + ConsoleOutputOptions, + Nullable, + Optional, +} from './Types'; type Message = { lines: number[]; @@ -117,6 +123,9 @@ class MemLabConsole { }; private static singleton: MemLabConsole; + public annotations: {[key: string]: ConsoleOutputAnnotation} = { + STACK_TRACE: 'stack-trace', + }; protected constructor() { this.sections = { @@ -442,13 +451,18 @@ class MemLabConsole { this.printStr(this.style(msg, 'mid')); } - public lowLevel(msg: string): void { + public lowLevel(msg: string, options: ConsoleOutputOptions = {}): void { if (this.shouldBeConcise('lowLevel')) { return this.overwrite(msg); } this.logMsg(msg); if (this.config.muteConfig?.muteLowLevel) { - return; + if ( + options.annotation !== this.annotations.STACK_TRACE || + this.config.muteConfig?.muteError + ) { + return; + } } this.clearPrevOverwriteMsg(); this.printStr(this.style(msg, 'low')); diff --git a/packages/core/src/lib/Types.ts b/packages/core/src/lib/Types.ts index ba8a2795..b7c69283 100644 --- a/packages/core/src/lib/Types.ts +++ b/packages/core/src/lib/Types.ts @@ -2446,3 +2446,11 @@ export type JSONifyOptions = { forceJSONifyDepth?: number; serializationHelper?: ISerializationHelper; }; + +/** @internal */ +export type ConsoleOutputAnnotation = 'stack-trace'; + +/** @internal */ +export type ConsoleOutputOptions = { + annotation?: ConsoleOutputAnnotation; +}; diff --git a/packages/core/src/lib/Utils.ts b/packages/core/src/lib/Utils.ts index 7aed3873..776d986c 100644 --- a/packages/core/src/lib/Utils.ts +++ b/packages/core/src/lib/Utils.ts @@ -1300,7 +1300,9 @@ function callAsync(f: AnyAyncFunction): void { promise.catch((e: unknown) => { const parsedError = getError(e); info.error(parsedError.message); - info.lowLevel(parsedError.stack ?? ''); + info.lowLevel(parsedError.stack ?? '', { + annotation: info.annotations.STACK_TRACE, + }); }); } } @@ -1892,7 +1894,9 @@ function haltOrThrow( } // only print stack trace in verbose mode if (config.verbose) { - info.lowLevel(err.stack ?? ''); + info.lowLevel(err.stack ?? '', { + annotation: info.annotations.STACK_TRACE, + }); } else { info.topLevel( 'Use `memlab help` or `memlab -h` to get helper text', @@ -2036,7 +2040,9 @@ export function runShell( if (config.verbose || config.isContinuousTest) { if (ex instanceof Error) { info.lowLevel(ex.message); - info.lowLevel(ex.stack ?? ''); + info.lowLevel(ex.stack ?? '', { + annotation: info.annotations.STACK_TRACE, + }); } } if (options.throwError) {