logger.ts in Motia.dev codebase.
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.
References:
-
https://github.com/MotiaDev/motia/blob/main/packages/core/src/logger.ts
-
https://github.com/MotiaDev/motia/blob/main/packages/core/src/pretty-print.ts#L61