多并发情况下日志信息中如何区分不同线程(客户端)调用
????? 在企业开发中,常常会遇到这样的需求:通过一个唯一标识将一个线程(或者一个客户端)从开始进入系统一直到退出该系统完整的系统调用路径产生的所有日志串联起来。
????? 这样做带来的一个明显的好处就是:通过命令 grep? 唯一标识? *.log 可以获取该线程(客户端)本次调用的所有日志。这对于排查系统问题是有莫大好处的。下面列举两种解决方案:
?
?? 在处理之前,必须整理出所有系统调用的入口点。比如系统A,有三个入口点,分别是通过页面访问,外部系统调用A系统发布出去的WS服务,A系统接收外部系统发送的消息。
?
?方案一:通过埋点或者拦截器在系统入口方法调用之前设置本地线程变量的值,一般是当前系统时间,比如:
???????????? org.apache.log4j.NDC.push(System.nanoTime());
???????????? 在线程(客户端调用)退出的时候,调用:
???????????? org.apache.log4j.NDC.remove();
?
???????????? 注意配置文件中的布局格式中一定要加上%x
???????????? 可参考:http://blog.csdn.net/NEU_20063508/article/details/3872226
?
方案二:通过埋点或者拦截器在系统入口方法调用之前设置本地线程变量的值,一般是当前系统时间。和方案一不同,这里的当前时间是放在ThreadLocal变量中的。比如:
? private static ThreadLocal<Long> timeKey=new ThreadLocal<Long>();
? timeKey.set(System.nanoTime());
?
? 然后对Log日志输出器做一个封装,重写所有的日志输出方法,使得每个日志输出的后面都加上timeKey.get();方法
?
? 最后在线程调用退出的时候,清空资源:
?timeKey.set(null);
?