Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

log4j2: Location for setting Log4jContextSelector system property for asynchronous logging

I am attempting to set up asynchronous logging (for performance reasons) within REST web methods that currently run in a liberty profile server.

In order to do this, I have set up the following property:

System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");

My problem is that no matter where I do this, sometimes it works and logging is very fast, and sometimes it doesn't.

I have tried (a) in the constructor for the class containing all the REST web methods (b) in the filter doFilter method that gets called prior to the REST method (c) in the filter init method (d) in the REST method itself

None of these locations work consistently.

Can anyone offer an explanation for this behaviour, and if possible a suggested way of fixing the problem.

EDIT: It appears that log4j is being initialised prior to calling setProperty. So what I need to do is set up the property via liberty profile instead.

like image 210
James Hutchinson Avatar asked Nov 26 '14 16:11

James Hutchinson


People also ask

Where do Log4j2 properties go?

We should put log4j2. properties anywhere in the application's classpath. Log4j2 will scan all classpath locations to find out this file and then load it. We have put the file in resources folder.

What is root logger in Log4j2?

This concept is known as Logger Hierarchy. Logger Hierarchy is made up of set of LoggerConfig objects with a parent-child relationship. The topmost element in every Logger Hierarchy is the Root Logger. If Log4j2 doesn't find the configuration file, only Root Logger will be used for logging with logging level as ERROR.

What is AsyncLoggerContextSelector?

public class AsyncLoggerContextSelector extends ClassLoaderContextSelector. ContextSelector that manages AsyncLoggerContext instances. As of version 2.5, this class extends ClassLoaderContextSelector for better web app support.


2 Answers

There is an undocumented method of setting this value for your project without having to manually pass in the system property value during start up.

Add a file named log4j2.component.properties to your classpath. This can be done in most maven or gradle projects by saving it in src/main/resources.

This is file is simply java.util.Properties file. Set the value for the context selector by adding the following line to the file.

Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector

Log4j will attempt to read the system property first. If the system property is null, then it will fall back to the values stored in this file by default.

The code that performs this setup is located at Log4jContextFactory.java:91.

File Location

like image 116
Jamel Toms Avatar answered Sep 19 '22 09:09

Jamel Toms


My problem is that no matter where I do this, sometimes it works and logging is very fast, and sometimes it doesn't.

Add that code in a static initializer block in the class that defines your main entry point.

public class MainClass {
    // NOTE: Nothing can appear before this initializer
    // NOTE: This initializer must be in the class that contains your entry point
    static {
        System.setProperty("Log4jContextSelector",
            "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
    }

    public static void main(final String[] args) {
        // Do anything you want to here
    }
}

According to the Java specification, static initialization occurs in the order it is declared. Therefore, the System.setProperty call is guaranteed to happen before the Log4j initialization.

like image 37
Jeff G Avatar answered Sep 20 '22 09:09

Jeff G