Hacker News new | ask | show | jobs
by puppetmaster3 3700 days ago
The logging in java is supper idiotic. This is because everyone agrees that Java's logging is shit.

So every library uses something else. I have a small project and have 4 logging systems (that I had to integrate).

ps: if you are a business person and have an option on this, I don't care for it regardless of your pov.

5 comments

Yes, this is exactly right. What a fucking nightmare. Every time I need to set up java logging for a new project, update a project, revisit an old project, I am dragged back to logging configuration hell.

Which logging package do I use? What is the logging config file called and where do I put it? How do I specify it? What do I do if different packages use different packages? A logging layer on TOP of other logging packages only makes things worse.

I'm sure many Java people remember the XML library hell. Each time you integrated another package that relied on XML configuration, you had to be sure to have the right version of the xerces library. Except that XML was simpler because XML itself didn't change that much. Logging is much worse.

To go on an even longer rant: Everything has become so fractured and distributed in the name of good modularity. Except that the interfaces are underspecified, or if adequately specified, they keep wiggling around. And good luck finding documentation to help you configure. It's got to match your version of every component, or you will likely fail. I am working on a project involving jetty, a Postgres database, a JDBC connection pool, and a logging system. Absolutely conventional stuff. I spent a couple of DAYS trying to do things the right way, doing XML config of everything. I absolutely could not make it work. I finally wrote my own trivial connection pool and configured everything in code. Took half an hour, done. I don't care that I can't swap out my logging system at runtime. That's a stupid thing to do anyway. When I need to change my connection pool, I will modify my code configuring it and re-deploy. The slightly improved flexibility is just not worth the fragility and maintenance headaches of doing things the "right" way.

It's even more fun when your project uses native libraries, with their own logging, that you can't seem to override at all. (Looking at Mesos, right now.)
Yeah, it's the exact situation described in that XKCD: "There are 14 competing standards! Let's create one that is perfect for everyone's use-case!" "There are 15 competing standards..."

https://xkcd.com/927/

And, as you noticed, pretty much every Java project will reach a point where it has to deal with all four-ish of the major logging frameworks. Some module, somewhere, will include an Apache dependency and then you get JCL, and some other purist will insist on java.util.logging and away you go.

With that said, it really isn't that bad to fix. You can use the SLF4J bridge modules and dump all 4 of the logging systems to a single output system. This doesn't actually have to be via SLF4J either - there are modules to dump SLF4J out to JCL or JUL or whatever.

http://www.slf4j.org/legacy.html

This is one of those things about Java that's annoying as hell to get set up, but you plug through it for an hour and then you never need to touch it again. And the next time you can crib from your working build and 99% of it will be the same.

I like to imagine that particular XKCD was written with Java logging in mind.
I doubt that you have used the SLF4J bridge in any realsitic situation, else you would not say that it works.
I have and it works fine.
I don't believe you.

Even the docs say it does not work w/ multiple loggers. But I'm not here to teach, good luck.

You're quite simply wrong - the docs do not say that anywhere.

What they do say is that you are not allowed to route loggers circularly - if you route (for example) JUL through SLF4J, you are not allowed to route that output back to JUL, otherwise messages would never be dumped to output.

That's why I said that you have not used it in anger in production environments. Anyway, good luck.
Yup. This is the best that I've found:

(Gradle dependencies format)

compile group: 'ch.qos.logback:logback-classic:1.1.3'

compile group: 'org.slf4j:jcl-over-slf4j:1.7.12'

compile group: 'org.slf4j:jul-to-slf4j:1.7.12'

compile group: 'org.slf4j:log4j-over-slf4j:1.7.12'

At least you only need to configure one logging subsystem then.

slf4j API should be in the compile group. At minimum, logback-classic should be runtime, as should jul-to-slf4j.
Good points. This config is from an app - not a library.
I do not think Java is the only outlier here. In general library authors should never force a logger to write to anything. It should be a do-nothing logger. It should provide a configuration so logs are going through the application utilizing the library. If I am wrong interpreting your comment, let me know.

[1]: http://docs.python-guide.org/en/latest/writing/logging/#logg...

So how does state-of-the-art logging work these days?
Well if you really want to talk to "state-of-the-art" the closest would be the principle of "12-factor application." So basically everything goes through stdout and stderr, and the dameon running the server (like monit or supervisord) just captures them and redirect to a stdout file and a stderr file.

Not hard, just so many people including myself is used to writing logger....

If your libs use multiple loggers, then you are SOL.