Concept
Sinobu provides a minimalist, high-performance logging library designed with an emphasis on garbage-less operation and zero-boilerplate code. It is especially well-suited for high-throughput applications where every microsecond and memory allocation matters.
π No Boilerplate
Logging is as simple as calling a static method like I#info(Object)
. Therefore,
thereβs no need to create logger instances per class. This approach dramatically reduces
code clutter and eliminates repetitive logger setup.
void log() {
I.info("Hello Logging");
}
β»οΈ Garbage Less
Many logging libraries create temporary objects (log events, strings, byte arrays, etc.) each time they output logs, causing GC latency; Sinobu tackles this problem head on and does not create new objects unless you explicitly request stack trace.
β‘ High Performance
Sinobu is engineered for speed. Its optimized encoding, buffer reuse, and minimal synchronization mean it can outperform many mainstream logging libraries. Even under heavy logging loads, it maintains consistent performance with minimal CPU and memory impact. Check benchmark.
Usage
Logging is performed via static methods such as I#info(Object)
or
I#info(String, Object)
. These methods support various input types:
Object
- UseObject#toString()
representation as message.Supplier
- Delaying the construction of message avoids extra processing when the log level prevents writing.Throwable
- A message and a stack trace back to the cause are written.
void basic() {
I.trace("Write your message");
}
void lazyEvaluation() {
I.debug(() -> "Delaying the construction of message.");
}
void throwable() {
try {
mayBeThrowError();
} catch (Exception e) {
I.error("Write message and stack trace");
I.error(e);
}
}
Most methods come in two forms:
- Without category - logs to the default system category.
- With category - the first argument specifies the log category, allowing fine-grained control.
void categorized() {
I.debug("Write message in system category");
I.warn("database", "Write message in database category");
}
Configuration
Logging behavior can be configured via environment variables (I#env(String)
Configuration keys follow a specific pattern to allow both fine-grained and global
control.
Resolution Order
When any environment variable is required, configuration values are resolved in the following order:
- Look for
category.property
(e.g.system.file
) - If not found, look for
*.property
(e.g.*.file
) - If still not found, use the built-in default (e.g.
Level#WARNING
)
Log Appender
Log messages can be routed to different output destinations. While logs may go to the
console by default (depending on the underlying System#out
implementation),
Sinobu allows you to explicitly configure destinations. You can even configure
multiple destinations for the same logger category.
Property Key | Value Type | Description |
---|---|---|
category.console |
Level |
Enables console logging for the specified category. |
category.file |
Level |
Enables file logging for the specified category. |
category.extra |
Level |
Enables extra logging for the specified category.
You must define I#Logger as extra logger. |
File Logging Options
Options specific to file logging when category.file
is enabled.
Log files are typically named category<Date>.log
(e.g. database2024-10-27.log
).
Property Key | Value Type | Description |
---|---|---|
category.dir |
String |
Specifies the directory where log files for this category should be created. Default is .log |
category.append |
boolean |
If true , appends to existing log files for this category. If false , overwrites. Default is true . |
category.rotate |
int |
Number of past daily log files to keep for this category. Older files are deleted. 0 disables rotation. Default is 90. |
Formatting Options
Options related to the formatting of log messages for a specific category.
Property Key | Value Type | Description |
---|---|---|
category.caller |
Level |
Includes caller info for messages in this category at or above the given level. Can impact performance. |