如何打日志的一些总结

反例:

如何打日志的一些总结_第1张图片

这个demo里面,典型的空指针异常,如果这样打印日志,输出的结果毫无意义,因为没有异常栈,无法精确定位到哪一行。

日志和异常:

日志是日志,异常是异常

1.并不是一定要抛了异常才要打日志

2.即使抛了异常打日志,如果只打了错误名称,也很难找问题。

如何打日志的一些总结_第2张图片

线上的截图

订单最好打印订单号

请求参数最好说明是哪个参数的那个字段

案例一:

线上报警日志

如何打日志的一些总结_第3张图片

根据该日志 定位到VatDeclarationForm.java:247 行

java.lang.Exception: Unparseable date: “Invalid date”

at com.souche.financial.report.json.VatDeclarationForm.getExcel(VatDeclarationForm.java:247)

at sun.reflect.GeneratedMethodAccessor273.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at com.souche.optimus.core.engine.ParamResolverFactory.invoke(ParamResolverFactory.java:127)

at com.souche.optimus.core.controller.AbstractJsonController.invoke(AbstractJsonController.java:54)

at com.souche.optimus.core.controller.JsonController.doRender(JsonController.java:76)

at sun.reflect.GeneratedMethodAccessor232.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:498)

at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)

at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)

at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)

at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)

at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)

at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)

at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)

at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)

at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)

at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)

at com.souche.optimus.core.interceptor.CrossDomainFilter.doFilter(CrossDomainFilter.java:21)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)

at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)

at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)

at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:676)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)

at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)

at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1539)

at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1495)

at com.alibaba.ttl.TtlRunnable.run(TtlRunnable.java:49)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)

at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

at java.lang.Thread.run(Thread.java:748)

定位到VatDeclarationForm.java:247 行

try catch范围太大,无法定位Invalid date 哪里来的。

如何打日志的一些总结_第4张图片

换一种写法:
如何打日志的一些总结_第5张图片

推荐打印的时候 打log.info("{}",e); 会打印出异常栈

log.info("{}",e.getMessage()); 不会打印异常栈

应该要记录异常栈,这样才可以精确到行找到问题所在。 e.getmessage 推荐使用在返回给接口调用方的时候,或者小范围自己明确知道可能出现错误的地方。

注意! 返回异常栈给调用方,外部调用方又不能看到你的代码,总不能还要去调用方那边看日志。

反面案例:gateway 调server ,server没有处理异常,然后异常被抛到了gateway。

日志级别:

如何打日志的一些总结_第6张图片

如何打日志的一些总结_第7张图片

改回info之后

如何打日志的一些总结_第8张图片

开发和测试联调阶段,可以多打一些debug级别的日志,logback.xml 设置成debug ,上线之后关掉就没有了。

日志的作用:

1.报错了知道错在哪

2.没报错的时候,知道关键节点的数据状态 ,很多时候并没有报错,但是就是数据的内容或者状态不对。

如果没有日志,就只能debug模式自己调 ,线上没法debug。

日志给谁看:

debug日志给开发和测试看。

info和error日志给开发测试运维看。

什么时候看:

开发自测的时候,通过debug日志埋点可以知道自己的数据流在每个阶段的状态

比如说 接收到数据 参数->处理完成 参数->返回结果 参数 有三个阶段

每个阶段埋点打印日志,这样可以快速知道自己的数据在经历每个节点的时候的具体内容

很多时候是没有报错,但是就是数据内容和预期不一致。

特别是对于测试来说,如果测试出现问题,结果不对,能找到原因。 我们的测试是比较负责的,会去找原因,

而不是让开发自己去找原因。

什么情况下打日志:

1.开发环境下,流程上埋点debug日志

2.关键节点 打info日志:

比如说

a. 外部接口调用 入参信息 非常重要

b.数据校验或者操作 校验的参数信息 非常重要

c. 外部交互比如说mq 发送的内容信息

3.为了保证不影响正常流程的erro日志。 比如说,excel解析,

在每一行的时候,不能因为一行的异常没有被捕获而导致整个文件解析失败。

因此最好在最外层的时候就将整行解析方法try -catch ,出现问题打印error日志 ,记录出错的原始数据和信息

如何打日志的一些总结_第9张图片
inoke解析一行的数据,如果在verify和dohandler里面都没有被开发捕获到的异常

就会进入到try-catch 而不会导致整个文件的解析失败。

4.高危操作打日志:

比如说删数据, 因为如果到时候明细找不到了,没法区分到底是我删了还是真的对方没有推送过来

如何打日志的一些总结_第10张图片

总结:

日志要给出当前操作做了什么

使用的什么数据.

好的日志应该被看成文档注释的一部分.

最后一点, 切记不要在日志中包含密码和个人隐私信息,比如说不要在日志里面把人家用户信息账户密码都打印出来!

错误日志示范:request可能为空,导致本来没问题的代码,打日志打出来空指针。

log.debug(“Processing request with id: {}”, request.getId());

  1. 日志打印集合。LIst user

log.debug(“Processing request with id: {}”,user));

万一user有100万条呢? 日志刷屏是一回事,搞不好打日志打出来内存溢出。

集合 一般打印条数和这个集合的查询关键字。 这样真的有需要的话,可以根据关键字去数据库查。

3.核心方法调用前后加上了日志

因为一旦出现问题,比如说方法里面发生了死锁。这种情况下都只有输入日志, 不会有输出日志。

最后:

不要用system.out.print 和e.printStatcktrace 打日志

这两个输出是到控制台,而不是到日志文件。

我们看日志的时候,看的是日志文件,而不是控制台。

如果是高并发接口里面不要加e.printStatcktrace

如何打日志的一些总结_第11张图片

里面封装了个system.err的流,而且还加了同步锁。

你可能感兴趣的:(支付平台开发相关)