Log4j打印日志添加线程ID

目的:

区分每个请求用户,更好的跟踪分析问题(用户登录之后加上userId更佳)

在进行多线程编程时,经常会在调试信息中看到线程的处理流程,需要在日志中体现当前线程信息。因Java中的线程名称采用了默认的“Thread-1”等字符串,定位不方便。

分析:

在JDK1.5开始对Thread类加入了getId()方法,即每个线程都有一个唯一的数字来代替。

在记录日志时,是否可以通过记录线程ID来提升日志线程信息的清晰度?

 

解决:

Log4j默认只提供了对线程名称的现实,即使用占位符%t来显示名称。

如果需要显示线程ID,需要拓展log4j。

 

1.拓展Log4j的PatternParser

代码:

package org.apache.log4j;

import org.apache.log4j.helpers.FormattingInfo;
import org.apache.log4j.helpers.PatternConverter;
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.spi.LoggingEvent;

public class ExPatternParser extends PatternParser {
	 
	 public ExPatternParser(String pattern) {
	   super(pattern);
	  }
	 
	 /**
	   * 重写finalizeConverter,对特定的占位符进行处理,T表示线程ID占位符
	   */
	  @Override
	  protected void finalizeConverter(char c) {
	   if (c == 'T') {
	    this.addConverter(new ExPatternConverter(this.formattingInfo));
	   } else {
	    super.finalizeConverter(c);
	   }
	  }
	 
	 private static class ExPatternConverter extends PatternConverter {
	 
	  public ExPatternConverter(FormattingInfo fi) {
	    super(fi);
	   }
	 
	  /**
	    * 当需要显示线程ID的时候,返回当前调用线程的ID
	    */
	   @Override
	   protected String convert(LoggingEvent event) {
	    return String.valueOf(Thread.currentThread().getId());
	   }
    }
}

2.拓展PatternLayout类,使用拓展的ExPatternParser类

代码:

package org.apache.log4j;

import org.apache.log4j.PatternLayout;
import org.apache.log4j.helpers.PatternParser;

public class ExPatternLayout extends PatternLayout {
	 
	 public ExPatternLayout(String pattern) {
	   super(pattern);
	  }
	 
	 public ExPatternLayout() {
	   super();
	  }
	  
	  /**
	   * 重写createPatternParser方法,返回PatternParser的子类
	   */
	  @Override
	  protected PatternParser createPatternParser(String pattern) {
	   return new ExPatternParser(pattern);
	  }
	 }

3.修改Log4j的配置文件,将输出样式修改为拓展类ExPatternLayout

#设置输出样式  
log4j.appender.appender1.layout=org.apache.log4j.ExPatternLayout  


到此已经扩展完成,将以上内容编译后(可以打成jar包)和log4j.jar一同使用(使用同一个类装载器装载),然后配置log4j.properties类,修改

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout


log4j.appender.stdout.layout=ex.log4j.ExPatternLayout

在输出格式中增加%T(log4j定义%t表示线程名称,%T没有定义,所以这里使用%T表示线程ID),

log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %T %c %5p - %m%n

下面就按照平常的习惯使用log4j即可,再输出的日志中就会包含线程ID,例如:

2009-03-29 10:43:58 1 test.log.Log4jTest  INFO - ok

时间后面的'1'就表示线程id,当在多线程环境下,例如web环境,用这种方式就能很容易区分出一次web请求过程中打印出的日志信息,而不会和其他web请求打印出的日志信息混淆。这样即增加的日志的可读性,也不会输出太多的无用信息。


例子:

log4j.appender.console.layout.ConversionPattern=[%d{HH:mm:ss.SSS}] [%-3p] %x %c{1}:  %m%n

[11:03:36.656] [INFO] [<T=U0Lg2h5HdGqMpvaS,U=9709677>] CommonWebFilter:  >>>>>>> Completed request[/omm/http/pss/text][360.86ms].


4.运行程序。

demo可在资源区下载



另一种方式:

你可以做到这一点的方法之一是增加它的log4j MDC。增加它的Web请求。我们这样做是在过滤器在每个请求的开始。例如:。

import org.apache.log4j.MDC;
...
 // Add username to MDC
 String username = ...;
 MDC.put("user", username);
然后加 [%X{user}] 为您的转换模式。




转载地址: http://wenhai.iteye.com/blog/2037765

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在Qt中创建两个线程打印日志,你可以使用自定义的`QThread`类和信号槽机制。下面是一个示例代码,展示了如何在两个线程打印日志: ```cpp #include <QCoreApplication> #include <QThread> #include <QDebug> // 自定义的工作线程类 class WorkerThread : public QThread { Q_OBJECT public: void run() override { // 执行一些耗时的任务并打印日志 for (int i = 0; i < 5; ++i) { qDebug() << "Thread " << QThread::currentThreadId() << ": Working..." << i; msleep(1000); // 暂停1秒 } } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 创建两个工作线程 WorkerThread thread1; WorkerThread thread2; // 启动两个线程 thread1.start(); thread2.start(); return a.exec(); } #include "main.moc" ``` 在上述代码中,我们首先定义了一个自定义的工作线程类`WorkerThread`,继承自`QThread`。在`run()`函数中,我们执行了一个简单的耗时任务,并在每次迭代中打印当前线程ID和迭代计数。 在`main()`函数中,我们创建了两个`WorkerThread`对象`thread1`和`thread2`。然后,通过调用`start()`函数启动这两个线程。 运行这个示例代码后,你将看到两个线程交替打印日志,每秒打印一次,如下所示: ``` Thread 0x7f9d34002700 : Working... 0 Thread 0x7f9d30004700 : Working... 0 Thread 0x7f9d30004700 : Working... 1 Thread 0x7f9d34002700 : Working... 1 Thread 0x7f9d30004700 : Working... 2 Thread 0x7f9d34002700 : Working... 2 Thread 0x7f9d30004700 : Working... 3 Thread 0x7f9d34002700 : Working... 3 Thread 0x7f9d30004700 : Working... 4 Thread 0x7f9d34002700 : Working... 4 ``` 注意:每次运行时线程ID可能会有所不同。 希望这可以帮助你实现在两个线程打印日志!如果还有其他疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值