93

Question

Is it possible to make Log4J display the full path of the file it used for configuration?


Background

I have a love-hate relationship with log4j. In good times, it's great but when it's not working, it can be one of the most difficult things to debug. I manage all the logging in our application. As such, I'm very familiar with logging and the default initialization procedure defined in the manual. Still, it seems that, every few weeks, logging breaks and I spend a lot of time sorting out the problem.

This time, it's severely broken. Every single log statement everywhere is being dumped to the console and I can't figure out why. The same exact code base that used my log4j.xml files last week, is suddenly using some other configuration. Nothing obvious has changed. My only guess is, a few dependencies have changed and I suspect Maven has downloaded some evil JAR that's breaking everything.

If I could just figure out which configuration file Log4J decided to use at startup, I could tackle this and most other problems easily.


Summary

Is there some way to tell Log4J to print which file it used for configuration? Alternatively, is there a way to break a running application and use the debugger to answer this question (maybe with an expression or by inspecting variables)?

gMale
  • 17,147
  • 17
  • 91
  • 116
  • 1
    The background sounds like a multiple binding problem. From https://www.slf4j.org/codes.html#multiple_bindings: The warning emitted by SLF4J is just that, a warning. Even when multiple bindings are present, SLF4J will pick one logging framework/implementation and bind with it. The way SLF4J picks a binding is determined by the JVM and for all practical purposes should be considered random. – newur Jun 14 '18 at 12:30

3 Answers3

94

Yes, simply add log4j.debug to the JVM system variables. For example:

java -Dlog4j.debug -cp ... some.class.name

Log4j will then output something like the following:

log4j: Trying to find [log4j.xml] using context classloader sun.misc.Launcher$AppClassLoader@1f7182c1.  
log4j: Using URL [file:/C:/Users/matt/workspace/projectname/target/test-classes/log4j.xml] for automatic log4j configuration.  
log4j: Preferred configurator class: org.apache.log4j.xml.DOMConfigurator  
log4j: System property is :null  
log4j: Standard DocumentBuilderFactory search succeded.  
log4j: DocumentBuilderFactory is: org.apache.xerces.jaxp.DocumentBuilderFactoryImpl  
log4j: debug attribute= "null".  
log4j: Ignoring debug attribute.  
log4j: reset attribute= "false".  
log4j: Threshold ="null".  
...

For reference see the manual and the FAQ.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
matt b
  • 138,234
  • 66
  • 282
  • 345
  • 7
    For some reason, setting this flag does not have any effect in my project, maybe because it uses SLF4J. I tried to get to know why, but I finally ended up checking manually 21 configuration files which are there ;) – Line Oct 17 '18 at 09:52
  • 6
    Note that in log4j2, the property has changed to log4j2.debug, and you also may need to set -Dorg.apache.logging.log4j.simplelog.StatusLogger.level=TRACE if you are trying to debug issues with finding the config file. – user2163960 Mar 27 '20 at 04:59
7

I am using Log4J2 and if you want to get the file from inside your Java Program this worked for me:

LoggerContext lContect = LogManager.getContext();
Field f = lContect.getClass().getDeclaredField("configuration");
f.setAccessible(true);
XmlConfiguration iWantThis = (XmlConfiguration) f.get(lContect);
System.out.println("Config File: " + iWantThis.getName());
Ben
  • 2,771
  • 6
  • 33
  • 45
  • 1
    On the one hand side, this was exactly what I was looking for, on the other hand changing the config file from the output had no effect. So one has to be really really sure that Log4J2 is actually used. I had a multiple binding problem - as described here https://www.slf4j.org/codes.html#multiple_bindings - so the actual logger was slf4j-simple. – newur Jun 14 '18 at 12:27
  • I was also using debugger and set a breakpoint on constructor of org.apache.logging.log4j.util.PropertiesUtil . This is where the files named log4j2.component.properties are located and loaded. I've discovered that two files were loaded, first from target/test-classes and second from target/classes and property from the latter was overwriting property from the first. – rychu Jul 28 '20 at 16:17
  • What are the import statements needed for defining LoggerContext, Field, and XmlConfiguration. My log4j2 jar files do not have Field.class in them (api or core jar). Please add to your example code. Thanks. – Art Swri Dec 02 '21 at 04:33
  • I tried this and I get error message: Exception in thread "main" java.lang.NoSuchFieldException: configuration at java.lang.Class.getDeclaredField(Class.java:2070) – Alain Désilets Feb 07 '22 at 14:00
1

The log4j 2 equivalent for this is to set <Configuration status="trace"> in the configuration file. This will display the location from where the log4j2 configuration file is loaded, as well as other internal details of the log4j2 configuration process. By default the status logger level is WARN, so you only see notifications when there is a problem.

If the configuration file is not found correctly, you can still enable log4j2 internal status logging by setting system property org.apache.logging.log4j.simplelog.StatusLogger.level to TRACE.

Remko Popma
  • 35,130
  • 11
  • 92
  • 114
  • 12
    But if you're trying to find out which configuration value is being used, adding that to a configuration value that might not be active won't do any good! – Omaha Mar 09 '16 at 17:17
  • 1
    I have the same issue. Reminds me of an old Dilbert cartoon where Dilbert tells a tech support guy that he can't access his email. To which, the tech support guy replies that he can't help him unless he sends him a formal request by email. – Alain Désilets Feb 07 '22 at 13:59