资讯详情

一个优秀的日志应该是什么样的

发布时间:2026/10/7 1:52:10

500+
企业客户服务经验
120+
行业领域内容覆盖
3000+
原创页面设计沉淀
98%
客户满意度

一个优秀的日志应该是什么样的

在上一篇一个合格的日志应该是什么样的我们打印的日志已经基本可用了。在线上接口行为和预期的不一致时INFO日志又不够详细看不出问题我们希望临时将日志级别修改为DEBUG要怎么做呢1. 修改日志级别1. 集成actuator基于spring-boot-starter的应用可以通过actuator修改日志级别。首先要添加actuator的依赖。dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-actuator/artifactId/dependency在application.properties中暴露端点management.endpoints.web.exposure.include*2. 查看日志级别1. 获取所有端点首先通过actuator获取可用的端点列表确认logger的端点存在curl-shttp://192.168.31.52:8080/actuator|jq.响应格式如下{_links:{self:{href:http://192.168.31.52:8080/actuator,templated:false},loggers:{href:http://192.168.31.52:8080/actuator/loggers,templated:false},loggers-name:{href:http://192.168.31.52:8080/actuator/loggers/{name},templated:true}}}2. 查看日志级别查看当前系统的所有Logger的级别curl-shttp://192.168.31.52:8080/actuator/loggers|jq.响应格式如下{levels:[OFF,ERROR,WARN,INFO,DEBUG,TRACE],loggers:{ROOT:{configuredLevel:INFO,effectiveLevel:INFO},com.keyniu:{effectiveLevel:INFO},com.keyniu.dis:{effectiveLevel:INFO}}}你也可以指定查看某个包的日志级别比如com.keyniu的curl-shttp://192.168.31.52:8080/actuator/loggers/com.keyniu|jq.响应格式如下{effectiveLevel:INFO}3. 设置日志级别通过POST请求修改日志级别curl-XPOST http://192.168.31.52:8080/actuator/loggers/com.keyniu-HContent-Type: application/json-d{configuredLevel: DEBUG}再次查询日志级别后可以发现级别已经更新为DEBUG4. 基于代码修改一般的公司是不允许在线上暴露actuator端点的所以我们经常会自定义修改日志级别的逻辑。代码修改的逻辑在不同的日志框架下是不同的我们以logback为例publicstaticvoidsetLogLevel(StringloggerName,Stringlevel){Loggerlogger(Logger)LoggerFactory.getLogger(loggerName);logger.setLevel(Level.toLevel(level));// 支持 OFF/ERROR/WARN/INFO/DEBUG/TRACE}Spring对此做了封装屏蔽了不同日志框架的差异我们可以通过LoggingSystem来完成日志级别修改。publicstaticvoidsetLogLevel(StringloggerName,LogLevellevel){LoggingSystemloggingSystemLoggingSystem.get(ClassLoader.getSystemClassLoader());loggingSystem.setLogLevel(loggerName,level);}2. 指定用户修改通过修改日志级别确实解决了问题不过日志级别的修改是全局的所有用户都受到影响而且也不可能在线上长期开启。所以往往我们会想要给特定的用户打印DEBUG日志比如内部人员、反馈问题的用户。通过logback本身提供的MDC我们能将指定请求标为要求打印DEBUG日志这段逻辑可以放在HandlerInterceptor中实现。1. 设置MDC标志publicclassDebugHandlerInterceptorimplementsHandlerInterceptor{OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{Stringuidrequest.getHeader(user-id);booleanxdebugdebugUid.contains(uid)||1.equals(request.getParameter(xdebug));MDC.put(xdebug,xdebug);returntrue;}OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{MDC.clear();}}2. 实现DEBUG日志再定义一个工具类用来判断是否要打印DEBUG日志publicclassDebugHelper{publicstaticbooleanisDebugEnabled(Loggerlogger){return1.equals(MDC.get(debug))||logger.isDebugEnabled();}}打印日志的时候需要自行判断DebugHelper.isDebugEnabledif(DebugHelper.isDebugEnabled(log)){log.info(debug info goes here);}这个方案简单直观不过对用户来说不太友好必须自己调用DebugHelper.isDebugEnabled的判断需要通过log.info来打印DEBUG日志3. slf4j的内部实现我们使用slf4j的时候时候都是从这一行代码开始的基于lombok的Slf4j只是帮我们生成了这一行代码privateLoggerlogLoggerFactory.getLogger(HelloWorldController.class);LoggerFactory的实现流程如下:当我们调用LoggerFactory时LoggerFactory会用两种方式寻找ILoggerFacotry的实现通过环境变量slf4j.provider获取配置通过ServiceLoader读取provider调用ILoggerFacotry.getLogger获取对应的日志实现返回一个实现了 org.slf4j.Logger 实现在原理清晰的前提下扩展的方案基本也明确了就是提供ILoggerFacotry的实现返回我们自己的org.slf4j.Logger的实现这个类的debug方法要包含我们的MDC里的xdebug的判断。我尝试了两种方案自定义SLF4JServiceProviderKeyniuSLF4jServiceProvider 配置-Dslf4j.providercom.keyniu.dis.logger.KeyniuSLF4jServiceProvider修改logback的实现修改Logger的isDebugEnabled和debug方法4. 扩展SLF4jServiceProvider1. 实现KeyniuSLF4jServiceProvider代码和LogbackServiceProvider一致只是修改ILoggerFacotry的实现publicclassKeyniuSLF4jServiceProviderimplementsSLF4JServiceProvider{staticfinalStringNULL_CS_URLhttp://logback.qos.ch/codes.html#null_CS;publicstaticStringREQUESTED_API_VERSION2.0.99;privateLoggerContextdefaultLoggerContext;privateIMarkerFactorymarkerFactory;privateLogbackMDCAdaptermdcAdapter;...publicILoggerFactorygetLoggerFactory(){returnnewKeyniuLoggerFactory(this.defaultLoggerContext);}...}2. 实现ILoggerFactory实现ILoggerFactory返回自己的Logger对象publicclassKeyniuLoggerFactoryimplementsILoggerFactory{privateLoggerContextloggerContext;publicKeyniuLoggerFactory(LoggerContextloggerContext){this.loggerContextloggerContext;}OverridepublicLoggergetLogger(Strings){returnnewKeyniuLogger(this.loggerContext.getLogger(s));}}3. 修改Logger的实现修改所有的debug和isDebugEnabled判断MDC的xdebug的值publicclassKeyniuLoggerimplementsorg.slf4j.Logger{privatech.qos.logback.classic.Loggerback;publicKeyniuLogger(ch.qos.logback.classic.Loggerback){this.backback;}OverridepublicbooleanisDebugEnabled(){returnback.isDebugEnabled()||1.equals(MDC.get(xdebug));}Overridepublicvoiddebug(Strings){if(1.equals(MDC.get(xdebug))){back.info(s);}else{back.debug(s);}}}4. 修改启动参数java-Dslf4j.providercom.keyniu.dis.logger.KeyniuSLF4jServiceProvider com.keyniu.dis.DiveInMain5. 最终失败SLF4J(I):Attemptingtoloadprovidercom.keyniu.dis.logger.KeyniuSLF4jServiceProviderspecified viaslf4j.providersystem propertyExceptionin threadmainjava.lang.IllegalArgumentException:LoggerFactoryis not aLogbackLoggerContextbutLogbackis on theclasspath.EitherremoveLogbackor the competing implementation(classcom.keyniu.dis.logger.KeyniuLoggerFactoryloaded from file:/target/classes/).Ifyou are usingWebLogicyou will needtoaddorg.slf4jtoprefer-application-packages inWEB-INF/weblogic.xml:com.keyniu.dis.logger.KeyniuLoggerFactoryatorg.springframework.util.Assert.instanceCheckFailed(Assert.java:592)atorg.springframework.util.Assert.isInstanceOf(Assert.java:511)atorg.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:401)atorg.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:128)atorg.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:238)原因是spring的LogbackLoggingSystem要求ILoggerFactory返回的LoggerFactory对象必须实现LoggerContext 而LoggerContext.getLog是一个final方法、返回的类是final类这条路走不通。5. 修改logback实现publicfinalLoggergetLogger(Class?clazz){returnthis.getLogger(clazz.getName());}修改logback的ch.qos.logback.classic.LoggerContext的getLogger实现返回KeyniuLogger虽然可用但是修改第三方包并不是好的想法。暂时采用第2步的方案。https://blog.keyniu.com/web/
热门专题

继续阅读更多专题内容

围绕企业服务、数字化转型与官网运营的常青话题,持续输出深度内容

企业官网建设指南 企业托管服务模式 财税政策与解读 企业数字化转型 官网SEO与获客 网站安全与运维
配套服务

读完这篇文章,了解更多服务

从整站搭建到SEO布局,17项核心服务助您打造高转化的企业官网

01

企业托管整站搭建

从信息架构到栏目预留,搭建可生长的企业站点骨架,每个页面独立原创设计。...

了解详情
02

规整可信网页设计

雪地靴温暖风原创设计,金属铜线条贯穿全页,拒绝通用模板与AI流水线。...

了解详情
03

企业服务SEO布局

关键词体系与语义化结构,从建站源头为搜索排名而生。...

了解详情
04

业务预约咨询表单

多场景表单与线索收集体系,把访问流量转化为可追踪的销售线索。...

了解详情
05

企业服务站点运维

安全巡检、数据备份与内容更新支持,全年守护网站稳定运行。...

了解详情
06

全终端商务适配

电脑、平板、手机一致呈现,移动端体验与转化同样出色。...

了解详情
需要专业建议?

让专业顾问为您解读行业趋势

关于企业官网建设、SEO获客与数字化转型的任何疑问,欢迎一对一咨询我们的专业顾问。