[slf4j-dev] Release of SLF4J version 1.6.0-RC0

Ralph Goers rgoers at apache.org
Fri Apr 30 15:24:22 CEST 2010


Generally when I don't reply it isn't because I love the idea.

I can't think of any use cases where I'd want to construct a logging event that way. It also would seem that you would be taking what is currently a structure private to Logback and making it public as it would make no sense for SLF4J to have one LoggingEvent and Logback to have another.

In short, it doesn't really solve what Joern and I have been looking for with support for the Message and doesn't provide much value that I can see.

Ralph

On Apr 30, 2010, at 6:15 AM, Ceki Gülcü wrote:

> 
> Should the lack of response to my LoggingEvent proposal be interpreted as approval or as resignation?
> 
> On 27/04/2010 1:04 PM, Ceki Gülcü wrote:
>> Ralph,
>> 
>> Thanks for sharing these different use cases. I agree with you that
>> adding a throwable or a marker to a message does not necessarily make
>> sense. And yes, we could do
>> 
>> LogEvent event = new LogEvent(Level.ERROR,msg).addParam("p0").add(t);
>> logger.log(event);
>> 
>> I also understand that the point of the Message interface is to provide
>> a bit more structure around the message, not encapsulate all the logging
>> attributes such as the Marker, Level, etc into it.
>> 
>> There are two distinct problems here. One is the encapsulation of
>> various logging attributes (Marker, Level etc) and the other is the
>> structure of messages.
>> 
>> The encapsulation problem is important because I don't want to add 5x4
>> new methods to the Logger interface multiplied by the 6 implementations.
>> We can't just keep adding methods to the Logger interface. Hence the
>> idea of LoggingEvent. Given that a Message is data point in
>> LoggingEvent, you can still write:
>> 
>> LoggingEvent event =
>> new LoggingEvent(new AuditMessage("msg0", "type0"))).add(t);
>> logger.error(event);
>> 
>> or
>> 
>> LoggingEvent event =
>> new LoggingEvent(Level.ERROR,
>> new AuditMessage("msg0", "type0"))).add(t);
>> logger.error(event);
>> 
>> 
>> On 27/04/2010 6:38 AM, Ralph Goers wrote:
>>> Adding a throwable to an event with structured data makes no sense.
>>> The throwable, or components of it, would be part of the structured
>>> data. To do what you are suggesting you might as well do:
>>> 
>>> LogEvent event = new LogEvent(Level.ERROR,
>>> msg).addParam("parm1").addThrowable(t);
>>> logger.log(event);
>>> 
>>> The point of the Message interface is to provide a bit more structure
>>> around the message, not encapsulate all the logging attributes such as
>>> the Marker, Level, etc into it. For example, for auditing I can do:
>>> 
>>> public class AuditMessage extends StructuredDataMessage {
>>> public AuditMessage(String msg, String type) {
>>> super("Audit at 12345", msg);
>>> }
>>> }
>>> 
>>> public class LogiinMessage extends AuditMessage {
>>> public LoginMessage(String userId) {
>>> super("Login Succeeded", "Login");
>>> put("userid", userid);
>>> }
>>> }
>>> 
>>> For an Object such as a HashMap I could do:
>>> 
>>> public HashMapMessage<K,V> implements Message {
>>> private Map<K,V> map;
>>> 
>>> public HashMapMessage(Map<K,V> map) {
>>> this.map = map;
>>> }
>>> 
>>> public String getFormattedMessage() {
>>> StringBuilder sb = new StringBuidler();
>>> for (Map.Entry<K,V> entry : map.entrySet()) {
>>> if (sb.size()> 0) {
>>> insertPad(sb);
>>> }
>>> formatEntry(Map.Entry<K,V> entry, sb);
>>> }
>>> }
>>> protected void insertPad(StringBuilder sb) {
>>> sb.append(" ");
>>> }
>>> protected void formatEntry(Map.Entry<K,V> entry, StringBuilder sb) {
>>> sb.append(entry.getKey()).append("="),append(entry.getValue());
>>> }
>>> }
>>> 
>>> which now allows me to easily override this if I just want to change
>>> how each entry is formatted.
>>> 
>>> And so on.
>>> 
>>> Ralph
>>> 
>>> On Apr 26, 2010, at 1:08 PM, Ceki Gülcü wrote:
>>> 
>>>> 
>>>> OK. Instead of passing a Message, one would pass an Event which would
>>>> contain a Message as well as optionally other data.
>>>> 
>>>> Example 1)
>>>> 
>>>> Event event = new Event("hello {}").addParam("world").add(marker);
>>>> logger.error(event);
>>>> 
>>>> Example 2)
>>>> 
>>>> Event event = new Event(structredData).add(throwable);
>>>> logger.error(event);
>>>> 
>>>> 
>>>> On 26/04/2010 3:38 PM, Ralph Goers wrote:
>>>>> In general, I agree with Joern. The point of the Message interface
>>>>> is to make it easy to create all different kinds of Messages. A
>>>>> StructuredData message really has no good way to implement
>>>>> addParam() or event addThrowable.
>>>>> 
>>>>> Ralph
>>>>> 
>>>>> On Apr 26, 2010, at 5:09 AM, Joern Huxhorn wrote:
>>>>> 
>>>>>> 
>>>>>> On 26.04.2010, at 10:58, Ceki Gülcü wrote:
>>>>>> 
>>>>>>> On 24/04/2010 3:55 PM, Joern Huxhorn wrote:
>>>>>>> 
>>>>>>>> One of my goals in slf4j-n was to reduce the number of methods in
>>>>>>>> the
>>>>>>>> Logger interface.
>>>>>>>> This was seemingly a bad idea since it would have a performance
>>>>>>>> impact,
>>>>>>>> in the case where a message isn't actually logged, as Ralph
>>>>>>>> reported.
>>>>>>>> 
>>>>>>>> Because of this, it would be very wise to keep all the methods
>>>>>>>> that are
>>>>>>>> already present in the Logger interface and simply add
>>>>>>>> debug(Message)
>>>>>>>> debug(Message, Throwable)
>>>>>>>> debug(Marker, Message)
>>>>>>>> debug(Marker, Message, Throwable)
>>>>>>>> [same for other levels plus generic log(Level, ...)-methods]
>>>>>>>> 
>>>>>>>> The designer in me doesn't like the "bloated" (in the sense that
>>>>>>>> some
>>>>>>>> methods could be dropped without losing functionality) interface,
>>>>>>>> but
>>>>>>>> the realist in me accepts that performance is more important than
>>>>>>>> aesthetics ;)
>>>>>>> 
>>>>>>> Can't we coalesce debug(Message), debug(Message, Throwable),
>>>>>>> debug(Marker, Message) and debug(Marker, Message, Throwable) into
>>>>>>> a single variant?
>>>>>>> 
>>>>>>> Here is an idea:
>>>>>>> 
>>>>>>> try {
>>>>>>> ...
>>>>>>> } catch(Throwable t) {
>>>>>>> Message m = new
>>>>>>> Message("hello{}").addParam("word").add(marker).add(t);
>>>>>>> logger.error(m);
>>>>>>> }
>>>>>>> 
>>>>>>> This approach incurs the cost of creating and building the Message
>>>>>>> object regardless of whether the request will be logged or not. I
>>>>>>> suspect that the bulk of the cost is due to the object creation
>>>>>>> incurred by new Message(...) and not due to the addition of extra
>>>>>>> data incurred in calling addParam() and the other add() methods.
>>>>>>> Thus, performance-wise we are in the same position as the original
>>>>>>> Message proposal but now we can get rid of all the overloaded
>>>>>>> variants dealing with Marker and throwable.
>>>>>>> 
>>>>>> 
>>>>>> Well, the idea of the Message interface (!) was to enable lazy
>>>>>> initialization (in contrast to a simply toString) without adding
>>>>>> too many additional requirements to it.
>>>>>> 
>>>>>> http://github.com/huxi/slf4j/blob/slf4j-redesign/slf4j-n-api/src/main/java/org/slf4j/core/Message.java
>>>>>> 
>>>>>> 
>>>>>> It would be much more work to implement a custom Message with the
>>>>>> suggestion above. More work implies more chances of faulty
>>>>>> implementation, for example in case of Marker support. The
>>>>>> addParam() method would be quite a mistake, too, since a different
>>>>>> implementation of Message might use key/value-pairs as parameters.
>>>>>> (This is something that I'd really like to do since it would also
>>>>>> enable easier translations)
>>>>>> 
>>>>>> I see that interface as the main extension point of SLF4J& Logback.
>>>>>> The Message instance is supposed to end up in the appenders in case
>>>>>> of Logback, so custom appenders could handle custom Message
>>>>>> implementations in arbitrary ways without having to parse anything.
>>>>>> 
>>>>>> We could, however, add the Throwable to the Message interface. I
>>>>>> left it out of the interface and added it only to the
>>>>>> ParameterizedMessage implementation to keep the interface as clean
>>>>>> as possible.
>>>>>> 
>>>>>> This would reduce the interface to debug(Message) and debug(Marker,
>>>>>> Message), at least.
>>>>>> 
>>>>>> How about
>>>>>> 
>>>>>> interface Message
>>>>>> {
>>>>>> Message set(Throwable); // instead of setThrowable to be more concise?
>>>>>> Throwable getThrowable();
>>>>>> }
>>>>>> 
>>>>>> in addition?
>>>>>> 
>>>>>> My problem is: I'm not really sure if I'll like this while using it ;)
>>>>>> Regardless of the way we'll implement it in the Message, it will
>>>>>> always be less concise (concerning both brevity and readability)
>>>>>> than code using the four methods...
>>>>>> 
>>>>>> Joern.
> 
> _______________________________________________
> slf4j-dev mailing list
> slf4j-dev at qos.ch
> http://qos.ch/mailman/listinfo/slf4j-dev



More information about the slf4j-dev mailing list