日志输出

项目开发中,日志使用是必不可少的。有了日志可以记录程序的运行过程,方便我们查找关键信息,也方便快速定位解决问题。
1、什么情况下要使用日志呢?

  • 编程语言提示异常:如今各类主流的编程语言都包括异常机制,业务相关的流行框架有完整的异常模块。这类捕获的异常是系统告知开发人员需要加以关注的,是质量非常高的报错。应当适当记录日志,根据实际结合业务的情况使用warn或者error级别。
  • 业务流程预期不符:除开平台以及编程语言异常之外,项目代码中结果与期望不符时也是日志场景之一,简单来说所有流程分支都可以加入考虑。取决于开发人员判断能否容忍情形发生。常见的合适场景包括外部参数不正确,数据处理问题导致返回码不在合理范围内等等。
  • 系统核心角色,组件关键动作:系统中核心角色触发的业务动作是需要多加关注的,是衡量系统正常运行的重要指标,建议记录INFO级别日志,比如电商系统用户从登录到下单的整个流程;微服务各服务节点交互;核心数据表增删改;核心组件运行等等,如果日志频度高或者打印量特别大,可以提炼关键点INFO记录,其余酌情考虑DEBUG级别。
  • 系统初始化:系统或者服务的启动参数。核心模块或者组件初始化过程中往往依赖一些关键配置,根据参数不同会提供不一样的服务。务必在这里记录INFO日志,打印出参数以及启动完成态服务表述。
    2、常用的日志框架什么?

2.1 常用的日志框架
log4j、Logging、commons-logging、slf4j、logback
2.2 日志框架怎么选

  • commons-loggin、slf4j 只是一种日志抽象门面,不是具体的日志框架。 log4j、logback 是具体的日志实现框架。
  • 在比较关注性能的地方,选择Logback或自己实现高性能Logging API可能更合适。推荐:slf4j + logback.
  • 在已经使用了Log4j的项目中,如果没有发现问题,继续使用可能是更合适的方式:推荐组合为:slf4j + log4j2.
  • 如果不想有依赖则使用java.util.logging或框架容器已经提供的日志接口。

3、日志如何使用?

3.1指定类日志输出
使用指定类初始化日志对象,在日志输出的时候,可以打印日志信息所在的类。在项目开发过程中,经常需要打印日志信息,往往会在每个类的第一行加上形如以下代码:

public static final Logger logger =LoggerFactory.getLogger(XXX.class);

2、不要使用具体的日志实现类

InterfaceImpl interface = new InterfaceImpl();

上面的写法是错误的。应该面向接口的对象编程,而不是面向实现,这也是软件设计模式的原则,正确的做法应该是。

Interface interface = new InterfaceImpl();

3、日志框架里面也是如此,上面也说了,日志有门面接口,有具体实现的实现框架,所以大家不要面向实现编程。
输出Exceptions的全部Throwable信息。因为log.error(msg)和log.error(msg,e.getMessage())这样的日志输出方法会丢失掉最重要的StackTrace信息。

void foo(){
    try{
       //do somehing 
    }catch(Exception e){
        log.error(e.getMessage());//错误示范
        log.erroe("Bad Things",e.getMessage());//错误示范
        log.error("Bad Things",e);//正确演示
    }
}

4、不允许记录日志后又抛出异常。如捕获异常后又抛出了自定义业务异常,此时无需记录错误日志,由最终捕获方进行异常处理。不能又抛出异常,又打印错误日志,不然会造成重复输出日志。

void foo() throws LogException{
    try{
        //do somehing 
    }catch(Exception e){
        log.error("Bad Things",e);//正确
        throw new LogException("Bad Things",e);
    }
}

5、不允许使用标准输出
包括System.out.println()和System.error.println()语句。因为这个只会打印到控制台,而不会记录到日志文件中,不方便管理日志。此外,标准输出不会显示类名和行号信息,一旦代码中大量出现标准输出的代码,且日志中打印有标准输出的内容,很难定位日志内容和日志打印的位置,根本无法排查问题,想删除无用日志输出也改不动,这个是笔者在重构古董代码的时候亲自踩过的一个坑。

void foo(){
    try{
       //do somehing 
    }catch(Exception e){
        Syste.out.println(e.getMessage());//错误
        System.error.println(e.getMessage());//错误
        log.error("Bad Things",e);//正确
    }
}

6、不允许出现printStackTrace

void foo(){
    try{
       //do somehing 
    }catch(Exception e){
        e.printStacktrace();//错误
        log.error("Bad Things",e);//正确
    }
}

来看一下它的源码:

public void printStackTrace() {
    printStackTrace(System.err);
}

它其实也是利用 System.err 输出到了Tomcat控制台。
7、
不要在大循环中打印日志
如果你的框架使用了性能不高的 Log4j 框架,那就不要在上千个 for 循环中打印日志,这样可能会拖垮你的应用程序,如果你的程序响应时间变慢,那要考虑是不是日志打印的过多了。

for(int i=0; i<2000; i++){
    log.info("XX");
}

最好的办法是在循环中记录要点,在循环外面总结打印出来。

五、参考资料
Java 程序如何正确地打日志
Java 应用中的日志
优秀日志实践准则
Java常用日志框架介绍

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值