Layout for Logback, which converts log events to JSON objects using GSON
Note: directory tests does not contain any unit tests :) .
This library contains layout for Logback, see more about layouts; this layout converts every log event to JSON object like this one (but in one line - if without some configuration):
{
"sequenceNumber": "8000000000000003",
"timestamp": 1670263878164,
"thread": "main",
"level": "ERROR",
"logger": "me.ore.logback.gson.layout.test.Main",
"message": "We have problem",
"error": "java.lang.RuntimeException: Wrapping error\r\n\tat me.ore.logback.gson.layout.test.Main.lambda$main$0(Main.java:36)\r\n\tat me.ore.logback.gson.layout.LogbackGsonLayout.useExtraParamsMap(LogbackGsonLayout.java:62)\r\n\tat me.ore.logback.gson.layout.test.Main.main(Main.java:17)\r\nCaused by: java.lang.IllegalStateException: This is invalid state\r\n\tat me.ore.logback.gson.layout.test.Main.lambda$main$0(Main.java:34)\r\n\tat me.ore.logback.gson.layout.LogbackGsonLayout.useExtraParamsMap(LogbackGsonLayout.java:62)\r\n\tat me.ore.logback.gson.layout.test.Main.main(Main.java:17)\r\n\t\u003c2 common frame(s) omitted\u003e",
"processId": "8374656874",
"processKey": "Module:generating-report",
"userId": "3af2fbd7-ab40-4803-aaa1-1330467184dd",
"nested": {
"date": "2022-12-06T00:11:18.152+06:00",
"number": 123.6,
"boolean": true,
"string": "My text"
}
}
JSON object above generated by code in class me.ore.logback.gson.layout.test.Main.
There are some configurations, see below.
Download as maven dependency:
<dependency>
<groupId>me.o-r-e</groupId>
<artifactId>logback-gson-layout</artifactId>
<version>0.0.3</version>
</dependency>
Binaries and other examples can be found at https://search.maven.org/artifact/me.o-r-e/logback-gson-layout/0.0.3/jar.
In appender configuration (typically - for file appender) use encoder of class
ch.qos.logback.core.encoder.LayoutWrappingEncoder
and layout of class
me.ore.logback.gson.layout.LogbackGsonLayout
.
Minimal configuration for console appender looks like this:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="me.ore.logback.gson.layout.LogbackGsonLayout"/>
</encoder>
</appender>
There are some configuration parameters can be applied inside
<layout class="me.ore.logback.gson.layout.LogbackGsonLayout"></layout>
,
for example:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="me.ore.logback.gson.layout.LogbackGsonLayout">
<logLineSeparator>"
"</logLineSeparator>
<stackTraceLineSeparator>"
"</stackTraceLineSeparator>
<propertySequenceNumber>sequenceNumber</propertySequenceNumber>
<propertyTimestamp>timestamp</propertyTimestamp>
<propertyThread>thread</propertyThread>
<propertyLevel>level</propertyLevel>
<propertyLogger>logger</propertyLogger>
<propertyMessage>message</propertyMessage>
<propertyError>error</propertyError>
<defaultMessage>[NO-MSG]</defaultMessage>
<gsonBuilderConfigurer>me.ore.logback.gson.layout.test.Config</gsonBuilderConfigurer>
</layout>
</encoder>
</appender>
Configuration parameters:
Name | Default value | Description |
---|---|---|
logLineSeparator | Default system line separator, result of java.lang.System.lineSeparator() | This line separator used to separate event records from each other. |
stackTraceLineSeparator |
"\r\n"
|
This line separator which separates lines of error stack trace. |
propertySequenceNumber | "sequenceNumber" |
Set one or more of these properties to rename JSON fields |
propertyTimestamp | "timestamp" |
|
propertyThread | "thread" |
|
propertyLevel | "level" |
|
propertyLogger | "logger" |
|
propertyMessage | "message" |
|
propertyError | "error" |
|
defaultMessage | "" |
This text will replace blank log event message. "Blank" - empty message or message with space characters only. |
gsonBuilderConfigurer |
Class which implements
me.ore.logback.gson.layout.LogbackGsonBuilderConfigurer
.
In this class you can configure instance of class com.google.gson.GsonBuilder . This instance of com.google.gson.GsonBuilder used to create instance of class
com.google.gson.Gson
.
Created instance of com.google.gson.Gson used to convert log event to JSON object.
In implementation of me.ore.logback.gson.layout.LogbackGsonBuilderConfigurer
you can set pretty printing, add type adapters, and so on.
Example can be found
here
.
|
You can add extra fields in event JSON object;
for example - fields processId
, processKey
, userId
and nested
in example in section "What this library does" above have been added in that way.
Simplest way - use one of LogbackGsonLayout.useExtraParamsMap
methods:
class MyClass {
public void myLogging() {
LogbackGsonLayout.useExtraParamsMap(map -> {
map.put("userId", "3af2fbd7-ab40-4803-aaa1-1330467184dd");
map.put("processKey", "Module:generating-report");
map.put("processId", "8374656874");
LOGGER.info("Info message");
});
}
}
Another way - work directly with holder of such extra parameters map:
class MyClass {
public void myLogging() {
try {
HashMap<String, Object> map = new HashMap<>();
LogbackGsonLayout.setExtraParams(map);
// OR
LogbackGsonLayout.EXTRA_PARAMS_HOLDER.set(map);
map.put("userId", "3af2fbd7-ab40-4803-aaa1-1330467184dd");
LOGGER.info("Info message");
} finally {
LogbackGsonLayout.removeExtraParams();
// OR
LogbackGsonLayout.EXTRA_PARAMS_HOLDER.remove();
}
}
}
Note:
- if name (key) of extra parameter overlaps with "main" JSON fields, such parameter will be silently skipped; "main" JSON fields described in table "Configuration parameters" in section "Logback configuration" above;
- if extra parameter value will not be
null
,java.lang.String
, 'java.lang.Number' orjava.lang.Boolean
, then JSON serializer (com.google.gson.Gson
) will use type adapters and/or java reflection, which can slow down logs' generation.
Block finally
is mostly optional - because
after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist)
(found at https://docs.oracle.com/javase/8/docs/api/java/lang/ThreadLocal.html)