[hibernate-dev] Obtaining loggers

Gunnar Morling gunnar at hibernate.org
Wed May 22 10:56:22 EDT 2013


I agree in general, addressing the issue at build time is surely better.

Given that the logger is obtained only once per class I'd think the
difference is not huge, though. In particular I think SecurityManager#**
getClassContext() should be fast since it is on the execution path of all
the j.l.Class methods such as getFields() etc. (when a security manager is
enabled). So I'd assume the calls from LoggerFactory shouldn't make a big
difference. I haven't measured it, though.

--Gunnar


2013/5/22 Steve Ebersole <steve at hibernate.org>

> Both really.  You are adding a runtime performance hit to offset a
> possible development-time error.  To me (if this is a real problem y'all
> have had to deal with), I'd rather see a build time check
> (checkstyle/findbugs rule maybe) that validates this by making sure that
> obtaining a logger is not passing a class other than the calling class.
>
>
> On Wed 22 May 2013 08:42:37 AM CDT, Gunnar Morling wrote:
>
>> 2013/5/22 Steve Ebersole <steve at hibernate.org
>> <mailto:steve at hibernate.org>>
>>
>>     I am not a fan of what goes on inside LoggerFactory.make().
>>      That's just my opinion.
>>
>>
>> Why is this?
>>
>> Which approach do you mean, the one creating a stack trace or the
>> other one using SecurityManager#**getClassContext()? Or both :)
>>
>>
>>
>>
>>     On Wed 22 May 2013 08:05:51 AM CDT, Sanne Grinovero wrote:
>>
>>         Let's simplify my reply to address verbosity only then:
>>         Search does:
>>
>>             private static final Log log = LoggerFactory.make();
>>
>>         Looks good?
>>
>>         Sanne
>>
>>         On 22 May 2013 13:57, Steve Ebersole <steve at hibernate.org
>>         <mailto:steve at hibernate.org>> wrote:
>>
>>             Y'all are trying to solve a different problem imo.
>>
>>             The "problem" I am looking to solve is simply verbosity.
>>              Both the problem
>>             and the solution have an equal possibility for copy-paste
>>             errors.
>>
>>             Whereas y'all are trying to remove the possibility of
>>             these copy-paste
>>             problems.  BTW, I use IntelliJ IDEA "Live templates" to
>>             deal with that. I
>>             have a template named log; so I simply type "log"+TAB and
>>             get a proper log
>>             statement.
>>
>>
>>             On Wed 22 May 2013 02:51:03 AM CDT, Gunnar Morling wrote:
>>
>>
>>                 2013/5/21 Sanne Grinovero <sanne at hibernate.org
>>                 <mailto:sanne at hibernate.org>
>>                 <mailto:sanne at hibernate.org <mailto:sanne at hibernate.org
>> >>>
>>
>>
>>
>>                      Have you seen how Search does it?
>>
>>                          private static final Log log =
>>                 LoggerFactory.make();
>>
>>                      The implementation of LoggerFactory#make is:
>>
>>                         public static Log make() {
>>                              Throwable t = new Throwable();
>>                              StackTraceElement directCaller =
>>                 t.getStackTrace()[1];
>>                              return Logger.getMessageLogger( Log.class,
>>                      directCaller.getClassName() );
>>                          }
>>
>>                      We introduced this a while back after having
>>                 spotted some copy/paste
>>                      mistakes which had lead to have the wrong logger;
>>                 however there is a
>>                      catch:
>>                      each class initialization triggers a stacktrace
>>                 initialization. Sure
>>                      it's an initialization cost only, but still I
>>                 wonder how large the
>>                      cost is, adding up all classes: maybe we should
>>                 just replace it with a
>>                      checkstyle rule to verify its correctness.
>>
>>
>>                 An alternative implementation of LoggerFactory could
>>                 be this (based on
>>                 [1]):
>>
>>                      public final class LoggerFactory {
>>
>>                 private static CallerProvider callerProvider = new
>>                 CallerProvider();
>>
>>                          public static Log make() {
>>                              return Logger.getMessageLogger( Log.class,
>>                 callerProvider.getCallerClass(**__).getCanonicalName() );
>>
>>                          }
>>
>>                          private static class CallerProvider extends
>>                 SecurityManager {
>>                              public Class<?> getCallerClass() {
>>                                  return getClassContext()[2];
>>                          }
>>                      }
>>
>>                 SecurityManager#__**getClassContext() is a native
>>
>>                 method, so one doesn't
>>                 know how it is implemented, but I guess it's faster
>>                 than initializing
>>                 a stack trace, while still allowing for the concise
>>                 LoggerFactory.make(); usage.
>>
>>                 Btw. another copy-and-paste safe pattern enabled by
>>                 Java 7 is this
>>                 (suggested in "The Well-Grounded Java Developer"):
>>
>>                      Logger logger = Logger.getMessageLogger(
>>                          Log.class,
>>                 MethodHandles.lookup().__**lookupClass().__**
>> getCanonicalName()
>>
>>                 );
>>
>>                 This can't be pushed into a factory class, though,
>>                 making more verbose
>>                 than the factory approach.
>>
>>                 --Gunnar
>>
>>                 [1]
>>
>>                 http://beust.com/weblog/2011/_**
>> _07/15/accessing-the-class-__**object-in-a-static-context/<http://beust.com/weblog/2011/__07/15/accessing-the-class-__object-in-a-static-context/>
>>
>>                 <http://beust.com/weblog/2011/**
>> 07/15/accessing-the-class-**object-in-a-static-context/<http://beust.com/weblog/2011/07/15/accessing-the-class-object-in-a-static-context/>
>> >
>>
>>
>>                      Also, each module needs to have its own copy of
>>                 the LoggerFactory to
>>                      hardwire the correct Log.class interface, so you
>>                 could still import
>>                      the LoggerFactory from an alien module by
>>                 mistake, but that's likely
>>                      spotted by the typesafety of it as you wouldn't
>>                 have the expected
>>                      logger methods.
>>
>>                      Sanne
>>
>>
>>                      On 21 May 2013 22:24, Steve Ebersole
>>                 <steve at hibernate.org <mailto:steve at hibernate.org>
>>                      <mailto:steve at hibernate.org
>>
>>                 <mailto:steve at hibernate.org>>> wrote:
>>                      > Forgot...  So really this just allows more
>>                 conciseness in
>>                      obtaining the
>>                      > logger.  So from:
>>                      >
>>                      > private static final CoreMessageLogger LOG =
>>                      Logger.getMessageLogger(
>>                      > CoreMessageLogger.class,
>>                 CollectionLoadContext.class.__**getName() );
>>
>>                      >
>>                      > to:
>>                      >
>>                      > private static final CoreMessageLogger LOG =
>>                      CoreLogging.messageLogger(
>>                      > CollectionLoadContext.class );
>>                      >
>>                      >
>>                      > On 05/21/2013 04:21 PM, Steve Ebersole wrote:
>>                      >> I was getting tired of statements in the
>>                 source code to get logger
>>                      >> instances that spread across sometimes 4 lines
>>                 because of JBoss
>>                      >> Logging's verbose means of acquiring a message
>>                 logger.  So I
>>                      created a
>>                      >> more concise form for this for hibernate-core,
>>                      hibernate-entitymanager
>>                      >> and hibernate-envers.  I mainly limited it to
>>                 these projects
>>                      because
>>                      >> they have lots of these calls, whereas the
>>                 others do not.  Feel
>>                      free
>>                      >> to copy the approach to the other projects if
>>                 someone wants.
>>                      >>
>>                      >> Essentially each of those projects define a
>>                 class with 4 static
>>                      >> methods.  Taking the hibernate-core one as an
>>                 example:
>>                      >>
>>                      >>
>>                      >> import org.jboss.logging.Logger;
>>                      >>
>>                      >> /**
>>                      >>  * Quite sad, really, when you need helpers
>>                 for generating
>>                      loggers...
>>                      >>  *
>>                      >>  * @author Steve Ebersole
>>                      >>  */
>>                      >> public class CoreLogging {
>>                      >>     /**
>>                      >>      * Disallow instantiation
>>                      >>      */
>>                      >>     private CoreLogging() {
>>                      >>     }
>>                      >>
>>                      >>     public static CoreMessageLogger
>>                 messageLogger(Class
>>                      >> classNeedingLogging) {
>>                      >>         return messageLogger(
>>                 classNeedingLogging.getName() );
>>                      >>     }
>>                      >>
>>                      >>     public static CoreMessageLogger
>>                 messageLogger(String
>>                      loggerName) {
>>                      >>         return Logger.getMessageLogger(
>>                 CoreMessageLogger.class,
>>                      >> loggerName );
>>                      >>     }
>>                      >>
>>                      >>     public static Logger logger(Class
>>                 classNeedingLogging) {
>>                      >>         return Logger.getLogger(
>>                 classNeedingLogging );
>>                      >>     }
>>                      >>
>>                      >>     public static Logger logger(String
>>                 loggerName) {
>>                      >>         return Logger.getLogger( loggerName );
>>                      >>     }
>>                      >> }
>>                      >>
>>                      >> I just plan on replacing these calls as
>>                 opportunities arise, rather
>>                      >> than all in one fell swoop.
>>                      >
>>                      > ______________________________**
>> ___________________
>>
>>                      > hibernate-dev mailing list
>>                      > hibernate-dev at lists.jboss.org
>>                 <mailto:hibernate-dev at lists.**jboss.org<hibernate-dev at lists.jboss.org>
>> >
>>                 <mailto:hibernate-dev at lists.__**jboss.org<http://jboss.org>
>>                 <mailto:hibernate-dev at lists.**jboss.org<hibernate-dev at lists.jboss.org>
>> >>
>>
>>                      >
>>                 https://lists.jboss.org/__**
>> mailman/listinfo/hibernate-dev<https://lists.jboss.org/__mailman/listinfo/hibernate-dev>
>>                 <https://lists.jboss.org/**mailman/listinfo/hibernate-dev<https://lists.jboss.org/mailman/listinfo/hibernate-dev>
>> **>
>>                      ______________________________**___________________
>>
>>                      hibernate-dev mailing list
>>                 hibernate-dev at lists.jboss.org
>>                 <mailto:hibernate-dev at lists.**jboss.org<hibernate-dev at lists.jboss.org>
>> >
>>                 <mailto:hibernate-dev at lists.__**jboss.org<http://jboss.org>
>>                 <mailto:hibernate-dev at lists.**jboss.org<hibernate-dev at lists.jboss.org>
>> >>
>>                 https://lists.jboss.org/__**
>> mailman/listinfo/hibernate-dev<https://lists.jboss.org/__mailman/listinfo/hibernate-dev>
>>                 <https://lists.jboss.org/**mailman/listinfo/hibernate-dev<https://lists.jboss.org/mailman/listinfo/hibernate-dev>
>> **>
>>
>>
>>
>>
>>


More information about the hibernate-dev mailing list