2025October
logger in storybook codebase.
In this article, we review logger in storybook codebase. We will look at:
- client-logger.ts file.
I study patterns used in an open source project found on Github Trending. For this week, I reviewed some parts of Storybook codebase and wrote this article.

client-logger.ts file
logger
In storybook/code/core/src/client-logger.ts, you will find the following code:
export const logger = { trace: (message: any, ...rest: any[]): void => { if (currentLogLevelNumber <= levels.trace) { console.trace(message, ...rest); } }, debug: (message: any, ...rest: any[]): void => { if (currentLogLevelNumber <= levels.debug) { console.debug(message, ...rest); } }, info: (message: any, ...rest: any[]): void => { if (currentLogLevelNumber <= levels.info) { console.info(message, ...rest); } }, warn: (message: any, ...rest: any[]): void => { if (currentLogLevelNumber <= levels.warn) { console.warn(message, ...rest); } }, error: (message: any, ...rest: any[]): void => { if (currentLogLevelNumber <= levels.error) { console.error(message, ...rest); } }, log: (message: any, ...rest: any[]): void => { if (currentLogLevelNumber < levels.silent) { console.log(message, ...rest); } }, } as const;
Here is an example, demonstrated in storybook/code/core/src/theming/ensure.ts
import { logger } from 'storybook/internal/client-logger'; ... const missing = deletedDiff(light, input); if (Object.keys(missing).length) { logger.warn( dedent` Your theme is missing properties, you should update your theme! theme-data missing: `, missing ); }
once
once is another method defined to show a log only once:
const logged = new Set(); export const once = (type: keyof typeof logger) => (message: any, ...rest: any[]) => { if (logged.has(message)) { return undefined; } logged.add(message); return logger[type](message, ...rest); }; once.clear = () => logged.clear(); once.trace = once('trace'); once.debug = once('debug'); once.info = once('info'); once.warn = once('warn'); once.error = once('error'); once.log = once('log');
pretty
pretty is defined in the same file as shown below:
export const pretty = (type: keyof typeof logger) => (...args: Parameters<LoggingFn>) => { const argArray: Parameters<LoggingFn> = [] as any; if (args.length) { const startTagRe = /<span\s+style=(['"])([^'"]*)\1\s*>/gi; const endTagRe = /<\/span>/gi; let reResultArray; argArray.push(args[0].replace(startTagRe, '%c').replace(endTagRe, '%c')); while ((reResultArray = startTagRe.exec(args[0]))) { argArray.push(reResultArray[2]); argArray.push(''); } // pass through subsequent args since chrome dev tools does not (yet) support console.log styling of the following form: console.log('%cBlue!', 'color: blue;', '%cRed!', 'color: red;'); for (let j = 1; j < args.length; j++) { argArray.push(args[j]); } } // eslint-disable-next-line prefer-spread logger[type].apply(logger, argArray); }; pretty.trace = pretty('trace'); pretty.debug = pretty('debug'); pretty.info = pretty('info'); pretty.warn = pretty('warn'); pretty.error = pretty('error');
About me:
Hey, my name is Ramu Narasinga. I study codebase architecture in large open-source projects.
Email: ramu.narasinga@gmail.com
Study the patterns used in large OSS projects at Think Throo.