`
nudtgk2000
  • 浏览: 72772 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

用Log4j实现线程独立日志

阅读更多

需求:

      在一个项目里,我使用Log4j生成日志,我不希望任务线程组各个线程都记录在同一个日志里,那样太乱了,而是单独生成日志记录。这样的话,需要针对每个线程创建Logger实例,实例名应对应线程名,而每个Logger实例的文件名应分别对应于实例名或者线程名。

 

思想:

      在网上搜了很多文章后,我还是找不到在配置文件里根据Logger实例以变量形式设置动态File的方法。那么只能打源码的主意了。打开 org.apache.log4j.DailyRollingFileAppender 的源码简单分析了一下:DailyRollingFileAppender 继承了FileAppender类,它个构造方法是DailyRollingFileAppender (Layout layout, String filename, String datePattern),那么可以写个自定义的Appender继承DailyRollingFileAppender,在构造方法里直接将filename设成当前线程名;再将Appender、layout的参数设置及与Logger的绑定封装在一个静态方法里就可以达到目的了。

 

具体代码:

 

自定义Appender

package threadlogger.appender;

import java.io.File;
import java.io.IOException;

import org.apache.log4j.DailyRollingFileAppender;
import org.apache.log4j.Layout;

/**
 * @author Kevin Kwok
 */
public class ThreadSeperateDailyRollingFileAppender extends
        DailyRollingFileAppender
{
    public ThreadSeperateDailyRollingFileAppender() {}
    
    public ThreadSeperateDailyRollingFileAppender(Layout layout, String datePattern) throws IOException
    {
        // 改动只有这点:以线程名命名日志文件
        super(layout,
                "log" + File.separator + Thread.currentThread().getName(),
                datePattern);
    }
}

 

 封装获得线程独立日志的Logger实例的类:

package threadlogger;

import java.io.IOException;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

import threadlogger.appender.ThreadSeperateDailyRollingFileAppender;

/**
 * @author Kevin Kwok
 */
public class ThreadLogger
{
    ThreadLogger() {};

    public static Logger getLogger()
    {
        Logger logger = null;
        // 创建一个Logger实例, 就以线程名命名
        logger = Logger.getLogger(Thread.currentThread().getName());
        
        PatternLayout layout = new PatternLayout("%-4r %-5p [%d{yyyy-MM-dd HH:mm:ss,SSS}] %l%t: %m%n");

        // 控制台输出
        ConsoleAppender concoleAppender = new ConsoleAppender(layout, "System.out");

        // 文件输出
        ThreadSeperateDailyRollingFileAppender R = null;
        try
        {
            R = new ThreadSeperateDailyRollingFileAppender(layout, "'.'yyyy-MM-dd'.log'");
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        // 参数配置, 因为没有找到仅靠配置文件的办法, 只好放在这里设
        R.setAppend(false);
        R.setImmediateFlush(true);
        R.setThreshold(Level.WARN);

        // 绑定到Logger
        logger.setLevel(Level.DEBUG);
        logger.addAppender(concoleAppender);
        logger.addAppender(R);
        
        return logger;
    }

}

 测试例程:package testlog;

import org.apache.log4j.Logger;

import threadlogger.ThreadLogger;

/**
 * @author Kevin Kwok
 */
public class TestLog
{
    // 这是主线程的Logger,这些不需独立日志的类也可以创建为普通的Logger,通过配置文件配置参数
    static Logger logger = ThreadLogger.getLogger();

    public TestLog() {}

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        logger.warn(TestLog.class + " started!");
        
        ThreadBody threadBody = new ThreadBody();
        for(int i=0; i<5; ++i) {
            new Thread(threadBody).start();
        }

        logger.debug("this is debug");
        logger.info("this is info");
        logger.warn("this is warn");
        logger.error("this is error");
    }

}

class ThreadBody implements Runnable
{
    public ThreadBody() {}

    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run()
    {
        // 注意线程独立的Logger实例要在run方法内实现
        Logger logger = ThreadLogger.getLogger();
        
        logger.warn(Thread.currentThread().getName() + " started!");
        
        logger.debug("this is debug");
        logger.info("this is info");
        logger.warn("this is warn");
        logger.error("this is error");

        logger.warn(Thread.currentThread().getName() + " finished!");
    }
    
}

 

测试结果:

 

0    WARN  [2012-11-05 14:31:40,227] testlog.TestLog.main(TestLog.java:21)main: class testlog.TestLog started!
27   DEBUG [2012-11-05 14:31:40,254] testlog.TestLog.main(TestLog.java:28)main: this is debug
27   INFO  [2012-11-05 14:31:40,254] testlog.TestLog.main(TestLog.java:29)main: this is info
27   WARN  [2012-11-05 14:31:40,254] testlog.TestLog.main(TestLog.java:30)main: this is warn
28   ERROR [2012-11-05 14:31:40,255] testlog.TestLog.main(TestLog.java:31)main: this is error
30   WARN  [2012-11-05 14:31:40,257] testlog.ThreadBody.run(TestLog.java:49)Thread-1: Thread-1 started!
33   WARN  [2012-11-05 14:31:40,260] testlog.ThreadBody.run(TestLog.java:49)Thread-0: Thread-0 started!
36   WARN  [2012-11-05 14:31:40,263] testlog.ThreadBody.run(TestLog.java:49)Thread-3: Thread-3 started!
38   WARN  [2012-11-05 14:31:40,265] testlog.ThreadBody.run(TestLog.java:49)Thread-2: Thread-2 started!
40   DEBUG [2012-11-05 14:31:40,267] testlog.ThreadBody.run(TestLog.java:51)Thread-2: this is debug
40   INFO  [2012-11-05 14:31:40,267] testlog.ThreadBody.run(TestLog.java:52)Thread-2: this is info
40   WARN  [2012-11-05 14:31:40,267] testlog.ThreadBody.run(TestLog.java:53)Thread-2: this is warn
41   ERROR [2012-11-05 14:31:40,268] testlog.ThreadBody.run(TestLog.java:54)Thread-2: this is error
41   WARN  [2012-11-05 14:31:40,268] testlog.ThreadBody.run(TestLog.java:56)Thread-2: Thread-2 finished!
44   DEBUG [2012-11-05 14:31:40,271] testlog.ThreadBody.run(TestLog.java:51)Thread-3: this is debug
46   INFO  [2012-11-05 14:31:40,273] testlog.ThreadBody.run(TestLog.java:52)Thread-3: this is info
46   WARN  [2012-11-05 14:31:40,273] testlog.ThreadBody.run(TestLog.java:53)Thread-3: this is warn
47   ERROR [2012-11-05 14:31:40,274] testlog.ThreadBody.run(TestLog.java:54)Thread-3: this is error
47   WARN  [2012-11-05 14:31:40,274] testlog.ThreadBody.run(TestLog.java:56)Thread-3: Thread-3 finished!
38   WARN  [2012-11-05 14:31:40,265] testlog.ThreadBody.run(TestLog.java:49)Thread-4: Thread-4 started!
49   DEBUG [2012-11-05 14:31:40,276] testlog.ThreadBody.run(TestLog.java:51)Thread-1: this is debug
50   INFO  [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:52)Thread-1: this is info
50   WARN  [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:53)Thread-1: this is warn
50   ERROR [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:54)Thread-1: this is error
50   WARN  [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:56)Thread-1: Thread-1 finished!
50   DEBUG [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:51)Thread-0: this is debug
50   INFO  [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:52)Thread-0: this is info
50   DEBUG [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:51)Thread-4: this is debug
50   WARN  [2012-11-05 14:31:40,277] testlog.ThreadBody.run(TestLog.java:53)Thread-0: this is warn
51   INFO  [2012-11-05 14:31:40,278] testlog.ThreadBody.run(TestLog.java:52)Thread-4: this is info
51   ERROR [2012-11-05 14:31:40,278] testlog.ThreadBody.run(TestLog.java:54)Thread-0: this is error
51   WARN  [2012-11-05 14:31:40,278] testlog.ThreadBody.run(TestLog.java:53)Thread-4: this is warn
51   ERROR [2012-11-05 14:31:40,278] testlog.ThreadBody.run(TestLog.java:54)Thread-4: this is error
51   WARN  [2012-11-05 14:31:40,278] testlog.ThreadBody.run(TestLog.java:56)Thread-0: Thread-0 finished!
51   WARN  [2012-11-05 14:31:40,278] testlog.ThreadBody.run(TestLog.java:56)Thread-4: Thread-4 finished!

 

 同时,log文件夹下出现了main、Thread-0~Thread-4五个日志文件,记录了各自线程的信息。

 

 

参考:

log4j 动态日志文件名 的线程安全问题

- End -

1
3
分享到:
评论

相关推荐

    Log4j2实现不同线程不同级别日志输出到不同的文件中

    在“Log4j2实现不同线程不同级别日志输出到不同的文件中”这个主题中,我们将深入探讨如何利用Log4j2实现这一高级日志管理需求。 1. **日志级别**: - 在Log4j2中,日志级别包括DEBUG、INFO、WARN、ERROR、FATAL...

    log4j按功能保存日志

    Log4j是一款广泛使用的Java日志记录框架,它允许开发者按照功能模块或特定需求记录应用程序运行过程中的事件信息。在“log4j按功能保存日志”的场景中,我们通常会利用Log4j的配置灵活性,将不同功能的日志分别写入...

    Log4j多线程实践-LogTest

    - 通过正确配置和使用Log4j,我们可以在多线程环境中实现每个线程独立的日志输出,这对于调试、性能分析和问题定位非常有帮助。 - `LogTest`项目提供了一个实用的例子,演示了如何在实践中应用这些概念,有助于...

    Log4j日志文档和Log4j包

    Log4j提供了一个根Logger,也支持自定义Logger,以实现不同模块的独立日志管理。 6. **Filters**:过滤器允许更精细地控制哪些日志信息会被记录。你可以根据日志级别、日志源或其他条件来过滤日志。 7. **Lookups*...

    Log4j多线程读取多个配置文件

    在IT行业中,日志记录是系统监控和故障排查的关键部分,而Log4j作为Java领域广泛使用的日志框架,能够帮助开发者实现灵活、高效的日志处理。本文将深入探讨如何利用Log4j实现多线程环境下读取多个配置文件,以达到...

    apache-log4j-1.2.16.rar_apache log4j 1.2.16_log4j source code_lo

    深入研究Log4j 1.2.16的源代码,你可以了解到如何实现日志事件的线程安全处理,以及如何优化日志性能,比如通过缓存日志输出格式来减少不必要的字符串连接操作。此外,源码中还包含了一些关键的类,如Category...

    log4j 日志打印jar

    Log4j,作为Java领域中最广泛使用的日志记录框架之一,其强大的功能和灵活性深受开发者喜爱。本文将详细介绍Log4j的基本概念、配置和使用,以及如何将其融入自定义的日志记录工具中。 1. **Log4j简介** - Log4j是...

    log4j2用户指南

    Log4j2 支持日志分离,即在一个应用程序中使用多个独立的日志记录配置: - **Separate ClassLoaders**:使用不同的类加载器隔离日志配置。 - **Separate Contexts**:每个配置使用独立的 LoggerContext。 #### 15....

    ssh+aop+log4j+日志拦截器+注解

    标题中的"ssh+aop+log4j+日志拦截器+注解"涉及到的是Java Web开发中的几个核心组件和技术,这些技术在构建大型、分布式的企业级应用时常常被使用。下面将详细介绍这些知识点: 1. SSH (Spring, Struts, Hibernate)...

    Log4j.properties配置详解

    Log4j 是一个广泛使用的日志记录框架,尤其在Java应用程序中。它的核心在于灵活性和可配置性,允许开发者按照需求定制日志记录的方式。在Log4j.properties配置文件中,我们可以通过设置Logger、Appender和Layout来...

    java日志操作之Log4j

    它最初是作为Jakarta项目的一部分出现的,随着时间的发展,Log4j逐渐成为了一个独立且功能强大的日志解决方案。Log4j的设计理念是灵活与高效,它允许开发者轻松地配置日志输出的位置、格式以及级别。 #### 日志的...

    log4j配置文件和jar包

    Log4j是一款广泛使用的Java日志记录框架,它允许开发者以灵活的方式控制程序的日志输出。在Java应用程序中,日志记录是至关重要的,因为它帮助我们跟踪错误、调试代码、监控系统性能以及进行安全审计。Log4j因其高度...

    log4j-1.2.15

    除了基本的日志功能,log4j-1.2.15还支持一些高级特性,如异步日志记录(使用AsyncAppender)、日志事件的自定义处理(通过编写自定义Appender和Layout)、MDC(Mapped Diagnostic Context)和NDC(Nested ...

    springboot-log4j.zip

    在Java开发领域,Spring Boot是一个...通过引入Log4j依赖,配置日志输出格式和级别,以及在代码中使用`Logger`接口,我们可以实现高效且易于管理和分析的日志系统。这在开发、调试和维护Spring Boot应用时非常有用。

    log4Qt--qt日志系统

    Log4Qt,顾名思义,是Apache Log4J日志框架的一个Qt实现,为Qt应用程序提供了强大的日志处理功能。由于Log4Qt的文档相对较少,理解其工作原理和用法往往需要参考Log4J的资料。本文将深入探讨Log4Qt的核心概念、配置...

    log4j.properties的简单运用

    Log4j是一款广泛使用的日志框架,它允许我们自定义日志级别、格式以及输出目的地。本文将围绕`log4j.properties`配置文件,探讨其基本用法和重要概念。 一、Log4j的基本结构 Log4j主要由三个核心组件构成:Logger...

    log4j常用配置详解

    ### log4j常用配置详解 ### #### 一、log4j.properties 配置解析 #### 在Java开发领域中,log4j是一款非常流行的日志框架,它提供了丰富的配置选项来满足...希望本文能帮助大家更好地理解和使用log4j进行日志管理。

    log4j.rar,避免在官网上找不到

    5. **多线程支持**:Log4j在多线程环境下表现稳定,每个线程都有独立的日志记录对象,避免了同步开销。 6. **日志级别**:Log4j提供了TRACE、DEBUG、INFO、WARN、ERROR和FATAL六种日志级别,可以根据需要调整日志...

    log4j 1.2.8 jar 包含源码

    Log4j 是一个广泛使用的 Java 日志框架,由 Apache 软件基金会开发。它为应用程序提供了灵活的日志记录功能,允许开发者调整日志级别,定制日志格式,以及将日志输出到不同的目的地,如控制台、文件、数据库等。...

Global site tag (gtag.js) - Google Analytics