一篇文章彻底搞清JAVA日志框架的使用

Java
292
0
0
2023-12-04
标签   Java框架

一、 Java 日志框架发展历程

  • 1996年,欧洲安全电子市场项目组编写了自己的程序跟踪API,后发展成为 log 4j,并成为Apache基金会项目成员;
  • 2002年Java1.4,Sun推出Java Util Loggin(JUL),模仿了Log4j的实现;
  • 2002年Apache推出Jakarta Commons Logging(JCL),定义了一套日志接口和简单的Simple Log实现,支持运行时动态加载日志组件。从官网看,2014年1.2版本后就没在更新了。
  • 2006年,Ceki Gülcü创建了slf4j和Logback(也是Log4j的作者);
  • 2012年,Apache开发Log4j 2,其与Log4j1不兼容。

二、一些基本概念

1. 接口与实现

  • Commons Logging和Slf4j定义的是接口,需要给出具体的实现再使用;
  • 一般Slf4j与Logback组合使用,Commons Logging与Log4j组合使用。

2. 日志信息输出目的地

  • 控制台
  • 打印到文件
  • 打印到网络
  • 写入数据库

三、Jakarta Commons Logging(JCL)

1. 框架结构

JCL由Apache提供的一个通用日志API,包名: org.apache.commons.logging ,有两个抽象类:

  • Log:基本记录器
  • LogFactory:负责创建Log实例

2. LogFactory查找日志工具的顺序

  1. 寻找当前factory中名叫 org.apache.commons.logging.Log 配置属性的值;
  2. 寻找系统中属性中名叫 org.apache.commons.logging.Log 的值;
  3. 如果应用程序的classpath中有log4j,则使用相关的包装(wrapper)类(Log4JLogger);
  4. 如果应用程序运行在jdk1.4的系统中,使用相关的包装类(Jdk14Logger);
  5. 使用简易日志包装类(SimpleLog)。

3. 日志严重性排序

 // 非常严重的错误
log.fatal(Object message);
log.fatal(Object message, Throwable t);
// 一般运行期间错误
log.error(Object message);
log.error(Object message, Throwable t);
// 警告性错误
log.warn(Object message);
log.warn(Object message, Throwable t);
// 有意义的日志信息
log.info(Object message);
log.info(Object message, Throwable t);
// 调试信息
log.debug(Object message);
log.debug(Object message, Throwable t);
// 更完整的跟踪链信息
log.trace(Object message);
log.trace(Object message, Throwable t); 

4. 基本使用示例

3.4.1 maven引用

 <dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>.2</version>
</dependency> 

3.4.2 java示例

 
// 引用
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

// 创建日志对象
// 没有其它日志实现的时候,会自动实现jdk自带的日志JUL
private static Log log = LogFactory.getLog(Test.class);

// 调用,建议调用日志时都使用is...Enabled进行判断 
if (log.isDebugEnabled()) {
     log.debug("debug test");
}

3.4.3 运行结果

5. 使用JCL+Log4j

3.5.1 maven引用

 <!--  -->
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>.2</version>
</dependency>
<dependency>
    <groupId>logj</groupId>
    <artifactId>logj</artifactId>
    <version>.2.17</version>
</dependency> 

3.5.2 创建commons-loggin.properties文件

 org.apache.commons.logging.Log = org.apache.commons.logging.impl.LogJLogger
 

3.5.3 创建log4j.properties

 #配置根  Loggers控制日志的输出级别与日志是否输出
logj.rootLogger=trace,console
 
#配置输出到控制台  Appenders是指定日志的输出方式
logj.appender.console=org.apache.log4j.ConsoleAppender
#指定输出控制台
logj.appender.console.Target = System.out
#指定布局,输出日志的格式
logj.appender.console.layout=org.apache.log4j.PatternLayout
#指定布局的参数
logj.appender.console.layout.ConversionPattern=[%-10p] %r %l %d{yyyy-MM-dd HH:mm:ss.SSS} %m%n 

3.5.4 java示例

   @Test
  public void test() throws Exception{
      // 获取log日志记录器对象
      Log log = LogFactory.getLog(JCLTest.class);
      if(log.isInfoEnabled()){
      log.info("hello jcl");
      }
   } 

3.5.5 运行结果

四、slf4j

1. 功能介绍

slf4j类似JCL提供日志接口,可以选用的实现有:NLOG4J、SimpleLogger、logback、log4j等,也可以通过slf4j提供的API实现来开发相应的适配器,如:Log4jLoggerAdapter、JDK14LoggerAdapter。

2. 使用slf4j+log4j

log4j是apache实现的一个开源日志组件。(Wrapped implementations)

4.2.1 maven引用

 <dependencies>
    <dependency>
        <groupId>org.slfj</groupId>
        <artifactId>slfj-log4j12</artifactId>
        <version>.7.25</version>
    </dependency>
</dependencies> 

4.2.2 java示例

 import org.slfj.Logger;
import org.slfj.LoggerFactory;

/**
 * @author Cade on-10-14
 */public class test {
    private static final Logger logger = LoggerFactory.getLogger(test.class);
    public static void main(String[] args){
        if(logger.isInfoEnabled()){
            logger.info("hello");
        }
    }
}

4.2.3 运行结果

3. slf4j+log4j 日志写mysql数据库

4.3.1 maven引用

 <dependencies>
    <dependency>
        <groupId>org.slfj</groupId>
        <artifactId>slfj-log4j12</artifactId>
        <version>.7.25</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>.1.18</version>
    </dependency>
</dependencies> 

4.3.2 log4j.properties

 # 日记级别(单个级别) 文件/控制台
logj.rootLogger=debug, stdout, file ,datasource

# Redirect log messages to console
logj.appender.stdout=org.apache.log4j.ConsoleAppender
logj.appender.stdout.Target=System.out
logj.appender.stdout.layout=org.apache.log4j.PatternLayout
logj.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# Rirect log messages to a log file
logj.appender.file=org.apache.log4j.RollingFileAppender
logj.appender.file.File=test.log
logj.appender.file.MaxFileSize=5MB
logj.appender.file.MaxBackupIndex=10
logj.appender.file.layout=org.apache.log4j.PatternLayout
logj.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

#下面是配置将日志信息插入数据库,
#配置输出目标为数据库(假如要将日志在控制台输出,配置为logj.appender. stdout =org.apache.log4j.ConsoleAppender;将日志写入文件,配置为log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
#这样的配置在许多地方都要有,需要可查有关资料),当然你也可以自己扩展org.apache.logj.jdbc.JDBCAppender这个类,只需要在这里配置就可以了例如我们配置我自己扩展的MyJDBCAppender,配置为#log4j.appender.db=com.neam.commons.MyJDBCAppender
logj.appender.datasource=org.apache.log4j.jdbc.JDBCAppender
logj.appender.datasource.layout=org.apache.log4j.PatternLayout
logj.appender.datasource.driver=com.mysql.jdbc.Driver
#定义什么级别的错误将写入到数据库中
logj.appender.datasource.BufferSize=1
#设置缓存大小,就是当有条日志信息是才忘数据库插一次,我设置的数据库名和表名均为user
logj.appender.datasource.URL=jdbc:mysql://数据库ip:3306/数据库名称?characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull
logj.appender.datasource.user=数据库账号
logj.appender.datasource.password=数据库密码
logj.appender.datasource.sql=insert into logs (class,method,create_time,log_ level ,log_line,msg) values ('%C','%M','%d{yyyy-MM-dd HH:mm:ss}','%p','%l','%m')

4.3.3 数据库建表

 CREATE TABLE `logs`  (
  `class` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `method` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `create_time` datetime() NULL DEFAULT NULL,
  `log_level` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `log_line` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `msg` varchar() CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf COLLATE = utf8_general_ci ROW_FORMAT = Compact; 

4.3.4 java代码

 //注意导入的包都是slfj的包


import org.slfj.Logger;
import org.slfj.LoggerFactory;

public class test {
    private static final Logger log = LoggerFactory.getLogger(test.class);
    public static void main(String[] args) {
        if(log.isInfoEnabled()){
            log.info("logback的--info日志--输出了");
        }
    }
} 

4.3.5 运行结果

一篇文章彻底搞清JAVA日志框架的使用

4. 使用slf4j+logback

logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架。是slf4j的原生实现。(Native implementations)

logback特点:

  • 更快的执行速度
  • 充分的测试
  • 自动重新载入配置文件
  • 优雅地从I/O错误中恢复
  • 自动清除旧的日志归档文件
  • 自动压缩归档日志文件

4.4.1 maven引用

 <dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>.1.2</version>
</dependency> 

4.4.2 配置文件logback.xml

 <?xml version=".0" encoding="UTF-8"?>
<!--
scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒当scan为true时,此属性生效。默认的时间间隔为分钟。
debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
-->
<configuration scan="false" scanPeriod=" seconds" debug="false">
    <!-- 定义日志的根目录 -->
    <property name="LOG_HOME" value="/app/log" />
    <!-- 定义日志文件名称 -->
    <property name="appName" value="netty"></property>
    <!-- ch.qos.logback.core.ConsoleAppender 表示控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <Encoding>UTF-</Encoding>
        <!--
        日志输出格式:%d表示日期时间,%thread表示线程名,%-level:级别从左显示5个字符宽度
        %logger{} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符
        -->
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 滚动记录文件,先将日志记录到指定文件,当符合某个条件时,将日志记录到其他文件 -->  
    <appender name="appLogAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <Encoding>UTF-</Encoding>
        <!-- 指定日志文件的名称 -->  
        <file>${LOG_HOME}/${appName}.log</file>
        <!--
        当发生滚动时,决定 RollingFileAppender 的行为,涉及文件移动和重命名
        TimeBasedRollingPolicy: 最常用的滚动策略,它根据时间来制定滚动策略,既负责滚动也负责出发滚动。
        -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!--
            滚动时产生的文件的存放位置及文件名称 %d{yyyy-MM-dd}:按天进行日志滚动 
            %i:当文件大小超过maxFileSize时,按照i进行文件滚动
            -->
            <fileNamePattern>${LOG_HOME}/${appName}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <!-- 
            可选节点,控制保留的归档文件的最大数量,超出数量就删除旧文件。假设设置每天滚动,
            且maxHistory是,则只保存最近365天的文件,删除之前的旧文件。注意,删除旧文件是,
            那些为了归档而创建的目录也会被删除。
            -->
            <MaxHistory></MaxHistory>
            <!-- 
            当日志文件超过maxFileSize指定的大小是,根据上面提到的%i进行日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
            -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!--
        日志输出格式:%d表示日期时间,%thread表示线程名,%-level:级别从左显示5个字符宽度 %logger{50} 表示logger名字最长50个字符,否则按照句点分割。 %msg:日志消息,%n是换行符
        -->     
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [ %thread ] - [ %-level ] [ %logger{50} : %line ] - %msg%n</pattern>
        </layout>
    </appender>

    <!-- 
    logger主要用于存放日志对象,也可以定义日志类型、级别
    name:表示匹配的logger类型前缀,也就是包的前半部分
    level:要记录的日志级别,包括 TRACE < DEBUG < INFO < WARN < ERROR
    additivity:作用在于children-logger是否使用 rootLogger配置的appender进行输出,false:表示只用当前logger的appender-ref,true:表示当前logger的appender-ref和rootLogger的appender-ref都有效
    -->
    <!-- hibernate logger -->
    <logger name="org.hibernate" level="error" />
    <!-- Spring framework logger -->
    <logger name="org.springframework" level="error" additivity="false"></logger>

    <logger name="com.creditease" level="info" additivity="true">
        <appender-ref ref="appLogAppender" />
    </logger>

    <!-- 
    root与logger是父子关系,没有特别定义则默认为root,任何一个类只会和一个logger对应,
    要么是定义的logger,要么是root,判断的关键在于找到这个logger,然后判断这个logger的appender和level。 
    -->
    <root level="info">
        <appender-ref ref="stdout" />
        <appender-ref ref="appLogAppender" />
    </root>
</configuration> 

4.4.3 java代码

 //注意导入的包都是slfj的包
import org.slfj.Logger;
import org.slfj.LoggerFactory;

public class test {

    private static final Logger LOGGER = LoggerFactory.getLogger(test.class);

    public static void main(String[] args) {
        if(LOGGER.isInfoEnabled()){
            LOGGER.info("logback的--info日志--输出了");
        }
    }

} 

4.4.4 运行结果

五、日志组件冲突

如果在引用的项目里使用了log4j,如: zookeeper 使用了log4j,在pom中解决冲突:

 <dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>.4.9</version>
  <exclusions>
<exclusion>
<groupId>org.slfj</groupId>
<artifactId>slfj-log4j12</artifactId>
</exclusion>
              <exclusion>
                  <groupId>logj</groupId>
                  <artifactId>logj</artifactId>
              </exclusion>
</exclusions>
</dependency> 

可以使用

 mvn dependecy:tree 

查看依赖情况,或者在idea 的Maven窗口可以方便地看到引用情况。

六、Spring中使用Log4j

web.xml 设置:

 <!-- 设置根目录 -->  
   <context-param>    
       <param-name>webAppRootKey</param-name>    
       <param-value>webapp.root</param-value>    
   </context-param>    

   <context-param>  
    <param-name>logjConfigLocation</param-name>  
    <param-value>/WEB-INF/classes/logj.properties</param-value>  
</context-param>  
<!--表示 开一条watchdog线程每60秒扫描一下配置文件的变化;这样便于日志存放位置的改变 -->  
<context-param>    
        <param-name>logjRefreshInterval</param-name>    
        <param-value></param-value>    
   </context-param>   
<listener>  
    <listener-class>org.springframework.web.util.LogjConfigListener</listener-class>  
</listener> 

七、SpringBoot2 使用 logback

1. 引用

 <?xml version=".0" encoding="UTF-8"?>
<project xmlns="#;
         xmlns:xsi="#;
         xsi:schemaLocation=" #;>
    <modelVersion>.0.0</modelVersion>

    <groupId>com.xundh</groupId>
    <artifactId>javalearn</artifactId>
    <version>.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>.0.0.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>.0.0.RELEASE</version>
        </dependency>
    </dependencies>
    
</project> 

添加Springboot的引用后,可以在idea中查看已经包含了log的几个组件:

2. 创建logback.xml

 <?xml version=".0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration  scan="true" scanPeriod=" seconds">

    <contextName>logback</contextName>
    <!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
    <property name="log.path" value="./logs" />

    <!-- 彩色日志 -->
    <!-- 彩色日志依赖的渲染类 -->
    <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
    <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
    <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
    <!-- 彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>


    <!--输出到控制台-->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>info</level>
        </filter>
        <encoder>
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            < charset >UTF-8</charset>
        </encoder>
    </appender>


    <!--输出到文件-->

    <!-- 时间滚动输出 level为 DEBUG 日志 -->
    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_debug.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
            <charset>UTF-</charset> <!-- 设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 日志归档 -->
            <fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory></maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 INFO 日志 -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_info.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
            <charset>UTF-</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 每天日志归档路径以及格式 -->
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory></maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!-- 时间滚动输出 level为 WARN 日志 -->
    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_warn.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
            <charset>UTF-</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory></maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录warn级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>warn</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <!-- 时间滚动输出 level为 ERROR 日志 -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${log.path}/log_error.log</file>
        <!--日志文件输出格式-->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-level %logger{50} - %msg%n</pattern>
            <charset>UTF-</charset> <!-- 此处设置字符集 -->
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <!--日志文件保留天数-->
            <maxHistory></maxHistory>
        </rollingPolicy>
        <!-- 此日志文件只记录ERROR级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--
        <logger>用来设置某一个包或者具体的某一个类的日志打印级别、
        以及指定<appender>。<logger>仅有一个name属性,
        一个可选的level和一个可选的addtivity属性。
        name:用来指定受此logger约束的某一个包或者具体的某一个类。
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
              还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
              如果未设置此属性,那么当前logger将会继承上级的级别。
        addtivity:是否向上级logger传递打印信息。默认是true。
    -->
    <!--<logger name="org.springframework.web" level="info"/>-->
    <!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
    <!--
        使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
        第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
        第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
     -->


    <!--
        root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
        level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
        不能设置为INHERITED或者同义词NULL。默认是DEBUG
        可以包含零个或多个元素,标识这个appender将会添加到这个logger。
    -->

    <!--开发环境:打印控制台-->
    <springProfile name="dev">
        <logger name="com.xundh.view" level="debug"/>
    </springProfile>

    <root level="info">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="DEBUG_FILE" />
        <appender-ref ref="INFO_FILE" />
        <appender-ref ref="WARN_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>

    <!--生产环境:输出到文件-->
    <!--<springProfile name="pro">-->
    <!--<root level="info">-->
    <!--<appender-ref ref="CONSOLE" />-->
    <!--<appender-ref ref="DEBUG_FILE" />-->
    <!--<appender-ref ref="INFO_FILE" />-->
    <!--<appender-ref ref="ERROR_FILE" />-->
    <!--<appender-ref ref="WARN_FILE" />-->
    <!--</root>-->
    <!--</springProfile>-->

</configuration> 

3. 运行效果

六、Lombok 日志注解

Lombok可以用来创建 slf4j+logback的日志

1. 使用方法

6.1.1 maven引用

 <dependencies>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>.18.14</version>
        <scope>provided</scope>
    </dependency>
</dependencies> 

6.1.2 java代码

 //注意导入的包都是slfj的包

import lombok.extern.slfj.Slf4j;

@Slfj
public class test {
    public static void main(String[] args) {
        if(log.isInfoEnabled()){
            log.info("logback的--info日志--输出了");
        }
    }
} 

其它配置与slf4j+logback类似。

6.1.3 运行效果

八、logback+redis

1. 依赖

 <dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>.1.1</version>
</dependency>
<dependency>
    <groupId>com.cwbase</groupId>
    <artifactId>logback-redis-appender</artifactId>
    <version>.1.5</version>
</dependency> 

2. logback.xml

 <configuration>
  <property name="type.name" value="" />
  <appender name="TEST" class="com.cwbase.logback.RedisAppender">
    <source>test-application</source>
    <!--type 可定为项目类型-->
    <type>${type.name}</type>
    <!--redis ip-->
    <host>你的redis ip</host>
    <!--redis存放的key-->
    <key>logstash:redis</key>
    <tags>test-</tags>
    <mdc>true</mdc>
    <location>true</location>
    <callerStackIndex></callerStackIndex>
    <!--additionalField添加附加字段 用于head插件显示-->
    <additionalField>
      <key>MyKey</key>
      <value>MyValue</value>
    </additionalField>
    <additionalField>
      <key>MySecondKey</key>
      <value>MyOtherValue</value>
    </additionalField>
  </appender>
  <!--日志输出-->
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
      <!--日志回滚周期天-->
      <maxHistory></maxHistory>
    </rollingPolicy>
    <!-- <encoder>
       <pattern>%logger{} - %message%n%xException{5}</pattern>
     </encoder>-->
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-relative [%thread] %-5level %logger{35} %caller{3} - %msg%n%xException{5}</pattern>
    </encoder>

  </appender>

  <logger name="application" level="DEBUG" />

  <root level="DEBUG">
    <appender-ref ref="STDOUT" />
    <appender-ref ref="TEST" />
  </root>

</configuration> 

九、logback+logstash

可以在第七条基础上,让logstash从redis获取数据,或直接使用logstash-logback插件。

1. 依赖

 <!-- Logstash encoder -->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>.4</version>
</dependency> 

2. logback.xml添加内容

 <?xml version=".0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml"/>
 
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are  by default assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
 
    <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <param name="Encoding" value="UTF-"/>
        <remoteHost>logstash ip</remoteHost>
        <port></port>
        <!-- encoder is required -->
        <encoder class="net.logstash.logback.encoder.LogstashEncoder" />
    </appender>
 
    <root level="info">
        <appender-ref ref="logstash" />
        <appender-ref ref="STDOUT" />
    </root>
 
</configuration> 

十、日志上 阿里云

使用阿里云的日志服务,可以避免自行搭建ELK的复杂配置。对于云上分布式的应用来说,使用阿里云是一个比较好的选择方案。

文档地址:

1. 申请阿里云日志服务

  • 按提示申请服务后,创建Project
  • 按提示创建logstore
  • 点击logstore、数据接入后的加号,可以看到有很多接入方式,这里选择logback-sdk写入:

2. 添加依赖

 <dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>.5.0</version>
</dependency>
<dependency>
    <groupId>com.aliyun.openservices</groupId>
    <artifactId>aliyun-log-logback-appender</artifactId>
    <version>.1.15</version>
</dependency> 

3. logback.xml配置文件

   <!--为了防止进程退出时,内存中的数据丢失,请加上此选项-->
  <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>

  <appender name="aliyun" class="com.aliyun.openservices.log.logback.LoghubAppender">
    <!--必选项-->
    <!-- 账号及网络配置 -->
    <endpoint>your project endpoint</endpoint>
    <accessKeyId>your accesskey id</accessKeyId>
    <accessKeySecret>your accesskey</accessKeySecret>

    <!-- sls 项目配置 -->
    <project>your project</project>
    <logStore>your logStore</logStore>
    <!--必选项 (end)-->

    <!-- 可选项 -->
    <topic>your topic</topic>
    <source>your source</source>

    <!-- 可选项 详见 '参数说明'-->
    <totalSizeInBytes></totalSizeInBytes>
    <maxBlockMs></maxBlockMs>
    <ioThreadCount></ioThreadCount>
    <batchSizeThresholdInBytes></batchSizeThresholdInBytes>
    <batchCountThreshold></batchCountThreshold>
    <lingerMs></lingerMs>
    <retries></retries>
    <baseRetryBackoffMs></baseRetryBackoffMs>
    <maxRetryBackoffMs></maxRetryBackoffMs>
    
    <!-- 可选项 通过配置 encoder 的 pattern 自定义 log 的格式 -->
    <encoder>
        <pattern>%d %-level [%thread] %logger{0}: %msg</pattern>
    </encoder>
    
    <!-- 可选项 设置 time 字段呈现的格式 -->
    <timeFormat>yyyy-MM-dd'T'HH:mmZ</timeFormat>
    <!-- 可选项 设置 time 字段呈现的时区 -->
    <timeZone>UTC</timeZone>
  </appender>

  <!-- 可用来获取StatusManager中的状态
  <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
  --> 

4. java代码

 package com.aliyun.openservices.log.logback.example;

import org.slfj.Logger;
import org.slfj.LoggerFactory;
import org.slfj.MDC;

/**
 * Created by brucewu on/1/8.
 */public class LogbackAppenderExample {

    private static final Logger LOGGER = LoggerFactory.getLogger(LogbackAppenderExample.class);

    public static void main(String[] args) {

        MDC.put("MDC_KEY","MDC_VALUE");
        MDC.put("THREAD_ID", String.valueOf(Thread.currentThread().getId()));

        LOGGER.trace("trace log");
        LOGGER.debug("debug log");
        LOGGER.info("info log");
        LOGGER.warn("warn log");
        LOGGER.error("error log");
    }

} 

5. 查询示例

十一、idea 彩色日志插件

1. 安装插件Grep Console

2. 运行效果