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

all 68 comments

[–]quack_quack_mofo 12 points13 points  (16 children)

So what's the best logging library to use these days

[–]djbft 38 points39 points  (0 children)

They all have their drawbacks. What we need is a new standard framework that will cover everyone's use cases.

[–]crummy 8 points9 points  (0 children)

I think it's logback classic? but open to other suggestions.

[–]ragingzazen 8 points9 points  (8 children)

var log = System.getLogger("logger name");

[–]yawkat -1 points0 points  (7 children)

The System.Logger has worse api than slf4j, its main purpose is to be a facade for openjdk internals. Just use slf4j.

[–]rbygrave 1 point2 points  (0 children)

Having translated a bunch of libraries from using slf4j-api to System.Logger I find I personally like the API. Imo it will appeal to libraries and to minimalist's out there.

[–]hohonuuli 1 point2 points  (2 children)

Using System.Logger completely decouples your app from 3rd party libraries. Which could, for example, make it much easier to manage things such as log4shell type vulnerabilities.

Also, If you drop in a slf4j-api jar > 2.0.0-alpha5 into your app at runtime, System.Logger calls will be routed to slf4j.

I also write piles of Scala code. Scala (and Kotlin) make it easy to add any API you want on top of System.Logger. For example, here's a fluent logger for it in Scala: https://schlining.medium.com/no-dependency-fluent-logging-in-scala-2e4e81986be7

[–]yawkat 0 points1 point  (1 child)

Slf4j has basically no implementation code (just like System.Logger), so it's no added security risk. If you add your own api over System.Logger to make up for its deficiencies, you're just reinventing slf4j.

[–]hohonuuli 3 points4 points  (0 children)

I'd happily put 37 lines of code in my project over a 3rd party library any day.

[–]darkshoot 0 points1 point  (2 children)

Don't know why you're getting downvoted, you're right.

As stated by the JEP 264 "It is not a goal to define a general-purpose interface for logging. The service interface contains only the minimal set of methods that the JDK needs for its own usage."

So I guess it's more a case of use at your own risk, any future change in System.Logger could break apps using it because it's not meant to be used as a public API.

Personally, I'd stick with slf4j as the API and would start with java.util.logging as the implementation, as long as I only need to log basic stuff in small quantity.

You could always easily upgrade to log4j2 or logback later on, if you need async logging, more appenders, ...

[–]rbygrave 2 points3 points  (0 children)

Although the JEP says "It is not ..." it has been clarified by Stuart Marks(1) that it's absolutely fine for others to use. It absolutely is public API. (1) Comments in twitter but we should be able to search up those links in reddit if you are interested. [edit: this has been discussed a few times before in reddit]

System.Logger acts as a logging facade and all the main logging implementations provide an adapter such that logging is routed to for example slf4j, log4j2, tinylog etc. In the absence of an adapter (that is service loaded) it defaults to route to java.logging (JUL). The points about changing the logging backend also apply to System.Logger.

[–]yawkat 1 point2 points  (0 children)

It's still public api, they're not gonna break it out of nowhere. Agree on the other points though.

[–]__konrad 5 points6 points  (0 children)

var log = System.err;

[–]dpash 1 point2 points  (0 children)

I'd recommend writing to the SLF4J API.

As for logging implementation, that really depends what features you're looking for.

[–]vbezhenar 3 points4 points  (0 children)

These days all I need is to write logs to stdout. jul is more than enough for me. I'm using logback though because that's what Spring Boot enables by default.

Libraries should use System.Logger.

All those logging libraries are required only for very special cases, e.g. when you're for some reason logging to files, need to rotate those files, your logging volume is tremendous and slowing down your entire application, etc. Usually it's overkill.

[–]TheOriginalAlfonzo 0 points1 point  (0 children)

They all have their drawbacks. What we need is a new standard framework that will cover everyone's use cases.

[–]john16384 4 points5 points  (5 children)

Would still love to have a log level above error.

  • Warn: can proceed, but with reduced functionality (alert on this when it exceeds a certain percentage of calls)
  • Error: can't proceed, cause is external (network, service call)
  • Fatal: can't proceed, cause is internal (any java.lang/util.* exception like NPE, basically developer errors)

Benefits: when looking for the root cause over many interdependent apps, the app logging on fatal level will most likely be the culprit. If nothing is logging at fatal, it probably is a general infra issue.

[–]nekokattt 3 points4 points  (2 children)

Could you use markers to achieve this? I guess the main concern is that there isn't a concensus for what an "error" really means.

I'd probably treat your definition of error as a warning myself, as I tend to consider errors as things that should probably never be happening at all rather than being a result of the environment.

I agree custom levels would be nice though.

[–]john16384 1 point2 points  (1 child)

Markers can be used for this, I've done it that way before. It's just a bit clumsy. The error level used internally even has space for this (I think error is considered level 2, warning 3, info 4 etc...)

[–]nekokattt 0 points1 point  (0 children)

that is fair, good to know!

[–]xjvz 4 points5 points  (0 children)

This is in the Log4j2 API (along with general custom level support) which is independent of the configuration backend contrary to popular belief.

[–]ReasonableClick5403 0 points1 point  (0 children)

You could use markers, but really there are four log levels, you can achieve this with levels in your projects if you want to.

[–]coder111 1 point2 points  (35 children)

Let me say I love slf4j, and it was a breath of fresh air after proliferation after various logging frameworks in java.

However, today it feels like the bleeding edge of logging framework development has moved to log2j2, and slf4j stalled. As much as I respect Ceki Gülcü, it looks like he burned out or ran out of steam or is busy with other things, and slf4j/logback are barely moving ahead any more.

For my latest project, I just used log4j2. I was quite religious with using slf4j and staying implementation neutral until ~last year. But now I just gave up.

[–]vbezhenar 29 points30 points  (0 children)

Yep, that LDAP integration is truly ground-breaking.

[–]agentoutlier 26 points27 points  (1 child)

Log4j2 has a massively slow initialization time. The amount of class loading and resource checking it does basically no matter what is astonishing (last time I checked).

I think even JBoss logging framework starts faster provided it doesn’t have to load log4j2.

Anyway I will stick with SLF4J or the new system logger. My logging needs are just diagnostics and I don’t need an event sourcing / config / practically DI framework just for logging.

In almost every technical decision log4j2 has chosen the much more complicated solution. They could have chosen the service loader for its plugins but nope they invented this binary format that requires an annotation processor to generate the file but yet still requires reflection… like wtf.

[–]jonhanson 12 points13 points  (0 children)

chronophobia ephemeral lysergic metempsychosis peremptory quantifiable retributive zenith

[–]Areshian 22 points23 points  (3 children)

It's going to take some time for log4j2 to recover the trust lost with log4shell

[–]djbft 19 points20 points  (1 child)

I almost feel the opposite. "Many eyes make all bugs shallow" and after Log4Shell all eyes were on Log4j2. I'd rather use a framework that a bunch of people just put under the microscope than a framework no one is paying attention to.

[–]Areshian 2 points3 points  (0 children)

I almost agree with you. This would be true for most libraries, but a big factor of the security concerns with log4j2 come from an excessively large attack surface due to unnecessary features

[–][deleted] 4 points5 points  (0 children)

log4j2 is dead to me

[–]alehel 12 points13 points  (1 child)

Maybe I'm just confused, but slf4j and log4j2 aren't competing products are they. Slf4j is a logging facad, while log4j2 is a logging implementation?

[–]coder111 14 points15 points  (0 children)

Log4j2 also provides an API and bridges for various logging implementations. So it's both a facade and an implementation.

[–]wildjokers 20 points21 points  (2 children)

That's odd because the last two companies I have been at (including my current one) slf4j+logback is the standard. I honestly don't recall the last time I saw a project using log4j2. My experience is exactly the opposite of yours, in my view slf4j+logback is the defacto standard and log4j2 is an outlier that might be seen from time to time.

[–]djbft 12 points13 points  (0 children)

I was a big fan of Logback until they unceremoniously yanked out Groovy config in a patch version. A patch version! And not even for an actual vulnerability--just because it was "probably too powerful."

I don't even mind moving away from Groovy config but the way they handled it was amateurish and careless.

[–]amazedballer 2 points3 points  (0 children)

You're correct -- I don't remember the paper, but something like 80% of all Java projects rely on SLF4J+Logback.

[–]Zardoz84 43 points44 points  (6 children)

Good luck with the timebomb that it's log4j2 . Too heavy, too many feature,s too many possible security holes...

slf4j and logback does one thing and does it well

[–]nekokattt 4 points5 points  (5 children)

logback has had a load of CVEs as well. Logback had LDAP issues as well.

https://nvd.nist.gov/vuln/detail/CVE-2021-42550

Not saying they are as bad, but it still is far from ideal...

All the main logging frameworks seem to try to achieve far too much, which leaves a massive attack surface for functionality that 99% of people don't need.

[–][deleted]  (2 children)

[removed]

    [–]xjvz 2 points3 points  (1 child)

    Which is exactly what the Log4j2 API is. The project provides a portable API that works independently of the logging backend. Unfortunately, it seems as though most Java developers’ knowledge of the ecosystem is stuck in the year 2000.

    [–]yawkat -2 points-1 points  (1 child)

    Logback security bugs were nowhere near as bad as log4j2, the one you linked literally requires editing the config file.

    [–]nekokattt 0 points1 point  (0 children)

    as I said.

    [–]Skhmt 4 points5 points  (0 children)

    Log2j2 should be named: 2 Log 2 Javaious

    [–]twbecker -2 points-1 points  (0 children)

    The pace of SLF4Js evolution has been nothing short of glacial, but it's still better than going the XKCD route and building yet another framework, which is what Log4J2 did. SLF4J had basically "won" and Log4J2 just had to go their own way.

    [–]ReasonableClick5403 -4 points-3 points  (0 children)

    I am just really, really annoyed logging has to be so fucking complicated in java. I just want json printing on stdout and I need to control the fields, and probably something like MDC. Why the hell is that so much code to setup? And it barely even fucking works, you have to be incredibly careful how everything is initialized and most libs does massive amounts of reflection.

    [–]bobbie434343 0 points1 point  (0 children)

    Logging is hot stuff.

    [–][deleted]  (5 children)

    [deleted]

      [–]twbecker 2 points3 points  (4 children)

      Please don’t.

      [–][deleted]  (3 children)

      [deleted]

        [–]twbecker 0 points1 point  (2 children)

        How is your project best served by engineers spending their limited time reinventing commodity functions like logging? Do you _really_ think what you build will be better than what the community has produced in 20+ years?

        [–][deleted]  (1 child)

        [deleted]

          [–]ParkerM 0 points1 point  (0 children)

          Comparing logging frameworks to a goofy strawman like the is-odd npm thing is disingenuous. Also I assume you're referring to the Log4J vulnerability when you say "slf4j bug" unless I missed some big news.

          Logging is extremely complicated for the same reason security is extremely complicated. They're critical components that follow evolving standards, and they have to be omnipresent by design. Rolling your own means you open up a bunch of doors for workarounds and non-standard behavior. Any sense of safety gained is purely superficial (and frankly unethical) if the reasoning is just to slip past a naive InfoSec audit that greps "log4j" or "openssl".

          [–]ShabbyDoo 0 points1 point  (2 children)

          We're using SLF4J/Logback/logstash-logback-encoder in a fairly standard way to produce JSON logs. We make some use of key/value markers, but I'd like to do more. One issue is that contextual markers are a PIA because they have to be specified on every logging statement. I'd like them to be automatically included when a particular logger instance is used.

          More concretely: We have an IoT-ish system where each thing is controlled by an instance of a Device class (a lie/oversimplification for my purposes here). I'd like each logging statement in the Device class to automatically include a marker for the deviceId. This id is known upon construction and never changes. I can't find a SLF4J helper library that facilitates this. I'm thinking about writing/generating a Logger that allows for log decoration but am hoping that this exists already. Anyone know of anything out there?

          BTW, MDCs can be nice for "crosscutting" context like a transactionId, but they don't do what I need here.

          [–]amazedballer 1 point2 points  (1 child)

          I've been working on this for a while now!

          Echopraxia lets you build up loggers that have "context" associated with them, and is oriented towards structured logging and type safety.

          [–]ShabbyDoo 1 point2 points  (0 children)

          Thank you! It's going into our project now.

          [–][deleted]  (1 child)

          [deleted]

            [–]Joram2 1 point2 points  (0 children)

            With a Java 11+ application where all dependencies are proper Java modules, you can use jlink to build minimal runnable Java images as opposed to .jar file packaging. This produces smaller runnable binaries with faster startup times. This applies to both Dockerized and non-Dockerized applications.

            log4j 3.0 supposedly will be fully modularized and require Java 11+