T Master This kind of intrusive wrapping around Log4j categories have been discussed and disapproved on this mailinglist numerous times. I'm sure you can see why.
A true generic wrapping around an underlying log provider would have to utilize interfaces, factories and adapters to real implementions in a way that the underlying API could be substituted by configuration settings. Regards, -- Thomas | -----Original Message----- | From: T Master [mailto:[EMAIL PROTECTED]] | Sent: 14 January 2002 20:48 | To: Log4J Users List | Subject: Re: Clever Logging? | | | Easy. | | What I did was this: | Define a class that has methods to log under differerent Categories: | | e.g. | | MyLogger | { | Category good = Category.getInstance("GOOD"); | Category error = Category.getInstance("ERROR"); | | public void logGood( String msg){ good.info(msg); } | | public void logError( String msg){ err.info(msg); } | | public boolean isGoodEnabled() { return good.isInfoEnabled(); } | public boolean isErrorEnabled() { return error.isInfoEnabled(); } | | } | | | This way, no developers knew the underneath api (could be swapped | in future | or whatever else). | Also, copy and paste programmers wouldn't have to be shot by me :o) | | | T Master | | | ----- Original Message ----- | From: "Silvert, Stan" <[EMAIL PROTECTED]> | To: <[EMAIL PROTECTED]> | Sent: Monday, January 14, 2002 1:39 PM | Subject: Clever Logging? | | | > I am responsible for defining standards around how our developers use | Log4J. | > When our company started using Log4J a couple of months ago, I told | > developers to use this technique in their code: | > | > public class MyClass { | > private static final Category LOG = | > Category.getInstance(MyClass.class.getName()); | > private static boolean DEBUG() { return LOG.isDebugEnabled(); } | > } | > | > So, for all debug statements, write something like this: | > if (DEBUG()) LOG.debug("The value of my vars are: " + v1 + " and " + | v2); | > | > If not a debug statement, just do something like this: | > LOG.info("My info message"); | > | > That all worked fine, except that developers would make the mistake of | > putting the wrong class name inside the getInstance() method. | This would | > usually happen when they would cut and paste code. | > | > So, one of our developers came up with a clever solution to cut down on | the | > mistakes. He created a logging utility that could | automatically read the | > stack frames, discover which class logged the message, and | invoke logging | > from the proper Category. | > | > Here is how he did it: | > | > public class LogUtil { | > /** | > * Extends <code>java.lang.SecurityManager</code> to provide the | > <code>getClassName()</code> | > * method. | > */ | > private static class ClassGetter extends SecurityManager { | > // Inner class necessary because getClassContext() is protected | > | > /** | > * Returns the name of the calling class. | > * @return the name of the calling class | > */ | > public String getClassName() { | > // getClassContext() returns the current execution | stack trace | > // as an array of classes -- the element at index 0 is the | class | > // of the currently executing method, the element at index 1 | is | > // the class of that method's caller, and so on. So, 0 is | going | > // to be this class (ClassGetter), 1 will be LogUtil, and 2 | will | > // be the magic number we are after. | > return getClassContext()[2].getName(); | > } | > } | > private static ClassGetter classGetter = new ClassGetter(); | > | > /** | > * Returns the name of the calling class. | > * Intended to be used from static methods or initializers to | > automagically | > * determine the calling class's name. | > * @return the name of the calling class | > */ | > public static String getClassName() { | > return classGetter.getClassName(); | > } | > | > /////////////////////////////////////////////////////////////////// | > | > /** | > * Returns <code>true</code> if debugging is enabled for a given | > category | > * | > * @return <code>true</code> if debugging is enabled, | > * <code>false</code> if not | > */ | > public static boolean DEBUG() { | > Category cat = Category.getInstance(classGetter.getClassName()); | > return cat.isDebugEnabled(); | > } | > | > /////////////////////////////////////////////////////////////////// | > | > /** | > * Logs the given message with <code>DEBUG</code> priority, to the | > category | > * automagically derived from the calling class name. | > * | > * @param msg the message to log | > */ | > public static void debug(String msg) { | > Category cat = Category.getInstance(classGetter.getClassName()); | > cat.debug(msg); | > } | > } | > | > This looks very nice and seems to solve all the problems quite well - | except | > for one thing. I have been reading about how some JIT's can | remove stack | > frames during optimization. This would cause messages to once again be | > logged under the wrong Category. | > | > My questions to the folks on this list are, | > What is your opinion of both techniques? | > Do you know other developers who have tried the "clever" | approach and run | > into the "disappearing stack frame" problem? | > Is there another solution we are overlooking? (short of | disabling cut and | > paste from everyone's IDE) | > | > Thanks in advance for your input. | > | > Stan Silvert | > | > | > -- | > To unsubscribe, e-mail: | <mailto:[EMAIL PROTECTED]> | > For additional commands, e-mail: | <mailto:[EMAIL PROTECTED]> | > | | | -- | To unsubscribe, e-mail: | <mailto:[EMAIL PROTECTED]> | For additional commands, e-mail: | <mailto:[EMAIL PROTECTED]> | | -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
