Logo

dev-resources.site

for different kinds of informations.

Is your Java log utility class reporting itself as the source of your logs? Learn how to fix it!

Published at
10/12/2024
Categories
java
logging
slf4j
log4j2
Author
luis_cardozo
Categories
4 categories in total
java
open
logging
open
slf4j
open
log4j2
open
Author
12 person written this
luis_cardozo
open
Is your Java log utility class reporting itself as the source of your logs? Learn how to fix it!

Image description

In the fast-paced environment of modern software development, effective logging is crucial for efficient debugging and system monitoring. However, inconsistent or inaccurate line numbers in log outputs can make troubleshooting time-consuming. Recently, I identified that our internal logging utility was reporting itself as the source of the logs. This needed to be addressed to enhance the log precision.

The Problem

When using a custom utility class to handle logs, it will start reporting itself as the source of the log, as the utility class is the one that finally calls the actual log framework (in my case, it was SLF4J, with Log4J2 as the backend).

So, if the utility class is called InternalLogger, the log will look something like:

2024-10-11T18:10:57,345 [finagle/netty4-6] (InternalLogger.java:34) INFO ...  
Enter fullscreen mode Exit fullscreen mode

Here, the reported source file and line number points to a location within the logging utility itself, rather than where the log call was actually made in the application code. This behavior mitigates the effectiveness of logs in debugging and pinpointing issues quickly.

The Solution

First I thought of manually walking down the stack trace and filtering out some elements before reporting the line number. This approach would be very costly, and I didn’t want to slow down our logging process.

Luckily, I found in this StackOverflow answer that SLF4J provides an interface called LocationAwareLogger, which Log4J2 supports, so, we can filter the utility class by simply passing the Log Utility Class' FQCN (Fully Qualified Class Name).

My original utility class looked something like this:

public class InternalLogger {

  private static final Logger LOG = LoggerFactory.getLogger(InternalLogger.class);

  public void log(EventLog eventLog) {
    //... get message and logLevel from eventLog
    switch (logLevel) {
      case DEBUG:
        LOG.debug(message);
        break;
      case WARN:
        LOG.warn(message);
Enter fullscreen mode Exit fullscreen mode

For this solution, I declared the Logger class FQCN and added a private helper function to log with a LocationAwareLogger:

private static final String LOGGER_UTIL_FQCN = InternalLogger.class.getName();

  private void locationAwareLog(int level, String message) {
    ((LocationAwareLogger) LOG).log(null, LOGGER_UTIL_FQCN, level, message, null, null);
  }
Enter fullscreen mode Exit fullscreen mode

And changed my old code to call it if supported:

switch (logLevel) {
  case DEBUG:
    if (LOG instanceof LocationAwareLogger) {
      locationAwareLog(LocationAwareLogger.DEBUG_INT, message);
    } else {
      LOG.debug(message);
    }
    break;
  case WARN:
    if (LOG instanceof LocationAwareLogger) {
      locationAwareLog(LocationAwareLogger.WARN_INT, message);
    } else {
      LOG.warn(message);
    }
//...
Enter fullscreen mode Exit fullscreen mode

Unluckily, SLF4J doesn't provide a way to provide the level as an argument (i.e. LOG.log(level, message)). If it did, the code would be a little less verbose.

After implementing this change, logs now accurately report the caller’s line number, significantly improving traceability:

2024-10-11T18:45:26,692 [finagle/netty4-6] (ActualLogic.java:1059) INFO ...
Enter fullscreen mode Exit fullscreen mode

Notice the difference: InternalLogger.java:34 versus ActualLogic.java:1059, which indicates a more precise location of the log origin within the application code.

Conclusion

By incorporating SLF4J's LocationAwareLogger, I have transformed our logging system from a source of confusion into a precise diagnostic tool. This change enables accurate reporting of the caller's line number instead of that of the logging utility, greatly enhancing our ability to diagnose issues swiftly and accurately.

This improvement not only streamlines debugging but also reduces response times when addressing software issues.

Developers facing similar challenges should consider this approach to elevate the effectiveness of their logging systems. With clearer and more accurate logs, they can turn what was once ambiguous data into actionable insights, improving both operational efficiency and software reliability. Optimized logging is crucial for meeting the challenges of today’s fast-paced development landscape and ensuring high-quality software outcomes.

logging Article's
30 articles in total
Favicon
🐹 Golang Integration with Kafka and Uber ZapLog 📨
Favicon
Mastering GoFrame Logging: From Zero to Hero
Favicon
Quickly and easily filter your Amazon CloudWatch logs using Logs Insights
Favicon
Avoiding console.log in Production: Best Practices for Robust Logging
Favicon
Freeware: Java Utility Package (Version 2024.12.08) released
Favicon
Kubernetes DaemonSets: Managing System-Level Components Across Every Node
Favicon
AWS CloudWatch: Implementing Data Protection Policy for Sensitive Log Data!
Favicon
Mastering Python Logging: From Basics to Advanced Techniques
Favicon
Docker Logging Drivers: A Comprehensive Guide for Effective Log Management
Favicon
How to Contact Robinhood Support Without Logging In
Favicon
Best Practices for Effective Logging Strategies
Favicon
How EKF Simplifies Logging
Favicon
Introducing implicit contexts in LogTape 0.7.0
Favicon
Simple Python Logging - and a digression on dependencies, trust, and Copy/pasting code
Favicon
Creating a Robust Logging System in C
Favicon
Understanding Logging in Kubernetes - From Containers to Nodes
Favicon
Making Wooster Talk: A Deep Dive into Structured Logging
Favicon
Logging con Python
Favicon
Freeware: Java Utility Package (Version 2024.10.26) released
Favicon
Is your Java log utility class reporting itself as the source of your logs? Learn how to fix it!
Favicon
Golang: Importância de planejar como exibir logs em aplicações de uso intenso
Favicon
Docker Advance Part 2: Docker Logging
Favicon
System Design 10 - Distributed Logging and Monitoring: Keeping an Eye on Your System’s Every Move
Favicon
Mask logs using logstash logback in java with regex
Favicon
Observability - 5(Logging using EFK)
Favicon
Observability
Favicon
Software Devs Picked These 2 Log Formats
Favicon
Error Handling and Logging in Node.js Applications
Favicon
Logging in Python: Best Practices
Favicon
microlog 6: New feature – Log Topics

Featured ones: