记一次线上找寻日志的苦恼——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项目,别问我为什么要使用maven去做,而不是去下载jar包,maven的使用是一个java程序员必备的技能,你不会maven就不要告诉别人你是搞java的,maven的使用给大家推荐一个,请大家自行脑补。http://maven.apache.org/

     第一步: 创建项目(创建maven项目,使用的开发工具为eclipse)

     第二步: 加入slf4j和log4j以及log4j与slf4j的适配包,这里给大家推荐一个maven依赖,将这些都配置好,妈妈再也不担心jar包兼容性问题了
     

  <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的定义在下面的代码,可以任意起名。等级可分为OFFFATALERRORWARNINFODEBUGALL,如果配置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,而且还要在真正开始一个项目之前准备好工作,不要上来就写,导致后期问题很多,重构的时候被喷,所以这些项目基本的要牢牢记住,不要因为这些引起别人的厌烦。
最后那大家可以关注我的公众微信号(定期会发一些内容,目前微信公众号刚刚成立,希望大家多多支持呀)
猿了个猿

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值