[logback-dev] RFC: LoggingEvent redesign
Joern Huxhorn
jhuxhorn at googlemail.com
Wed Feb 25 00:32:03 CET 2009
Hi Ceki
On 24.02.2009, at 20:00, Ceki Gulcu wrote:
>
> Joern,
>
> Accepting parameters of type Object instead of String opens the door
> for nasty bugs as you point out. At the same time, it also
> constitutes an important extension point for logback within the
> limits imposed by the SLF4J API.
>
At this point I'm wondering if such an extension is really a good idea
at all.
Don't use a hammer to screw a screw. Ok, it would kind of work, but
you'd be better of using a screwdriver instead.
The hammer is slf4j/logback, a magnificent framework for application
logging. The screwdriver would be an auditing framework (see http://audit.qos.ch/apidocs/index.html
:D).
A pretty good indicator that slf4j is, in fact, the wrong tool for the
job, is that log levels are mostly meaningless in an audit context.
> I think that the org.slf4j.Logger class should contain a waring (in
> red) about the arguments being evaluated asynchronously.
But, uhm, don't get me wrong but... isn't the SLF4J concept of
parameterized logging kind of pointless with that warning in place?
What am I supposed to do about that warning? I mean as the user of
slf4j?
I'd like to log the state of an object so I call logger.debug("{}",
object). With the warning above I have not the slightest idea when the
event will actually be handled. It could happen synchronously or in
two days (rhetoric exaggeration). In the next line of my own code I
change something in that object and log it again in the same way.
Essentially 4 things can happen at this point:
1.) everything works as *I* would expect it to, i.e. synchronous
logging with the two different states of the object.
2.) two events are created, both containing the state of the object
after my second change.
3.) neither 1.) nor 2.) but *some* other state is logged because I'll
keep changing my object and the events are handled *much* later.
4.) the events would contain some senseless garbage because my object
(as most) isn't thread-safe and the evaluation of toString() would
happen while the object is being changed in my thread.
I'd seriously go nuts in the cases 2.) to 4.) and you could probably
hear my scream in Switzerland ;)
(You know, I'm a bit touchy about debugging tools that lie to me...
The Codewarrior debugger once lied to me about the content of
variables and I had a screenshot to prove it but, unfortunately, I
lost it while leaving the company...)
My only chance to prevent this uncertainty would be logger.debug("{}",
object.toString()) which isn't much better than the log4j methods,
right?
I'm really wondering why nobody else panics about those scenarios.
Such a change could potentially break lots of existing code!
> At present time, we serialize stringified version of the arguments.
> However, we could imagine that certain types, such as maps and
> collections, or other well-defined types be serialized as is
> (without transformation into String). Thus, not only would be it
> possible to take advantage of specific object types locally but also
> remotely.
This would complicate logback. A lot.
It also has the real risk of creating what we call "eierlegende
Wollmilchsau" in Germany. That's a fantasy animal that produces eggs,
wool, milk and ham. There just isn't any suitable translation for it
that does the original justice. dict.leo.org translates it to "all-in-
one device suitable for every purpose" but it's just not the same. The
idea is that you simply won't be able to create such a thing and,
therefore, would inevitably fail trying.
Instead of trying to be everything for everyone just stay focused on
the main topic.
> Regarding the lazy evaluation of LoggingEvent fields such as caller
> data and others, the current approach is highly dynamic. For
> example, if an appender named A requires caller data but is not on
> the processing path of the current logging event, then caller data
> will not be evaluated. Setting caller data evaluation as an option
> at the level of the logger context is not as flexible.
It's not as flexible but also more deterministic. I'd know, for sure,
what data will be obtained. If I'm not interested in caller data then
no appender will be able to force it on me. The appender would be
required to be able to cope with missing information instead.
> Moreover, if any single appender performs the computation of a given
> field in logging event, that field become available for all
> subsequent appenders.
In my case, the field will be available to all appenders if it is
enabled in the logger context. It would simplify a lot. It would, for
example, prevent the comment in AsynchronousAppenderBase that
ThreadName and CallerData must be obtained synchronously if required ;)
Appenders would just use the events as they receive them - without any
worries...
> I tend to think that the way logging event does lazy evaluation of
> fields works quite well.
That's correct with the current appenders but asynchronous appenders
would fail horribly with the current implementation because both
caller data and thread name would be wrong. Both would return the data
of the thread executing the respective getter method instead of the
correct data from the originating thread...
If the lazy initialization of those fields would be done synchronously
while the event is created, the event would have a real chance to be a
candidate for immutability (see my previous mail).
I'm not talking about the lazy formatting of messagePattern +
arguments to message because that wouldn't be a problem since the
worst case is formatting more than once in case of threading chaos.
Since both messagePattern and arguments won't change nothing bad can
and will happen. It would just be less efficient but nobody would get
"hurt" in the process...
Joern.
More information about the logback-dev
mailing list