Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 如何以编程方式为多个线程创建单独的Log4j2滚动文件追加器和记录器_Multithreading_Logging_Testng_Log4j2 - Fatal编程技术网

Multithreading 如何以编程方式为多个线程创建单独的Log4j2滚动文件追加器和记录器

Multithreading 如何以编程方式为多个线程创建单独的Log4j2滚动文件追加器和记录器,multithreading,logging,testng,log4j2,Multithreading,Logging,Testng,Log4j2,我在多个线程上运行TestNG测试(同时在多个设备上运行Appium测试),并希望在不同的文件中的不同线程上编写测试日志。在这里,线程是在测试流开始之前自动创建的 因此,我想以编程方式创建单独的appender和单独的logger,这样每个appender将只连接到自己的线程,然后在一个线程中创建的记录器将只在该线程中创建appender 请让我知道如何一步一步地实现它。首先,这感觉像是一个问题,特别是因为您没有提供任何关于为什么要使用编程解决方案的理由 可以逐个线程地实现单独的日志文件,而无需

我在多个线程上运行TestNG测试(同时在多个设备上运行Appium测试),并希望在不同的文件中的不同线程上编写测试日志。在这里,线程是在测试流开始之前自动创建的

因此,我想以编程方式创建单独的appender和单独的logger,这样每个appender将只连接到自己的线程,然后在一个线程中创建的记录器将只在该线程中创建appender

请让我知道如何一步一步地实现它。

首先,这感觉像是一个问题,特别是因为您没有提供任何关于为什么要使用编程解决方案的理由

可以逐个线程地实现单独的日志文件,而无需以编程方式创建记录器和附加器。由于我相信这是一个更为理想的解决方案,我将提供一个演示如何做到这一点

解释

此解决方案将使用和为每个
线程创建附加器。下面的示例将使用一个简单的
FileAppender
,但您可以非常轻松地在
RollingFileAppender
中进行交换。由于您没有声明需要为每个线程使用不同的日志级别,下面的示例将不会实现此功能。最后,示例将不使用TestNG,因为它需要设置一些开销;相反,将使用一个简单的类和一个创建两个线程的main

实施示例

log4j2.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Routing name="MyRoutingAppender">
            <Routes pattern="$${ctx:threadName}">
                <Route>
                    <File
                        fileName="logs/${ctx:threadName}/log.txt"
                        name="appender-${ctx:threadName}">
                        <PatternLayout>
                            <Pattern>[%date{ISO8601}][%-5level][%t] %m%n</Pattern>
                        </PatternLayout>
                    </File>
                </Route>
            </Routes>
        </Routing>
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="[%date{ISO8601}][%-5level][%t] %m%n" />
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="Thread" level="TRACE" additivity="false">
            <AppenderRef ref="STDOUT" />
            <AppenderRef ref="MyRoutingAppender" />
        </Logger>
        <Root level="WARN">
            <AppenderRef ref="STDOUT" />
        </Root>
    </Loggers>
</Configuration>
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;

public class MultiThreadLog4j2SepFilesMain {
    //Create a lock to use for synchronizing the getting of the logger
    private static final Object lock = new Object();

    public static void main(String[] args) {
        Thread t1 = new Thread(new Runnable(){

            public void run() {
                //Set up the context before getting logger
                ThreadContext.put("threadName", Thread.currentThread().getName());

                //Get the logger for this thread
                Logger log = null;
                synchronized(lock){
                    log = LogManager.getLogger(Thread.currentThread().getName());
                }

                //Generate some logs
                log.info("here's the first thread");

                //Wait a while so that threads interleave
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //Generate more logs
                log.debug("some debug in first thread");
                log.info("finishing first thread");

            }}, "Thread.1"); //Use a name that will allow us to use Thread.getName when getting the logger inside the thread

        Thread t2 = new Thread(new Runnable(){

            public void run() {
                //Set up the context before getting logger
                ThreadContext.put("threadName", Thread.currentThread().getName());

                //Get logger for this thread
                Logger log = null;
                synchronized(lock){
                    log = LogManager.getLogger(Thread.currentThread().getName());
                }

                //Generate some logs
                log.info("here's the second thread");
                log.debug("some debug in second thread");

            }}, "Thread.2"); //Use a name that will allow us to use Thread.getName when getting the logger inside the thread

        //Start both threads
        t1.start();     
        t2.start();
    }
}