1

There is a class called Test, which extends from Thread. How do I configure log4j2 so that for each Test thread my own log file is created.

I'm trying to do this:

public class Test extends Thread {

private String name;

private Logger LOGGER;

public Test(String name) {
    this.name=name;
}

@Override
public void run() {

    System.setProperty("taskLogFolder", Global.getInstance().getLogRoot().toString());
    System.setProperty("taskLogName", name);

    LoggerContext loggerContext = Configurator.initialize(name, new File(Global.getInstance().getAppRoot()+WEB_INF_DIR+"taskLog4j2.xml").toString());

    LOGGER = loggerContext.getLogger(name);

    for(int i=0;i<100;i++) {
        LOGGER.info(LOGGER.getName()+" "+i);
    }

    //LOGGER.info(LOGGER.getName());

}

}

But at startup one file is output.

new Test("task-8").start();
new Test("task-2").start();
new Test("task-3").start();
new Test("task-4").start();
new Test("task-5").start();
new Test("task-6").start();
new Test("task-7").start();

Earlier I used log4j and there I did it, but I do not understand how.

What am I doing wrong?

taskLog4j2.xml file:

    <?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" monitorInterval = "30">

    <Properties>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [thread-id %T] %l - %msg%n</Property>
    </Properties>

    <Appenders>
        <RollingFile name="fileLogger" fileName="${sys:taskLogFolder}/${sys:taskLogName}.log" filePattern="${sys:taskLogFolder}/${sys:taskLogName}-%d{yyyy-MM-dd}.log">
            <PatternLayout>
                <pattern>${pattern}</pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true" />
            </Policies>
        </RollingFile>

        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="${pattern}" />
        </Console>
    </Appenders>

    <Loggers>
        <Root level="info" additivity="false">
            <appender-ref ref="console" />
            <appender-ref ref="fileLogger" />
        </Root>
        <Logger name="com.test.*" level="info">
            <appender-ref ref="fileLogger" level="info" />
        </Logger>
    </Loggers>

</Configuration>

for @Sudheera answer

2017-12-12 22:22:46,942 task-3 ERROR Unable to invoke factory method in class org.apache.logging.log4j.core.appender.RollingFileAppender for element RollingFile: java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.RollingFileAppender java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.RollingFileAppender
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:229)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:134)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:958)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:898)
at org.apache.logging.log4j.core.appender.routing.RoutingAppender.createAppender(RoutingAppender.java:271)
at org.apache.logging.log4j.core.appender.routing.RoutingAppender.getControl(RoutingAppender.java:255)
at org.apache.logging.log4j.core.appender.routing.RoutingAppender.append(RoutingAppender.java:225)
at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:448)
at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:433)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:403)
at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:63)
at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:146)
at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2116)
at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2100)
at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1994)
at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1966)
at org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1303)
at com.test.Test.run(Test.java:20)
2

1 Answer 1

4

You can write a Log4J config plugin for custom name lookup and use it through a router configuration. Here's the fixed code for you. I have added Log4jThreadLookup class for look up the thread name from the log4j config context. Just make sure this class is available in the class path. I also changed the configuration file and the Test class as well.

Log4jThreadLookup class

package com.test;

import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.lookup.StrLookup;

@Plugin(name = "thread", category = StrLookup.CATEGORY)
public class Log4jThreadLookup implements StrLookup {

    public String lookup(String key) {
        return Thread.currentThread().getName();
    }

    public String lookup(LogEvent event, String key) {
        return event.getThreadName();
    }

}

Configuration

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" monitorInterval = "30">

    <Properties>
        <Property name="pattern">%d{yyyy-MM-dd HH:mm:ss.SSS} [%level] [thread-id %T] %l - %msg%n</Property>
    </Properties>

    <Appenders>
        <Routing name="Routing">
            <Routes pattern="$${thread:threadName}">
                <Route>
                    <RollingFile name="logFile-${thread:threadName}"
                                 fileName="logs/tasks-${thread:threadName}.log" filePattern="logs/tasks-${thread:threadName}-%d{yyyy-MM-dd}.log">
                        <PatternLayout>
                            <pattern>${pattern}</pattern>
                        </PatternLayout>
                        <Policies>
                            <TimeBasedTriggeringPolicy interval="1" modulate="true" />
                        </Policies>
                    </RollingFile>
                </Route>
            </Routes>
        </Routing>
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="${pattern}" />
        </Console>
    </Appenders>

    <Loggers>
        <Root level="info" additivity="false">
            <appender-ref ref="console" />
            <appender-ref ref="Routing" />
        </Root>
        <Logger name="com.test.*" level="info">
            <appender-ref ref="Routing" level="info" />
        </Logger>
    </Loggers>

</Configuration>

Test class

package com.test;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Test extends Thread {

    private static final Logger LOGGER = LogManager.getLogger(Test.class);
    private final String name;

    public Test(String name) {
        this.name = name;
    }

    @Override
    public void run() {
        Thread.currentThread().setName(name);

        for (int i = 0; i < 100; i++) {
            LOGGER.info(LOGGER.getName() + " " + i);
        }

    }
}

output

Sign up to request clarification or add additional context in comments.

6 Comments

where should the .xml file be located?
log4j2.xml should be located inside src/main/resources can you post a screenshot of your directory structure and files.. I suspect you have two .xml log4j config files
my .xml file locatated in classpath root src/log4j2.xml. I create a empty project and put your log4j2.xml from example. Attach .jar file log4j and run it.
Here's my project. take a clone and run.. please mark my answer as accepted if it works for you. github.com/catchsudheera/stackOverflowSolutions
The fact is that I do not use the maven project. I have a Web application, and there is no folder resources.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.