TL;DR I demo a project that uses all the techniques set up previously to show a Logback environment that can be used without modification in different environments.
- Application Logging in Java: Creating a Logging Framework
- Application Logging in Java: Adding Configuration
- Application Logging in Java: Converters
- Application Logging in Java: Markers
- Application Logging in Java: Appenders
- Application Logging in Java: Logging Costs
- Application Logging in Java: Encoders
- Application Logging in Java: Tracing 3rd Party Code
- Application Logging in Java: Filters
- Application Logging in Java: Putting it all together
This blog post is going to discuss an example of a packaged library that you'd set up for your projects, available as the
logback-structured-config module in terse-logback. There's more detail in the project itself, but for this post I'm going to be discussing the whys more than the hows.
The one thing I'm adding here that I haven't devoted a post to specifically is logging in JSON – since logstash-logback-encoder was the inspiration for this series and I'm not doing anything fancy with it, I think it's covered in the README. Technically, since there are several JSON objects all in one file / stream, this is called "newline delimited JSON" or NDJSON or jsonlines. In this project, both text and JSON formats are rendered independently, but if you only output JSON it's not a huge deal, because you can read JSON logs as text with a special log viewer such as jl, json-log-viewer, or otros log viewer.
So. This project sets up multiple appenders, and then composes those appenders together in different ways. The appenders are broken out into different resource xml files and then included together: this means that downstream projects have the option of overriding those resources if they need to, by ensuring that their resource appears ahead of the library in classpath search order. Notably, the censors are broken out distinctly, since they can be very application specific.
Starting with the beginning of logback.xml:
The audio appenders are set up to use system beeps, rather than playing with the Java Sound API, as it's hard to justify including sound clips in a library, and developers will no doubt want to use their own. The audio appenders also use a budget evaluator to ensure that they don't beep incessently, and also have
EnabledFilter so they can be quickly disabled from configuration.
Past that point, the application will compose appenders together by the environment. For example, the development appender does everything – it writes to the console, plays sounds, writes to a log file, and will write detailed information in JSON. Meanwhile, the test environment will only write out to a log file.
There is a selector appender which will select the appropriate environment: only the appender matching the
logback.environment key will be used.
Typically, you'll set
logback.conf, or on the command line as a system property.
Finally, the selector is wrapped with a
UniqueIdEventAppender. This appender decorates
ILoggingEvent with a unique id, currently a 128 bit flake id using base-62 encoding, and this decorating appender is used as the one and only appender for root. At the very end, the logging levels are set from HOCON.
The bulk of the configuration is done through
logback-reference.conf, as described in part 2. A full description is on github, but the overview is that there's
levels section that allows the logback levels to be set:
And then there are
context properties that are exposed to logback as the appropriate scope. Almost everything goes into the
local scope. Again, this allows for downstream projects to override values by adding a
logback.conf to the application.
And that about does it! I'm glad to finally get this out, and this concludes the blog posts about Logback configuration. I'm not done yet, though. The next series of posts is going to be about logging APIs, about which there's a whole bunch more to say, and is going to have its own github project to address the issue of what you put into your logs and how.