-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for Custom Value Serializer in Log4jEventBuilder#addKeyValue() and Asynchronous Serialization #2996
Comments
LOL. @vy Remember the Renderer I wanted to add for use in ScopedContext? Here is another use for it. |
@rgoers, yes, I do. Note that I wasn't against the
User is using SLF4J. You're suggesting him to
@AlexxeyKa will be the judge of this. 1 |
@vy Thanks for your reply. I agree that using
While switching to The core of my request is to store the key-values passed via I think this option
...is a good way, but it’s important that Regarding |
It is worth noting that in #1813, we agreed to that For those not accustomed to the difference between log message and event, there is a note in the Messages documentation page. {
"log.level": "INFO",
"message": "Unable to insert data into my_table.",
"error.type": "java.lang.RuntimeException",
"error.message": null,
"error.stack_trace": [
{
"class": "com.example.Main",
"method": "doQuery",
"file.name": "Main.java",
"file.line": 36
},
{
"class": "com.example.Main",
"method": "main",
"file.name": "Main.java",
"file.line": 25
}
],
"marker": "SQL",
"log.logger": "com.example.Main",
"tags": [
"SQL query"
],
"labels": {
"span_id": "3df85580-f001-4fb2-9e6e-3066ed6ddbb1",
"trace_id": "1b1f8fc9-1a0c-47b0-a06f-af3c1dd1edf9"
},
"@timestamp": "2024-05-23T09:32:24.163Z",
"log.origin.class": "com.example.Main",
"log.origin.method": "doQuery",
"log.origin.file.name": "Main.java",
"log.origin.file.line": 36,
"process.thread.id": 1,
"process.thread.name": "main",
"process.thread.priority": 5
} |
@ppkarwasz Thank you for noticing this. If the map with key-values passed via |
We can provide a
StringBuilderFormattable
specialization there. That is, we can changeaddKeyValue()
implementation such that:But,
JsonTemplateLayout
is employed, it will encode theMap<String, String>
passed and this will result in"kvPairs": {"yourKey": "{\"some-value\": \"you-already-JSONified\"}"}
. See?There is so much to unpack here.
For one, logging as follows
is a bad-practice, because this implies an assumption on the logging layout employed, which contradicts with the separation-of-concerns practiced with the logging API vs. logging implementation separation. What if the used layout is XML? etc. Hence, we should avoid encoding payloads with assumptions on the employed layout. Instead, we should allow registering arbitrarily-typed parameters, if necessary, with sufficient encoding hints (e.g., extending from
MultiFormatStringBuilderFormattable
) and let them be handled by the employed layout.Currently,
addKeyValue()
admissions get registered to aMap<String, String>
– we should amend this with aMap<String, Object>
. Though the bigger problem is how KV-pairs are passed to theLogBuilder
:That is,
log4j-slf4j2-impl
hacks auto-clearing thread context (i.e.,CloseableThreadContext
) to pass the KV-pairs all the way down to the layout. This is due to the fact thatLogBuilder
of Log4j doesn't have a counterpart for arbitrary KV-pairs and the feature that comes closest to it we can leverage (and we did) is thread context. There are a couple of angles we can approach this problem from:String
-typed values inCloseableThreadContext
– LOG4J2-1648 proposes this. Registering instances of custom types in a thread context can cause memory leakage in Java EE container environments, though this should not be a problem forCloseableThreadContext
.LogBuilder
to accept custom KV-pairs"Improve performance in high-throughput logging environments [by offloading the log event encoding to a background thread]" this is a claim that cannot hold without given sufficient context. Given the context, most of the time it becomes a special case rather than a general one we can practice for every user. Nevertheless, if we can pass arbitrary objects in KV-pairs (and effectively allow the layout to take charge of the complete encoding effort), you can combine this with asynchronous logging to effectively encode events in a thread different from the one invoking the logging API.
The text was updated successfully, but these errors were encountered: