1

I am using Spring IOC and autowired bean of Logger which is a custom wrapper around logger.

    @Autowired
    private Loggers logger;

which has some wrapper code basically for formatting string's and printing values of enumns in case enums are passed.

       public class Loggers implements Serializable {

        private static final long serialVersionUID = 1L;

        public static Logger TRACE = LogManager.getLogger("com.mypackage.class");
        public static String msgXidFormat = " %s : %s : %s ";
        public static String msgFormat = " %s : %s ";

        public static Logger getLogger(Class clazz) {
            Logger logger = LogManager.getLogger(clazz);
            return logger;
        }

        public void info(String message) {
            TRACE.info(String.format(msgXidFormat,message);
        }
}

And there are some statements which are logged from the Application classes where this Logger bean has been autowired for Ex ::

logger.info("Lion is the king of the Jungle");

where logger refers to the above class.

And this is the log4j pattern Layout in log4j2.xml I am using to print the message along with Class name and Line Number.

<PatternLayout pattern="%d{ISO8601}{GMT} %-5p %c{1}:%L - %m%n"/>

But I am getting the class name for every class as Loggers where i expect the class from which this log statement was first requested. Is there any way i can handle this by not changing the code,as there are lot of classes where this been has been autowired. If any one had faced similar situation or have some idea on it please Share.

Anand Kadhi
  • 1,790
  • 4
  • 27
  • 40
  • I don't see anywhere in your code where the logger may learn the class of the caller. Is this because you don't know how, or am I missing anything ? – merours Aug 19 '15 at 09:32
  • @fxm, That is the thing, and there are ample of classes where the Logger class is autowired,I am looking for an approach to not change by going into every class and changing, but rather any shortcut approach if caller information can be told the Logger. – Anand Kadhi Aug 19 '15 at 09:37
  • You are using the `TRACE` - Logger always. That's why it will log always `Loggers` classname. You'd have to use `getLogger` to get a class-specific Logger. Don't know how that's done with Spring IOC, though. – Fildor Aug 19 '15 at 09:49
  • A quick and dirty (and hacky) solution would be to get the classname from the stack trace with the following code : `Thread.currentThread().getStackTrace()[2].getClassName();` Here, I'm accessing the third entry because 0 is `Thread` and `1` is `Loggers`. I'll take a closer look after lunch :) – merours Aug 19 '15 at 10:03
  • @fxm, Thanks for the update but i didn't find a way to incorporate this into existing class as i am directly calling the info method of the apache logger. can you suggest – Anand Kadhi Aug 19 '15 at 10:23
  • @fxm, There is also no setter available from the apache Logger which we can use to set runtime class name. – Anand Kadhi Aug 19 '15 at 10:42
  • Can't you use this snippet in your Loggers#getLogger ? – merours Aug 19 '15 at 13:04
  • 1
    To do what you want you have to create a LoggerFactory that extends AbstractLoggerFactory and a Custom Logger. This is necessary so you can define the FQCN of your LoggerFactory and Logger. Once you do that Log4j will be able to determine what class is calling your implementation. You can see examples of this in Log4j itself as the SLF4J adapter, The Log4j 1.x bridge also does something similar. – rgoers Aug 26 '15 at 06:32
  • This is the problem with field injection. If you want a shortcut, Aspects? – mttdbrd Sep 23 '15 at 16:31
  • possible duplicate of [Spring autowired...pass source class to autowired class](http://stackoverflow.com/questions/25717778/spring-autowired-pass-source-class-to-autowired-class) – mttdbrd Sep 23 '15 at 16:35
  • 1
    Looks like this has already been answered. Use reflection: http://stackoverflow.com/questions/25717778/spring-autowired-pass-source-class-to-autowired-class – mttdbrd Sep 23 '15 at 16:35

0 Answers0