日志最佳实战
1. logback
2. 开发debug,生产info , 异常error
3. 使用self4j的占位符方式输入日志。多个参数输出,参数项使用数组的形式。举例 : logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);
此种形式在确定日志输出级别前,不会拼接字符串,注意:占位符只适用于与字符串。 // LOGGER.isDebugEnabled()
4. 访问日志和错误日志记录到不同的文件中,方便查询
5. 外部接口输入和输出处加记录日志,方便调试
6. 所有怀疑影响性能的地方加上日志记录,不要怕日志多
7. 明确日志的每一项输出
8. 异常日志输出出现异常的具体位置。log中记录内容 e:logger.info("Exception is : ",e); 可以记录异常的堆栈信息
9. 日志中包含充分的信息,日志中的时间戳要精确到毫秒。
10. ERROR:运行时异常以及预期之外的错误。
WARN:预期之外的运行时状况,不一定是错误的情况。
INFO:运行时产生的事件。
DEBUG:与程序运行时的流程相关的详细信息。
11. 每个记录器对象都有一个运行时对应的严重性级别。该级别可以通过配置文件或代码的方式来进行设置。如果没有显式指定严重性级别,则会根据记录器名称的层次结构关系
往上进行查找,直到找到一个设置了严重性级别的名称为止。比如名称为“com.myapp.web.IndexController”的记录器对象,如果没有显式指定其严重性级别,则会依次
查找是否有为名称“com.myapp.web”、“com.myapp”和“com”指定的严重性级别。如果仍然没有找到,则使用根记录器配置的值。
12. 前一天的日志自动压缩
13. MDC和NDC来处理多用户同时访问日志信息。NDC和MDC是log4j用于存储应用程序的上下文信息(context infomation),从而便于在log中使用这些上下文信息。
NDC采用了一个类似栈的机制来push存储上下文信息,每一个线程都独立地储存上下文信息。比如说一个servlet就可以针对每一个request创建对应的NDC,储存客户端
地址等等信息。相关的信息使用NDC.push(message); 在log的时候将信息输出。在相应的PatternLayout中使用”%x”来输出存储的上下文信息MDC内部使用了类似map
的机制来存储信息,相对应的方法,MDC.put(key,value);在配置PatternLayout的时候使用:%X{key}来输出对应的value
14. 日志聚合与分析
参考文章:http://www.ibm.com/developerworks/cn/java/j-lo-practicelog/
http://www.cnblogs.com/zhengyun_ustc/archive/2012/12/15/logging_bp.html
http://www.oschina.net/translate/why-use-sl4j-over-log4j-for-logging
所需jar包: logback-classic-1.1.2.jar logback-core-1.1.2.jar slf4j-api-1.6.1.jar
配置文件模板:
<!-- scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。 scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。 当scan为true时,此属性生效。默认的时间间隔为1分钟。 --> <configuration scan="true" scanPeriod="2 seconds" debug="false"> <!-- 控制台 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <!-- 日志记录内容:时间,线程,级别,类,日志信息,换行 --> <pattern>%d [%thread] %-5level [%c] - %msg%n </pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> <!-- 普通日志 --> <appender name="normal" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/normal/cmserver_normal.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/cmserver_normal.%d{yyyy-MM-dd}.log.zip</fileNamePattern> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level [%c] - %msg%n</pattern> </encoder> </appender> <logger name="normal" level="INFO" additivity="false"> <appender-ref ref="normal" /> </logger> <!-- 异常日志 --> <appender name="exception" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>logs/exception/cmserver_exception.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>logs/exception/cmserver_exception.%d{yyyy-MM-dd}.log.zip</fileNamePattern> </rollingPolicy> <encoder> <pattern>%d [%thread] %-5level [%c] - %msg%n</pattern> </encoder> </appender> <!-- additivity属性为false,表示此loger的打印信息不再向上级传递 --> <logger name="exception" level="INFO" additivity="false"> <appender-ref ref="exception"/> </logger> </configuration>
测试类:
public class LogTest { //定义一个全局的记录器,通过LoggerFactory获取 private final static Logger logger = LoggerFactory.getLogger(LogTest.class); //正常日志 private final static Logger normalLogger = LoggerFactory.getLogger("normal"); //异常日志 private final static Logger exceptionLongger = LoggerFactory.getLogger("exception"); public static void main(String[] args) { while(true){ // 普通日志 normalLogger.info(" LogTest : {}","This is a test !" ); try { Thread.sleep(2000); plus(); }catch(Exception e){ // 异常日志 exceptionLongger.error("error :" ,e ); logger.error("error :" ,e ); } } } public static void plus(){ int b = 1; int c = b/0;; } }