生产环境定位日志太麻烦怎么办?建议了解一下日志框架的MDC功
对于每一个开发者来说,查询接口的执行日志都是一个高频率的操作,每当测试说接口有问题时,我们都需要去服务器或者日志系统上查报错的原因。
一般情况下,我们会通过对应的关键字或者接口地址去查询这个接口到底报了什么错,但是这带来一个问题,就是我们可能少打日志或者忘打某些关键字的日志,导致查询记录比较麻烦。
那么有没有一种简单高效的方法,即使我们在日志中不打印任何关键字,系统会自动生成一个关键字,让我们一次性查询出这个接口的所有log记录呢?MDC
MDC是日志门面框架SLF4J提供的一个类,可以提供在多线程情况下记录日志的功能,log4j、logback、log4j2都有对这个类的实现。
从本质上来说,MDC可以看做一个ThreadLocal,由于其线程安全的特性,可以让我们轻松安全的保存数据。
MDC主要的API有clear()、get()、put()、remove()方法等,简洁的api让我们使用上手基本没有难度。如何使用
1,修改日志打印格式
以日志框架logback为例,在logback。xml中,找到日志打印规则的配置,添加X{reqId}属性,其中reqId可以任意指定,你写其他的属性也可以,博主这里演示指定为reqId。encoderpatternX{reqId}d{yyyyMMddHH:mm:ss。SSS}〔thread〕5levelfile:linemsgnpatterncharsetUTF8charsetencoder
2,添加过滤器MDCFilter
ps。使用拦截器也可以,效果是一样的。对每个接口做拦截。ComponentAllArgsConstructorOrder(Ordered。HIGHESTPRECEDENCE)Slf4jpublicclassMDCFilterimplementsFilter{Overridepublicvoidinit(FilterConfigfilterConfig)throwsServletException{}OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain){try{给每个请求接口生成一个requestIdStringrequestIdRandomUtil。randomNumbers(10);这里的reqId就是上面配置的,要保持一致MDC。put(reqId,reqId:requestId);chain。doFilter(request,response);}finally{MDC。clear();}}Overridepublicvoiddestroy(){}}
经过简单的两步就配置好了,下面我们看一下效果。PostMapping(valuemdcTest)publicResponseEntityObjectmdcTest(Stringid,Stringname){log。info(测试日志打印,id{},name{},id,name);log。info(测试日志打印1);log。info(测试日志打印2);log。info(测试日志打印3);log。info(测试日志打印4);returnResponseEntity。ok()。build();}
每一行日志都有一个关键字reqId:9723829830,这样我们查询日志时只需要查询关键字9723829830就可以直接查出来这个接口所有的执行记录了。
如果想更方便的话,也可以把这个关键字直接输出到每一个接口的响应头或者响应体中。进阶使用
对于普通的web应用我们可以直接拦截每个接口,自动生成一个请求id,那么对于微服务项目,一个接口可能会产生很多服务的调用,那如何一次性查出来所有系统内的日志呢?
对于日志的搜集本文暂不考虑,咱们先说如何做请求id的传递。
其实也很简单,当我们有多个系统间的调用时,把reqId放到request的header中进行传递,然后下游系统获取这个id就可以了。
比如下方的拦截器:publicclassLogInterceptorimplementsHandlerInterceptor{OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{如果有上层调用就从header中取出上层的IDStringtraceIdrequest。getHeader(reqId);if(traceIdnull){如果没有,就生成一个默认的traceIdRandomUtil。randomNumbers(10);}MDC。put(reqId,traceId);returntrue;}OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{}OverridepublicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsException{调用结束后删除MDC。remove(reqId);}}MDC存在的一些问题
我们在上文说过,MDC的本质是ThreadLocal,它会把数据都绑定到当前线程上。但是当我们使用多线程的时候,就会带来一个数据丢失的问题。
所以,我们需要进行线程间的数据传递,保证MDC数据不丢失。
以线程池传递数据为例,ThreadPoolTaskExecutor提供了一个taskDecorator装饰器,通过这个属性,我们就可以实现属性的传递。
首先,定义一个MDCContextDecorator,publicclassMDCContextDecoratorimplementsTaskDecorator{OverridepublicRunnabledecorate(Runnablerunnable){MapString,StringpreviousMDC。getCopyOfContextMap();return(){try{if(previous!null){MDC。setContextMap(previous);}runnable。run();}finally{MDC。clear();}};}}
然后设置线程池的taskDecorator属性,publicThreadPoolTaskExecutorexecutor(){ThreadPoolTaskExecutorexecutornewThreadPoolTaskExecutor();executor。setCorePoolSize(5);executor。setMaxPoolSize(20);。。。其他属性设置线程属性的自动传递executor。setTaskDecorator(newMDCContextDecorator());returnexecutor;}最后
MDC的使用其实很简单,对于我们查询日志也很有帮助,应用也算是非常广泛了。有兴趣的同学也可以去看一下它的内部实现,代码也并不复杂。
头条创作挑战赛
我是程序员拾山,欢迎关注我,期待与大家一起学习成长,也感谢您的点赞和关注。
若不缴纳社保,每月往银行存1500元,15年后取到的钱够不够养老?每月存1500元,一年就是1。8万元,15年是27万元。15年后本金和利息能有多少呢?现在一年期整存整取定期存款基准利率是1。5,三年期整存整取定期存款基准利率是2。75。银行开出
1973年如果存1200元进银行,到今天变成多少钱?一九七三年有1200元是一笔巨款了。为什么这么说呢?按照我国有统计数字以来,1978年全国人均可支配收入是171。2元,城镇人均可支配收入343。4元,农村人均可支配收入133。6
为什么银行每天要押运现金?银行网点,下班以后,是不允许留一分钱现金的。这个规章制度,是目前所有银行通用的。目的也是为了安全考虑,毕竟银行下班后是没有人值班的,如果留下现金,也就是等于留下了安全隐患。而且,现
你所居住地的房价为多少钱一平?你当地房价多少钱一平?我先来说说房子的现实情况。房价一直以来都是普通人民最关心的话题。在目前的社会发展环境以及主流思想和传统观念的三坐大山之下。你没有房子,就意味着你将会失去人生中
不交养老金,每月存1000,30年后够养老吗?大概率讲,是不能的。每月存1000元,一年1。2万元,30年本金为36万元。看起来,也是一笔不小的财富了。如果再考虑到,每年投资产生的利息,财富积累会更多。如果按照每年积攒1。2万
工厂里的工艺工程师是做什么的?薪资如何?工艺工程师是制造业公司里的一个技术类岗位,主要负责提升企业产品的工艺水平提升产品的质量,堪称工厂里技术通才,什么都要接触,什么都要懂一点。工艺工程师主要可分成制造工艺工程师和机械工
大额存钱银行给的不是存款单,而是银行卡和一张单据卡里面也没钱,这是为什么?大额存款是中国人民银行2015年6月15日正式推出的,发行渠道股份制银行,国有银行,地方银行,网络银行。产品体系个人30万起(小银行20万起),公司1000万起。期限有1月3月6月
被判无期的人,每天在监狱里做什么?我在重刑监狱待过,和几百被判无期死缓的犯人打过几年交道。这些犯人大多是1983年严打抓进来的,他们来自浙江上海和广东,有被判处无期徒刑的,有被判处死刑缓期两年执行的,还有18年以上
工地上的小工一般多少钱一天?我有个邻居在工地上做小工,我了解这个行情。这里说的小工,就是没有什么技术含量,不像木工,瓦工,油漆工那么高的工资,但是也不是太低。老冯他常年在工地上做小工,有时候工资高一点,有时候
江苏苏州无锡常州未来三年房价走势如何?苏州小幅上涨,无锡大幅上涨,常州中幅上涨。苏州较其他二座城市房价高了很多,随着国家层次控地价控房价的同时,已经房价高位的苏州大幅上涨的基础不存在,但城市吸附能力强,且通货膨胀货币贬
下岗职工怎么交社保?关于下岗职工,实际上很多人把有关概念搞错了。真正的下岗职工指的是1993年开始,国家对国有企业富余职工进行安置的有关措施。让有关富余的职工脱离原工作岗位,但是还会保持跟职工的劳动关
死刑犯干活吗?死刑犯干不干活?看您这话问的!死刑犯还干活?想想也知道,手铐脚镣的,死刑犯还怎么干活?!再者,死刑犯是要归西的人了,反正也蹦哒不了几天,不如做个顺水人情,让死刑犯爽上个九个月或者是
身为兰州人,你坐过时间最长的火车是去哪里的?路上怎样消磨时间?我做过时间最长的火车是去尼泊尔的时候,从济南坐到拉萨,中间在石家庄北短暂停留,然后一路到拉萨。你知道那是多久吗,整整两天两夜,四十八小时。拉萨下车,又是高反又是劳累,感觉自己轻飘飘
你们觉得哪里的彩礼最贵?谢邀。你们觉得哪里的彩礼最高?我的回答是我觉得我们这里的彩礼也是挺高的吧,有的十几万,还有的20多万,也有30多万的。至于那里的彩礼最高,我也没有实际调查过,有的地方还有七八十万1
退休老人拿着很高的退休金,还到处去打工,你怎么看?老人干了一辈子,颐养天年是正理,生活节奏慢下来,吃吃做做玩玩,捡拾年轻时想做而没时间做的兴趣爱好,填满生活空间,增加生活趣味,多好。可就有不按常理出牌的,我同事的父母,老俩退休多年
猪价一直下跌,玉米价格却是大涨,老百姓还适合继续养猪吗?养养继续养,养起自己吃,农民千万不要去买养猪场的猪肉肉,农民不养猪都去买养猪场的肉肉,肉肉就涨起三十几元钱1斤。对吧?肉肉涨价城里居民就得摸大钱钱买肉肉吃。农民不为他(她们想想,就
一般事业单位能出现45年工龄吗?你好,目前事业单位男性工作人员是60周岁退休,想要有45年工龄意味着15岁前参加工作,属于童工的范筹,违反目前的劳动政策,不能认定工龄。所以,一般情况下,事业单位很难出现45年工龄
干一份不如意的工作,每天的心情都很压抑,吃力不讨好,是果断辞职还是将就混日子?在做决定之前,你得先分析一下吃力不讨好的原因吧。工作不如意,吃力不讨好,不一定是这份工作不适合你,你的工作方式也有问题。职场上很多人都在做吃力不讨好的事。有的人成天忙忙碌碌就是不出
死刑犯在最后一夜,要求出监狱看家人怎么办?实话实说,这个问题很荒谬。监狱是国家机器,不会照顾个人情绪,进了监狱(看守所)任何个人情绪和想法与行为,都必须置于法律之下。死刑犯在最后一夜,要求出监狱去看家人,怎么可能呢?想都不
大家有在医院遇到过诡异的事情吗?诡异的事情在医院肯定少不了,因为医院死人是常有的事,因此,出现诡异的事情也就不足为奇了。先说说我母亲住院期间发生的事,我母亲患胆结石住院,有二十多天吧,在住院十多天的一晚上,别人都
困难户的标准是什么?困难户的标准是什么?困难残疾人生活补贴对象为本省城乡低保家庭中的残疾人。重度残疾人护理补贴对象为户籍在本省的残疾等级为一级二级且需要长期照护(长期照护是指因残疾产生的特殊护理消费品
借钱不还,采取什么方式最有效?这个问题在当今社会出现的案例太多了,可见如今的人很多都已经失去了彼此最基本的信任,往大了说就是诚信缺失。说实话,很多人借钱真正还不起的是少数,大多数还是有钱不愿意还,十有八九都是这