记一次线上找寻日志的苦恼——slf4j与log4j的使用
Posted 猿了个猿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次线上找寻日志的苦恼——slf4j与log4j的使用相关的知识,希望对你有一定的参考价值。
故事发生在一个苦逼的晚上,那晚在公司帮领导(代码是我们领导自己写的,这个项目不是太重要,没有经常性维护)找线上日志,通过在linux上面找遇到的问题:
1、项目中使用了日志,但是日志没有保存到文件里面了,只能通过Catalina.out中搜索了,这个catalina.out文件达到的500M,在里面找内容,苦苦寻觅了好久终于找到问题的所在了,结果是内容太长了,而数据库里面的字段太短了,导致插入失败,他是使用的text类型,而text类型的最大值为64kb,结果数据比64kb还有大,无奈,我建议换成longtext,完美解决问题。
通过这个问题,日志查询太麻烦了,领导让做日志分割,然后第二天的故事就开始了,我去重构代码,发现具体的日志竟然有apach的commonlog,还有log4j,快吐血了,让我重构的,没办法只能吐血去重构了, 最终选用了slf4j+log4j的方式作为整套的日志组件。
1、slf4j
slf4j,简单日志门面,不是具体的日志解决方案,它只服务于各式各样的日志系统,具体的日志是有log4j,logback等来实现,具体的介绍可以查看slf4j的官网
2、log4j
通过log4j,我们可以控制日志信息的输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件具体记录器等,具体的可以查看log4j官网
3、slf4j与log4j的使用
第一步: 创建项目(创建maven项目,使用的开发工具为eclipse)
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.2</version>
</dependency>
第三步:新建log4j.properties文件
# 日志输出级别(INFO)和输出位置(stdout,R)
log4j.rootLogger=all, stdout , R
# 日志输出位置为控制台
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
# 日志输出位置为文件
log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.File=D:\\Tomcat 5.5\\logs\\qc.log
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n
# 定义相应包路径下的日志输出级别
log4j.logger.com.alibaba=DEBUG
log4j.logger.com.opensymphony.oscache=ERROR
log4j.logger.org.springframework=DEBUG
log4j.logger.com.ibatis.db=WARN
log4j.logger.org.apache.velocity=FATAL
log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN
log4j.logger.org.hibernate=DEBUG
log4j.logger.org.logicalcobwebs=WARN
说明:
· log4j.rootCategory=ALL, stdout , R
此句为将等级为INFO的日志信息输出到stdout和R这两个目的地,stdout和R的定义在下面的代码,可以任意起名。等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,如果配置OFF则不打出任何信息,如果配置为INFO这样只显示INFO, WARN, ERROR的log信息,而DEBUG信息不会被显示,具体讲解可参照第三部分定义配置文件中的logger。
· log4j.appender.stdout=org.apache.log4j.ConsoleAppender
此句为定义名为stdout的输出端是哪种类型,可以是org.apache.log4j.ConsoleAppender(控制台),org.apache.log4j.FileAppender(文件),org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
· log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
此句为定义名为stdout的输出端的layout是哪种类型,可以是org.apache.log4j.htmlLayout(以HTML表格形式布局),org.apache.log4j.PatternLayout(可以灵活地指定布局模式),org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
· log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n
如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern,打印参数如下:%m 输出代码中指定的消息;%M 输出打印该条日志的方法名;%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL;%r 输出自应用启动到输出该log信息耗费的毫秒数;%c 输出所属的类目,通常就是所在类的全名;%t 输出产生该日志事件的线程名;%n 输出一个回车换行符,Windows平台为"rn”,Unix平台为"n”;%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2002-10-18 22:10:28,921;%l 输出日志事件的发生位置,及在代码中的行数;[QC]是log信息的开头,可以为任意字符,一般为项目简称。输出示例[TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean 'MyAutoProxy'
log4j的配置文件如下
#配置根Logger
log4j.rootLogger = [ level ] , appenderName1 , appenderName2 , …
#配置日志信息输出目的地Appender
log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1
…
log4j.appender.appenderName.optionN = valueN
#配置日志信息的格式(布局)
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1 = value1
…
log4j.appender.appenderName.layout.optionN = valueN
其中lavel有如下几种(按照高地顺序,降序排列)
OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
Appender 为目的地log4j提供了几种方式
org.apache.log4j.ConsoleAppender(控制台),
org.apache.log4j.FileAppender(文件),
org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
Layout:日志输出格式,Log4j提供的layout有以下几种:
org.apache.log4j.HTMLLayout(以HTML表格形式布局),
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
打印参数: Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,如下:
%m 输出代码中指定的消息
%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
%r 输出自应用启动到输出该log信息耗费的毫秒数
%c 输出所属的类目,通常就是所在类的全名
%t 输出产生该日志事件的线程名
%n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n”
%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},输出类似:2002年10月18日 22 : 10 : 28, 921
%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java: 10 )
第三步:使用
package com.yuanleyuan.log4j_slf4j_test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Hello world!
*
*/
public class App {
private static Logger log = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
// error
log.error("error");
// info
log.info("info{},{}", "参数化1", "参数化2");
// warn
log.warn("warn{}", "warn....");
boolean debugEnabled = log.isDebugEnabled();
if (debugEnabled) {
log.debug("debug{}", "debug......");
}
}
}
输出结果
[QC] ERROR [main] com.yuanleyuan.log4j_slf4j_test.App.main(16) | error
[QC] INFO [main] com.yuanleyuan.log4j_slf4j_test.App.main(18) | info参数化1,参数化2
[QC] WARN [main] com.yuanleyuan.log4j_slf4j_test.App.main(20) | warnwarn....
[QC] DEBUG [main] com.yuanleyuan.log4j_slf4j_test.App.main(24) | debugdebug......
大家都看到了吧,建议大家,忘记System.out,而要牢牢的记住log,而且还要在真正开始一个项目之前准备好工作,不要上来就写,导致后期问题很多,重构的时候被喷,所以这些项目基本的要牢牢记住,不要因为这些引起别人的厌烦。
以上是关于记一次线上找寻日志的苦恼——slf4j与log4j的使用的主要内容,如果未能解决你的问题,请参考以下文章