[hibernate-dev] Obtaining loggers
Steve Ebersole
steve at hibernate.org
Wed May 22 09:51:36 EDT 2013
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/>
>
>
> 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>
> <mailto:hibernate-dev at lists.__jboss.org
> <mailto:hibernate-dev at lists.jboss.org>>
>
> >
> 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>
> <mailto:hibernate-dev at lists.__jboss.org
> <mailto:hibernate-dev at lists.jboss.org>>
> https://lists.jboss.org/__mailman/listinfo/hibernate-dev
> <https://lists.jboss.org/mailman/listinfo/hibernate-dev>
>
>
>
>
More information about the hibernate-dev
mailing list