You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by Nick Williams <ni...@nicholaswilliams.net> on 2013/07/29 22:39:54 UTC

LOG4J2-242 (Fluent Logging)

I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:

interface Logger:
    + MessageBuilder trace();
    + MessageBuilder debug();
    + MessageBuilder info();
    + MessageBuilder warn();
    + MessageBuilder error();
    + MessageBuilder fatal();
    + MessageBuilder log(Level);

+ interface MessageBuilder:
    message(String);
    message(Object);
    message(String, Object...);
    marker(Marker);
    exception(Throwable);
    argument(Object);
    arguments(Object...);
    log();

Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:

- Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.

- Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.

- Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.

I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.

Nick
---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Re: LOG4J2-242 (Fluent Logging)

Posted by Gary Gregory <ga...@gmail.com>.
On Mon, Jul 29, 2013 at 4:54 PM, Paul Benedict <pb...@apache.org> wrote:

> Flogger. Very nice... or painful.
>

It was just shorthand, but I'm not a fan of a fluent interface here, so I
would not want it to clutter the API, especially when I think of crowding
an auto-complete pop-up in an IDE.

I am wondering how necessary this is ATM, compared to other bug fixing. It
seems like it could be added in 2.1 if more than one person (or a handful)
asks for it.

Gary

On Jul 29, 2013 3:48 PM, "Gary Gregory" <ga...@gmail.com> wrote:
>
>> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <
>> nicholas@nicholaswilliams.net> wrote:
>>
>>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going
>>> to work something like this:
>>>
>>> interface Logger:
>>>     + MessageBuilder trace();
>>>     + MessageBuilder debug();
>>>     + MessageBuilder info();
>>>     + MessageBuilder warn();
>>>     + MessageBuilder error();
>>>     + MessageBuilder fatal();
>>>     + MessageBuilder log(Level);
>>>
>>> + interface MessageBuilder:
>>>     message(String);
>>>     message(Object);
>>>     message(String, Object...);
>>>     marker(Marker);
>>>     exception(Throwable);
>>>     argument(Object);
>>>     arguments(Object...);
>>>     log();
>>>
>>> Bruce (the requester) had suggested adding the methods that return
>>> MessageBuilder to a different interface (as opposed to Logger) to keep from
>>> cluttering the Logger API. The way I see it our options are:
>>>
>>> - Create a FluentLogger interface to house these methods. I don't like
>>> this option because A) it complicates things significantly, B) it makes
>>> users have to call a different method on LogManager (getFluentLogger) to
>>> get a FluentLogger, and C) it means users have to have a Logger and a
>>> FluentLogger if they want to use both APIs.
>>>
>>> - Create a FluentLogger interface that extends Logger. This option is
>>> much better. It avoids cluttering the Logger API if that's all someone
>>> wants to use, it doesn't require someone to have a Logger and FluentLogger
>>> if they want to use both APIs, and it doesn't complicate the implementation
>>> significantly (all implementations can just implement FluentLogger). It
>>> does still mean LogManager (and related classes/interfaces) need getLogger
>>> and getFluentLogger methods, which I don't necessarily like.
>>>
>>> - Just add these methods to Logger, which is what I intended to do from
>>> the get-go and is what I still think is the best option.
>>>
>>
>>  - and there's option 4: Don't do it.
>>
>> At first glance, adding these methods to Logger looks confusing and
>> cluttered. The less messy solution seems to me FLogger extends Logger.
>>
>> Gary
>>
>>
>>>
>>> I'm going to proceed with #3 for now, but if someone has a strong
>>> opinion otherwise please voice it so that we can discuss before I complete
>>> this.
>>>
>>> Nick
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>>
>>>
>>
>>
>> --
>> E-Mail: garydgregory@gmail.com | ggregory@apache.org
>> Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
>> Spring Batch in Action <http://www.manning.com/templier/>
>> Blog: http://garygregory.wordpress.com
>> Home: http://garygregory.com/
>> Tweet! http://twitter.com/GaryGregory
>>
>


-- 
E-Mail: garydgregory@gmail.com | ggregory@apache.org
Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
Spring Batch in Action <http://www.manning.com/templier/>
Blog: http://garygregory.wordpress.com
Home: http://garygregory.com/
Tweet! http://twitter.com/GaryGregory

Re: LOG4J2-242 (Fluent Logging)

Posted by Nick Williams <ni...@nicholaswilliams.net>.
On Jul 29, 2013, at 3:54 PM, Paul Benedict wrote:
> Flogger. Very nice... or painful.

Depends on your preferences I suppose. ;-)

> On Jul 29, 2013 3:48 PM, "Gary Gregory" <ga...@gmail.com> wrote:
> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
> I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:
> 
> interface Logger:
>     + MessageBuilder trace();
>     + MessageBuilder debug();
>     + MessageBuilder info();
>     + MessageBuilder warn();
>     + MessageBuilder error();
>     + MessageBuilder fatal();
>     + MessageBuilder log(Level);
> 
> + interface MessageBuilder:
>     message(String);
>     message(Object);
>     message(String, Object...);
>     marker(Marker);
>     exception(Throwable);
>     argument(Object);
>     arguments(Object...);
>     log();
> 
> Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:
> 
> - Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.
> 
> - Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.
> 
> - Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.
> 
>  - and there's option 4: Don't do it.
> 
> At first glance, adding these methods to Logger looks confusing and cluttered. The less messy solution seems to me FLogger extends Logger.
> 
> Gary
>  
> 
> I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.
> 
> Nick
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
> For additional commands, e-mail: log4j-dev-help@logging.apache.org
> 
> 
> 
> 
> -- 
> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
> Java Persistence with Hibernate, Second Edition
> JUnit in Action, Second Edition
> Spring Batch in Action
> Blog: http://garygregory.wordpress.com 
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory


---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org


Re: LOG4J2-242 (Fluent Logging)

Posted by Paul Benedict <pb...@apache.org>.
Flogger. Very nice... or painful.
On Jul 29, 2013 3:48 PM, "Gary Gregory" <ga...@gmail.com> wrote:

> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <
> nicholas@nicholaswilliams.net> wrote:
>
>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going
>> to work something like this:
>>
>> interface Logger:
>>     + MessageBuilder trace();
>>     + MessageBuilder debug();
>>     + MessageBuilder info();
>>     + MessageBuilder warn();
>>     + MessageBuilder error();
>>     + MessageBuilder fatal();
>>     + MessageBuilder log(Level);
>>
>> + interface MessageBuilder:
>>     message(String);
>>     message(Object);
>>     message(String, Object...);
>>     marker(Marker);
>>     exception(Throwable);
>>     argument(Object);
>>     arguments(Object...);
>>     log();
>>
>> Bruce (the requester) had suggested adding the methods that return
>> MessageBuilder to a different interface (as opposed to Logger) to keep from
>> cluttering the Logger API. The way I see it our options are:
>>
>> - Create a FluentLogger interface to house these methods. I don't like
>> this option because A) it complicates things significantly, B) it makes
>> users have to call a different method on LogManager (getFluentLogger) to
>> get a FluentLogger, and C) it means users have to have a Logger and a
>> FluentLogger if they want to use both APIs.
>>
>> - Create a FluentLogger interface that extends Logger. This option is
>> much better. It avoids cluttering the Logger API if that's all someone
>> wants to use, it doesn't require someone to have a Logger and FluentLogger
>> if they want to use both APIs, and it doesn't complicate the implementation
>> significantly (all implementations can just implement FluentLogger). It
>> does still mean LogManager (and related classes/interfaces) need getLogger
>> and getFluentLogger methods, which I don't necessarily like.
>>
>> - Just add these methods to Logger, which is what I intended to do from
>> the get-go and is what I still think is the best option.
>>
>
>  - and there's option 4: Don't do it.
>
> At first glance, adding these methods to Logger looks confusing and
> cluttered. The less messy solution seems to me FLogger extends Logger.
>
> Gary
>
>
>>
>> I'm going to proceed with #3 for now, but if someone has a strong opinion
>> otherwise please voice it so that we can discuss before I complete this.
>>
>> Nick
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>
>>
>
>
> --
> E-Mail: garydgregory@gmail.com | ggregory@apache.org
> Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
> Spring Batch in Action <http://www.manning.com/templier/>
> Blog: http://garygregory.wordpress.com
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory
>

Re: LOG4J2-242 (Fluent Logging)

Posted by Remko Popma <re...@yahoo.com>.
I don't see the benefit either...
The goal of a fluent interface is to be able to combine many calls (usually on different objects) into a chained call that can be on a single line and reads like English.

The canonical example is: (before)
{code}
private void makeNormal(Customer customer) { Order o1 = new Order(); customer.addOrder(o1); OrderLine line1 = new OrderLine(6, Product.find("TAL")); o1.addLine(line1); OrderLine line2 = new OrderLine(5, Product.find("HPK")); o1.addLine(line2); OrderLine line3 = new OrderLine(3, Product.find("LGV")); o1.addLine(line3); line2.setSkippable(true); o1.setRush(true); }
{code}


After:
{code}
private void makeFluent(Customer customer) { customer.newOrder() .with(6, "TAL") .with(5, "HPK").skippable() .with(3, "LGV") .priorityRush(); 
    }
{code}

I don't think this is necessary in the logging API because we *already have a single call*. 
{code}
Logger.error("Error while ordering {} {} and shipping to {}", 5, "bread baskets", "France", caughtException);
{code}

Splitting this up into multiple calls so we can call it fluent is not an improvement. 
There is no complexity that needs to be simplified IMO...

Remko


________________________________
 From: Ralph Goers <ra...@dslextreme.com>
To: Log4J Developers List <lo...@logging.apache.org> 
Sent: Tuesday, July 30, 2013 7:45 AM
Subject: Re: LOG4J2-242 (Fluent Logging)
 


I actually started to work on this myself several weeks ago and came to the conclusion that I just couldn't grasp how it is better - with one exception. You can reuse the MessageBuilder and replace the message or arguments, etc. But that seems dangerous as it wouldn't be thread safe.

Ralph

On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:

On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
>
>I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:
>>
>>interface Logger:
>>    + MessageBuilder trace();
>>    + MessageBuilder debug();
>>    + MessageBuilder info();
>>    + MessageBuilder warn();
>>    + MessageBuilder error();
>>    + MessageBuilder fatal();
>>    + MessageBuilder log(Level);
>>
>>+ interface MessageBuilder:
>>    message(String);
>>    message(Object);
>>    message(String, Object...);
>>    marker(Marker);
>>    exception(Throwable);
>>    argument(Object);
>>    arguments(Object...);
>>    log();
>>
>>Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:
>>
>>- Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.
>>
>>- Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.
>>
>>- Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.
>>
>
>
> - and there's option 4: Don't do it.
>
>
>At first glance, adding these methods to Logger looks confusing and cluttered. The less messy solution seems to me FLogger extends Logger.
>
>
>
>Gary
> 
>
>
>>I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.
>>
>>Nick
>>---------------------------------------------------------------------
>>To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>>For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>
>>
>
>
>-- 
>
>E-Mail: garydgregory@gmail.com | ggregory@apache.org 
>Java Persistence with Hibernate, Second Edition
>JUnit in Action, Second Edition
>Spring Batch in Action
>Blog: http://garygregory.wordpress.com 
>Home: http://garygregory.com/
>Tweet! http://twitter.com/GaryGregory

Re: LOG4J2-242 (Fluent Logging)

Posted by Nick Williams <ni...@nicholaswilliams.net>.
Ahh. Good point. Will do.

N

On Aug 2, 2013, at 3:45 PM, Gary Gregory wrote:

> Nick,
> 
> Please attach your patch to the JIRA for safekeeping.
> 
> Gary
> 
> 
> On Thu, Aug 1, 2013 at 9:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
> Ok, I'm hearing a lot of conflicting ideas here. So I'm going to shelve my changes for now (I'm just glad that I had only finished the code, and not the tests), stop progress on the issue, and mark it for a later version, unless someone things we should move forward with this.
> 
> I'm a smidge disappointed, mostly because I was really proud of how I designed it :-), but I won't be using it personally so I'm not that invested.
> 
> Nick
> 
> On Jul 29, 2013, at 8:14 PM, Gary Gregory wrote:
> 
>> I thought about this a little more in the context of avoiding Logger becoming a kitchen sink.
>> 
>> This is today already a mini-leak in toward kitchen sink-ness due to the (good IMO) addition of the printf APIs.
>> 
>> The way I see it, if I am a 'classic' programmer, I will not use the fluent API, and vice-versa, if I am a fluent programmer, I'll use the fluent API and not the standard API.
>> 
>> So why should both crowd the same interface. In fact why should all THREE (fluent, standard, and printf) be in the same interface.
>> 
>> I like the LogManager.get<Style>Logger approach proposed earlier.
>> 
>> If I am a fluent programmer, then I call getFluentLogger() and I get a clean fluent API sans extra stuff.
>> 
>> If I am a classic programmer, then I call getLogger() and I get a clean standard API sans extra fluent stuff.
>> 
>> Whether or not we want a getPrintfLogger() I know not yet, but I think it worth mentioning.
>> 
>> Logger can even implement toFluentLogger(), toLogger() and toPrintfLogger().
>> 
>> Having separate interfaces lets you have your fluent API without crowding the standard API.
>> 
>> Thoughts,
>> Gary
>> 
>> 
>> 
>> On Mon, Jul 29, 2013 at 7:57 PM, Remko Popma <re...@yahoo.com> wrote:
>> It is unfortunate that you've already put a lot of work into this.
>> For me, I am firmly in the "don't do this" camp. (Sorry Nick)
>> 
>> I think a fluent interface would add unnecessary complexity that does not add any value. 
>> We currently have a single method call that does a bunch of work.
>> IMO, splitting up that work to make it "look fluent" is not what fluent is about. Fluent is more than just a coding style, it should simplify and remove clutter.
>> 
>> The canonical example uses fluent correctly, *to reduce complexity*:
>> {code}
>>     private void makeNormal(Customer customer) {
>>         Order o1 = new Order();
>>         customer.addOrder(o1);
>>         OrderLine line1 = new OrderLine(6, Product.find("TAL"));
>>         o1.addLine(line1);
>>         OrderLine line2 = new OrderLine(5, Product.find("HPK"));
>>         o1.addLine(line2);
>>         OrderLine line3 = new OrderLine(3, Product.find("LGV"));
>>         o1.addLine(line3);
>>         line2.setSkippable(true);
>>         o1.setRush(true);
>>     }
>> {code}
>> 
>> After:
>> {code}
>>    private void makeFluent(Customer customer) {
>>         customer.newOrder()
>>                 .with(6, "TAL")
>>                 .with(5, "HPK").skippable()
>>                 .with(3, "LGV")
>>                 .priorityRush(); 
>>     }
>> 
>> 
>> {code}
>> 
>> In the above example a fluent interface adds value because it allows many objects to cooperate and it removes clutter.
>> But I would argue that we don't have any clutter that needs removing.
>> 
>> Remko 
>> 
>> From: Nick Williams <ni...@nicholaswilliams.net>
>> 
>> To: Log4J Developers List <lo...@logging.apache.org> 
>> Sent: Tuesday, July 30, 2013 8:08 AM
>> 
>> Subject: Re: LOG4J2-242 (Fluent Logging)
>> 
>> Well that's unfortunate. I just finished it. :-( Haven't committed it yet...
>> 
>> I'm not sure what the advantage is to delaying it to 2.1. Is it just to study it further? I understand "do it" and "don't do it," but I don't understand "do it later."
>> 
>> I've heard a few "I don't like it fluent" and "I didn't understand how it's better" assertions, and I think that's missing the point. I don't have a particular fondness for fluent APIs, but some people use a different programming style and prefer them. Just because person A doesn't like or understand how fluent is better, doesn't mean that person B doesn't like or understand how fluent is better. Person B might like fluent so much they write their own logging API wrapper around ours. Person B might not be able to wrap their head around non-fluent APIs for one reason or another.
>> 
>> Is there a major difference between these two lines of code?
>> 
>> logger.error("This is a message with {} arguments {}.", arg1, arg2, throwable);
>> logger.error().message("This is a message with {} arguments{}.").arguments(arg1, arg2).exception(throwable);
>> 
>> No, no real difference. However, I /can/ see how it's more obvious that throwable is an /exception/ and not an /argument to the message/. And while I would probably, personally, use the first line, I can certainly understand how someone might prefer the second line.
>> 
>> We're not talking about changing the existing API methods. We're talking about adding API methods to support this different style of programming that some people prefer. If, after all, our goal is to further adoption of Log4j, wouldn't it make sense to offer something like this that many people use, even if we ourselves aren't familiar with it or don't prefer it?
>> 
>> My $0.02.
>> 
>> N
>> 
>> On Jul 29, 2013, at 5:52 PM, Paul Benedict wrote:
>> 
>>> Whoever said this is a 2.1 feature, I concur.
>>> 
>>> 
>>> On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <ra...@dslextreme.com> wrote:
>>> I actually started to work on this myself several weeks ago and came to the conclusion that I just couldn't grasp how it is better - with one exception. You can reuse the MessageBuilder and replace the message or arguments, etc. But that seems dangerous as it wouldn't be thread safe.
>>> 
>>> Ralph
>>> 
>>> On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:
>>> 
>>>> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
>>>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:
>>>> 
>>>> interface Logger:
>>>>     + MessageBuilder trace();
>>>>     + MessageBuilder debug();
>>>>     + MessageBuilder info();
>>>>     + MessageBuilder warn();
>>>>     + MessageBuilder error();
>>>>     + MessageBuilder fatal();
>>>>     + MessageBuilder log(Level);
>>>> 
>>>> + interface MessageBuilder:
>>>>     message(String);
>>>>     message(Object);
>>>>     message(String, Object...);
>>>>     marker(Marker);
>>>>     exception(Throwable);
>>>>     argument(Object);
>>>>     arguments(Object...);
>>>>     log();
>>>> 
>>>> Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:
>>>> 
>>>> - Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.
>>>> 
>>>> - Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.
>>>> 
>>>> - Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.
>>>> 
>>>>  - and there's option 4: Don't do it.
>>>> 
>>>> At first glance, adding these methods to Logger looks confusing and cluttered. The less messy solution seems to me FLogger extends Logger.
>>>> 
>>>> Gary
>>>>  
>>>> 
>>>> I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.
>>>> 
>>>> Nick
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>>>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>>> 
>>>> 
>>>> 
>>>> 
>>>> -- 
>>>> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
>>>> Java Persistence with Hibernate, Second Edition
>>>> JUnit in Action, Second Edition
>>>> Spring Batch in Action
>>>> Blog: http://garygregory.wordpress.com 
>>>> Home: http://garygregory.com/
>>>> Tweet! http://twitter.com/GaryGregory
>>> 
>>> 
>>> 
>>> 
>>> -- 
>>> Cheers,
>>> Paul
>> 
>> 
>> 
>> 
>> 
>> 
>> -- 
>> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
>> Java Persistence with Hibernate, Second Edition
>> JUnit in Action, Second Edition
>> Spring Batch in Action
>> Blog: http://garygregory.wordpress.com 
>> Home: http://garygregory.com/
>> Tweet! http://twitter.com/GaryGregory
> 
> 
> 
> 
> -- 
> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
> Java Persistence with Hibernate, Second Edition
> JUnit in Action, Second Edition
> Spring Batch in Action
> Blog: http://garygregory.wordpress.com 
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory


Re: LOG4J2-242 (Fluent Logging)

Posted by Gary Gregory <ga...@gmail.com>.
Nick,

Please attach your patch to the JIRA for safekeeping.

Gary


On Thu, Aug 1, 2013 at 9:39 PM, Nick Williams <nicholas@nicholaswilliams.net
> wrote:

> Ok, I'm hearing a lot of conflicting ideas here. So I'm going to shelve my
> changes for now (I'm just glad that I had only finished the code, and not
> the tests), stop progress on the issue, and mark it for a later version,
> unless someone things we should move forward with this.
>
> I'm a smidge disappointed, mostly because I was really proud of how I
> designed it :-), but I won't be using it personally so I'm not that
> invested.
>
> Nick
>
> On Jul 29, 2013, at 8:14 PM, Gary Gregory wrote:
>
> I thought about this a little more in the context of avoiding Logger
> becoming a kitchen sink.
>
> This is today already a mini-leak in toward kitchen sink-ness due to the
> (good IMO) addition of the printf APIs.
>
> The way I see it, if I am a 'classic' programmer, I will not use the
> fluent API, and vice-versa, if I am a fluent programmer, I'll use the
> fluent API and not the standard API.
>
> So why should both crowd the same interface. In fact why should all THREE
> (fluent, standard, and printf) be in the same interface.
>
> I like the LogManager.get<Style>Logger approach proposed earlier.
>
> If I am a fluent programmer, then I call getFluentLogger() and I get a
> clean fluent API sans extra stuff.
>
> If I am a classic programmer, then I call getLogger() and I get a clean
> standard API sans extra fluent stuff.
>
> Whether or not we want a getPrintfLogger() I know not yet, but I think it
> worth mentioning.
>
> Logger can even implement toFluentLogger(), toLogger() and
> toPrintfLogger().
>
> Having separate interfaces lets you have your fluent API without crowding
> the standard API.
>
> Thoughts,
> Gary
>
>
>
> On Mon, Jul 29, 2013 at 7:57 PM, Remko Popma <re...@yahoo.com> wrote:
>
>> It is unfortunate that you've already put a lot of work into this.
>> For me, I am firmly in the "don't do this" camp. (Sorry Nick)
>>
>> I think a fluent interface would add unnecessary complexity that does not
>> add any value.
>> We currently have a single method call that does a bunch of work.
>> IMO, splitting up that work to make it "look fluent" is not what fluent
>> is about. Fluent is more than just a coding style, it should simplify and
>> remove clutter.
>>
>> The canonical example uses fluent correctly, *to reduce complexity*:
>> {code}
>>
>>     private void makeNormal(Customer customer) {
>>         Order o1 = new Order();
>>         customer.addOrder(o1);
>>         OrderLine line1 = new OrderLine(6, Product.find("TAL"));
>>         o1.addLine(line1);
>>         OrderLine line2 = new OrderLine(5, Product.find("HPK"));
>>         o1.addLine(line2);
>>         OrderLine line3 = new OrderLine(3, Product.find("LGV"));
>>         o1.addLine(line3);
>>         line2.setSkippable(true);
>>         o1.setRush(true);
>>     }
>>
>>
>> {code}
>>
>>
>> After:
>> {code}
>>
>>    private void makeFluent(Customer customer) {
>>         customer.newOrder()
>>                 .with(6, "TAL")
>>                 .with(5, "HPK").skippable()
>>                 .with(3, "LGV")
>>                 .priorityRush();
>>
>>     }
>> {code}
>>
>>
>> In the above example a fluent interface adds value because it allows many
>> objects to cooperate and it removes clutter.
>> But I would argue that we don't have any clutter that needs removing.
>>
>> Remko
>>
>>   ------------------------------
>>  *From:* Nick Williams <ni...@nicholaswilliams.net>
>>
>> *To:* Log4J Developers List <lo...@logging.apache.org>
>> *Sent:* Tuesday, July 30, 2013 8:08 AM
>>
>> *Subject:* Re: LOG4J2-242 (Fluent Logging)
>>
>> Well that's unfortunate. I just finished it. :-( Haven't committed it
>> yet...
>>
>> I'm not sure what the advantage is to delaying it to 2.1. Is it just to
>> study it further? I understand "do it" and "don't do it," but I don't
>> understand "do it later."
>>
>> I've heard a few "I don't like it fluent" and "I didn't understand how
>> it's better" assertions, and I think that's missing the point. I don't have
>> a particular fondness for fluent APIs, but some people use a different
>> programming style and prefer them. Just because person A doesn't like or
>> understand how fluent is better, doesn't mean that person B doesn't like or
>> understand how fluent is better. Person B might like fluent so much they
>> write their own logging API wrapper around ours. Person B might not be able
>> to wrap their head around non-fluent APIs for one reason or another.
>>
>> Is there a major difference between these two lines of code?
>>
>> logger.error("This is a message with {} arguments {}.", arg1, arg2,
>> throwable);
>> logger.error().message("This is a message with {}
>> arguments{}.").arguments(arg1, arg2).exception(throwable);
>>
>> No, no real difference. However, I /can/ see how it's more obvious that
>> throwable is an /exception/ and not an /argument to the message/. And while
>> I would probably, personally, use the first line, I can certainly
>> understand how someone might prefer the second line.
>>
>> We're not talking about changing the existing API methods. We're talking
>> about adding API methods to support this different style of programming
>> that some people prefer. If, after all, our goal is to further adoption of
>> Log4j, wouldn't it make sense to offer something like this that many people
>> use, even if we ourselves aren't familiar with it or don't prefer it?
>>
>> My $0.02.
>>
>> N
>>
>> On Jul 29, 2013, at 5:52 PM, Paul Benedict wrote:
>>
>> Whoever said this is a 2.1 feature, I concur.
>>
>>
>> On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <ra...@dslextreme.com>wrote:
>>
>> I actually started to work on this myself several weeks ago and came to
>> the conclusion that I just couldn't grasp how it is better - with one
>> exception. You can reuse the MessageBuilder and replace the message or
>> arguments, etc. But that seems dangerous as it wouldn't be thread safe.
>>
>> Ralph
>>
>> On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:
>>
>> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <
>> nicholas@nicholaswilliams.net> wrote:
>>
>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going
>> to work something like this:
>>
>> interface Logger:
>>     + MessageBuilder trace();
>>     + MessageBuilder debug();
>>     + MessageBuilder info();
>>     + MessageBuilder warn();
>>     + MessageBuilder error();
>>     + MessageBuilder fatal();
>>     + MessageBuilder log(Level);
>>
>> + interface MessageBuilder:
>>     message(String);
>>     message(Object);
>>     message(String, Object...);
>>     marker(Marker);
>>     exception(Throwable);
>>     argument(Object);
>>     arguments(Object...);
>>     log();
>>
>> Bruce (the requester) had suggested adding the methods that return
>> MessageBuilder to a different interface (as opposed to Logger) to keep from
>> cluttering the Logger API. The way I see it our options are:
>>
>> - Create a FluentLogger interface to house these methods. I don't like
>> this option because A) it complicates things significantly, B) it makes
>> users have to call a different method on LogManager (getFluentLogger) to
>> get a FluentLogger, and C) it means users have to have a Logger and a
>> FluentLogger if they want to use both APIs.
>>
>> - Create a FluentLogger interface that extends Logger. This option is
>> much better. It avoids cluttering the Logger API if that's all someone
>> wants to use, it doesn't require someone to have a Logger and FluentLogger
>> if they want to use both APIs, and it doesn't complicate the implementation
>> significantly (all implementations can just implement FluentLogger). It
>> does still mean LogManager (and related classes/interfaces) need getLogger
>> and getFluentLogger methods, which I don't necessarily like.
>>
>> - Just add these methods to Logger, which is what I intended to do from
>> the get-go and is what I still think is the best option.
>>
>>
>>  - and there's option 4: Don't do it.
>>
>> At first glance, adding these methods to Logger looks confusing and
>> cluttered. The less messy solution seems to me FLogger extends Logger.
>>
>> Gary
>>
>>
>>
>> I'm going to proceed with #3 for now, but if someone has a strong opinion
>> otherwise please voice it so that we can discuss before I complete this.
>>
>> Nick
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>
>>
>>
>>
>> --
>> E-Mail: garydgregory@gmail.com | ggregory@apache.org
>> Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
>> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
>> Spring Batch in Action <http://www.manning.com/templier/>
>> Blog: http://garygregory.wordpress.com
>> Home: http://garygregory.com/
>> Tweet! http://twitter.com/GaryGregory
>>
>>
>>
>>
>>
>> --
>> Cheers,
>> Paul
>>
>>
>>
>>
>>
>
>
> --
> E-Mail: garydgregory@gmail.com | ggregory@apache.org
> Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
> Spring Batch in Action <http://www.manning.com/templier/>
> Blog: http://garygregory.wordpress.com
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory
>
>
>


-- 
E-Mail: garydgregory@gmail.com | ggregory@apache.org
Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
Spring Batch in Action <http://www.manning.com/templier/>
Blog: http://garygregory.wordpress.com
Home: http://garygregory.com/
Tweet! http://twitter.com/GaryGregory

Re: LOG4J2-242 (Fluent Logging)

Posted by Nick Williams <ni...@nicholaswilliams.net>.
Ok, I'm hearing a lot of conflicting ideas here. So I'm going to shelve my changes for now (I'm just glad that I had only finished the code, and not the tests), stop progress on the issue, and mark it for a later version, unless someone things we should move forward with this.

I'm a smidge disappointed, mostly because I was really proud of how I designed it :-), but I won't be using it personally so I'm not that invested.

Nick

On Jul 29, 2013, at 8:14 PM, Gary Gregory wrote:

> I thought about this a little more in the context of avoiding Logger becoming a kitchen sink.
> 
> This is today already a mini-leak in toward kitchen sink-ness due to the (good IMO) addition of the printf APIs.
> 
> The way I see it, if I am a 'classic' programmer, I will not use the fluent API, and vice-versa, if I am a fluent programmer, I'll use the fluent API and not the standard API.
> 
> So why should both crowd the same interface. In fact why should all THREE (fluent, standard, and printf) be in the same interface.
> 
> I like the LogManager.get<Style>Logger approach proposed earlier.
> 
> If I am a fluent programmer, then I call getFluentLogger() and I get a clean fluent API sans extra stuff.
> 
> If I am a classic programmer, then I call getLogger() and I get a clean standard API sans extra fluent stuff.
> 
> Whether or not we want a getPrintfLogger() I know not yet, but I think it worth mentioning.
> 
> Logger can even implement toFluentLogger(), toLogger() and toPrintfLogger().
> 
> Having separate interfaces lets you have your fluent API without crowding the standard API.
> 
> Thoughts,
> Gary
> 
> 
> 
> On Mon, Jul 29, 2013 at 7:57 PM, Remko Popma <re...@yahoo.com> wrote:
> It is unfortunate that you've already put a lot of work into this.
> For me, I am firmly in the "don't do this" camp. (Sorry Nick)
> 
> I think a fluent interface would add unnecessary complexity that does not add any value. 
> We currently have a single method call that does a bunch of work.
> IMO, splitting up that work to make it "look fluent" is not what fluent is about. Fluent is more than just a coding style, it should simplify and remove clutter.
> 
> The canonical example uses fluent correctly, *to reduce complexity*:
> {code}
>     private void makeNormal(Customer customer) {
>         Order o1 = new Order();
>         customer.addOrder(o1);
>         OrderLine line1 = new OrderLine(6, Product.find("TAL"));
>         o1.addLine(line1);
>         OrderLine line2 = new OrderLine(5, Product.find("HPK"));
>         o1.addLine(line2);
>         OrderLine line3 = new OrderLine(3, Product.find("LGV"));
>         o1.addLine(line3);
>         line2.setSkippable(true);
>         o1.setRush(true);
>     }
> {code}
> 
> After:
> {code}
>    private void makeFluent(Customer customer) {
>         customer.newOrder()
>                 .with(6, "TAL")
>                 .with(5, "HPK").skippable()
>                 .with(3, "LGV")
>                 .priorityRush(); 
>     }
> 
> {code}
> 
> In the above example a fluent interface adds value because it allows many objects to cooperate and it removes clutter.
> But I would argue that we don't have any clutter that needs removing.
> 
> Remko 
> 
> From: Nick Williams <ni...@nicholaswilliams.net>
> 
> To: Log4J Developers List <lo...@logging.apache.org> 
> Sent: Tuesday, July 30, 2013 8:08 AM
> 
> Subject: Re: LOG4J2-242 (Fluent Logging)
> 
> Well that's unfortunate. I just finished it. :-( Haven't committed it yet...
> 
> I'm not sure what the advantage is to delaying it to 2.1. Is it just to study it further? I understand "do it" and "don't do it," but I don't understand "do it later."
> 
> I've heard a few "I don't like it fluent" and "I didn't understand how it's better" assertions, and I think that's missing the point. I don't have a particular fondness for fluent APIs, but some people use a different programming style and prefer them. Just because person A doesn't like or understand how fluent is better, doesn't mean that person B doesn't like or understand how fluent is better. Person B might like fluent so much they write their own logging API wrapper around ours. Person B might not be able to wrap their head around non-fluent APIs for one reason or another.
> 
> Is there a major difference between these two lines of code?
> 
> logger.error("This is a message with {} arguments {}.", arg1, arg2, throwable);
> logger.error().message("This is a message with {} arguments{}.").arguments(arg1, arg2).exception(throwable);
> 
> No, no real difference. However, I /can/ see how it's more obvious that throwable is an /exception/ and not an /argument to the message/. And while I would probably, personally, use the first line, I can certainly understand how someone might prefer the second line.
> 
> We're not talking about changing the existing API methods. We're talking about adding API methods to support this different style of programming that some people prefer. If, after all, our goal is to further adoption of Log4j, wouldn't it make sense to offer something like this that many people use, even if we ourselves aren't familiar with it or don't prefer it?
> 
> My $0.02.
> 
> N
> 
> On Jul 29, 2013, at 5:52 PM, Paul Benedict wrote:
> 
>> Whoever said this is a 2.1 feature, I concur.
>> 
>> 
>> On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <ra...@dslextreme.com> wrote:
>> I actually started to work on this myself several weeks ago and came to the conclusion that I just couldn't grasp how it is better - with one exception. You can reuse the MessageBuilder and replace the message or arguments, etc. But that seems dangerous as it wouldn't be thread safe.
>> 
>> Ralph
>> 
>> On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:
>> 
>>> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
>>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:
>>> 
>>> interface Logger:
>>>     + MessageBuilder trace();
>>>     + MessageBuilder debug();
>>>     + MessageBuilder info();
>>>     + MessageBuilder warn();
>>>     + MessageBuilder error();
>>>     + MessageBuilder fatal();
>>>     + MessageBuilder log(Level);
>>> 
>>> + interface MessageBuilder:
>>>     message(String);
>>>     message(Object);
>>>     message(String, Object...);
>>>     marker(Marker);
>>>     exception(Throwable);
>>>     argument(Object);
>>>     arguments(Object...);
>>>     log();
>>> 
>>> Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:
>>> 
>>> - Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.
>>> 
>>> - Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.
>>> 
>>> - Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.
>>> 
>>>  - and there's option 4: Don't do it.
>>> 
>>> At first glance, adding these methods to Logger looks confusing and cluttered. The less messy solution seems to me FLogger extends Logger.
>>> 
>>> Gary
>>>  
>>> 
>>> I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.
>>> 
>>> Nick
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>> 
>>> 
>>> 
>>> 
>>> -- 
>>> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
>>> Java Persistence with Hibernate, Second Edition
>>> JUnit in Action, Second Edition
>>> Spring Batch in Action
>>> Blog: http://garygregory.wordpress.com 
>>> Home: http://garygregory.com/
>>> Tweet! http://twitter.com/GaryGregory
>> 
>> 
>> 
>> 
>> -- 
>> Cheers,
>> Paul
> 
> 
> 
> 
> 
> 
> -- 
> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
> Java Persistence with Hibernate, Second Edition
> JUnit in Action, Second Edition
> Spring Batch in Action
> Blog: http://garygregory.wordpress.com 
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory


Re: LOG4J2-242 (Fluent Logging)

Posted by Gary Gregory <ga...@gmail.com>.
I thought about this a little more in the context of avoiding Logger
becoming a kitchen sink.

This is today already a mini-leak in toward kitchen sink-ness due to the
(good IMO) addition of the printf APIs.

The way I see it, if I am a 'classic' programmer, I will not use the fluent
API, and vice-versa, if I am a fluent programmer, I'll use the fluent API
and not the standard API.

So why should both crowd the same interface. In fact why should all THREE
(fluent, standard, and printf) be in the same interface.

I like the LogManager.get<Style>Logger approach proposed earlier.

If I am a fluent programmer, then I call getFluentLogger() and I get a
clean fluent API sans extra stuff.

If I am a classic programmer, then I call getLogger() and I get a clean
standard API sans extra fluent stuff.

Whether or not we want a getPrintfLogger() I know not yet, but I think it
worth mentioning.

Logger can even implement toFluentLogger(), toLogger() and toPrintfLogger().

Having separate interfaces lets you have your fluent API without crowding
the standard API.

Thoughts,
Gary



On Mon, Jul 29, 2013 at 7:57 PM, Remko Popma <re...@yahoo.com> wrote:

> It is unfortunate that you've already put a lot of work into this.
> For me, I am firmly in the "don't do this" camp. (Sorry Nick)
>
> I think a fluent interface would add unnecessary complexity that does not
> add any value.
> We currently have a single method call that does a bunch of work.
> IMO, splitting up that work to make it "look fluent" is not what fluent is
> about. Fluent is more than just a coding style, it should simplify and
> remove clutter.
>
> The canonical example uses fluent correctly, *to reduce complexity*:
> {code}
>
>     private void makeNormal(Customer customer) {
>         Order o1 = new Order();
>         customer.addOrder(o1);
>         OrderLine line1 = new OrderLine(6, Product.find("TAL"));
>         o1.addLine(line1);
>         OrderLine line2 = new OrderLine(5, Product.find("HPK"));
>         o1.addLine(line2);
>         OrderLine line3 = new OrderLine(3, Product.find("LGV"));
>         o1.addLine(line3);
>         line2.setSkippable(true);
>         o1.setRush(true);
>     }
>
> {code}
>
> After:
> {code}
>
>    private void makeFluent(Customer customer) {
>         customer.newOrder()
>                 .with(6, "TAL")
>                 .with(5, "HPK").skippable()
>                 .with(3, "LGV")
>                 .priorityRush();
>
>     }
> {code}
>
>
> In the above example a fluent interface adds value because it allows many
> objects to cooperate and it removes clutter.
> But I would argue that we don't have any clutter that needs removing.
>
> Remko
>
>   ------------------------------
>  *From:* Nick Williams <ni...@nicholaswilliams.net>
>
> *To:* Log4J Developers List <lo...@logging.apache.org>
> *Sent:* Tuesday, July 30, 2013 8:08 AM
>
> *Subject:* Re: LOG4J2-242 (Fluent Logging)
>
> Well that's unfortunate. I just finished it. :-( Haven't committed it
> yet...
>
> I'm not sure what the advantage is to delaying it to 2.1. Is it just to
> study it further? I understand "do it" and "don't do it," but I don't
> understand "do it later."
>
> I've heard a few "I don't like it fluent" and "I didn't understand how
> it's better" assertions, and I think that's missing the point. I don't have
> a particular fondness for fluent APIs, but some people use a different
> programming style and prefer them. Just because person A doesn't like or
> understand how fluent is better, doesn't mean that person B doesn't like or
> understand how fluent is better. Person B might like fluent so much they
> write their own logging API wrapper around ours. Person B might not be able
> to wrap their head around non-fluent APIs for one reason or another.
>
> Is there a major difference between these two lines of code?
>
> logger.error("This is a message with {} arguments {}.", arg1, arg2,
> throwable);
> logger.error().message("This is a message with {}
> arguments{}.").arguments(arg1, arg2).exception(throwable);
>
> No, no real difference. However, I /can/ see how it's more obvious that
> throwable is an /exception/ and not an /argument to the message/. And while
> I would probably, personally, use the first line, I can certainly
> understand how someone might prefer the second line.
>
> We're not talking about changing the existing API methods. We're talking
> about adding API methods to support this different style of programming
> that some people prefer. If, after all, our goal is to further adoption of
> Log4j, wouldn't it make sense to offer something like this that many people
> use, even if we ourselves aren't familiar with it or don't prefer it?
>
> My $0.02.
>
> N
>
> On Jul 29, 2013, at 5:52 PM, Paul Benedict wrote:
>
> Whoever said this is a 2.1 feature, I concur.
>
>
> On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <ra...@dslextreme.com>wrote:
>
> I actually started to work on this myself several weeks ago and came to
> the conclusion that I just couldn't grasp how it is better - with one
> exception. You can reuse the MessageBuilder and replace the message or
> arguments, etc. But that seems dangerous as it wouldn't be thread safe.
>
> Ralph
>
> On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:
>
> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <
> nicholas@nicholaswilliams.net> wrote:
>
> I'm working on LOG4J2-242 to add the ability to log fluently. It's going
> to work something like this:
>
> interface Logger:
>     + MessageBuilder trace();
>     + MessageBuilder debug();
>     + MessageBuilder info();
>     + MessageBuilder warn();
>     + MessageBuilder error();
>     + MessageBuilder fatal();
>     + MessageBuilder log(Level);
>
> + interface MessageBuilder:
>     message(String);
>     message(Object);
>     message(String, Object...);
>     marker(Marker);
>     exception(Throwable);
>     argument(Object);
>     arguments(Object...);
>     log();
>
> Bruce (the requester) had suggested adding the methods that return
> MessageBuilder to a different interface (as opposed to Logger) to keep from
> cluttering the Logger API. The way I see it our options are:
>
> - Create a FluentLogger interface to house these methods. I don't like
> this option because A) it complicates things significantly, B) it makes
> users have to call a different method on LogManager (getFluentLogger) to
> get a FluentLogger, and C) it means users have to have a Logger and a
> FluentLogger if they want to use both APIs.
>
> - Create a FluentLogger interface that extends Logger. This option is much
> better. It avoids cluttering the Logger API if that's all someone wants to
> use, it doesn't require someone to have a Logger and FluentLogger if they
> want to use both APIs, and it doesn't complicate the implementation
> significantly (all implementations can just implement FluentLogger). It
> does still mean LogManager (and related classes/interfaces) need getLogger
> and getFluentLogger methods, which I don't necessarily like.
>
> - Just add these methods to Logger, which is what I intended to do from
> the get-go and is what I still think is the best option.
>
>
>  - and there's option 4: Don't do it.
>
> At first glance, adding these methods to Logger looks confusing and
> cluttered. The less messy solution seems to me FLogger extends Logger.
>
> Gary
>
>
>
> I'm going to proceed with #3 for now, but if someone has a strong opinion
> otherwise please voice it so that we can discuss before I complete this.
>
> Nick
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>
>
>
>
> --
> E-Mail: garydgregory@gmail.com | ggregory@apache.org
> Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
> Spring Batch in Action <http://www.manning.com/templier/>
> Blog: http://garygregory.wordpress.com
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory
>
>
>
>
>
> --
> Cheers,
> Paul
>
>
>
>
>


-- 
E-Mail: garydgregory@gmail.com | ggregory@apache.org
Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
Spring Batch in Action <http://www.manning.com/templier/>
Blog: http://garygregory.wordpress.com
Home: http://garygregory.com/
Tweet! http://twitter.com/GaryGregory

Re: LOG4J2-242 (Fluent Logging)

Posted by Remko Popma <re...@yahoo.com>.
It is unfortunate that you've already put a lot of work into this.
For me, I am firmly in the "don't do this" camp. (Sorry Nick)

I think a fluent interface would add unnecessary complexity that does not add any value. 
We currently have a single method call that does a bunch of work.
IMO, splitting up that work to make it "look fluent" is not what fluent is about. Fluent is more than just a coding style, it should simplify and remove clutter.

The canonical example uses fluent correctly, *to reduce complexity*:
{code}
private void makeNormal(Customer customer) { Order o1 = new Order(); customer.addOrder(o1); OrderLine line1 = new OrderLine(6, Product.find("TAL")); o1.addLine(line1); OrderLine line2 = new OrderLine(5, Product.find("HPK")); o1.addLine(line2); OrderLine line3 = new OrderLine(3, Product.find("LGV")); o1.addLine(line3); line2.setSkippable(true); o1.setRush(true); }
{code}


After:
{code}
private void makeFluent(Customer customer) { customer.newOrder() .with(6, "TAL") .with(5, "HPK").skippable() .with(3, "LGV") .priorityRush(); 
    }
{code}

In the above example a fluent interface adds value because it allows many objects to cooperate and it removes clutter.
But I would argue that we don't have any clutter that needs removing.


Remko 


________________________________
 From: Nick Williams <ni...@nicholaswilliams.net>
To: Log4J Developers List <lo...@logging.apache.org> 
Sent: Tuesday, July 30, 2013 8:08 AM
Subject: Re: LOG4J2-242 (Fluent Logging)
 


Well that's unfortunate. I just finished it. :-( Haven't committed it yet...

I'm not sure what the advantage is to delaying it to 2.1. Is it just to study it further? I understand "do it" and "don't do it," but I don't understand "do it later."

I've heard a few "I don't like it fluent" and "I didn't understand how it's better" assertions, and I think that's missing the point. I don't have a particular fondness for fluent APIs, but some people use a different programming style and prefer them. Just because person A doesn't like or understand how fluent is better, doesn't mean that person B doesn't like or understand how fluent is better. Person B might like fluent so much they write their own logging API wrapper around ours. Person B might not be able to wrap their head around non-fluent APIs for one reason or another.

Is there a major difference between these two lines of code?

logger.error("This is a message with {} arguments {}.", arg1, arg2, throwable);
logger.error().message("This is a message with {} arguments{}.").arguments(arg1, arg2).exception(throwable);

No, no real difference. However, I /can/ see how it's more obvious that throwable is an /exception/ and not an /argument to the message/. And while I would probably, personally, use the first line, I can certainly understand how someone might prefer the second line.

We're not talking about changing the existing API methods. We're talking about adding API methods to support this different style of programming that some people prefer. If, after all, our goal is to further adoption of Log4j, wouldn't it make sense to offer something like this that many people use, even if we ourselves aren't familiar with it or don't prefer it?

My $0.02.

N


On Jul 29, 2013, at 5:52 PM, Paul Benedict wrote:

Whoever said this is a 2.1 feature, I concur.
>
>
>
>
>On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <ra...@dslextreme.com> wrote:
>
>I actually started to work on this myself several weeks ago and came to the conclusion that I just couldn't grasp how it is better - with one exception. You can reuse the MessageBuilder and replace the message or arguments, etc. But that seems dangerous as it wouldn't be thread safe.
>>
>>
>>Ralph
>>
>>On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:
>>
>>On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
>>>
>>>I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:
>>>>
>>>>interface Logger:
>>>>    + MessageBuilder trace();
>>>>    + MessageBuilder debug();
>>>>    + MessageBuilder info();
>>>>    + MessageBuilder warn();
>>>>    + MessageBuilder error();
>>>>    + MessageBuilder fatal();
>>>>    + MessageBuilder log(Level);
>>>>
>>>>+ interface MessageBuilder:
>>>>    message(String);
>>>>    message(Object);
>>>>    message(String, Object...);
>>>>    marker(Marker);
>>>>    exception(Throwable);
>>>>    argument(Object);
>>>>    arguments(Object...);
>>>>    log();
>>>>
>>>>Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:
>>>>
>>>>- Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.
>>>>
>>>>- Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.
>>>>
>>>>- Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.
>>>>
>>>
>>>
>>> - and there's option 4: Don't do it.
>>>
>>>
>>>At first glance, adding these methods to Logger looks confusing and cluttered. The less messy solution seems to me FLogger extends Logger.
>>>
>>>
>>>
>>>Gary
>>> 
>>>
>>>
>>>>I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.
>>>>
>>>>Nick
>>>>---------------------------------------------------------------------
>>>>To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>>>>For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>>>
>>>>
>>>
>>>
>>>-- 
>>>
>>>E-Mail: garydgregory@gmail.com | ggregory@apache.org 
>>>Java Persistence with Hibernate, Second Edition
>>>JUnit in Action, Second Edition
>>>Spring Batch in Action
>>>Blog: http://garygregory.wordpress.com 
>>>Home: http://garygregory.com/
>>>Tweet! http://twitter.com/GaryGregory
>>
>
>
>-- 
>
>Cheers,
>Paul

Re: LOG4J2-242 (Fluent Logging)

Posted by Nick Williams <ni...@nicholaswilliams.net>.
Well that's unfortunate. I just finished it. :-( Haven't committed it yet...

I'm not sure what the advantage is to delaying it to 2.1. Is it just to study it further? I understand "do it" and "don't do it," but I don't understand "do it later."

I've heard a few "I don't like it fluent" and "I didn't understand how it's better" assertions, and I think that's missing the point. I don't have a particular fondness for fluent APIs, but some people use a different programming style and prefer them. Just because person A doesn't like or understand how fluent is better, doesn't mean that person B doesn't like or understand how fluent is better. Person B might like fluent so much they write their own logging API wrapper around ours. Person B might not be able to wrap their head around non-fluent APIs for one reason or another.

Is there a major difference between these two lines of code?

logger.error("This is a message with {} arguments {}.", arg1, arg2, throwable);
logger.error().message("This is a message with {} arguments{}.").arguments(arg1, arg2).exception(throwable);

No, no real difference. However, I /can/ see how it's more obvious that throwable is an /exception/ and not an /argument to the message/. And while I would probably, personally, use the first line, I can certainly understand how someone might prefer the second line.

We're not talking about changing the existing API methods. We're talking about adding API methods to support this different style of programming that some people prefer. If, after all, our goal is to further adoption of Log4j, wouldn't it make sense to offer something like this that many people use, even if we ourselves aren't familiar with it or don't prefer it?

My $0.02.

N

On Jul 29, 2013, at 5:52 PM, Paul Benedict wrote:

> Whoever said this is a 2.1 feature, I concur.
> 
> 
> On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <ra...@dslextreme.com> wrote:
> I actually started to work on this myself several weeks ago and came to the conclusion that I just couldn't grasp how it is better - with one exception. You can reuse the MessageBuilder and replace the message or arguments, etc. But that seems dangerous as it wouldn't be thread safe.
> 
> Ralph
> 
> On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:
> 
>> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:
>> 
>> interface Logger:
>>     + MessageBuilder trace();
>>     + MessageBuilder debug();
>>     + MessageBuilder info();
>>     + MessageBuilder warn();
>>     + MessageBuilder error();
>>     + MessageBuilder fatal();
>>     + MessageBuilder log(Level);
>> 
>> + interface MessageBuilder:
>>     message(String);
>>     message(Object);
>>     message(String, Object...);
>>     marker(Marker);
>>     exception(Throwable);
>>     argument(Object);
>>     arguments(Object...);
>>     log();
>> 
>> Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:
>> 
>> - Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.
>> 
>> - Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.
>> 
>> - Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.
>> 
>>  - and there's option 4: Don't do it.
>> 
>> At first glance, adding these methods to Logger looks confusing and cluttered. The less messy solution seems to me FLogger extends Logger.
>> 
>> Gary
>>  
>> 
>> I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.
>> 
>> Nick
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>> 
>> 
>> 
>> 
>> -- 
>> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
>> Java Persistence with Hibernate, Second Edition
>> JUnit in Action, Second Edition
>> Spring Batch in Action
>> Blog: http://garygregory.wordpress.com 
>> Home: http://garygregory.com/
>> Tweet! http://twitter.com/GaryGregory
> 
> 
> 
> 
> -- 
> Cheers,
> Paul


Re: LOG4J2-242 (Fluent Logging)

Posted by Paul Benedict <pb...@apache.org>.
Whoever said this is a 2.1 feature, I concur.


On Mon, Jul 29, 2013 at 5:45 PM, Ralph Goers <ra...@dslextreme.com>wrote:

> I actually started to work on this myself several weeks ago and came to
> the conclusion that I just couldn't grasp how it is better - with one
> exception. You can reuse the MessageBuilder and replace the message or
> arguments, etc. But that seems dangerous as it wouldn't be thread safe.
>
> Ralph
>
> On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:
>
> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <
> nicholas@nicholaswilliams.net> wrote:
>
>> I'm working on LOG4J2-242 to add the ability to log fluently. It's going
>> to work something like this:
>>
>> interface Logger:
>>     + MessageBuilder trace();
>>     + MessageBuilder debug();
>>     + MessageBuilder info();
>>     + MessageBuilder warn();
>>     + MessageBuilder error();
>>     + MessageBuilder fatal();
>>     + MessageBuilder log(Level);
>>
>> + interface MessageBuilder:
>>     message(String);
>>     message(Object);
>>     message(String, Object...);
>>     marker(Marker);
>>     exception(Throwable);
>>     argument(Object);
>>     arguments(Object...);
>>     log();
>>
>> Bruce (the requester) had suggested adding the methods that return
>> MessageBuilder to a different interface (as opposed to Logger) to keep from
>> cluttering the Logger API. The way I see it our options are:
>>
>> - Create a FluentLogger interface to house these methods. I don't like
>> this option because A) it complicates things significantly, B) it makes
>> users have to call a different method on LogManager (getFluentLogger) to
>> get a FluentLogger, and C) it means users have to have a Logger and a
>> FluentLogger if they want to use both APIs.
>>
>> - Create a FluentLogger interface that extends Logger. This option is
>> much better. It avoids cluttering the Logger API if that's all someone
>> wants to use, it doesn't require someone to have a Logger and FluentLogger
>> if they want to use both APIs, and it doesn't complicate the implementation
>> significantly (all implementations can just implement FluentLogger). It
>> does still mean LogManager (and related classes/interfaces) need getLogger
>> and getFluentLogger methods, which I don't necessarily like.
>>
>> - Just add these methods to Logger, which is what I intended to do from
>> the get-go and is what I still think is the best option.
>>
>
>  - and there's option 4: Don't do it.
>
> At first glance, adding these methods to Logger looks confusing and
> cluttered. The less messy solution seems to me FLogger extends Logger.
>
> Gary
>
>
>>
>> I'm going to proceed with #3 for now, but if someone has a strong opinion
>> otherwise please voice it so that we can discuss before I complete this.
>>
>> Nick
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
>> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>>
>>
>
>
> --
> E-Mail: garydgregory@gmail.com | ggregory@apache.org
> Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
> JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
> Spring Batch in Action <http://www.manning.com/templier/>
> Blog: http://garygregory.wordpress.com
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory
>
>
>


-- 
Cheers,
Paul

Re: LOG4J2-242 (Fluent Logging)

Posted by Ralph Goers <ra...@dslextreme.com>.
I actually started to work on this myself several weeks ago and came to the conclusion that I just couldn't grasp how it is better - with one exception. You can reuse the MessageBuilder and replace the message or arguments, etc. But that seems dangerous as it wouldn't be thread safe.

Ralph

On Jul 29, 2013, at 1:48 PM, Gary Gregory wrote:

> On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <ni...@nicholaswilliams.net> wrote:
> I'm working on LOG4J2-242 to add the ability to log fluently. It's going to work something like this:
> 
> interface Logger:
>     + MessageBuilder trace();
>     + MessageBuilder debug();
>     + MessageBuilder info();
>     + MessageBuilder warn();
>     + MessageBuilder error();
>     + MessageBuilder fatal();
>     + MessageBuilder log(Level);
> 
> + interface MessageBuilder:
>     message(String);
>     message(Object);
>     message(String, Object...);
>     marker(Marker);
>     exception(Throwable);
>     argument(Object);
>     arguments(Object...);
>     log();
> 
> Bruce (the requester) had suggested adding the methods that return MessageBuilder to a different interface (as opposed to Logger) to keep from cluttering the Logger API. The way I see it our options are:
> 
> - Create a FluentLogger interface to house these methods. I don't like this option because A) it complicates things significantly, B) it makes users have to call a different method on LogManager (getFluentLogger) to get a FluentLogger, and C) it means users have to have a Logger and a FluentLogger if they want to use both APIs.
> 
> - Create a FluentLogger interface that extends Logger. This option is much better. It avoids cluttering the Logger API if that's all someone wants to use, it doesn't require someone to have a Logger and FluentLogger if they want to use both APIs, and it doesn't complicate the implementation significantly (all implementations can just implement FluentLogger). It does still mean LogManager (and related classes/interfaces) need getLogger and getFluentLogger methods, which I don't necessarily like.
> 
> - Just add these methods to Logger, which is what I intended to do from the get-go and is what I still think is the best option.
> 
>  - and there's option 4: Don't do it.
> 
> At first glance, adding these methods to Logger looks confusing and cluttered. The less messy solution seems to me FLogger extends Logger.
> 
> Gary
>  
> 
> I'm going to proceed with #3 for now, but if someone has a strong opinion otherwise please voice it so that we can discuss before I complete this.
> 
> Nick
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
> For additional commands, e-mail: log4j-dev-help@logging.apache.org
> 
> 
> 
> 
> -- 
> E-Mail: garydgregory@gmail.com | ggregory@apache.org 
> Java Persistence with Hibernate, Second Edition
> JUnit in Action, Second Edition
> Spring Batch in Action
> Blog: http://garygregory.wordpress.com 
> Home: http://garygregory.com/
> Tweet! http://twitter.com/GaryGregory


Re: LOG4J2-242 (Fluent Logging)

Posted by Gary Gregory <ga...@gmail.com>.
On Mon, Jul 29, 2013 at 4:39 PM, Nick Williams <
nicholas@nicholaswilliams.net> wrote:

> I'm working on LOG4J2-242 to add the ability to log fluently. It's going
> to work something like this:
>
> interface Logger:
>     + MessageBuilder trace();
>     + MessageBuilder debug();
>     + MessageBuilder info();
>     + MessageBuilder warn();
>     + MessageBuilder error();
>     + MessageBuilder fatal();
>     + MessageBuilder log(Level);
>
> + interface MessageBuilder:
>     message(String);
>     message(Object);
>     message(String, Object...);
>     marker(Marker);
>     exception(Throwable);
>     argument(Object);
>     arguments(Object...);
>     log();
>
> Bruce (the requester) had suggested adding the methods that return
> MessageBuilder to a different interface (as opposed to Logger) to keep from
> cluttering the Logger API. The way I see it our options are:
>
> - Create a FluentLogger interface to house these methods. I don't like
> this option because A) it complicates things significantly, B) it makes
> users have to call a different method on LogManager (getFluentLogger) to
> get a FluentLogger, and C) it means users have to have a Logger and a
> FluentLogger if they want to use both APIs.
>
> - Create a FluentLogger interface that extends Logger. This option is much
> better. It avoids cluttering the Logger API if that's all someone wants to
> use, it doesn't require someone to have a Logger and FluentLogger if they
> want to use both APIs, and it doesn't complicate the implementation
> significantly (all implementations can just implement FluentLogger). It
> does still mean LogManager (and related classes/interfaces) need getLogger
> and getFluentLogger methods, which I don't necessarily like.
>
> - Just add these methods to Logger, which is what I intended to do from
> the get-go and is what I still think is the best option.
>

 - and there's option 4: Don't do it.

At first glance, adding these methods to Logger looks confusing and
cluttered. The less messy solution seems to me FLogger extends Logger.

Gary


>
> I'm going to proceed with #3 for now, but if someone has a strong opinion
> otherwise please voice it so that we can discuss before I complete this.
>
> Nick
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
> For additional commands, e-mail: log4j-dev-help@logging.apache.org
>
>


-- 
E-Mail: garydgregory@gmail.com | ggregory@apache.org
Java Persistence with Hibernate, Second Edition<http://www.manning.com/bauer3/>
JUnit in Action, Second Edition <http://www.manning.com/tahchiev/>
Spring Batch in Action <http://www.manning.com/templier/>
Blog: http://garygregory.wordpress.com
Home: http://garygregory.com/
Tweet! http://twitter.com/GaryGregory