【问题标题】:Configuring log4j2 for threads为线程配置 log4j2
【发布时间】:2017-12-11 20:58:27
【问题描述】:

有一个名为Test 的类,它从Thread 扩展而来。如何配置 log4j2 以便为每个测试线程创建我自己的日志文件。

我正在尝试这样做:

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());

}

}

但在启动时会输出一个文件。

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();

之前我用过 log4j 并且在那里我做到了,但我不明白如何。

我做错了什么?

taskLog4j2.xml文件:

    <?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>

@Sudheera 回答

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)

【问题讨论】:

标签: java multithreading log4j2


【解决方案1】:

您可以编写一个用于自定义名称查找的 Log4J 配置插件,并通过路由器配置使用它。这是给你的固定代码。我添加了 Log4jThreadLookup 类,用于从 log4j 配置上下文中查找线程名称。只要确保这个类在类路径中可用。我还更改了配置文件和Test 类。

Log4jThreadLookup 类

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();
    }

}

配置

<?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>

测试类

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);
        }

    }
}

【讨论】:

  • .xml 文件应该放在哪里?
  • log4j2.xml 应该位于src/main/resources 中,您能否发布您的目录结构和文件的屏幕截图。我怀疑您有两个 .xml log4j 配置文件
  • 我的 .xml 文件位于类路径根 src/log4j2.xml。我创建了一个空项目并将您的 log4j2.xml 放在示例中。附加 .jar 文件 log4j 并运行它。
  • 这是我的项目。克隆并运行..如果它适合您,请将我的答案标记为已接受。 github.com/catchsudheera/stackOverflowSolutions
  • 事实是我没有使用maven项目。我有一个 Web 应用程序,但没有文件夹资源。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
  • 1970-01-01
  • 2012-11-06
  • 2013-04-09
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多