DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • How to Check if a Java Project Depends on A Vulnerable Version of Log4j
  • How to Secure Apache Ignite From Scratch
  • Adding Graph Retrieval to a RAG Pipeline With Python
  • Debugging and Performance Tuning in Pega Using PAL, Tracer, and Clipboard

Trending

  • The Request Timed Out, But the Payment Succeeded: Building Retry-Safe Mobile APIs
  • When One Docker Swarm Replica Became Unreachable Over an Overlay Network: A Production Case With Traefik
  • Git Blame Isn’t Enough: Building Verifiable Provenance for AI-Generated Code
  • Detection and Response Did Its Job. Now Someone Has to Actually Fix It.

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Coding
  3. Java
  4. Understanding System Logger

Understanding System Logger

I recently learned that instead of using SFL4J's API and the wanted implementation, you'd use System.Logger which is available since Java 9. Let's see how.

By 
Nicolas Fränkel
·
Feb. 14, 22 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
8.1K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

December was not a good time for Java developers and even less for Ops. The former had to repackage their apps with a fixed Log4J's version, and the latter had to redeploy them - several times. Yet, every cloud has a silver lining. In my case, I learned about System.Logger.

Snapshot of System Logger Tweet

In short, System.Logger is a façade over your logging engine. Instead of using, say, SFL4J's API and the wanted implementation, you'd use System.Logger instead of SLF4J. It's available since Java 9, and it's a bummer that I learned about it only recently.

System.Logger API

The API is a bit different than other logging APIs: it avoids different logging methods such as debug(), info() in favor of a single log() one where you pass a logging Level parameter.

System Logger API

If you don't provide any corresponding implementation on the classpath, System.Logger defaults to JUL.

Java
 
public class LoggerExample {

  private static final System.Logger LOGGER = System.getLogger("c.f.b.DefaultLogger"); // 1

  public static void main(String[] args) {
      LOGGER.log(DEBUG, "A debug message");
      LOGGER.log(INFO, "Hello world!");
  }
}


  1. Get the logger.

Running the above snippet outputs the following:

Plain Text
 
Dec 24, 2021 10:38:15 AM c.f.b.DefaultLogger main
INFO: Hello world!


Compatible Implementations

Most applications currently use Log4J2 or SLF4J. Both provide a compatible System.Logger implementation.

For Log4J, we need to add two dependencies:

XML
 
<dependencies>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>            <!-- 1 -->
        <version>2.17.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>    <!-- 2 -->
        <artifactId>log4j-jpl</artifactId>
        <version>2.17.0</version>
    </dependency>
</dependencies>


  1. Log4J implementation.
  2. Bridge from System.Logger to Log4J.

The same logging snippet as above now outputs the following:

Plain Text
 
11:00:07.373 [main] INFO  c.f.b.DefaultLogger - Hello world!


To use SLF4J instead, use the following dependencies:

XML
 
<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>               <!-- 1 -->
        <version>2.0.0-alpha5</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-jdk-platform-logging</artifactId> <!-- 2 -->
        <version>2.0.0-alpha5</version>
    </dependency>
</dependencies>


  1. Basic SLF4J implementation. Any other implementation will do, e.g. Logback.
  2. Bridge from System.Logger to Log4J.

The snippet outputs:

Plain Text
 
[main] INFO c.f.b.DefaultLogger - Hello world!


Your Own System.Logger Implementation

System.Logger relies on Java's ServiceLoader mechanism. Both log4j-jpl and slf4j-jdk-platform-logging contain a META-INF/services/java.lang.System$LoggerFinder file that points to a LoggerFinder implementation.

System Logger Implementation

We can create our own based on System.out for educational purposes.
The first step is to implement the logger itself.

Java
 
public class ConsoleLogger implements System.Logger {

    private final String name;

    public ConsoleLogger(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public boolean isLoggable(Level level) {
        return level.getSeverity() >= Level.INFO.getSeverity();
    }

    @Override
    public void log(Level level, ResourceBundle bundle, String msg, Throwable thrown) {
        if (isLoggable(level)) {
            System.out.println(msg);
            thrown.printStackTrace();
        }
    }

    @Override
    public void log(Level level, ResourceBundle bundle, String format, Object... params) {
        if (isLoggable(level)) {
            System.out.println(MessageFormat.format(format, params));
        }
    }
}


Then, we need to code the System.LoggerFinder:

Java
 
public class ConsoleLoggerFinder extends System.LoggerFinder {

    private static final Map<String, ConsoleLogger> LOGGERS = new HashMap<>(); // 1

    @Override
    public System.Logger getLogger(String name, Module module) {
        return LOGGERS.computeIfAbsent(name, ConsoleLogger::new);              // 2
    }
}


Keep a map of all existing loggers:

  1. Create a logger if it doesn't already exist and store it.

Finally, we create a service file:

Properties files
 
ch.frankel.blog.ConsoleLoggerFinder


And now, running the same code snippet outputs:

Plain Text
 
Hello world!


Conclusion

While the API is more limited than other more established logging APIs, System.Logger is a great idea. It offers a façade that's part of the JDK. Thus, it avoids using a third-party façade that needs to wire calls to another unrelated implementation, e.g. SLF4J to Log4J2.

For this reason, I think I'll be trying System.Logger if only to get some hands-on experience.

The complete source code for this post can be found in Maven format there.

Log4j Plain text Implementation

Published at DZone with permission of Nicolas Fränkel. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How to Check if a Java Project Depends on A Vulnerable Version of Log4j
  • How to Secure Apache Ignite From Scratch
  • Adding Graph Retrieval to a RAG Pipeline With Python
  • Debugging and Performance Tuning in Pega Using PAL, Tracer, and Clipboard

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook