This blog will discuss the value of utilizing logging libraries and run down the 10 best-reviewed logging tools we’ve come across for Node.js. Over at @playerzero we use node.js logging libraries often to create and manage log events. Learn more about how we’re bringing our unique approach to monitoring what matters to both front and backend applications today https://www.playerzero.app/ Pino Winston Bunyan Morgan Loglevel Log4js Npmlog Roarr Tracer Signale From a high-level perspective, Node.js logging is important because it helps developers to track the events and performance of their application, diagnose and fix issues, monitor system behavior, and make informed decisions. Logging provides a record of the activity of an application, allowing developers to identify and debug problems, understand user behavior, and improve the overall performance and stability of the system. Logging can also be useful in production environments for detecting and fixing errors, monitoring system performance, and detecting security incidents. Logging vs tracing Whenever something goes very wrong in an application, developers have the option to track down its source via a stack trace. But… relying on stack traces alone only paints half a picture. Tracing will provide you with information about the execution of an application, including the flow of requests, database queries, external API calls, and performance metrics - which can be quite useful. In general, traces are used to understand the behavior of an application on a granular level and to identify performance bottlenecks. Logging fills in the other half of the picture. Logging is the process of recording messages and events related to an application, such as errors, warnings, performance metrics, and debug information. Logging in Node.js is used to diagnose issues, understand user behavior, and improve the overall performance and stability of an application. It also provides a record of the activity in an application, allowing developers to identify and debug problems and make more informed decisions. Why use logging libraries for Node.js? There are several reasons why you should use Node.js logging libraries: - logging libraries provide detailed information about errors and issues, allowing developers to diagnose and fix problems more efficiently. Improved debugging - logging provides a clear view of the behavior and performance of an application, allowing developers to make informed decisions and improve the system. Enhanced visibility - logging libraries can be optimized for performance, reducing the overhead of logging and improving the overall performance of the system. Better performance - many logging libraries allow logs to be written to a centralized log server, making it easier to collect, view, and analyze log data. Centralized logging - logging libraries can be customized to meet specific needs, such as custom log levels, output formats, and filters. Customization Logging levels Logging levels are a way to categorize the importance or severity of log messages. Typically, there are several levels, ranging from critical errors to informational messages, and each level is associated with a numerical value that can be used to filter log messages in a library. Here are the most common levels: FATAL log level Perhaps unsurprisingly, the log level is a level of severity that indicates a critical error in an application - meaning that logs with a level indicate that the application can’t continue to run normally without developer intervention. FATAL FATAL ERROR log level The log level indicates that an application is currently capable of running, BUT, it is encountering a problem. Usually, this indicates that a required task in the application failed - that there was an exception, unexpected behavior, or incorrect inputs. ERROR WARN log level is a less severe log level than , but nevertheless, shouldn’t be ignored. logs can be used to proactively identify issues and prevent problems from becoming more severe as they indicate that something in your application could become a catalyst for a more significant problem. WARN ERROR WARN INFO log level The log level is a type of log message used in logging systems to indicate a general, informational message. It is typically used to log routine, expected events in the application or system, such as the start of a process, completion of a task, or a change in the state of the system. These alerts can generally be ignored since they are meant to confirm that an application is working properly. INFO DEBUG log level Typically, the log level provides information that’s useful strictly within the debugging process. logs are the most detailed type of log message, and provide a granular view of the inner workings of an application. The main purpose of logs is to help developers understand what the system is doing, identify bugs and issues, and diagnose problems. DEBUG DEBUG DEBUG 10 best Node.js logging libraries & how to get started with them #1. Pino Pino benefits Pino is a long-established and very popular logging tool, with over 10.9K Github stars and millions of downloads on npm. Pino is a popular logging library for Node.js because it provides several key features that make it well-suited for use in Node.js applications: - Pino is designed to be fast and lightweight, with a focus on performance. It uses a binary format for log messages, which allows it to generate log output quickly and efficiently. Fast - Pino logs messages in JSON format, which allows for easy parsing, filtering, and analysis of log data. This makes it easier to search, visualize, and analyze log data, and to integrate log data into other systems. Structured logs - Pino is designed to be highly extensible, and includes a number of built-in plugins that can be used to add additional functionality, such as writing log data to a file or sending log data to a remote server. Easy to extend - Pino is a highly efficient Node.js logging library due to its minimal resource utilization. The logging process with Pino gradually accumulates messages, leading to a throttling of the application and a decrease in the number of requests per second. Throttling is a technique where the function connected to an event is triggered to run only once within a specified time frame, even if the event is fired multiple times. Low overhead - Pino offers a variety of options for sending logs, including writing to files, displaying in the console, and utilizing platforms such as Sentry, Azure Application Insights, and CouchDB. Transports To use Pino in a Node.js application, follow these steps: Installing Pino To install Pino, simply install it by running the following command in a new directory: npm install pino - in your Node.js application, import Pino by adding the following line of code at the top of your file: Import const pino = require('pino'); Using Pino - initialize Pino by creating a logger instance, for example: Initialization const logger = pino({ level: 'info' }); This script produces logs with a logging level of and above on the console. INFO By setting the level to info, Pino will log messages with a logging level of , , , and . Messages with a logging level below , such as , will not be logged. INFO WARN ERROR FATAL INFO DEBUG This code only creates a Pino logger instance with the log level set to INFO. No log messages are generated or displayed until you log something using the logger instance. For example: logger.info('This is an info message'); This would produce the following output on the console: {"level":30,"time":1624825088703,"msg":"This is an info message","pid":1234,"hostname":"my-machine"} The logged data displayed on the console includes the log level, the timestamp when it was recorded, the message being logged, an identifier for the log, and the hostname. - you can use the instance to log other messages in your application as well. For example: Logging logger logger.warn('This is a warning message'); logger.error('This is an error message'); - by default, Pino logs to the console. If you want to change the output, you can use one of Pino's available transports that we mentioned earlier, such as writing to a file, sending logs to a remote service like Sentry, or using Azure Application Insights. For more information, you can refer to Pino's "Known Transports" section. Output Installing Pino pretty Pino’s basic NDJSON formatter feature is a great simple formatter for Pino logs, and it’s easy to set up. Here’s how to get it up and running: pino-pretty - install pino-pretty as a dependency in your Node.js project by running the following command in your terminal: Step 1 npm install pino-pretty - import in your Node.js application by adding the following line of code at the top of your file: Step 2 pino-pretty const pino = require('pino'); const pinoPretty = require('pino-pretty'); const logger = pino({ level: 'info' }); logger.pipe(pinoPretty()); With these two code snippets, you have installed and set it up to format your Pino logs. Now you can use the logger instance to log messages in your application and the logs will be displayed in a pretty, human-readable format on the console. pino-pretty Learn even more about debugging with Pino in by How to Debug Node.js with the Best Tools Available @RisingStack #2. Winston Winston benefits With over 20K stars on GitHub, Winston is a very popular logging library for Node.js. Winston is a unique logging library in the Node.js ecosystem because of its comprehensive feature set and ease of use. Some of the reasons why Winston stands out are: - Winston is highly customizable, and provides a variety of logging options and transport mechanisms that allow logs to be written to multiple outputs, such as the console, a file, or a remote server. Flexible - Winston provides a query-able log archive, which makes it easier to search and analyze logs. Queryable logs - Winston has a simple, easy-to-use API that makes it easy to get started with logging in a Node.js application. It provides a minimal set of core functionality, while also allowing developers to extend and customize the logging functionality as needed. Easy to use - Winston has a comprehensive documentation that provides detailed information about its API, and includes a number of examples and tutorials to help developers get started quickly and easily. Well-documented - Winston is an open-source project with a large and active community of developers, which helps ensure that the library is well-maintained, bug-free, and updated to keep up with the latest trends and technologies. Community-driven Installing Winston To install Winston in your Node.js project, you can use the npm package manager by running the following command in your terminal: npm install winston Using Winston Once the installation is complete, you can import and use Winston in your Node.js code by including the following line: const winston = require('winston'); You can then use the Winston library to configure and create your logging instances, for example: const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.Console() ] }); This creates a logger instance with an info level and a console transport. You can use this logger instance to log messages in your application, for example: logger.info('Hello World'); This will log the message to the console with the info log level. Hello World Logging levels in Winston Winston is equipped with six default logging levels, arranged in accordance with the guidelines outlined in the RFC5424 document. The levels are assigned numerical priority, with the highest severity being assigned the lowest number. The six levels and their respective priority values are: { error: 0, warn: 1, info: 2, http: 3, verbose: 4, debug: 5, silly: 6 } For each of the six log levels, there is a corresponding method on the logger object: logger.error('error'); logger.warn('warn'); logger.info('info'); logger.verbose('verbose'); logger.debug('debug'); logger.silly('silly'); You can also pass a string representing the logging level to the log() method: logger.log('error', 'error message'); logger.log('info', 'info message'); The property on the dictates which log messages will be passed on to the transports you’ve configured. For instance, if the property is set to , only log entries with a severity of or higher will be written and all others will be deprioritized. This means that in the current configuration, only log messages with levels of , , and will be outputted. level logger level info info info warn error #3. Bunyan Bunyan benefits Bunyan is a unique logging library for Node.js because of its focus on making log data more structured and readable (they achieve this by serializing logs as JSON objects rather than plain text). Here’s why Bunyan has 7k stars on Github: - unlike some other logging libraries, Bunyan logs data in a JSON format, making it easier to parse and integrate with other tools and platforms. JSON format - Bunyan supports multiple logging levels with flexible options to manage the log severity level and threshold. Flexible logging levels - In Bunyan, a feature exists called serialization, where functions convert a JavaScript object into a JSON-representable object. This allows a specific logger instance to have a serializer that links a log record field name to a serialization function. Serialization - Bunyan provides a simple, easy-to-use API for logging, making it accessible for developers of all skill levels. Easy-to-use API - Bunyan supports a variety of plugins and transports, such as the console, file, HTTP, and email, making it easier to customize logging output to meet specific needs and requirements. Plugins and Transports Installing Bunyan To install Bunyan, you can run the following command in your terminal or command prompt: npm install bunyan This will install the Bunyan library and its dependencies in your Node.js project. Once installed, you can require the library in your code and start using it. Using Bunyan - at the top of your JavaScript file, add the following line: Import Bunyan in your project const bunyan = require('bunyan'); - next, create a logger instance by using the following code: Create a logger instance const logger = bunyan.createLogger({ name: 'my-app-name', level: 'info' }); In this example, is the name of your application and level specifies the minimum level of logs you want to see. name - to log a message, simply call one of Bunyan's log methods, such as info, warn, or error, and pass in the message you want to log, like this: Log a message logger.info('This is an info log message'); logger.warn('This is a warn log message'); logger.error('This is an error log message'); - finally, run your code and you should see the logged messages in the console. Run your code By default, Bunyan outputs logs in JSON format, making it easier to parse and analyze logs with log management tools. You can also customize the format using Bunyan's streams option. #4. Morgan Morgan benefits Morgan is a unique logging library for Node.js for several reasons, mainly its unique positioning as middleware. This among other reasons has led it to be very popular, with 7.3K stars on GitHub at the time of our writing. Here’s a few reasons why Morgan is so popular: - Morgan operates as middleware in the Node.js Express framework, making it easy to integrate into existing Express-based applications. Middleware-based - Morgan offers a wide range of customization options, from log format to custom tokens, allowing developers to tailor their logs to their specific needs. Customizable - Morgan can write log data to a variety of output streams, including the console, files, or even remote servers. Streams-based - Morgan is designed to be fast and lightweight, making it suitable for high-traffic applications where performance is critical. Fast and lightweight - Morgan is specifically designed to log HTTP requests and responses, which is useful for debugging and analyzing web server performance. HTTP request logging Installing Morgan Start by installing the morgan package using npm: npm install morgan Using Morgan After completing the installation process, you need to import the library by using the "require" function and then integrate it into your Express.js application as middleware. The code for this would look like the following: var morgan = require('morgan'); app.use(morgan('dev')); The "dev" argument is a format option provided by Morgan. Morgan offers five different logging formats, including: has a minuscule output. tiny includes response time and abbreviates the log by default. short provides a concise, color-coded output for use during development dev also uses the Apache combined log output. common utilizes the standardized Apache combined log output. combined You can choose between these formats by using the appropriate argument when integrating Morgan into your application, as shown below: app.use(morgan('combined')); app.use(morgan('common')); app.use(morgan('dev')); app.use(morgan('short')); app.use(morgan('tiny')); #5. Loglevel Loglevel benefits Loglevel is a bit less popular than some of the other options listed here, with 2.4K stars on Github, but it remains a great, lightweight logging library nonetheless. Here are a few reasons why loglevel is a unique logging library for Node.js: - loglevel is a very lightweight library, making it ideal for situations where you need a minimal amount of code overhead. Minimal code footprint - loglevel provides dynamic logging levels, which allows you to change the logging level at runtime, making it easy to switch between different levels of logging detail without having to modify the code. Dynamic logging levels - the API of loglevel is simple, providing an easy-to-use and flexible way to log messages. Simple API - loglevel is compatible with both Node.js and web browsers, making it a versatile choice for logging in a variety of environments. Browser compatibility - loglevel is built on top of log4js, which is a widely used logging library, ensuring compatibility across different platforms. Cross-platform compatibility Installing Loglevel To set up loglevel, you need to install it first using npm: npm install loglevel Using Loglevel Once you have it installed, you can import it in your Node.js project and start using it by setting the log level: const log = require('loglevel'); log.setLevel(log.levels.ERROR); By setting the log level to you are specifying that only log messages with a severity level of will be logged. After setting the log level, you can use the following methods to log messages at different levels: ERROR, ERROR log.trace('This is a trace message'); log.debug('This is a debug message'); log.info('This is an info message'); log.warn('This is a warning message'); log.error('This is an error message'); The log level you set will determine which messages will be logged and which will be ignored. For example, if the log level is set to info, only messages logged using and log.warn or log.error will be displayed. log.info #6. Log4js Log4js benefits Of course, we couldn’t mention loglevel without also listing its big brother, Log4js. Log4js is a JavaScript logging library that was started as a port of the popular Java logging library Log4j. It was created to provide a similar logging solution for JavaScript applications and has since evolved to provide advanced logging capabilities and features. With over 5.6k stars on Github, here’s some of the reasons why Log4js is so popular: - Log4js offers a range of options for logging, including log levels, different types of appenders (e.g. console, file, network), and the ability to specify different log configurations for different parts of the application. Flexibility in configuration - Log4js supports the creation of custom appenders, allowing developers to extend the library to meet their specific logging requirements. Custom appenders - Log4js allows developers to associate log messages with additional contextual information, such as the user's request data, to make log messages more useful for debugging. Support for log context - Log4js supports changing the log level at runtime, making it easier to manage logging in a production environment. Dynamic log level configuration - Log4js has built-in support for popular tools, such as Logstash and Graylog, making it easier to integrate logging into a wider application monitoring and analysis workflow. Integration with other tools Installing Log4js To install Log4js, you can use the npm package manager by running the following command in your terminal: npm install log4js This will install the latest version of Log4js and its dependencies. You can then require the library in your Node.js application and start using it to log messages. Using Log4js To get started using Log4js, first require it in your code and configure it: const log4js = require('log4js'); log4js.configure({ appenders: { console: { type: 'console' } }, categories: { default: { appenders: ['console'], level: 'info' } } }); const logger = log4js.getLogger(); You can then use the logger to log messages at different levels: logger.trace('Entering cheese testing'); logger.debug('Got cheese.'); logger.info('Cheese is Gouda.'); logger.warn('Cheese is quite smelly.'); logger.error('Cheese is too ripe!'); logger.fatal('Cheese was breeding ground for listeria.'); Here’s an example of using Log4js to log messages to multiple appenders (console and file) with different log levels: const log4js = require('log4js'); log4js.configure({ appenders: { console: { type: 'console' }, file: { type: 'file', filename: 'app.log' } }, categories: { default: { appenders: ['console'], level: 'info' }, file: { appenders: ['file'], level: 'error' } } }); const logger = log4js.getLogger(); const fileLogger = log4js.getLogger('file'); logger.info('This is an informational message'); fileLogger.error('This is an error message'); In this example, the logger with the category "default" is configured to log messages with level info or above to the console. The logger with the category "file" is configured to log messages with level error or above to the file. The two loggers can be used interchangeably to log messages to their respective appenders. #7. Npmlog Npmlog benefits The unique value of npmlog lies in its simplicity and minimal overhead, making it well suited for use in small-scale or performance-sensitive projects. It is easy to configure and integrates seamlessly with the npm ecosystem (unsurprising since its npm’s official logger utility), making it a popular choice for developers looking for a lightweight logging solution. Here’s a few reasons why npmlog made the list: - npmlog has a small codebase and minimal overhead, making it well suited for small-scale or performance-sensitive projects. Lightweight - npmlog is specifically designed for use within the npm ecosystem, making it easy to integrate with other npm packages and tools. Easy integration with npm - npmlog allows you to customize the log level, stream, and prefix, giving you full control over how your logs are generated and displayed. Customizable - npmlog is suitable for a wide range of projects, from small scripts to large applications, making it a versatile and flexible logging tool. Versatile - npmlog has a straightforward API and requires minimal setup, making it quick and easy to get started with logging in your Node.js project. Simple to use Installing Npmlog To install npmlog, you need to have Node.js and npm (Node Package Manager) installed on your machine. Then, you can run the following command in your terminal or command prompt: npm install npmlog This will download and install the latest version of npmlog and its dependencies, allowing you to use it in your Node.js project. Using Npmlog Here's an example of how to use npmlog in a Node.js project: const log = require('npmlog'); log.level = 'verbose'; log.verbose('This is a verbose message'); log.info('This is an informational message'); log.warn('This is a warning'); log.error('This is an error'); In this example, we start by requiring the module and assigning it to a variable. Then, we set the log level to , which means that messages with a log level of , , , and will be displayed. We then log messages at different levels using the , , , and methods. npmlog verbose verbose info warn error verbose info warn error Note that by default, npmlog writes to . If you need to write to , you can use the property. process.stderr process.stdout log.stream #8. Roarr Roarr benefits The roarr library is a Node.js logging tool that is designed to produce structured data without the need for initialization. It features a command-line interface (CLI) and supports environmental variables, making it versatile and easy to use. Additionally, roarr is compatible with both Node.js and browser environments, making it a versatile logging solution for a wide range of applications. Here are a few key points that highlight the unique value of the roarr library: - the library produces logs in a structured format, making it easy to process and analyze logs using machine-readable tools. Structured logging - roarr provides a rich set of metadata, such as request and response information, which can be used to diagnose issues and improve the overall quality of your logs. Rich metadata - despite its structured format, roarr logs are also designed to be human-readable, making it easy to understand the context and contents of your logs. Human-readable - the library provides a simple and intuitive API for logging, with no unnecessary complexity. Easy to use - the roarr library allows you to customize the appearance and content of your logs, including options for customizing the log level, stream, and metadata. Customizable Installing Roarr First, install roarr using npm: npm install roarr Using Roarr Next, import roarr into your code and create a logger: const Roarr = require('roarr').default; const logger = new Roarr({ context: { service: 'my-service' } }); Log messages using the method: log logger.info('Hello, world!'); By default, roarr logs will be output to the console. You can customize the log output by specifying a different stream, such as a file, using the option: stream const Roarr = require('roarr').default; const fs = require('fs'); const logger = new Roarr({ context: { service: 'my-service' }, stream: fs.createWriteStream('./my-service.log') }); This is just a basic example of how to use roarr. There are many more options and features available, so be sure to refer to the official roarr documentation for more information. #9. Tracer Tracer benefits Tracer is an open-source logging library for Node.js applications, developed by the Node.js community. It is designed to provide an efficient and flexible way to log messages and debugging information in Node.js applications. Tracer has been actively maintained and developed by a team of volunteers and is available for anyone to use and contribute to on Github. Here’s some of the features that make it a unique logging library: - Tracer uses asynchronous logging which means that logs are not blocking the execution of the program. Asynchronous logging - Tracer provides structured logging, which means that logs are organized into key-value pairs, making it easier to search, analyze and visualize log data. Structured logging - Tracer provides a customizable output format, allowing developers to choose the format and destination for their logs, including console, file, or cloud-based services like AWS CloudWatch. Customizable output - Tracer provides a rich logging context, including the ability to attach metadata such as request IDs, user IDs, and other information to logs. Rich Logging context - Tracer provides middleware support, allowing developers to easily add logging to their Express.js or Koa.js applications. Middleware support Installing Tracer Tracer can be installed using the Node Package Manager (npm). Here are the steps to install Tracer: Open your terminal or command prompt Change your current directory to your Node.js project directory Run the following command to install Tracer: npm install tracer This will install Tracer as a dependency in your project. You can then require it in your code and start using it to log messages. Using Tracer Here's an example of how to use Tracer in your code: const tracer = require('tracer'); const logger = tracer.console(); logger.info('Starting the application...'); In this example, we first require the Tracer library, then create a console logger using the method. Finally, we log an informational message using the method on the logger object. tracer.console() info Here's another example of using Tracer: const tracer = require('tracer'); const logger = tracer.dailyfile({root: './logs', maxLogFiles: 10}); logger.error('An error has occurred:', new Error('Something went wrong')); In this example, we're using the method to create a file logger that writes logs to a daily rotating file. The option specifies the directory where the log files will be stored, and the option limits the number of log files that will be kept. tracer.dailyfile root maxLogFiles Finally, we log an error message using the method on the logger object, along with an error object, providing more information about the error that has occurred. error #10. Signale Signale benefits Its Github page boasts of being “hackable and configurable to the core”, and that’s a major part of what makes Signale such a beloved logging library in the Node.js community. The library was created as a solution for the difficulties developers face when trying to log messages in Node.js applications, such as cluttered and hard-to-read logs. Here’s what makes it stand out from the pack: - Signale offers a variety of customizable log outputs, allowing developers to choose the output that best fits their needs, from simple console outputs to more advanced outputs like JSON and Logfmt. Customizable log outputs - Signale has a simple and intuitive API, making it easy for developers to use and understand, even for those who are new to logging. Intuitive API - Signale provides styled outputs, making logs more readable and visually appealing, making it easier to quickly identify important log messages. Styled output - Signale provides rich log context, such as timestamps and log levels, making it easier to analyze and understand logs. Rich Log context - Signale has a large and active community of developers and contributors, ensuring that the library is well-maintained and up-to-date with the latest technologies and best practices. Active community Installing Signale To install Signale, you can use npm, the Node.js package manager, by running the following command in your terminal: npm install signale Alternatively, you can also use yarn to install Signale by running the following command in your terminal: yarn add signale Once installed, you can import Signale into your Node.js application and start using it to log messages and debugging information. Using Signale Here's an example of importing Signale into your Node.js application and using it to log messages: const signale = require('signale'); // Log an info message signale.info('Starting up the server'); // Log a success message signale.success('Server started successfully'); // Log a warning message signale.warn('Low memory warning'); // Log an error message signale.error(new Error('An error occurred while processing data')); In this example, we import Signale into our Node.js application using the function. Then, we use the various logging methods provided by Signale, such as , , , and , to log different types of messages. Each of these methods has a distinctive symbol and color, making it easy to quickly identify the type of log message. require info success warn error You can find more information on how to use Signale, including additional logging methods and customization options, in the . Signale documentation Optimize Your Debugging Process with Node.js Log Libraries In search of a rapid and efficient method to debug your Node.js applications? Check out one or more of the libraries mentioned in this article, each of them is a great option. Pino, however is our personal logging library of choice for what that’s worth 😉 These logging libraries have proven to be crucial when debugging Node.js applications both in testing/development environments and in prod. Plus, by integrating them with a monitoring solution like PlayerZero, you can gain even greater insights into the performance of your Node.js applications. Book a Demo to learn more about how PlayerZero can help you optimize your backend application performance today! Also published . here
Share Your Thoughts