前言当线上出现问题,你的第一反应是什么?如果是我,我首先想到的就是查看日志:if...elseenter进入了哪个分支?是否缺少关键参数?是不是输入的参数有问题,没检查好没放进去?好的日志可以帮助我们快速定位问题。欺骗你的东西往往是最看不见的。好的日志就是让这些东西看不见!日志级别在Java应用中,日志一般分为以下五个级别:ERROR错误信息WARN警告信息INFO一般信息DEBUG调试信息TRACE跟踪信息1)ERRORERROR级别的日志一般出现在catch块中,用于记录影响在当前线程上。对于运行错误,出现Exception的地方,可以考虑打印ERROR日志,但不包括业务异常。需要注意的是,如果抛出异常,不要记录ERROR日志,应该在最后的地方处理,下面是错误的:try{inti=1/0;}catch(Exceptione){log.error("出了点问题,我不知道怎么了,哈哈哈哈!",e);thrownewCloudBaseException();}复制代码2)WARN应该不会出现,但是不会影响当前线程的执行,可以考虑打印WARN级别的日志,这样的情况还有很多,比如:各种pool的使用(线程池、连接池、缓冲池)超过阈值,到达报警线,记录业务异常。运行正常,但需要记录。3)INFO是使用最广泛的日志级别,使用范围广泛,用于记录系统的运行信息。例如,重要模块中的逻辑步骤呈现客户端请求参数,并记录调用第三方时的参数和参数。返回结构4)DEBUG调试日志用于记录所有你想知道的信息,往往是某个功能模块运行的详细信息、中间数据变化、性能信息等。生产环境一般关闭调试信息,需要开关机管理(比如SpringBootAdmin可以做到)。如果一直开启,会产生大量的Debug,而Debug日志在程序正常运行的时候大部分时间是没有用的。if(log.isDebugEnabled()){log.debug("开始执行,开始时间:[{}],参数:[{}]",startTime,params);log.debug("通过计算,得到参数一:[{}],参数二:[{}]",param1,param2);log.debug("Finalprocessingresult:[{}]",result);}copycode5)TRACE特别详细的系统运行完成信息,业务代码中一般不用,除非有特殊含义,一般换成DEBUG,其实我到现在都没用过这个级别的log。使用正确的格式如果打印日志是这样的:log.info("根据条件id:{}"+id+"查询用户信息");复制代码不要这样做,会生成很多字符串对象,占用空间,也影响性能。正确的做法是使用参数化信息:log.info("根据条件id查询用户信息:[{}]",id);复制代码不仅可以避免创建大量的字符串,还可以清楚地隔离参数,当需要复制参数时,只需要双击鼠标,而不是慢慢地用鼠标对齐和拖动。这样打出来的日志可读性强,对排查问题很有帮助!Tips1)多线程遇到如何打印多个线程一起执行的日志?有些系统涉及并发执行、定时调度等,多次执行的日志会混在一起。如果出现问题,很难排除故障。我们可以打印线程名称或者添加一个标志来表明这个日志属于哪里。一次执行:if(log.isDebugEnabled()){log.debug("执行ID=[{}],处理了ID=[{}]的消息,处理结果:[{}]",execId,id,result);}复制代码2)使用SpringBootAdmin灵活切换日志级别。最后写代码的时候,没有规范日志的意识,其实我让自己踩了很多坑,加班很多课。回想起来,想对学习期间的我说:“让你加班加点的事情,都隐藏在各种细节中!在写代码之前,先学会如何做好日志!”
