0

My class has an Id associated with it when instantiated. I want to be able to log that object level information similar to MDC/PatternLayout. Not sure if this would work if I put it in MDC because I do not know that one thread will execute one method of an object. Is there a way to do it in log4j?

2015-10-01 12:52:03,117 [priority="INFO", thread="ForkJoinPool-1-worker-7", myObjectId="3838901231"] com.company.projectA.classA - initialization started

In the above example myObjectId is for each object that should be printed without writing it in the logger.info() statements.

bluetech
  • 1,380
  • 3
  • 13
  • 22
  • Please clarify: when do you want to log that ID? Only when the object is instantiated? For all log statements associated with that object? When do you _not_ want to log that ID? – Remko Popma Oct 02 '15 at 16:51
  • Id is available after init() is called so after that point I want to print the id in all the logging statements. If the id is not available then it is ok to print empty string. – bluetech Oct 02 '15 at 18:34
  • Edit: I want to log Id in only those statements that are written inside the class. Anything statement outside the class should not print. It is almost like initializing a logger with the class name so that all the statements in the class will print that classname but along with id too if and when it is available. It would be nice to get the flexibility of MDC/PatternLayout. Id is available after init() is called so after that point I want to print the id in all the logging statements. If the id is not available then it is ok to print empty string. – bluetech Oct 02 '15 at 18:45

1 Answers1

1

Usually a logger is most efficiently declared as a static field, like this:

package com.mycomp.xyz;
class MyClass {
    private static Logger logger = LogManager.getLogger(MyClass.class);
    ....

A pattern layout containing %c (the logger name), will show the logger name (in this case com.mycomp.xyz.MyClass) in the log file.

One idea is to do something different and include the ID in the logger name.

So delay creating the logger until you know the ID, and then create it as LogManager.getLogger(getClass().getName() + "." + id). Note that the logger can no longer be a static field because there will be multiple instances: one for each ID.

Then the %c pattern layout converter will include the logger name plus ID for all log statements generated by this logger.

Remko Popma
  • 35,130
  • 11
  • 92
  • 114
  • Actually, I am already doing this but prepending the id [myObjectId="3838901231"] com.company.projectA.classA. I am still looking for a little more flexible way to do it. – bluetech Oct 02 '15 at 19:58
  • What is the problem you want to solve? What aspect don't you like? – Remko Popma Oct 02 '15 at 20:04
  • I have to hard code the key "myObjectId". I could put it in properties file but ideally it should be part of log4j.xml config file so that I can declare all the formatting there. Also, I have to initialize logger once again after I get the Id. – bluetech Oct 02 '15 at 20:58
  • Hm... There are other ways to do this, you could have a custom lookup plugin and perhaps instead of Strings log custom Message objects that include the ID so the lookup can extract the ID, but at this point you have to do a lot of work for this flexibility and I am not sure it's worth it. – Remko Popma Oct 02 '15 at 23:10
  • Would this help? http://stackoverflow.com/questions/27274467/how-to-customize-log4j2-rollingfileappender/27418802#27418802 – Remko Popma Oct 06 '15 at 00:03
  • Thanks for this but you were right there is a lot more work. There will only be one plugin class that has to work with all the instances of class and find out which Id to print. Not sure how that will work. Also, I have to change logging from SLF4J/log4j to log4j only. It's really a good feature of log4j but probbably won't work in my case. – bluetech Oct 06 '15 at 21:21
  • Yes, I think your current solution is a pretty good trade off. – Remko Popma Oct 07 '15 at 01:14