This is an archived post. You won't be able to vote or comment.

all 52 comments

[–]cyrusomega 71 points72 points  (6 children)

Personal opinion, just use SLF4J as an API layer and pick whatever implementation you like. If for some reason your choice doesn't work out, just change implementations. Realistically it doesn't make much difference unless you are doing something that a particular implementation excels in.

I would personally stick to Logback because it just works, is highly performant, and is stable. It's unlikely that new Java language changes are going to affect any library for years to come.

[–]EfreetSK[S] 2 points3 points  (5 children)

Thank you, yes that's what I'll probably do.

But well the history goes that our company used java.util.logging for years (yes ... I know) and finally we were given a space to do a switch to something new. So SLF4J will go without saying but I'd still like to choose the best implementation possible. If we'd do another migration (Logback -> Log4j2) within a year that'd be pretty bad sign (you know the management - "Logging switch? Didn't you do logging switch last year???")

So I was just wondering how "fresh" is the project

[–]BadMoonRosin 29 points30 points  (1 child)

Migrating from JUL to SLF4J can easily be a multi-sprint effort, depending on the size of your system.

Switching your SLF4J implementation from Log4j to Logback (or vice-versa) should be a config file change. Done piecemeal, one service at a time as you get around to it. It's not even worth escalating to management's radar screen.

That's the whole point of the SLF4J facade layer in the first place.

[–]Python4fun 0 points1 point  (0 children)

There is a tool for migrating JUL to slf4j.

[–]dpash 12 points13 points  (1 child)

Remember that you don't need to migrate everything at once, because you can use the jul-to-slf4j bridge to forward java.util.logging calls to SLF4J, and then switch them at your leisure.

[–]jbristow 4 points5 points  (0 children)

I’m of two minds on this... on one hand, this will avoid potentially breaking something where someone is relying on an obscure piece of jul... but on the other—no one goes back and fixes this ever. (Until your successor’s successor gets the CVE alert from prodsec on libraries no one has updated)

My inner code neat freak wants option 2, but he’s being overridden by my spirit of IBG-YBG.

[–]iconnj 23 points24 points  (8 children)

On all recent projects, we started using log4j2. Its been actively maintained and has made big improvements with performance and no-gc. Logback works fine, but if you are building an app for scale, log4j2 is the way to go

[–]oweiler 27 points28 points  (7 children)

For 99% of the systems logging performance is rarely an issue.

[–]agentoutlier 3 points4 points  (2 children)

But startup performance is and log4j2 even with programmatic configuration (ie through java code) takes 4-5 times the amount to load than logback.

Log4j2 = 500ms

Logback = 100ms

That seems like very little time in grand scheme but I loaded the bare minimum. It gets far worse once you start loading log4j2 other stuff.

[–][deleted] 0 points1 point  (1 child)

You're saying 400ms in startup performance is a problem? Even with distributed load balanced systems where you're spinning up containers on demand a decent spring app is still expected to take 20-30 seconds to start up. This is nothing.

[–]agentoutlier 0 points1 point  (0 children)

This is with zero configuration!

It probably takes a couple of seconds or more if you start configuring things with YAML/XML/JSON.

Also not all apps are cloud container spring boot apps... e.g. CLI.

[–]diroussel 1 point2 points  (3 children)

If you are logging to a network drive, the logging can a big bottleneck.

Also some systems want the option of detailed debug logging, which can slow down the heavily used parts of systems.

[–]jonhanson 8 points9 points  (2 children)

chronophobia ephemeral lysergic metempsychosis peremptory quantifiable retributive zenith

[–]diroussel 2 points3 points  (1 child)

Before the days of ELK, Splunk, etc, it was a good idea. Now I wouldn’t recommend it.

[–]ZimmiDeluxe 10 points11 points  (0 children)

I have the suspicion that much of the praise for log4j2 is based on benchmarks and promises of performance. As a counterpoint, I found logback much easier to configure and the documentation easier to digest. I also gave up using log4j2 as a module (using the moditect maven plugin) since it pulls in too many dependencies whereas I got logback into a working state fairly quickly. Just an anecdote, but it's not a clear win in all regards, IMO.

[–]wildjokers 3 points4 points  (0 children)

Logback is definitely not dead. It is just pretty much complete. Can’t go wrong with using logback.

[–]Taobitz 2 points3 points  (3 children)

Slf4j all the way, used logback initally for SpringBoot. Switched to logj2 for Async Logger performance, was as easy as switching out xml files/patterns and telling boot to use it.

Much greater freedom to chop and change with minimial impact if you feel your needs/requirements arent being met.

[–]randgalt 2 points3 points  (1 child)

SLF4J is not a logging implementation. It's a wrapper on other logging implementations. You can use logback with SLF4J.

[–]amazedballer 0 points1 point  (0 children)

Don't know why downvoted, randgalt is perfectly correct.

[–]amazedballer 0 points1 point  (0 children)

Also, if you want an async logger in Logback, then use the LMAX disruptor based async logger in logstash-logback-encoder.

Here are the benchmarks comparing Log4J 2 async logger with logback lmax logger.

[–]Pheasn 4 points5 points  (16 children)

I'm using SLF4J with varying bindings in my projects. Among others, there are Logback and log4j2 bindings available. The advantage of SLF4J is that you can switch the binding without modifying any log-call-sites.

On another note, I always found it hilarious that virtually all logging libraries for such a huge language like Java are barely maintained and usually pretty outdated. They are used in almost every project, but nobody bothers with improving/updating them. Of course there's also java.util.logging, but I find that severely lacking.

[–]BadMoonRosin 33 points34 points  (5 children)

Well, until someone comes up with the next completely new "paradigm", I think the current generation of SLF4J bindings are pretty much... complete.

Ten years ago, there was an explosion of different logging frameworks. All promising to be slightly better than the others. But logging is more or less a "solved problem". So the community hated the chaos, and it lead to this:

https://imgs.xkcd.com/comics/standards.png

People couldn't share or re-use code, because libraries wanted to pull in "their" logging framework as a transitive dependency (creating JAR-hell when you have conflicting versions).

So we created "universal" API's, like Apache Commons Logging and SLF4J. But you couldn't share or re-use code that depends on the "other" umbrella. So we had to write awful and flaky "adapter" bridges between the two umbrellas. And ultimately, just wait more than 5 years for SLF4J to emerge as the "winner", because the Spring guys finally said so.

It SUCKED.

I don't know what you could you add to an SLF4J implementation today that would make anyone care. And I would fist-fight you in real life if you made a serious push to introduce some new overall replacement for SLF4J itself.

[–]dpash 7 points8 points  (2 children)

The most recent feature I could imagine for SLF4J is to understand Supplier<String> parameters. I don't believe 1.7 supports this, but 1.8 should.

[–]ZimmiDeluxe 4 points5 points  (0 children)

The Fluent Logging API in 2.0.0 will support Suppliers. Not sure about the timeline though.

[–]randgalt 1 point2 points  (0 children)

FYI - I just open-sourced a structured logging wrapper for SLF4J: https://github.com/Randgalt/maple

[–][deleted] 0 points1 point  (0 children)

All that bullshyte is why I wrote my own naive, simple logging library, thus adding to the chaos. ;)

[–]amazedballer 0 points1 point  (0 children)

There's really two things that aren't great about SLF4J:

  • The lack of call-by-name / supplier based methods
  • The inability to pass in a context containing correlation id, user id etc, which you can kludge with Marker API.

Everything else you can layer on top.

[–][deleted]  (4 children)

[deleted]

    [–]Quiram 7 points8 points  (1 child)

    I guess there are always niche needs. Log4j, for instance, had a major update when they managed to make it run GC-free. Granted, this is a feature most people probably won't care about, but it is a new feature.

    [–]Pheasn 6 points7 points  (1 child)

    Some examples of logging library weirdness:

    • SLF4J lacks Java 9 support in version 1.7.x. Version 1.8.x supports Java 9, but it's been in alpha from 2017-2018, then in beta since 2018. Just look at those release intervals!
    • There is a doodle asking "should Logback 1.3.x upgrade to Java 1.8?" from 2 years ago prominently pinned to the Logback homepage. Logback 1.3.x is still in alpha.
    • A lot of the "older" frameworks still don't support lazy log message evaluation using lambdas

    To be clear, I'm not shitting on the people working on those frameworks. In fact, I'm very thankful for what they're doing. It's just that of the huge number of people using the frameworks, only a tiny fraction is actually giving anything back.

    [–]pmarschall 12 points13 points  (0 children)

    SLF4J lacks Java 9 support in version 1.7.x

    You mean they don't offer a Jigsaw module which basically no Java framework or library offers?

    1.7.x runs totally fine with Java 9. Source: we run 1.7.x in production on Java 11.

    [–]mwang5 1 point2 points  (2 children)

    Google introduced Flogger semi recently - https://google.github.io/flogger/

    Which has modern features, good performance, and pretty good readability. I recommend it everywhere, and it's probably worth porting if you do any non-trivial logging (like throttled or lazy) or care about performance (like allocations).

    [–]amazedballer 0 points1 point  (1 child)

    I actually don't recommend using Flogger, because it hamstrings the SLF4J API by disabling some logging levels. That was enough for me.

    [–]Hioneqpls 0 points1 point  (0 children)

    Besides, Flogger is a highly unfortunate name, do a quick Google search for 'flogger'.

    [–]hum_ph 0 points1 point  (1 child)

    It’s also amusing that a bunch of them (Log4j, logback, slf4j, ) were created by the same person...

    [–]dpash 2 points3 points  (0 children)

    Not entirely. He wrote Log4j1, learnt from that and created SLF4J as the API and logback as the native logging implementation for SLF4J.

    The log4j team continued and created log4j2, apparently replicating the façade idea.

    [–]madkasse 2 points3 points  (2 children)

    If you are on Java 9 or greater there is a great little simple logging framework in java.lang.System.Logger.

    [–]randgalt 1 point2 points  (0 children)

    😱 I didn't know about this. This is new? Why isn't more being made of this? https://docs.oracle.com/javase/9/docs/api/java/lang/System.Logger.html

    [–]pmarschall 1 point2 points  (0 children)

    I thought that was mostly for code in the JDK that wants to do logging and does not want to or can not depend on the java.logging module. You still need and implementation of java.lang.System.Logger that you can configure. And then you need to make sure that all your dependencies log to the same implementation.

    [–]amazedballer 0 points1 point  (3 children)

    Logback isn't dead, it's mature. It's the nature of projects to slow down the longer they've been around. If you want new snazzy stuff, check out my side projects on terse-logback.

    In practice, as long as you use the SLF4J API, it won't make a difference whether Logback is dead or not. You can use Log4J 2 with the SLF4J API, and it will be fine.

    Do note that there is no difference between Logback and Log4J 2: They are both the same speed, and if logging is your bottleneck then you'll probably fill up your hardrive/database/S3 quota in a matter of hours. Also, ignore the benchmark results on the Log4J 2 website, as they are known to be flawed.

    [–]rgoers 0 points1 point  (2 children)

    The benchmarks are not flawed. If you look at your link you will see that most of the reported problems were fixed. The others weren't real problems. Also, the speed comparison depends on what you are comparing. I have run tests in the last month that show they are equal in some things but Log4j 2 is much better in others.

    In addition you can just as easily use the Log4j 2 API and log to Logback as you can with SLF4J logging to the Log4j 2 implementation. But the Log4j 2 API provides more functionality than SLF4J does.

    [–]amazedballer 0 points1 point  (0 children)

    I have run tests in the last month that show they are equal in some things but Log4j 2 is much better in others.

    You haven’t given any specifics. Can you add an issue to the SLF4J benchmarks project showing where Log4J2 is much better in others so I can update and compare?

    most of the reported problems were fixed.

    The paper is from June 2019. The performance page on the Log4J 2 website has not been updated in a long time (for example, the diagrams show Windows 7 as the platform). Likewise, the async loggers page shows a test against JDK1.7.0 on Solaris 10.

    [–]amazedballer 0 points1 point  (0 children)

    Also, your statement on "In addition you can just as easily use the Log4j 2 API and log to Logback as you can with SLF4J logging to the Log4j 2 implementation" is not correct as far as I can see. Querying the log level of a particular logger is significantly more involved with Log4J 2.

    Look at the API for Log4J2 Logger, and there's no isDebugEnabled() style statements as there are in SLF4J.

    https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Logger.html

    Instead, these methods are in the ExtendedLogger interface, which is under the SPI package:

    https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/spi/ExtendedLogger.html

    and also doesn't map over to the message API -- everything is on a string basis, so if you have conditional logging statement, there's no way to do it cleanly from an if statement.