Tjahzi is a set of Java tools and appenders for sending logs to Grafana Loki.
Latest releases:
If you find the project useful (or not useful for some reason) please let me know to encourage further development. ⭐ Stars are also welcome ⭐ ;).
Tjahzi allows pushing log data to Loki. It uses a protobuf format to
push log lines with timestamps and labels. On top of that we
built appenders for log4j2, Logback, and log4j1.x/reload4j.
These feature:
- Logging does not allocate objects nor take any locks.
- Sending data to Loki in batches allocates as little as possible.
- We also provide a no-dependency version of these appenders.
- Includes in-house implementation of protobuf wire format for Loki to reduce dependencies and improve performance.
These points apply to log4j2 appender. Logback and log4j1.x
designs do not allow allocation-free operation, but we go to great
lengths to reduce allocations and even provide an optimized version of
the pattern layout for Logback.
For log4j2 appender quick start guide and detailed discussions see
this README.md.
For Logback appender quick start guide and detailed discussions see
this README.md.
For appender quick start guide and detailed discussions see this README.md.
The
log4j1.xwas discontinued by the Apache Foundation and is no longer updated. The Reload4j project is a drop in replacement forlog4j1.xwhich fixes "the most pressing security issues".The
log4j.jaris interchangeable withreload4j.jarand you can freely usereload4jappender even if you use oldlog4j1.x.
Logging should be lightweight and not interfere with the main business tasks of threads that happen to log a message. Asking the logging subsystem to log a message should be as CPU efficient as possible. That's a truism. Apart from computation itself, there are many other causes of jitter (varying speed of code execution). Thread can be slowed down by excessive allocations, by initialization code running in constructors of unnecessarily allocated objects, by garbage collector activity that is triggered by it. There can be configuration refresh checks on logging path, inter-thread signaling, etc.
To avoid these effects, we strive to adhere to the following principles (and document any violations):
- Lock free and wait free API
- Allocation free in a steady state
You can compare this with design principles of Aeron which are close to our hearts.
[via 10kB thread local buffer]
│
┌─────────────┐ Log ←──┘
│ Application │----------------┐
│ Thread 1 │ │
└─────────────┘ │
│
. ▼
┌────────────────────┐ ┌─────────┐ ┌─────────┐
. Log │ │ │ Log │ │ I/O │
----------------▶│ Log buffer ├--→---→--┤ shipper ├--→---→--┤ thread │
. │ │ │ agent │ │ (Netty) │
└────────────────────┘ └─────────┘ └─────────┘
. ▲
│
┌─────────────┐ Log │
│ Application │----------------------┘
│ Thread N │
└─────────────┘
For those interested, the wiki contains some information on log buffer sizing.
Check out this wiki article.
This work is released under MIT license. Feel free to use, copy and modify this work as long as you credit original authors. Pull and feature requests are welcome.
The log4j2-appender, logback-appender and reload4j-appender artifacts
ship GraalVM reachability metadata and work in native images out of the box:
- Reflection configuration for the appender and its nested configuration elements is embedded in each jar (for log4j2 it is generated by the log4j plugin annotation processor).
- All Tjahzi classes are marked for run time initialization. The off heap log buffer and the log shipper thread are created when the logging system starts, so the logging framework must not be initialized at image build time.
- Remember to include your logging configuration file as a resource in the
image (e.g.
logback.xmlvia aresource-config.json).
The shaded *-nodep artifacts are not supported in native images - class
relocation invalidates the bundled Netty reachability metadata. Use the
regular artifacts instead.
Native image support is exercised in CI: a smoke test application is
compiled with native-image and verified end to end against a real Loki
instance (see the native-image-test module, built with -Pnative).