巧用CurrentThread.Name来统一标识日志记录(java-logback篇)
_
| |
__ _ __ _ ___ _ __ __| | __ _
/ _` |/ _` |/ _ \ '_ \ / _` |/ _` |
| (_| | (_| | __/ | | | (_| | (_| |
\__,_|\__, |\___|_| |_|\__,_|\__,_|
__/ |
|___/
▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录
▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录(续)
▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录(完结篇)
▄︻┻┳═一asp.net拦截器
▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录(java-logback篇)
java版本支付中心,日志组件使用的是logback。logback.xml里日志pattern配置如下:
<!--本地日志目录-->
<property name="USER_HOME" value="${catalina.base}/logs/logback-srv" />
<property name="LOG_MSG" value="%X{sid}%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p [%c] - %m%n" />
<property name="LOG_DIR" value="${USER_HOME}/%d{yyyyMMdd}"/>
<!--2017-08-22 10:43:19.307 [DubboServerHandler-10.0.0.178:38001-thread-187] INFO [com.emax.paycenter.backend.facade.IPayCenterFacadeImpl]-->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${LOG_MSG}</pattern>
</encoder>
</appender>
pattern里有%t,即代表的是线程Id(起初,我误认为这个%t指的是线程Id!!!),而每一笔交易请求的处理是在一个单独的线程里,那么它就可以标记每一笔交易请求对应的所有日志。日志文件截图如下:

分析日志发现,这个线程标识如截图里的“DubboServerHandler-10.0.0.178:38001-thread-195”会被不同的交易请求重用,不能唯一标记一次请求的所有处理日志,这显然加大了线上问题的排障难度。昨天晚上,项目组里我们2人决定要针对这一点不足做一次改进。
之前的.net版支付中心,我对统一标记一笔交易请求的所有日志做过一次重构,见【巧用CurrentThread.Name来统一标识日志记录】。显然,java的也有必要用一个唯一的标识来标记一笔交易请求的所有日志。
当前线程的线程Id是只读的,我们改不了。那该怎么实现呢?
此前.net的经验告诉我用currentThread的Name属性来搞。可是问题来了,我在交易处理的第一个语句里给当前线程名赋值后,此后的各module各方法里的每一条log.info语句都要显式记录上当前线程名,改动太多了。而且,这样的代码不免有股怪怪的味道。
当然,另一个办法是按照.net版那种思路,做个日志代理类,对上面的调用log.info并显式记录当前线程名做个封装,然后,逻辑代码里记日志就调用这个代理类。这样实现的弊端与上面的方案半斤八两。
那怎么办呢?
问呗。
先问度娘,无解。
接着问同事,说可能要自己写一个apperder。对logback底层代码的未知会加大解决问题的难度。
【百度:logback 自定义appender
读logback源码系列文章(五)——Appender http://kyfxbl.iteye.com/blog/1173788】
无心插柳
我早上上班后,先了解了一下构造一个唯一字符串标识来给当前线程名赋值。然后在交易处理的的第一个语句前,写了如下两行代码,
public BaseResponse invoke(String requestJSON, BaseRequest baseRequest) throws Exception {
String threadName = String.format("%s_%s_%s",
baseRequest.getMethod(),
new SimpleDateFormat("HHmmssS").format(new Date()),
UUID.randomUUID().toString().toUpperCase().substring(0, 5));
Thread.currentThread().setName(threadName);
log.info("#IPayCenterFacadeImpl,调用服务:{}", baseRequest.getMethod());
log.info("#IPayCenterFacadeImpl,请求参数:{}", requestJSON);
//1.获取API接口实现
IPayCenterApi payCenterApi = (IPayCenterApi) payCenterServiceFactory.getService(baseRequest.getMethod());
//2.处理业务逻辑
BaseResponse result = payCenterApi.handle(requestJSON);
return result;
}
不经意间,在运行代码时,我发现%t那段的线程信息标识是我给当前线程名设置的那个字符串标识。
这才发现,%t或%thread输出的原来是产生日志的线程名!!
【调试代码可知 Thread.currentThread().getName():DubboServerHandler-192.168.40.80:28005-thread-2,Thread.currentThread().getId():246】
经过了这个波折,我们的问题最终得到解决,兴奋异常。看看下面的日志截图,一股强烈的成就感油然而生 O(∩_∩)O

巧用CurrentThread.Name来统一标识日志记录(java-logback篇)的更多相关文章
- 巧用CurrentThread.Name来统一标识日志记录(完结篇)
▄︻┻┳═一Agenda: ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录 ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录(续) ▄︻┻┳═一巧用Cur ...
- 巧用CurrentThread.Name来统一标识日志记录(续)
▄︻┻┳═一Agenda: ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录 ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录(续) ▄︻┻┳═一巧用Cur ...
- 巧用CurrentThread.Name来统一标识日志记录
▄︻┻┳═一Agenda: ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录 ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录(续) ▄︻┻┳═一巧用Cur ...
- (网页)Java日志记录框架Logback配置详解(企业级应用解决方案)(转)
转自CSDN: 前言 Logback是现在比较流行的一个日志记录框架,它的配置比较简单学习成本相对较低,所以刚刚接触该框架的朋友不要畏惧,多花点耐心很快就能灵活应用了.本篇博文不会具体介绍Logbac ...
- SLF4J - 一个允许你统一日志记录API的抽象层
一.什么是SLF4J 我们在做Java开发时,如果需要记录日志,有很多日志API可供选择,如: java.util.logging Apache log4j logback SLF4J又是个什么东东呢 ...
- slf4j+log4j在Java中实现日志记录
小Alan今天来跟大家聊聊开发中既简单又常用但必不可少的一样东西,那是什么呢?那就是日志记录,日志输出,日志保存. 后面就统一用日志记录四个字来形容啦. 日志记录是项目的开发中必不可少的一个环节,特别 ...
- 使用 logback + slf4j 进行日志记录
此处主要介绍maven web工程下如何使用 logback + slf4j 进行日志记录. logback主要包含三个组成部分:Loggers(日志记录器).Appenders(输出目的在).La ...
- 9.Spring Boot实战之配置使用Logback进行日志记录
转自:https://blog.csdn.net/meiliangdeng1990/article/details/54300227 Spring Boot实战之配置使用Logback进行日志记录 在 ...
- 用slf4j统一管理日志总结
用slf4j统一管理日志总结 参考网页:http://www.slf4j.org/ 一.使用slf4j统一管理并配置统一使用log4j日志 使用的jar:(slf4j-api-1.7.5.jar,jc ...
随机推荐
- autofac生命周期入门(如何避免内存泄漏)
如果你是一个IOC新手,那么生命周期可能会比较难以理解.以至于谈到这个问题时,一些老手也时常表示疑虑和害怕.一个令人不安的问题就是-对象没有在合适的时机被销毁.这样一来内存的使用率就会一直攀升,直到程 ...
- CSS 小技巧
CSS 小技巧 一.边框内圆角 我们在设计例如按钮等控件的时候,会遇到这样的设计:只有内侧有圆角,而边框或者描边的四个角还是保持直角的形状,用以下代码可以轻松的实现. #wrapper { width ...
- python数据结构之图论
本篇学习笔记内容为图的各项性质.图的表示方法.图ADT的python实现 图(Graph) 是数据结构和算法学中最强大的框架之一(或许没有之一).图几乎可以用来表现所有类型的结构或系统,从交通网络到通 ...
- regular expression (如何用Sed和正则表达式提取子字符串)
echo "mv u3_yunying.war u3_yunying.war_`date +%Y%m%d%H%M`" | sed "s/\(mv\) \(\w*.wa ...
- [qemu][kvm] 在一个vmware虚拟机里安装qemu-kvm虚拟机
说起来这个需求,简直是傻傻的.但却实实在在的摆在我的面前.... VM无外乎就是为了模拟场景:我现在要的场景就是一台很多个core的linux主机.但是我只有一个装了windows的笔记本.上边有一个 ...
- Java8 in action
解决的问题: behavior parameterization,即可以把一段code,逻辑作为参数传入: 这样做的目的,当然为了代码抽象和重用,把变化的逻辑抽象出去: 在java中,如果要实现beh ...
- 什么是Docker?(一)
Docker 最初是 dotCloud 公司创始人 Solomon Hykes 在法国期间发起的一个公司内部项目,它是基于 dotCloud 公司多年云服务技术的一次革新,并于 2013 年 3 月以 ...
- Navicat工具的使用 1
Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库 官网下载:https: ...
- 报错解决——SSL: CERTIFICATE_VERIFY_FAILED
SSL: CERTIFICATE_VERIFY_FAILED Python 升级到 2.7.9 之后引入了一个新特性,当使用urllib.urlopen打开一个 https 链接时,会验证一次 SSL ...
- 系统进不去怎么办?教你利用bootice工具引导修复系统
http://sh.qihoo.com/pc/9c2e9690a82b8cd38?sign=360_e39369d1 U盘装机大师下载地址 http://www.upandashi.com/down/