
On 09/03/2010 5:42 PM, Ralph Goers wrote:
On Mar 9, 2010, at 6:55 AM, Ceki Gülcü wrote:
Once you have a custom encoder, you can encode parameters as you see fit. This of course assumes logback as the slf4j backend since encoders exists only in logback. Given that parameters are passed to appenders unaltered from slf4j to logback, I don't think I am ignoring the question of getting the data to the appender, or am I?
Yes, you are. If you look at RFC 5424 you will see that it supports structured data elements inside an element id. The spec also supports multiple of these. By its nature, the MDC can already be wrapped in a structured element but other things cannot. They are just arbitrary parameters. It is possible that I might want to have two structured data sections in the output. With a Message this can easily be accomodated by creating a new Message class where getFormattedMessage knows that it will contain an array of StructuredDataMessages and will then format it accordingly. This can be done for virtually any object type. Having to do this with an encoder or layout means writing a lot of ugly code that tries to anticipate all the various objects that might get passed in.
Let's say you have a parameter of type 'House' you would like to log and you wrap it inside a new type called StructuredDataHouse and pass it to a logger as the first parameter (the message being "{}"). The RFC5424Encoder detects that this parameter supports RFC5424 encoding and asks StructuredDataHouse for its RFC5424 encoded data. RFC5424Encoder only neeeds to deals with objects supporting RFC5424 encoding, there is no need to anticipate other encoding types. The end result is very similar to asking your StructuredDataMessage in the org.slf4j.message package for its formatted message, except that the question is asked by a RFC5424Encoder. A different encoder would ask a different question.
Assuming the parameters get to the appender unaltered, an RFC5424Encoder could ask each parameter whether it can be encoded in RFC5424. If the argument supports RFC5424 encoding we would use the data supplied by the argument itself. Otherwise, we would use the value returned by toString() and prepend the key "argN=" for argument N as its generic RFC5424 encoding.
This is exactly my point. This sucks.
What sucks? It seems to me that such heuristic already provides better support for structured data then a *general* message type. If you are passed an object whose getFormatedMessage returns an arbitrary result, you would need some way of ensuring that it plays nicely with the RFC5424 format. The heuristic above provides a way.
For Object serialization which is another form of encoding, an Object encoder would ignore the RFC5424 capabilities of parameters and use serialization instead.
It seems that postponing the decision to transform an argument to its desired encoding up until the last minute without imposing a type is actually a pretty good design.
It is a good design for the overall layout. It is not a good design for formatting the objects where the objects themselves can do the formatting. With a slightly smarter method in the Message interface it is possible that the Message could even format itself based upon information passed from the layout/encoder.
What I am proposing still uses the formatting capabilities of each object, but it does so in a targeted way. If an object supports both X and Y encoding, an X-encoder would use the object's X-encoding capabilities whereas a Y-encoder would use the object's Y-encoding capabilities.
I have not coded any of this so it may all be a pile of vaporware crap.
I have. Several times. What Joern proposed works very well and is the model I am following for Log4j 2.0. The version on my slf4j/logback branch works and is binary compatible with current SLF4J versions but isn't as straightforward.
OK. I intend to look into Joern's and your code more carefully.
Ralph