Winston, a logger for just about everything.
In this article, we review a package called Winston.
Now, this is something I found in logger.ts file in n8n codebase and at line number 16, you will find this below import.
import winston from 'winston';
and it got me wondering what this package is about. So, when I quickly googled Winston
, I found this npm package.
Winston
Winstom is a logger for just about everything. Winston is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs. Each Winston logger can have multiple transports. So I think mainly what it does is you can provide a file name and all the logs can go into that file. That’s what I understood.
for example, you may want error logs to be stored in a persistent remote location like database, but all logs output to the console or a local file. So Winston aims to decouple parts of the logging process to make it more flexible and extensible. Attention is given to supporting flexibility in log formatting.
Usage
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
defaultMeta: { service: 'user-service' },
transports: [
//
// - Write all logs with importance level of `error`
// or higher to `error.log`
// (i.e., error, fatal, but not other levels)
//
new winston.transports.File({ filename: 'error.log', level: 'error' }),
//
// - Write all logs with importance level of `info` or higher
// to `combined.log`
// (i.e., fatal, error, warn, and info, but not trace)
//
new winston.transports.File({ filename: 'combined.log' }),
],
});
//
// If we're not in production then log to the `console` with the format:
// `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
//
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple(),
}));
}
This usage example in documentation demonstrates how you could write to a console and also to a file. Keep this in mind as we are going to need this information to understand how Winston
transports are configured in n8n logger.ts file.
Winston usage in n8n
this.internalLogger = winston.createLogger({
level: this.level,
silent: isSilent,
});
This code snippet is picked from L44 in logger.ts. Notice how it does not have any transports configured yet.
Console transport
private setConsoleTransport() {
const format =
this.level === 'debug' && inDevelopment
? this.debugDevConsoleFormat()
: this.level === 'debug' && inProduction
? this.debugProdConsoleFormat()
: winston.format.printf(({ message }: { message: string }) => message);
this.internalLogger.add(new winston.transports.Console({ format }));
}
This code snippet is picked from L116 in logger.ts.
File transport
private setFileTransport() {
const format = winston.format.combine(
winston.format.timestamp(),
winston.format.metadata(),
winston.format.json(),
);
const filename = path.join(
this.instanceSettingsConfig.n8nFolder,
this.globalConfig.logging.file.location,
);
const { fileSizeMax, fileCountMax } = this.globalConfig.logging.file;
this.internalLogger.add(
new winston.transports.File({
filename,
format,
maxsize: fileSizeMax * 1_048_576, // config * 1 MiB in bytes
maxFiles: fileCountMax,
}),
);
}
This code snippet is picked from L189 in logger.ts.
About me:
Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.
Configure features such as Changesets in your Next.js project using Think Throo CLI.
Email — ramu@thinkthroo.com
My Github — https://github.com/ramu-narasinga
My website — https://ramunarasinga.com
My YouTube channel — https://www.youtube.com/@ramu-narasinga
Learning platform — https://thinkthroo.com
Codebase Architecture — https://app.thinkthroo.com/architecture
Best practices — https://app.thinkthroo.com/best-practices
Production-grade projects — https://app.thinkthroo.com/production-grade-projects