java日志记录总结

日志现状

线上问题追踪,基于日志的统计分析等都离不开日志。Java领域常见的日志框架有:

1、commons-logging是一套日志接口

log4j apache log4j是一个基于java的日志工具,log4j2是其升级产品,但二者并不兼容。

2、slf4j是另一套日志接口

logback 是slf4j的一个实现

所以现在java领域的日志分为两大阵营:commons logging和slf4j,前者有apache背景,虽然一度让sfl4j市场领先,但新的log4j2也具有了slf4j的所有特性。

3、常用的组合方式为:slf4j与logback组合使用,commons logging与log4j组合使用。

两者相比更建议使用前者组合,原因:性能更高;开销更低;logback文档免费;

4、有些依赖如Spring本身的日志实现使用了Commons Logging,而我们指定的方案是slf4j+logback,这时需要在项目中将Commons Logging排除掉,一般采用maven的exclusion排除。

5、桥接包和实现包对应关系如下图,需要注意的是,连接层的jar包和实现的jar的版本要一致

 

jar包名说明
slf4j-log4j12-1.7.13.jarLog4j1.2版本的桥接器,需要将Log4j.jar加入Classpath。
slf4j-jdk14-1.7.13.jarjava.util.logging的桥接器,Jdk原生日志框架。
slf4j-jcl-1.7.13.jarJakarta Commons Logging 的桥接器. 这个桥接器将Slf4j所有日志委派给Jcl。
logback-classic-1.0.13.jar(logback-core-1.0.13.jar)Slf4j的原生实现,Logback直接实现了Slf4j的接口,因此使用Slf4j与Logback的结合使用也意味更小的内存与计算开销
  
多个日志jar包形成死循环的条件产生原因
log4j-over-slf4j.jar和slf4j-log4j12.jar同时存在由于slf4j-log4j12.jar的存在会将所有日志调用委托给log4j。但由于同时由于log4j-over-slf4j.jar的存在,会将所有对log4j api的调用委托给相应等值的slf4j,所以log4j-over-slf4j.jar和slf4j-log4j12.jar同时存在会形成死循环
jul-to-slf4j.jar和slf4j-jdk14.jar同时存在由于slf4j-jdk14.jar的存在会将所有日志调用委托给jdk的log。但由于同时jul-to-slf4j.jar的存在,会将所有对jul api的调用委托给相应等值的slf4j,所以jul-to-slf4j.jar和slf4j-jdk14.jar同时存在会形成死循环
  

在使用commons logging时为了减少构建日志信息的开销,通常的做法是

if(log.isDebugEnabled()){

    log.debug("User name: " +

    user.getName() + " buy goods id :" + good.getId());

}

而使用slf4j,你只需这么做:

log.debug("User name:{} ,buy goods id :{}", user.getName(),good.getId());

6、一个常用的依赖如下:

jcl-over-slf4j包是为了将一些早期使用commons-logging的桥接到slf4j

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>4.0.9.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.5.8</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.5.8</version>
    </dependency>
</dependencies>

6、logback取代log4j的理由:

1) 非常充分的文档、非常充分的测试、更快的实现等

2) 自动重新加载配置文件

3) 自动压缩已经打出来的log,使用RollingFileAppender再产生新文件时会自动压缩,异步处理。

日志使用方法

1、logback.xml配置文件

logback会依次尝试在 classpath 下查找文件 logback-test.xml,logback.xml,如果两个文件都不存在,logback会自动对自己进行配置,导致记录输出到控制台。

2、web.xml加入以下配置

webAppRootKey默认是webapp.root,如果同一个tomcat里启动多个应用,webAppRootKey会指向之前已经启动的项目,会出现启动不了的情况。

解决办法是为每个项目都加上该配置,最好用"工程名.root"来标识

<context-param>
    <param-name>webAppRootKey</param-name>
    <param-value>admin-web.root</param-value>
</context-param>

<!--配置文件的存放地址,classpath后面不要带*-->
<context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:log4j.properties</param-value>
</context-param>
<!--开一条监控线程每60秒动态扫描一下配置文件位置的变化。-->
<context-param>
    <param-name>log4jRefreshInterval</param-name>
    <param-value>60000</param-value>
</context-param>

logback.xml语法

logback.xml语法非灵活,基本结构如下:
以<configuration>开头,后面有零个或多个<appender>元素,有零个或多个<logger>元素,有最多一个<root>元素。

1) 根节点<configuration>,包含下面属性:
scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。

2) 子节点<property> :用来定义变量值,它有两个属性name和value

<property resource="application.properties" />
加载外部属性文件
<property name="LOG_HOME" value="/home/admin/logs" /> 
可以通过${LOG_HOME}在logger中引用        

3) 子节点<appender>:负责写日志的组件,它有两个必要属性name和class。name指定appender名称,class指定appender的全限定名
Appender主要用于存放日志对象,也可以定义日志类型、级别。有ConsoleAppender和RollingFileAppender两种
日志对象包括日志输出的目的地,目的地可以是控制台、文件、远程套接字服务器、 MySQL等数据库。
Logger级别:TRACE、DEBUG、INFO、WARN、ERROR。root logger 默认级别是 DEBUG。

级别排序为: TRACE < DEBUG < INFO < WARN < ERROR
3.1 ConsoleAppender 把日志输出到控制台,有以下子节点:
<encoder>:对日志进行格式化。

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder charset="UTF-8">
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
    </encoder>
</appender>

3.2 RollingFileAppender:滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件。有以下子节点:
1、<file>:被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建,没有默认值。
2、<rollingPolicy>:当发生滚动时,决定RollingFileAppender的行为,涉及文件移动和重命名。
        ch.qos.logback.core.rolling.TimeBasedRollingPolicy最常用的滚动策略,设置最大数量;
        <fileNamePattern>:必要节点
        <maxHistory>:可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每个月滚动,且<maxHistory>是6,则只保存最近6个月的文件,删除之前的旧文件。

//每天生成一个日志文件保存15天的
<appender name="FILE-DEBUG"    class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${log.root.folder}/cls-web-debug.log.%d{yyyy-MM-dd}</fileNamePattern>
        <maxHistory>15</maxHistory>
    </rollingPolicy>
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>DEBUG</level> 
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
    </encoder>
</appender>

3、<triggeringPolicy>: 条件满足时,告知 RollingFileAppender 触发滚动。日志文件大于50M时,触发滚动策略
        <maxFileSize>50MB</maxFileSize>

常搭配FixedWindowRollingPolicy使用,用于生产环境。

//当文件大于50M时,生成新的日志文件,窗口大小是1~50,当保存了50个文档后,将覆盖最早的日志文件
<appender name="RollingBaseSize" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>/home/data/logs/cls/cls-admin/cls-admin-web.log</file>

    <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
        <fileNamePattern>/home/data/logs/cls/cls-admin/cls-admin-web.%i.log</fileNamePattern>
        <minIndex>1</minIndex>
        <maxIndex>50</maxIndex>
    </rollingPolicy>

    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <maxFileSize>50MB</maxFileSize>
    </triggeringPolicy>

    <encoder>
        <pattern>%date [%thread] %-5level %class{0}.%method - %X{rule} - %msg%n</pattern>
    </encoder>
</appender>

4) 子节点<logger>:用来设置某一个包或具体的某一个类的日志打印级别、以及指定<appender>。
<logger>仅有一个name属性,一个可选的level。可以包含零个或多个<appender-ref>元素,标识这个appender将会添加到这个logger

5) 子节点<root>:它也是<logger>元素,但是它是根logger,是所有<logger>的上级。只有一个level属性,因为name已经被命名为"root",且已经是最上级了。

pattern语法

%d{yyyy-MM-dd HH:mm:ss.SSS} 显示日志记录时间

[%thread] 线程名

%-5level 日志级别

%logger{36}表示logger名字最长36个字符,否则按照句点分割。

%msg 显示输出消息

%n 当前平台下的换行符

%-5p 显示该条日志的优先级

%i 指定生成的索引

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值