Who need JULI (java util logging)?

495 views
Skip to first unread message

GrailsDeveloper

unread,
Aug 21, 2011, 8:43:32 AM8/21/11
to play-framework
Today I'm trying to improve testing of the Logger-Class of play. The
code isn't as clean as usual, because there are a lot of code so that
you can java-util-log. The only reason to use JULI I know, is that you
don't need a special jar. How ever in play log4j is included, so this
isn't really an argument.
I would suggest to make the code in 1.3 deprecated so that it can be
removed in 1.4? Before creating an ticket I want to know the opinion
from the community. So if you need it please answer to this topic.
Please don't start a discussion about slfj and logback again.

Niels

Alison Winters

unread,
Aug 21, 2011, 9:10:20 PM8/21/11
to play-framework
I don't know anyone who uses java.util.logging for anything. That
said, if there are people who want it desperately, then it would make
sense to use SLF4J (not necessarily Logback) in core since that allows
a pluggable back end. There would have to be some application-specific
way of selecting the back end logger, however. E.g. "play new" by
default sets up dependencies.yml with slf4j-log4j12, whereas "play new
--with-jul" sets it up with slf4j-jdk14. This approach I like better
than just removing java.util.logging support and hard-coding log4j
(even though I am happy with log4j).

Alison

On Aug 21, 8:43 am, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 22, 2011, 4:57:00 AM8/22/11
to play-framework
Hi
the problem with slf4j is that it doesn't support do write wrappers
around it like plays Logger class. As far as I know only log4j allows
this in a clean way.
Niels

J

unread,
Aug 22, 2011, 11:36:26 AM8/22/11
to play-framework
I don't use JULI but I am currently using the SLF4J interface (with
log4j as the implementing logger).

I hope that one day logback will be supported by Play, and the switch
will be seamless given that I'm already using SLF4J.

I'm not sure what you mean by:
"the problem with slf4j is that it doesn't support do write wrappers
around it like plays Logger class"

What's a do write wrapper?

On Aug 22, 4:57 am, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 22, 2011, 1:46:45 PM8/22/11
to play-framework
Hi J
>
> I'm not sure what you mean by:
> "the problem with slf4j is that it doesn't support do write wrappers
> around it like plays Logger class"
>
Well you don't call the log directly in Play. You use Logger as a
wrapper, which delegate to the log4j-implementation. If you do it
right (unfortunately Play doesn't) you can use all uppercase letters
from http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html
with no problem. If you do it wrong only %X do what you want.

If you know how you can use the patterns with slf4j and a static
logger-class, I would be glad to see the example.

Niels

J

unread,
Aug 23, 2011, 12:00:16 AM8/23/11
to play-framework
> Well you don't call the log directly in Play. You use Logger as a wrapper, which delegate to the log4j-implementation.

This is not the only way to log in Play. I chose not to use Play's
wrapper Logger (play.Logger) because by default it logs all messages
under a single logger (named "play"). I prefer the standard log4j
practice of defining a static logger per class. This allows for
granular adjustment of log levels for debugging purposes.

> If you do it right (unfortunately Play doesn't) you can use all uppercase letters from http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternL... with no problem. If you do it wrong only %X do what you want.

I'm not entirely clear what you mean by this. All letters (upper or
lowercase) can be used in PatternLayout. This is defined in your
log4j.properties (or log4j.xml) file. I have no problems using any of
the letters.

As mentioned, I'm currently using SLF4J with log4j as the backing
implementation. I've written a thin wrapper class around SLF4J but
only because I wanted Java 5 varargs support (otherwise it's not
necessary). I also have a log4j.xml file that defines my logging
pattern as well as appenders.

The hope is to one day use logback, as it is intended to be the
successor to log4j.

Hope this helps!

On Aug 22, 1:46 pm, GrailsDeveloper <opensourc...@googlemail.com>
wrote:
> Hi J
>
> > I'm not sure what you mean by:
> > "the problem with slf4j is that it doesn't support do write wrappers
> > around it like plays Logger class"
>
> Well you don't call the log directly in Play. You use Logger as a
> wrapper, which delegate to the log4j-implementation. If you do it
> right (unfortunately Play doesn't) you can use all uppercase letters
> fromhttp://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternL...

GrailsDeveloper

unread,
Aug 23, 2011, 3:36:30 AM8/23/11
to play-framework
Hi

On 23 Aug., 06:00, J <ja...@sumall.com> wrote:
> > Well you don't call the log directly in Play. You use Logger as a wrapper, which delegate to the log4j-implementation.
>
> This is not the only way to log in Play.  I chose not to use Play's
> wrapper Logger (play.Logger) because by default it logs all messages
> under a single logger (named "play").  I prefer the standard log4j
> practice of defining a static logger per class.  This allows for
> granular adjustment of log levels for debugging purposes.

This is clear and in this case you haven't any problems to use slf4j.

>
> > If you do it right (unfortunately Play doesn't) you can use all uppercase letters fromhttp://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternL... with no problem. If you do it wrong only %X do what you want.
>
> I'm not entirely clear what you mean by this.  All letters (upper or
> lowercase) can be used in PatternLayout.  This is defined in your
> log4j.properties (or log4j.xml) file.  I have no problems using any of
> the letters.

Of course you can define and use it, but the result will be wrong. It
will write, that all logs came from play.Logger. Which is not what you
wanted.

>
> As mentioned, I'm currently using SLF4J with log4j as the backing
> implementation.  I've written a thin wrapper class around SLF4J but
> only because I wanted Java 5 varargs support (otherwise it's not
> necessary).  I also have a log4j.xml file that defines my logging
> pattern as well as appenders.

And you get correct information, about the lines?

Niels

J

unread,
Aug 23, 2011, 11:00:28 AM8/23/11
to play-framework
> Of course you can define and use it, but the result will be wrong. It will write, that all logs came from play.Logger. Which is not what you wanted.

That's because you are using Play's global logger to log everything.
Log4j is correctly determining that logs are coming from play.Logger.
That is PRECISELY why I chose NOT to use play.Logger, because I want
my logs statements to come from where the code is being executed.

Looking at the play.Logger source code, I believe you can still
achieve what you want by setting "application.log.recordCaller" to
true in application.conf. Look closely at the code though, it uses
stack traces to determine calling code, which performs very poorly.

> And you get correct information, about the lines?

Yup, everything is accurate, but this is because I'm using log4j as I
described in my last post, and not play.Logger.

On Aug 23, 3:36 am, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 23, 2011, 2:35:37 PM8/23/11
to play-framework
Hi

On 23 Aug., 17:00, J <ja...@sumall.com> wrote:
> > Of course you can define and use it, but the result will be wrong. It will write, that all logs came from play.Logger. Which is not what you wanted.
>
> That's because you are using Play's global logger to log everything.
> Log4j is correctly determining that logs are coming from play.Logger.
> That is PRECISELY why I chose NOT to use play.Logger, because I want
> my logs statements to come from where the code is being executed.
>
> Looking at the play.Logger source code, I believe you can still
> achieve what you want by setting "application.log.recordCaller" to
> true in application.conf.  Look closely at the code though, it uses
> stack traces to determine calling code, which performs very poorly.

I know the code of Logger very well and as said before it use log4j in
a wrong way (with the side effect to write
'application.log.recordCaller'). However it is there decision to use a
log helper-class. This can be done with log4j *without* loosing the
information from where the logs statements come. The only trade off
you must have by the given api is that everything is logged under one
category. But this is a decision the team makes and which I
respected.

>
> > And you get correct information, about the lines?
>
> Yup, everything is accurate, but this is because I'm using log4j as I
> described in my last post, and not play.Logger.
You wrote before " I've written a thin wrapper class around SLF4J".
Now you call it directly???
Show me the wrapper and the result of %F:%L I'm sure as a result you
will get your wrapper class.

Niels

J

unread,
Aug 23, 2011, 4:59:36 PM8/23/11
to play-framework
> You wrote before " I've written a thin wrapper class around SLF4J". Now you call it directly???

I never said I used log4j directly, did I? I said I wrote a thin
wrapper class around SLF4J and log4j is the backing logger. The
wrapper is simply to add Java 5 varargs support - it does nothing
else. And I have no problems using any of the Pattern letters (with
or without my wrapper).

My original question was simply about "do write wrappers" because I
had never heard of them. I still don't know what a do write wrapper
is.

On Aug 23, 2:35 pm, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 24, 2011, 1:34:33 AM8/24/11
to play-framework
Hi

On 23 Aug., 22:59, J <ja...@sumall.com> wrote:
> > You wrote before " I've written a thin wrapper class around SLF4J". Now you call it directly???
>
> I never said I used log4j directly, did I?  

Sorry you are right.


> I said I wrote a thin
> wrapper class around SLF4J and log4j is the backing logger.  The
> wrapper is simply to add Java 5 varargs support - it does nothing
> else.  And I have no problems using any of the Pattern letters (with
> or without my wrapper).

A wrapper is for me a class which delegates the function-calls to
another class, in his case log4j or sl4fj. If I understand your right,
you have the following situation (caller stack)

Controller -> YourSLFJWrapper -> SLF4J-Interface -> SLF4J-Adapter ->
log4j

So I wonder what trick you have used that %F:%L not give back
YourSLFJWrapper:12.

Niels

J

unread,
Aug 24, 2011, 11:16:05 AM8/24/11
to play-framework
> Controller -> YourSLFJWrapper -> SLF4J-Interface ->  SLF4J-Adapter -> log4j
>
> So I wonder what trick you have used that %F:%L not give back YourSLFJWrapper:12.

The reason %F:%L works for me is because I'm creating a static logger
per class, which is the recommended approach with log4j (and other
logging libraries). So my thin wrapper delegates calls to SLF4J, but
I'm not using a single global wrapper (which is what play.Logger is).
Instead, I have a static wrapper/logger per class.

This was a conscious choice on my part because I did not want a single
global logger like play.Logger. To be honest, I don't see much
benefit to play.Logger unless you just want a single global logger.
Even in that case, it's just as easy to define a static global logger
somewhere in your own code. The other benefit I see is Java 5 varargs
support. For that, I created the aforementioned thin wrapper.

Sorry if I misunderstood your question from before. Hope this helps!

On Aug 24, 1:34 am, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 24, 2011, 12:06:02 PM8/24/11
to play-framework
Hi,

I fear I don't understanding you meaning of wrapper. Could you paste
your "thin wrapper delegates calls to SLF4J" at pastebin or such a
service? I would be really glad to know that SLF4J can be wrapped
without breaking log4j functionality.

> The reason %F:%L works for me is because I'm creating a static logger
> per class, which is the recommended approach with log4j (and other
> logging libraries).
With respect that wrong. %F:%L has nothing to do with the decision to
create a logger per class. This would works fine even if you only have
one log4j-Logger-instance.

J

unread,
Aug 24, 2011, 12:22:24 PM8/24/11
to play-framework
> With respect that wrong. %F:%L has nothing to do with the decision to create a logger per class. This would works fine even if you only have one log4j-Logger-instance.

Now you're confusing me again. You said that %F:%L (and other
uppercase letters) wasn't working correctly for you because it would
always display play.Logger. I'm telling you that this is correct
because you are using a single global Logger. And the reason they
work for me (by "work" I mean they display information from calling
code, not my wrapper class), is because I'm using a static logger per
class. I believe it is precisely why it works for me, and not you.

As for my wrapper, it's really irrelevant. It ONLY provides Java 5
varargs support. If I dont' care about varargs, then I just use SLF4J
directly and everything still works the same. I would still define a
static logger per class because that's the recommended approach.

My wrapper class is too long to paste (also because it spans 3
classes) but here's a quick overview:

1) public interface Logger extends org.slf4j.Logger - this interface
defines 5 methods (trace, error, warn, debug, info) with varargs
arguments

2) public class LoggerImpl implements Logger - implementation of above
interface. Constructor takes in a org.slf4j.Logger instance, which I
use to delegate all logging calls.

3) public class LoggerFactory - this is analogous to
org.slf4j.LoggerFactory. I use this LoggerFactory in order to create
the LoggerImpl instances, and I create one PER CLASS.

That's it. Again, this is ONLY for Java 5 varargs. Otherwise, I
would just use org.slf4j.LoggerFactory to create my logger instances,
and everything should work.

Hope this helps!


On Aug 24, 12:06 pm, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 24, 2011, 1:53:36 PM8/24/11
to play-framework
Hi

On 24 Aug., 18:22, J <ja...@sumall.com> wrote:
> > With respect that wrong. %F:%L has nothing to do with the decision to create a logger per class. This would works fine even if you only have one log4j-Logger-instance.
>
> Now you're confusing me again.  You said that %F:%L (and other
> uppercase letters) wasn't working correctly for you because it would
> always display play.Logger.  I'm telling you that this is correct
> because you are using a single global Logger.  And the reason they
> work for me (by "work" I mean they display information from calling
> code, not my wrapper class), is because I'm using a static logger per
> class.  I believe it is precisely why it works for me, and not you.

Yes and I can give you an example which shows the opposite. I would
repair it in play, but I don't know if it wanted to refactor such a
central class, from a nobody like me. Furthermore the JULI-support
makes it difficult.
The reason why you example works is, that you wrote your own logger,
which calls directly log4j-Logger I assume. There you can give the
FQCN to the log-method. So what must be done in plays Logger:

OldCode
/**
* Log with DEBUG level
* @param message The message pattern
* @param args Pattern arguments
*/
public static void debug(String message, Object... args) {
if (forceJuli || log4j == null) {
try {
juli.fine(format(message, args));
} catch (Throwable ex) {
juli.log(Level.SEVERE, "Oops. Error in Logger !", ex);
}
} else {
try {
if (recordCaller) {

org.apache.log4j.Logger.getLogger(getCallerClassName()).debug(format(message,
args));
} else {
log4j.debug(format(message, args));
}
} catch (Throwable ex) {
log4j.error("Oops. Error in Logger !", ex);
}
}
}

should be
/**
* Log with DEBUG level
* @param message The message pattern
* @param args Pattern arguments
*/
public static void debug(String message, Object... args) {
if (forceJuli || log4j == null) {
try {
juli.fine(format(message, args));
} catch (Throwable ex) {
juli.log(Level.SEVERE, "Oops. Error in Logger !", ex);
}
} else {
try {
org.apache.log4j.Logger currentLogger = log4j;
if (recordCaller) {
currentLogger =
org.apache.log4j.Logger.getLogger(getCallerClassName());
}
if (currentLogger.isDebugEnabled())
{
currentLogger.log(Logger.class.getName(),
org.apache.log4j.Level.DEBUG, format(message, args), null);
}

} catch (Throwable ex) {
log4j.error("Oops. Error in Logger !", ex);
}
}
}

Then %F%L would work perfectly. The key to enable this is to give
Logger.class.getName() to the log-method. Unfortunately neither
logback nor slf4j has such a functionality. Which makes a correct
implementation of plays Logger impossible.

> As for my wrapper, it's really irrelevant.  It ONLY provides Java 5
> varargs support.  If I dont' care about varargs, then I just use SLF4J
> directly and everything still works the same.  I would still define a
> static logger per class because that's the recommended approach.
>
> My wrapper class is too long to paste (also because it spans 3
> classes) but here's a quick overview:
>
> 1) public interface Logger extends org.slf4j.Logger - this interface
> defines 5 methods (trace, error, warn, debug, info) with varargs
> arguments
>
> 2) public class LoggerImpl implements Logger - implementation of above
> interface.  Constructor takes in a org.slf4j.Logger instance, which I
> use to delegate all logging calls.
>
> 3) public class LoggerFactory - this is analogous to
> org.slf4j.LoggerFactory.  I use this LoggerFactory in order to create
> the LoggerImpl instances, and I create one PER CLASS.
>
> That's it.  Again, this is ONLY for Java 5 varargs.  Otherwise, I
> would just use org.slf4j.LoggerFactory to create my logger instances,
> and everything should work.
>
> Hope this helps!
>

So if you send the code of one method of your LoggerImpl which calls
the delegater-class. I think it will become clear.

Niels

J

unread,
Aug 24, 2011, 2:11:31 PM8/24/11
to play-framework
> The reason why you example works is, that you wrote your own logger, which calls directly log4j-Logger I assume. There you can give the FQCN to the log-method.

I'm not sure why you don't believe me when I say that I'm not doing
anything special in my wrapper class. IT'S ONLY USED FOR JAVA 5
VARARGS SUPPORT.

You don't have to manually supply a FQCN in order to get %F:%L to work
properly UNLESS you are trying to do something clever like use a
global logger (like play.Logger). As I mentioned, I see very little
benefit to using play.Logger so I'm just using SLF4J (and log4j) the
STANDARD way, which will allow log4j to work as it is. %F:%L or
anything else just works the way it was intended.

Since you don't seem to believe me that my wrapper has nothing to do
with why %F:%L works, here it is: http://pastebin.com/RtnGEG9Q

Hopefully my usage of SLF4J on top of log4j is clear to you now. As
you can see, nothing special. I don't even reference log4j in my
wrapper code. Log4j is used because slf4j-log4j12-1.6.1.jar is
included with Play and is part of the classpath. The hope for me (and
many others I believe) is that logback can be used. And now that I
think about it, I might be able to use logback by putting the jar file
in front of slf4j-log4j12-1.6.1.jar, with zero code changes because
I'm using the SLF4J interface in my code. I will give that a try when
I have time.

I think this thread is no longer relevant to your original post about
JULI.

On Aug 24, 1:53 pm, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 24, 2011, 3:16:06 PM8/24/11
to play-framework
Hi,

On 24 Aug., 20:11, J <ja...@sumall.com> wrote:
> > The reason why you example works is, that you wrote your own logger, which calls directly log4j-Logger I assume. There you can give the FQCN to the log-method.
>
> I'm not sure why you don't believe me when I say that I'm not doing
> anything special in my wrapper class.  IT'S ONLY USED FOR JAVA 5
> VARARGS SUPPORT.
>
> You don't have to manually supply a FQCN in order to get %F:%L to work
> properly UNLESS you are trying to do something clever like use a
> global logger (like play.Logger).  As I mentioned, I see very little
> benefit to using play.Logger so I'm just using SLF4J (and log4j) the
> STANDARD way, which will allow log4j to work as it is.  %F:%L or
> anything else just works the way it was intended.
>
> Since you don't seem to believe me that my wrapper has nothing to do
> with why %F:%L works, here it is:http://pastebin.com/RtnGEG9Q
>
> Hopefully my usage of SLF4J on top of log4j is clear to you now.  As
> you can see, nothing special.  I don't even reference log4j in my
> wrapper code.  Log4j is used because slf4j-log4j12-1.6.1.jar is
> included with Play and is part of the classpath.  The hope for me (and
> many others I believe) is that logback can be used.  And now that I
> think about it, I might be able to use logback by putting the jar file
> in front of slf4j-log4j12-1.6.1.jar, with zero code changes because
> I'm using the SLF4J interface in my code.  I will give that a try when
> I have time.
>
> I think this thread is no longer relevant to your original post about
> JULI.

Well it's happens as feared it became a discussion about slf4j :-(
How ever I will see if can make a small app run able with your code. I
want to understand how %F will work in such a situation. Log4j
normally used FQCN for that. So it's difficult to me to believe that
it work. Specially I can't see the differences between your code and
the plays Logger, except that you use the Class as category. Perhaps
SLF4J use the category a FQCN? (np it use final static String FQCN =
Log4jLoggerAdapter.class.getName();) If you interested we could
switch to a private channel. If you can provide a simple "hello world"
it would be great.

And yes it would be great if play could provide there the choice of
using logging library.

Niels

J

unread,
Aug 24, 2011, 6:32:20 PM8/24/11
to play-framework
> So it's difficult to me to believe that it work.

Still skeptical huh? =)

With log4j, you can name your logger anything you want. In the case
of Play's global logger, they simply used the name "play". The
standard way, as I've mentioned, is to create a static logger per
class. Java's package hierarchy gives you a natural way of dividing
your logging statements by component.

Don't believe me? Here's a direct cut & paste from log4j's manual
(http://logging.apache.org/log4j/1.2/manual.html)

"Log4j makes it easy to name loggers by software component. This can
be accomplished by statically instantiating a logger in each class,
with the logger name equal to the fully qualified name of the class.
This is a useful and straightforward method of defining loggers. As
the log output bears the name of the generating logger, this naming
strategy makes it easy to identify the origin of a log message.
However, this is only one possible, albeit common, strategy for naming
loggers. Log4j does not restrict the possible set of loggers. The
developer is free to name the loggers as desired.

Nevertheless, naming loggers after the class where they are located
seems to be the best strategy known so far."

I choose to use the standard practice because there are many benefits
to it. I love Play, but I see very little benefit to using
play.Logger. But it's only my opinion.



On Aug 24, 3:16 pm, GrailsDeveloper <opensourc...@googlemail.com>
wrote:

GrailsDeveloper

unread,
Aug 25, 2011, 3:21:03 AM8/25/11
to play-framework
Hi,

On 25 Aug., 00:32, J <ja...@sumall.com> wrote:
> > So it's difficult to me to believe that it work.
>
> Still skeptical huh?  =)

Yes, because I look into the code of log4j and now again into SLF4J.
And after code-analysis it shouldn't work. So I still believe that you
see the class-name where you log, but I have doubt that you really see
the exact line number and filename. This is something I only believe
if I see a log snippet with the information.

>
> With log4j, you can name your logger anything you want.  In the case
> of Play's global logger, they simply used the name "play".  The
> standard way, as I've mentioned, is to create a static logger per
> class.  Java's package hierarchy gives you a natural way of dividing
> your logging statements by component.
>
> Don't believe me?  Here's a direct cut & paste from log4j's manual
> (http://logging.apache.org/log4j/1.2/manual.html)

Yes that right. Using Logger.getLogger(MyClass.class.getName()) is a
common pattern (I prefer getPackagename() for performance reasons,
because we have as our log the Classname as a special parameter). And
you get with it very simple the classname by %c with is more clever
than %C, which should the same if you name the class-name as Logger-
name. And it will be much faster. To be honest I'm unhappy with
logging everything under one category too. But as you know you have
the choice for your own classes.

Another clever solution is http://www.playframework.org/modules/betterlogs,
which adds many detail-information by class enhancing.

>
> I choose to use the standard practice because there are many benefits
> to it.  I love Play, but I see very little benefit to using
> play.Logger.  But it's only my opinion.
>

I hope you are not angry, that I'm so skeptical, but I see so much bad
log-implementations and I never the for slf4j a solution. If you can
send me via mail a little HelloWorld.java which produces the log-file
it would be really appreciated. I can promise you that I will destroy
them after I have understand the behavior of slfj4.

Niels

J

unread,
Aug 25, 2011, 11:06:35 AM8/25/11
to play-fr...@googlegroups.com
Perhaps you're right that %F or %L may not work.  Honestly I never use those letters because it's not recommended as performance is really poor.  All the uppercase letters have warnings about their usage: http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

But my main reason behind not using play.Logger is because I want to use a logger per class so that I can tune logging levels for specific components at runtime to debug problems.    In addition, I really wanted to use SLF4J as the interface so that I can switch to logback in the future.

> but I see so much bad log-implementations and I never the for slf4j a solution.

You do realize that SLF4J and logback was created by the original author of log4j, Ceki Gulcu??

Gülcü has since started the SLF4J and Logback[1] projects, with the intention of offering a successor to log4j.

Anyways, this was a fun thread.  When I have time, I will try to see if I can use logback in Play.  I will post on this group if I'm successful.

Thanks!

GrailsDeveloper

unread,
Aug 25, 2011, 1:53:19 PM8/25/11
to play-framework
Hi

On 25 Aug., 17:06, J <ja...@sumall.com> wrote:
> Perhaps you're right that %F or %L may not work.  Honestly I never use those
> letters because it's not recommended as performance is really poor.  All the
> uppercase letters have warnings about their
> usage:http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternL...

I know that the upper-case formatting not recommend, how ever if you
say you support log4j, then this should work correctly. Which doesn't
at play. At the moment we can fix it, but with logback or slf4j not.
Can you please so kindly and try %F.%L and check the result, so that
we could get this point clear?

>
> But my main reason behind not using play.Logger is because I want to use a
> logger per class so that I can tune logging levels for specific components
> at runtime to debug problems.    In addition, I really wanted to use SLF4J
> as the interface so that I can switch to logback in the future.
>
> > but I see so much bad log-implementations and I never the for slf4j a
>
> solution.
>
> You do realize that SLF4J and logback was created by the original author of
> log4j, Ceki Gulcu??
>
> http://en.wikipedia.org/wiki/Log4j:
> *Gülcü has since started the SLF4J <http://en.wikipedia.org/wiki/SLF4J> and
> Logback[1] <http://en.wikipedia.org/wiki/Log4j#cite_note-0> projects, with
> the intention of offering a successor to log4j.
> *

Yes I know this and was wondering, because before he was strongly
against layers like slf4j as long as he worked on log4j. As the moment
he start the commercial logback he starts thinking about a bridge, so
that the user can migrate. I think it was it's only change to create a
new log system.

>
> Anyways, this was a fun thread.  When I have time, I will try to see if I
> can use logback in Play.  I will post on this group if I'm successful.
>
> Thanks!

And please check the%F.%L.
Niels

J

unread,
Aug 26, 2011, 11:51:59 AM8/26/11
to play-fr...@googlegroups.com
I ran a quick test with two examples: one using my varargs wrapper, and one directly using SLF4J:

public class LoggerTest extends BaseController {

    protected static framework.logging.Logger WITH_WRAPPER = framework.logging.LoggerFactory.getLogger(LoggerTest.class);

    protected static org.slf4j.Logger WITHOUT_WRAPPER = org.slf4j.LoggerFactory.getLogger(LoggerTest.class);        

    public static void log() throws Exception {

        WITH_WRAPPER.info("A dumb log message");        

        WITHOUT_WRAPPER.info("A dumb log message");

    }

}

This is the PatternLayout I used (in log4j.xml):

            <param name="ConversionPattern" value="%d{ISO8601} %t %-5p %F:%L %C.%M ~ %m%n" />

The results were:

2011-08-26 15:42:51,708 play-thread-1 INFO  LoggerImpl.java:195 framework.logging.LoggerImpl.info ~ A dumb log message

2011-08-26 15:42:51,708 play-thread-1 INFO  LoggerTest.java:19 controllers.LoggerTest.log ~ A dumb log message


So with my wrapper, %F:%L %C.%M is not correct as you suspected.  BUT, it is correct if you just use SLF4J directly which is probably the recommended way.  For me, since I never use %F:%L %C.%M (due to poor performance), I feel like the benefit of having Java 5 varargs semantics is worth the wrapper class.  Note that my wrapper class is VERY different than play.Logger, which uses a single global logger (named "play").  Other than the thin Java 5 wrapper, I'm still using SLF4J the proper way and therefore I can change log levels per component (i.e. I can turn on DEBUG for all controllers, but not models, etc.).

I still hope to use logback one day, which I think is possible since I'm not using play.Logger.  I'll report back if I succeed.

Anyways, it was good discussing this with you!

Reply all
Reply to author
Forward
0 new messages