Log Levels Explained and How to Use Them
Log levels are essentially labels that indicate the severity or urgency of the various events in your application. Their primary purpose is to separate messages that are merely informational (meaning that the system is working normally) from those that describe a problem or potential problem, such as when recurring errors are detected in the system. Log levels also provide a way to regulate the amount of log data generated by your application so that only the relevant and necessary information is recorded, minimizing the storage requirements and ensuring efficient log management.
Developing a comprehensive production logging strategy for your applications hinges on a thorough understanding and proper utilization of log levels. Therefore, this article aims to provide valuable insights into the concept of log levels and equip you with the necessary techniques for using them effectively. Here are some of the key concepts you will learn by following through with this article:
- The significance of log levels.
- A brief history of log levels.
- Common log levels and how to use them effectively.
- Employing levels for regulating generated log volume.
- How to use log levels for post-logging analysis.
A brief history of log levels
Log levels for software applications have a rich history dating back to the 1980s. One of the earliest and most influential logging solutions for Unix systems, Syslog , introduced a range of severity levels, which provided the first standardized framework for categorizing log entries based on their impact or urgency.
The following are the levels defined by Syslog in descending order of severity:
- Emergency ( emerg ): indicates that the system is unusable and requires immediate attention.
- Alert ( alert ): indicates that immediate action is necessary to resolve a critical issue.
- Critical ( crit ): signifies critical conditions in the program that demand intervention to prevent system failure.
- Error ( error ): indicates error conditions that impair some operation but are less severe than critical situations.
- Warning ( warn ): signifies potential issues that may lead to errors or unexpected behavior in the future if not addressed.
- Notice ( notice ): applies to normal but significant conditions that may require monitoring.
- Informational ( info ): includes messages that provide a record of the normal operation of the system.
- Debug ( debug ): intended for logging detailed information about the system for debugging purposes.
Various application logging frameworks, such as Log4net and Log4j recognized the significance of severity and further refined the concept. These frameworks refined the Syslog levels to cater to the specific needs of various applications and environments. The log levels we commonly encounter today have evolved from this iterative process, and they have now become a fundamental aspect of effective logging across various software disciplines.
The specific log levels available to you may defer depending on the programming language, logging framework, or service in use. However, in most cases, you can expect to encounter levels such as FATAL , ERROR , WARN , INFO , DEBUG , and TRACE . While many logging frameworks allow you to override the default log levels and define custom ones, we generally advise sticking to the levels outlined below. They are arranged in decreasing order of urgency.
🔭 Want to centralize and monitor your application logs?
Head over to Better Stack and start ingesting your logs in 5 minutes.
1. FATAL
The FATAL log level is reserved for recording the most severe issues in an application. When an entry is logged at this level, it indicates a critical failure that prevents the application from doing any further useful work. Typically, such entries are logged just before shutting down the application to prevent data corruption or other detrimental effects.
To ensure timely awareness and swift response to fatal errors, you can configure a log management service, such as Better Stack, to provide instant alerts whenever such entries are logged. This allows you or relevant team members to react promptly and take necessary actions to address the critical situation before it affects your customers.
Examples of events that may be logged as FATAL errors include the following:
- Crucial configuration information is missing without fallback defaults.
- Loss of essential external dependencies or services required for core application operations (such as the database).
- Running out of disk space or memory on the server, causing the application to halt or become unresponsive.
- When a security breach or unauthorized access to sensitive data is detected.
By recoding such severe incidents at the FATAL log level to these severe incidents, you’ll ensure they receive the utmost attention and prompt resolution from the relevant stakeholders. Here’s a minimal example of how to log at the FATAL level using the Pino framework for Node.js applications:
const pino = require('pino'); const logger = pino( < formatters: < bindings: (bindings) =>< return < env: process.env.NODE_ENV || 'production', server: process.env.server, >; >, level: (label) => < return < level: label >; >, >, >); logger.fatal( new Error('no space available for write operations'), 'Disk space critically low' ); process.exit(1);
(/home/ayo/dev/betterstack/demo/nodejs-logging/index.js:21:3)\n at Module._compile (node:internal/modules/cjs/loader:1254:14)\n at Module._extensions..js (node:internal/modules/cjs/loader:1308:10)\n at Module.load (node:internal/modules/cjs/loader:1117:32)\n at Module._load (node:internal/modules/cjs/loader:958:12)\n at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)\n at node:internal/main/run_main_module:23:47">,"msg":"Disk space critically low">
When logging at the FATAL level, include as much information as possible to help diagnose and fix the problem quickly. At the bare minimum, include a stack trace, as demonstrated in the example above. However, including other relevant details that can assist in the troubleshooting and resolution process such as error messages, input data, or additional contextual information is highly encouraged!
2. ERROR
The ERROR log level indicates error conditions within an application that hinder the execution of a specific operation. While the application can continue functioning at a reduced level of functionality or performance, ERROR logs signify issues that should be investigated promptly. Unlike FATAL messages, ERROR logs do not have the same sense of urgency, as the application can continue to do useful work.
However, not all occurrences of errors or exceptions in your application should be logged at the ERROR level. For instance, if an exception is expected behavior and does not result in a degradation of application functionality or performance, it can be logged at a lower level, such as DEBUG . Similarly, errors with a potential for recovery, such as network connectivity issues with automated retry mechanisms, can be logged at the WARN level. Such conditions may be elevated to the ERROR level if recovery is unsuccessful after several attempts.
[s/t of errors being filtered in Better Stack]
Some examples of situations that are typically logged at the ERROR level include the following:
- External API or service failures impacting the application’s functionality (after automated recovery attempts have failed).
- Network communication errors, such as connection timeouts or DNS resolution failures.
- Failure to create or update a resource in the system.
- An unexpected error, such as the failure to decode a JSON object.
The example below demonstrates how you might record an error condition in your application. It uses the Zap logging framework for Go:
func main() < logger := zap.Must(zap.NewProduction()) defer logger.Sync() err := someThingThatCanFail() if err != nil logger.Error( "an error occurred while doing something that can fail", zap.Error(err), ) > >