In this article, we review logger.ts in Motia.dev codebase. We will look at:
logger class
prettyPrint function
colors.js package
Press enter or click to view image in full size
logger class
You will find the following code in packages/core/src/logger.ts.
export class Logger { /** * Why do we need two level of listeners? * * Core listeners pass along to children loggers. * * However, base listeners do not pass along to children loggers. * Those are specific to each logger in the hierarchy. */ private readonly listeners: LogListener[] = [] constructor( readonly isVerbose: boolean = false, private readonly meta: Record<string, unknown> = {}, private readonly coreListeners: LogListener[] = [], ) {} child(meta: Record<string, unknown>): Logger { return new Logger(this.isVerbose, { ...this.meta, ...meta }, this.coreListeners) } // eslint-disable-next-line @typescript-eslint/no-explicit-any private _log(level: string, msg: string, args?: any) { const time = Date.now() const meta = { ...this.meta, ...(args ?? {}) } prettyPrint({ level, time, msg, ...meta }, !this.isVerbose) this.coreListeners.forEach((listener) => listener(level, msg, meta)) this.listeners.forEach((listener) => listener(level, msg, meta)) } info(message: string, args?: unknown) { if (isInfoEnabled) { this._log('info', message, args) } } error(message: string, args?: unknown) { this._log('error', message, args) } debug(message: string, args?: unknown) { if (isDebugEnabled) { this._log('debug', message, args) } } warn(message: string, args?: unknown) { if (isWarnEnabled) { this._log('warn', message, args) } } // eslint-disable-next-line @typescript-eslint/no-explicit-any log(args: any) { this._log('info', args.msg, args) } addListener(listener: LogListener) { this.listeners.push(listener) } } export const globalLogger = new Logger()
_log
function is reused and accepts parameters as shown below:
private _log(level: string, msg: string, args?: any) {
Here, depending on the level, prettyPrint function applies a color to a text.
prettyPrint function
You will find prettyPrint function in packages/core/src/pretty-print.ts and it is defined as shown below:
// eslint-disable-next-line @typescript-eslint/no-explicit-any export const prettyPrint = (json: Record<string, any>, excludeDetails = false): void => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { time, traceId, msg, flows, level, step, ...details } = json const levelTag = levelTags[level] const timestamp = timestampTag(`[${new Date(time).toLocaleTimeString()}]`) const objectHasKeys = Object.keys(details).length > 0 console.log(`${timestamp} ${traceIdTag(traceId)} ${levelTag} ${stepTag(step)} ${msg}`) if (objectHasKeys && !excludeDetails) { console.log(prettyPrintObject(details)) } }
Here, levelTag is assigned a value based on level as shown below:
const levelTag = levelTags[level]
levelTags is defined at line #7 in pretty-print.ts as shown below:
const levelTags: Record<string, string> = { error: colors.red('[ERROR]'), info: colors.blue('[INFO]'), warn: colors.yellow('[WARN]'), debug: colors.gray('[DEBUG]'), trace: colors.gray('[TRACE]'), }
colors.js package
get color and style in your node.js console
Press enter or click to view image in full size
Usage
By popular demand, colors
now ships with two types of usages!
- The super nifty way
var colors = require('colors'); console.log('hello'.green); // outputs green text console.log('i like cake and pies'.underline.red) // outputs red underlined text console.log('inverse the color'.inverse); // inverses the color console.log('OMG Rainbows!'.rainbow); // rainbow console.log('Run the trap'.trap); // Drops the bass
2. or a slightly less nifty way which doesn’t extend String.prototype
var colors = require('colors/safe'); console.log(colors.green('hello')); // outputs green text console.log(colors.red.underline('i like cake and pies')) // outputs red underlined text console.log(colors.inverse('inverse the color')); // inverses the color console.log(colors.rainbow('OMG Rainbows!')); // rainbow console.log(colors.trap('Run the trap')); // Drops the bass
Learn more about colors.js package.
About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
Want to learn from open-source? Solve challenges inspired by open-source projects.
Top comments (0)