Logging frameworks and their key features

There are a wide variety of logging frameworks offered by mainstream languages. Some notable ones to mention include Log4j from Java, Serilog from C#, and Bunyan from Node.js. From the time of proliferation of these frameworks, and from their use cases, there are similarities in what features a logging framework should provides to its users. The following are the most desirable properties that logging frameworks should have:

  • Fast: Logging frameworks must ensure that they are not doing expensive operations when logging and should be able to process efficiently using as few CPU cycles as possible. For instance, in Java, if your log statements contain objects with lots of to_string() calls to them to just interpolate the object within the log message, then that's an expensive operation. This is considered an inefficient practice in Java.
  • Configurable outputs: It's very limiting to have the ability to log messages only to standard output. It stays only until the shell session and you need to manually paste the logs to a file to use them later. Logging frameworks should provide the ability to support multiple outputs, such as a file or even a network socket.
  • Log levels: The prominent feature of logging frameworks that makes them stand out from normal print-based logging is the ability to control what and when things get logged. This is usually implemented using the idea of log levels. A log level is a configurable filter that's usually implemented as a type that is checked for before sending the log output anywhere. The levels are usually in the following order, from lowest priority to highest priority:
    • Error: This level is suitable for logging events that are critical and those that may lead to invalid outputs from the application.
    • Warn: This level is suitable for events for which you have taken measures, but also want to know when it happens to take actions later if they occur frequently.
    • Info: This level can be used for normal events such as printing the application version, user logins, connection successful messages, and so on.
    • Debug: As the name suggests, this is used to support debugging. It is useful for monitoring the values of variables and how they get manipulated in different code paths when debugging.
    • Trace: This level is used when you want a step-by-step execution of your algorithm or any non-trivial function that you wrote. Method invocations with parameter and return values are things that can be put as trace logs.

Some of these names might differ slightly across frameworks, but the priorities they signify are mostly the same. In major logging frameworks, these levels are set by the logger during its initialization and any subsequent logging invocations check for the set level and filters out the logs accordingly. For example, a Logger object with the call to Logger.set_level(INFO) would allow all logs using levels above Info to be logged, while ignoring Debug and Trace logs.

  • Log filtering: It should be easy to log only the desired places in code and to turn off other logs based on the severity/importance of events.
  • Log Rotation: When logging to a file, it is imminent that prolonged logging will fill up disk space. A logging framework should provide facilities to limit the log file size and allow for the deletion of older log files.
  • Asynchronous logging: Logging invocations on the main thread have the possibility of blocking the main code from making progress. Even though an efficient logger would do as little as possible, it still does a blocking I/O call between the actual code. As such, it is desirable that most logging invocations are offloaded to a dedicated logger thread.
  • Log message attributes: Another thing worth mentioning are the attributes on log messages that get sent to the logging API. At a minimum, a logging framework should provide the following attributes to log messages:
    • Timestamp: The time at which the event happened
    • Log Severity: The importance of the message, for example, Error, Warning, Information, Debug, and so on
    • Event location: The place in the source code where the event happened
    • Message: The actual event message that describes what happened

Depending on these features, there are differences in how logging frameworks approach logging. Let's explore them next.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset