Have you ever looked at your website logs and realized they don’t make sense to you? Maybe your log levels have been abused, and now every log categorizes as “Error.” Or your logs fail to give clear information on what went wrong, or they reveal sensitive information that hackers may harvest.
Fixing these problems is possible! Let’s explore how you can write meaningful log messages and use log levels correctly. You’ll learn about the benefits of logging and how you can use logs to your advantage.
Let’s start with understanding why you should log in the first place.
Let’s find out about the importance of writing logs. If there’s a crash or an issue pops up, you’ll want to check your website’s logs. Here are five reasons you should keep logs for your website:
Next, let’s explore tips for writing log messages.
Let’s say you want to check your website’s logs, but you find only vague and ambiguous log entries. For example, a log might contain insufficient information about the actual problem. In other cases, a log might not be unique, or you may not be able to pinpoint the exact module that printed the log message. None of these situations is helpful when you want to debug a problem. Therefore, let’s take a look at five tips for writing clear and concise log messages.
Never log any secrets or personally identifiable information from users. You don’t want those logs to leak, revealing information about your clients. That’s a basic security consideration when logging.
Also, you don’t want to leak information about your application or environment. Doing so might expose important information for hackers, allowing them to gain further information about your application and maybe even breach your system.
A log message should be short and to the point. Don’t add too much information, such as describing what a function does. It’s enough to add information about the exact failure—for instance, “database connection failed.” You don’t have to describe the whole action.
The goal is to write a meaningful yet short log message so you can later go back and explore the code to find out what went wrong. Describing the code or action doesn’t make sense here.
You can easily get lost in your logs. Sometimes, you might be logging the same or a similar message in a different component. Therefore, it makes sense to add a unique identifier to make tracing a log easier. You may want to log the name of the active component that’s handling the request. You’ll get something like:
[INFO] component=formatter "object could not be formatted"
Next, let’s take a look at how you can enrich your logs with meta information.
Useful meta information about your logs can include:
If you provide this information and an error occurs, then debugging your application will be much easier.
To easily process your logs, apply standardization across them. For example, use the same date formats throughout your application. This makes it much easier for your operations team to aggregate all logs and make them discoverable because the logs don’t need extra processing.
In addition, use the same structure for your logs. Let’s say every log should start with the current date, followed by a timestamp and the user action. This makes your logs much easier to understand.
[INFO] 05.01.2020 07:05:45 AM user=3241 action=register msg="registration for user failed"
Now that you understand how to write meaningful, concise log entries, let’s explore improving your log levels.
The log level plays a key role in determining the severity of a log entry. It immediately tells the operations engineer if this log is worth further investigation. When you incorrectly apply a log level, you or the operations engineer might miss important information about your service. Therefore, let’s take a look at the different log levels and what they mean.
Trace level is the lowest log level possible. A trace log provides detailed information about an event. However, never use a trace log in a production environment. Because of the verboseness of trace logs, they can have a minimal impact on the performance of your application. Besides, a trace log often reveals detailed but important information about your application, such as code paths or variable values. A hacker can abuse this information to dig deeper into your application in order to prepare a possible attack. You have to remember that any information can be useful to gain further information about your service.
You might be using the debug log level for outputting any meaningful event in your software. Often, people use the debug level for outputting all events that happen. For example, every successful step for a specific request is logged so you have a detailed event path for each request. In short, the debug level creates verbose logging about your application.
Many organizations decide to not display debug logs because those logs are too verbose. If you prefer to keep some of the debug logs, keep only the ones that really add value. A non-meaningful log message often includes generic information, such as “X went wrong.” Try to specify what exactly went wrong, as shown in the log below.
[DEBUG] User module could not save user details to database for /api/users
Many organizations use the info log level as the lowest level for production applications. The info log level prints information about system-related informational actions or user-driven actions. For example, the info level logs every new request that enters an application program interface. In contrast, the debug level would also print all the executed steps for this request.
Next, let’s take a look at higher log levels that indicate potentially harmful situations.
The warning log level often indicates that a certain action might be harmful or might potentially lead to an error. For example, a request timed out, which can have several causes. The database might be unavailable, or the server experienced downtime, or one of many other issues happened. That’s the purpose of the warning log level: to indicate that something might be wrong.
Label any kind of error with the error log level. Let’s say that a database call fails to create a new user. The application should log this failure through the error log level.
The fatal log level is the most severe level. Use this log level only for rare events that cause your service to crash or otherwise have a big impact on your service. Let’s say your database is unavailable. Next, your code tries to establish a new connection object to your database. If the creation of this new connection object fails, it should be reported as a fatal event. Why? Your application can’t function correctly without the database connection and will likely crash.
Tip: Try to stick strictly to logging levels. If you correctly apply log levels, then your life will be easier when you’re debugging an error in your application. You don’t want to be investigating multiple warning or error messages per day while they turn out to be normal info messages.
Here’s how you can write logs for Node.js applications.
Logging is an important part of your website. Logs can not only tell you the health of your website but also help you calculate important metrics, including the error rate. In case of an error, logs help you find the problem more quickly.
When implementing logging for your website, make sure to stick to the checklist for writing meaningful log messages. Most important, never reveal sensitive information about your application, and add plenty of meta information where it’s useful.
Do you want to monitor visitors on your website? Check out Retrace’s real user monitoring.
If you would like to be a guest contributor to the Stackify blog please reach out to stackify@stackify.com