Overview of log4j configuration - java

I am rather confused by how to configure Log4j I have picked up following snippets, but something written that pulls these concepts together would be useful.
Log4j looks for properties/xml files in the CLASSPATH
You can supply
your own file using PropertyConfigurator.configure(filename) - what
if you call this twice. Are the files effectively merged or is only
the last one used.
You can supply an explicit file using -D on the
command line
I want to be able to
Supply a basic config file that remains static
Allow an individual developer to add an additional file with extra options without having ot exit this main file.

According to this documentation
The existing configuration is not cleared nor reset.
log4j itself stops at the first log4j.properties it find.
So when you call configure, my guess is:
if some configuration is already done then the current will be merged.
if configuration has not been done then log4j will not attempt to read any other log4j.properties
Your best best is to probably call configure with global and then with developer-specific file. But this should be easy to test.

Related

java.util.logging stops working when I incorporate a library that uses Log4j 2

I have an existing application that logs messages using the java.util.logging API. As far as I can see, there are no configuration files for it in the framework, though there is some code to create a file appender. When I run the application, I get log messages to the console and to a file.
Now, I need to incorporate a library that uses Log4j 2. When I do so, I lose the console logging from the main application (though log messages still get written to the file appender that is created programmatically).
I imagine that, since the file appender is working in the original application, that I can solve my problem by also programmatically creating a console appender in the main application. However, I don't know if that's right or a kludge.
So, my question: is there anything general that I need to know about making java.util.logging and Log4j 2 interoperate? If the original application is not coded properly or according to best practices, I can change it.
Now, I need to incorporate a library that uses Log4j 2. When I do so, I lose the console logging from the main application (though log messages still get written to the file appender that is created programmatically).
The
Log4jBridgeHandler will remove handlers if the install method is called from code. You can always print the log tree to see what handlers are attached or attach a tool like JConsole to inspect the logger tree with and without the 3rd party lib.
I imagine that, since the file appender is working in the original application, that I can solve my problem by also programmatically creating a console appender in the main application. However, I don't know if that's right or a kludge.
Programmatic configuration of the logger tree should be done with the LogManager config option:
A property "config". This property is intended to allow arbitrary configuration code to be run. The property defines a whitespace or comma separated list of class names. A new instance will be created for each named class. The default constructor of each class may execute arbitrary code to update the logging configuration, such as setting logger levels, adding handlers, adding filters, etc.
Create a stand alone named class that just installs the handlers in the constructor.
Set the java.util.logging.config.class system parameter to the name of your class.
Otherwise if you have a logging.properties you set config to your class name.
So, my question: is there anything general that I need to know about making java.util.logging and Log4j 2 interoperate? If the original application is not coded properly or according to best practices, I can change it.
The java.util.logging.LogManager can only see classes on the system class loader. In that case log configuration in code is required to gain access to the correct classloader.
It might be easier to remove all JUL configuration and bridge to Log4j2. You can then leverage the configuration needed through that framework.

Delaying Log4j initialization

My application is going to have a configuration file that configures its settings.
I want this to be the only configuration file the application uses,
The application will be run from a jar file, which means that log4j will be started as soon as the application is run.
Is there any way to delay initialization of log4j so i can use information from configuration file to configure log4j and then start log4j?
As Andreas writes, you (or a library you call) obviously use Log4J. But without a short code example, we can't tell you what's going on (Hint: by removing code to get a short example, you might find the culprit yourself).
According to the Documentation it should even be possible (starting from release 2.4) to change the configuration programmatically after Log4J started.

How to configure J.U.L. logging during JUnit tests?

I have the same problem as this: How to set the log level to DEBUG during Junit tests? - except I'm working with java.util.logging, not Log4j.
Specifically, I'm converting an existing (Maven-built) application from Log4j to java.util.logging, in order to comply with a customer requirement (not negotiable). Everything uses SLF4J, so code changes are minimal. There are over a thousand test classes, spread across a few modules; we currently have a log4j.properties file in the src/test/resources of those modules to customize the log output of the tests.
I think it's important for log output to be easily customizable for tests: if a developer breaks a test and wants to read the log output, I'd prefer they locally tweak the log config than start messing with the (carefully chosen) log levels in the code, leading to "everything logged at info" syndrome. Note that I want the test log config to apply to "the test+application code when executed under test conditions".
I don't want to add log settings to each and every Test class (as suggested here: How to set the Loglevel for a JUnit Test), because of the large number of tests. It seems like the wrong solution. I also don't want to go editing the JVM's logging.properties file, as that would affect everything. This app isn't the only thing I do. I'd also have to get everyone else to make the same changes.
The existing system works because Log4j picks up /log4j.properties from the classpath. Is there an equivalent mechanism for java.util.logging?
Current thinking: add a logging.properties file to replace the existing config, and try and hack the Maven config to set the java.util.logging.config.file param to point at it. Is there a neater way?
A project-wide src/test/resources/logging.properties can be set specifically for unit testing via the java.util.logging.config.file System property using a single line in your #BeforeClass method:
System.setProperty("java.util.logging.config.file", ClassLoader.getSystemResource("logging.properties").getPath());
Is there a neater way?
That is probably the most reliable method to set the logging configuration.
Is there an equivalent mechanism for java.util.logging?
Configuration options are listed in the java.util.logging.LogManager documentation. You can:
Set the java.util.logging.config.file property and use a properties file.
Set the java.util.logging.config.class property and create a class file with a no argument constructor to execute any code you desire to manually configure the loggers.
Use LogManager.readConfiguration(InputStream) and ClassLoader.getResourceAsStream(String) to load a new configuration. This logic can be combined with java.util.logging.config.class property too.

How can we tell log4j where is the properties file?

I know we can put it in the home directory of the project and it works as a charm. But really I want to put it under a directory name "Conf" for convenience of later maintenance. How can we do this?
log4j gives option to use different file as input. Also you can do a watch on the contents. See http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PropertyConfigurator.html#configureAndWatch(java.lang.String, long) for details
I don't know about 'we', but the log4j documentation is perfectly clear.
http://logging.apache.org/log4j/1.2/manual.html will tell you that log4j searches for log4j.properties or log4j.xml in the classpath, until and unless you use a system property to tell it to look for a different file or in a different place.
You might also find http://robertmaldon.blogspot.com/2007/09/programmatically-configuring-log4j-and.html interesting as an example of explicit configuration from code; it does not use a log4j.properties At All.

Update log4j within app and have log4j.properties updated

I have multiple applications using log4j for their logging, each loading settings from separate log4j.properties loaded from the classpath (just a file on disk, not in a .jar or anything that would make it read-only). In each of these applications, I want to allow updating the log level through the regular UI.
I use a common utility class for this, which is shared between applications. I can do that for the lifetime of the app, but since the changes aren't persisted back out to the appropriate log4j.properties file, on next restart, it's reset to the specific level in the properties file.
Since it's just loaded from the classpath, I don't know the full path to the logfile in each application, and since it's a common class, I'd rather not hardcode paths. Is there a way to get log4j to write back its changes to its on-disk configuration?
I suggest you flip the problem on its head.
Always write changes to the log4j.properties file on disk, and then install the listener that checks for changes in that file and updates the appropriate log levels.

Categories

Resources