Java日志设计&实践(3) - 开发篇

1.选择恰当的日志级别
2.输出明确的提示文字和充分的现场信息
3.输出内容一行搞定,不要换行
4.其他

 

1.选择恰当的日志级别

选择日志级别时需要遵循一些通用规范,不可随意定义

log4j的日志级别,由低到高排列:all trace debug info warn error fatal off
其中,all off仅用以log4j配置文件中开启或关闭所有日志,trace fatal一般也用不到
对于开发人员来说,只需要关注debug info warn error

debug
    正常情况下不需要输出,只有当出问题时才需要输出的日志信息,由于生产环境无法单步调试,可以把debug级别的日志想象成你在生成环境中debug
info
    可能要关注或者只有比较重要的信息才需要输出,如:用户登录、退出、后台job执行时长等
warn
    存在一些潜在的危险时输出的日志,比如:请求参数中包含攻击注入脚本
error
    如:请求数据库时的SQL异常

当然,最好的方法还是参考优秀的开源代码
   

2.输出明确的提示文字和充分的现场信息

要点:
1)明确的提示文字,看到这段提示文本就可以知道发生了什么,不需要再去扒拉源码
2)充分的现场信息,如:用户信息、引发异常的参数值、异常栈信息等

举例:
LOG.warn("Unknown value for includeParams parameter to URL tag: " + includeParams);
LOG.warn("Unable to put request parameters (" + extractQueryString() + ") into parameter map.", e);
LOG.warn("Could not find token mapped to token name " + tokenName);

 

3.一条日志一行搞定

这个是为了方便跟踪和分析日志,使用grep命令时不至于仅看到一条日志的部分内容

 

4.其他

 

4.1.尽量使用一套日志接口,强烈推荐slf4j

两大理由:
1)使用{}占位符,避免字符串拼接

以刚才三个log为例
LOG.warn("Unknown value for includeParams parameter to URL tag: " + includeParams);
LOG.warn("Unable to put request parameters (" + extractQueryString() + ") into parameter map.", e);
LOG.warn("Could not find token mapped to token name " + tokenName);

如果改用slf4j的话,写法如下:
log.warn("Unknown value for includeParams parameter to URL tag: {}", includeParams);
log.warn("Unable to put request parameters ({}) into parameter map.", extractQueryString(), e);
log.warn("Could not find token mapped to token name {}", tokenName);

2)执行实际日志输出前强制检查log是否开启

组合使用log4j+slf4j时,执行的warn方法实际是这样的:
  public void warn(String format, Object arg) {
    if (logger.isEnabledFor(Level.WARN)) {
      FormattingTuple ft = MessageFormatter.format(format, arg);
      logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable());
    }
  }

 

4.2.不要使用System.out.println()

这个就不多说了,日志中看到一句莫名其妙hello,world你会怎么想,怎么查????

4.3.不要使用e.printStackTrace()

这种打印只能输出到catalina.out中,无法单独制定输出目的文件,还会导致日志输出混乱

4.4.slf4j打印异常堆栈信息

两个例子:

try {
    if (true) {
        throw new RuntimeException("i‘m ok");
    }
} catch (Exception e) {
    log.error("Error. param:{}, param2:{}, param3:{}", param, param2, param3, e);
}

将打印:

ERROR 2015-01-17 15:11:51,426 Error. param:0, param2:2, param3:false [cn.xxt.log.test.Slf4jTest.main(Slf4jTest.java:36)]

java.lang.RuntimeException: i‘m ok

    at cn.xxt.log.test.Slf4jTest.main(Slf4jTest.java:33) 
   

try {
    if (true) {
        throw new RuntimeException("i‘m sorry");
    }
} catch (Exception e) {
    log.error("Error. param:{}, param2:{}, param3:{}, {}", param, param2, param3, e);
}

将打印:

ERROR 2015-01-17 15:11:51,429 Error. param:0, param2:2, param3:false, java.lang.RuntimeException: i‘m sorry [cn.xxt.log.test.Slf4jTest.main(Slf4jTest.java:44)]

差异:前者输出了异常栈信息,后者没有

原因:后者用{}占位符打印异常对象e,导致异常栈信息没有输出

 

参考文档

为什么要使用SLF4J而不是Log4J

http://www.importnew.com/7450.html

时间: 2024-08-09 16:01:48

Java日志设计&实践(3) - 开发篇的相关文章

Java日志设计&实践(1) - 常见问题

日常开发.运维过程中经常会碰到以下几个问题: 什么情况下需要输出日志? 已明确需要输出日志时,如何选择日志级别? 已明确需要输出日志时,日志中需要输出哪些东东? 一个Tomcat加载多个工程,如何确定日志中的内容是哪个工程的? 多个Tomcat同时加载同一个工程,可以使用log4j的DailyRollingFileAppender等文件类Appender吗? 多个Tomcat同时加载同一个工程,可以分别指定日志输出目录吗? 日志中的中文乱码怎么办? 可以动态调整一个类的日志级别吗? 一天日志文件

Java日志设计&实践(2) - 设计篇

设计阶段主要考虑几个问题 按应用或功能拆分日志,但要把握度,过犹不及 日志配置需支持动态调整 使用Spring的Log4jConfigListener,实现动态调整日志级别 web.xml对应位置加入如下内容 <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.properties</param-value> </c

Java日志信息存库(logback篇)

一.Logback简介 Logback是由log4j创始人设计的又一个开源日志组件.logback当前分成三个模块:logback-core,logback- classic和logback-access.logback-core是其它两个模块的基础模块.logback-classic是log4j的一个 改良版本.此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日志系统如log4j或JDK14 Logging.logback-access访问模块与Servl

Java日志信息存库(log4j篇)

一.Log4j简介 在一个完整的J2EE项目开发中,日志是一个非常重要的功能组成部分.它可以记录下系统所产生的所有行为,并按照某种规范表达出来.我们可以通过日志信息为系统进行排错,优化系统的性能,或者根据这些信息调整系统等行为.Log4j是Apache针对于日志信息处理的一个开源项目,其最大特点是通过一个配置文件就可以灵活地控制日志信息的输出方式(控制台.文件和数据库等).日志输出格式及日志信息打印级别等,而不需要修改应用的代码. 二.编写背景 作为一名程序猿在开发中总能遇到一些比较奇葩的需求,

数据库系统概论【设计与应用开发篇】

一.关系数据理论 作为一个二维表,关系要符合一个最基本的条件:每一个分量必须是不可分割的数据项.满足了这个条件的关系模式就属于第一范式(1NF) 数据依赖是一个关系内部属性与属性之间的一种约束关系.这种关系是通过属性间值得相等与否体现出来的数据间相关联系.包括:函数依赖(Functional Dependency,FD)和多值依赖(Multi-Valued Dependency,MVD). 关系数据库规范化过程主要克服数据库逻辑结构中的问题:      (1).数据冗余     (2).更新异常

Java日志规范

前言 一个在生产环境里运行的程序如果没有日志是很让维护者提心吊胆的,有太多杂乱又无意义的日志也是令人伤神.程序出现问题时候,从日志里如果发现不了问题可能的原因是很令人受挫的.本文想讨论的是如何在Java程序里写好日志. 一般来说日志分为两种:业务日志和异常日志,使用日志我们希望能达到以下目标: 对程序运行情况的记录和监控: 在必要时可详细了解程序内部的运行状态: 对系统性能的影响尽量小 Java日志框架 Java的日志框架太多了... Log4j 或 Log4j 2 - Apache的开源项目,

EntityFramework之领域驱动设计实践

EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领域驱动设计实践 (二):分层架构 EntityFramework之领域驱动设计实践 (三):案例:一个简易的销售系统 EntityFramework之领域驱动设计实践 (四):存储过程 - 领域驱动的反模式 EntityFramework之领域驱动设计实践 (五):聚合 EntityFramewor

(转)EntityFramework之领域驱动设计实践

EntityFramework之领域驱动设计实践 - 前言 EntityFramework之领域驱动设计实践 (一):从DataTable到EntityObject EntityFramework之领域驱动设计实践 (二):分层架构 EntityFramework之领域驱动设计实践 (三):案例:一个简易的销售系统 EntityFramework之领域驱动设计实践 (四):存储过程 - 领域驱动的反模式 EntityFramework之领域驱动设计实践 (五):聚合 EntityFramewor

Java日志系统框架的设计与实现

推荐一篇好的文章介绍java日志系统框架的设计的文章:http://soft.chinabyte.com/database/438/11321938.shtml 文章内容总结: 日志系统对跟踪调试.程序状态记录.数据恢复等功能有重要作用 日志系统一般作为服务进程或者系统调用存在,我们一般程序中使用系统调用 常用日志系统包括log4j的简单介绍 日志系统的系统架构 日志系统的信息分级 日志输出的设计 下面是全文的引用: 在Java领域,存在大量的日志组件,open-open收录了21个日志组件.日