Springboot之简化日志管理

日志管理

1.Log 日志组件能干什么

  • 日志能干的事情很多,对于学习程序,测试的工程师来说,日志能够定位问题,解决问题,是最大的功能点。
  • 记录一切 日志帮助我们记录程序功能都干了什么,无论是正常的输入输出还是出现异常,都可以用日志记录
  • 定位问题 日志可以帮助程序员调试问题,帮助测试人员定位问题
  • 记录分析用户行为 统计分析师用来记录用户的一起行为,用于分析用户的习惯和商业价值
  • 备份和还原实时数据 数据库工程师用来作为一种特殊的数据库

2.常用日志框架

  • Log4j Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一
  • Log4j 2 Apache Log4j 2是apache开发的一款Log4j的升级产品
  • Commons Logging Apache基金会所属的项目,是一套Java日志接口,之前叫Jakarta Commons Logging,后更名为Commons Logging
  • Slf4j 类似于Commons Logging,是一套简易Java日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)
  • Logback 一套日志组件的实现(slf4j阵营)。
  • Jul (Java Util Logging),自Java1.4以来的官方日志实现。

常用日志框架:logback+sl4j

通过将相应的库添加到classpath可以激活各种日志系统,然后在classpath根目录下提供合适的配置文件可以进一步定制日志系统,配置文件也可以通过Spring Environment的logging.config属性指定。

Java 中的日志框架主要分为两大类:日志门面和日志实现。

日志门面:日志门面定义了一组日志的接口规范,它并不提供底层具体的实现逻辑。Apache Commons Logging 和 Slf4j 就属于这一类。

日志实现:日志实现则是日志具体的实现,包括日志级别控制、日志打印格式、日志输出形式(输出到数据库、输出到文件、输出到控制台等)。Log4j、Log4j2、Logback 以及 Java Util Logging 则属于这一类。

将日志门面和日志实现分离其实是一种典型的门面模式,这种方式可以让具体业务在不同的日志实现框架之间*切换,而不需要改动任何代码,开发者只需要掌握日志门面的 API 即可。

3.配置文件

日志系统 定制配置
Logback logback-spring.xml,logback-spring.groovy,logback.xml,logback.groovy
Log4j log4j.properties或log4j.xml
Log4j2 log4j2-spring.xml或log4j2.xml
JDK (Java Util Logging) logging.properties

1.如果可能的话,建议你使用-spring变种形式定义日志配置(例如,使用logback-spring.xml而不是logback.xml)。如果你使用标准的配置路径,Spring可能不能够完全控制日志初始化。

2.Java Util Logging从可执行jar运行时会导致一些已知的类加载问题,我们建议尽可能不使用它。

3.lombok的神组合,使用lombok的@Slf4j 注解,省去配置声明log的繁琐,提高开发效率。

4.日志级别及使用

日志级别从低到高分为: TRACE < DEBUG < INFO < WARN < ERROR < FATAL

默认级别是 INFO,因此 INFO 级别以下的日志,不会被打印出来

<!--大多数情况都是配合Slf4j使用-->
//Logger和LoggerFactory导入的是org.slf4j包
private final static Logger logger = LoggerFactory.getLogger(Xxxx.class);
//Logger和LogManager导入的是org.apache.logging包
private static final Logger LOG = LogManager.getLogger(Xxxx.class); 
   

5.日志输出

通常日志以文本流的形式存储在磁盘,也可以把日志存储在关系型数据库中或 No Sql 中

  • 文本
  • 关系型数据库
<!--logbakck文件中添加配置-->
<appender name="mysql" class="ch.qos.logback.classic.db.DBAppender">
        <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
            <dataSource class="com.alibaba.druid.pool.DruidDataSource">
                <url>jdbc:mysql://localhost:3306/log?useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false&amp;serverTimezone=GMT%2B8</url>
                <driverClassName>com.mysql.cj.jdbc.Driver</driverClassName>
                <username>root</username>
                <password>xxxxxx</password>
            </dataSource>
        </connectionSource>
</appender>
<!--数据库ddl sql-->
BEGIN;
DROP TABLE IF EXISTS logging_event_property;
DROP TABLE IF EXISTS logging_event_exception;
DROP TABLE IF EXISTS logging_event;
COMMIT;
 
BEGIN;
CREATE TABLE logging_event 
  (
    timestmp         BIGINT NOT NULL,
    formatted_message  TEXT NOT NULL,
    logger_name       VARCHAR(254) NOT NULL,
    level_string      VARCHAR(254) NOT NULL,
    thread_name       VARCHAR(254),
    reference_flag    SMALLINT,
    arg0              VARCHAR(254),
    arg1              VARCHAR(254),
    arg2              VARCHAR(254),
    arg3              VARCHAR(254),
    caller_filename   VARCHAR(254) NOT NULL,
    caller_class      VARCHAR(254) NOT NULL,
    caller_method     VARCHAR(254) NOT NULL,
    caller_line       CHAR(4) NOT NULL,
    event_id          BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY
  );
COMMIT;


 
 
BEGIN;
CREATE TABLE logging_event_property
  (
    event_id       BIGINT NOT NULL,
    mapped_key        VARCHAR(254) NOT NULL,
    mapped_value      TEXT,
    PRIMARY KEY(event_id, mapped_key),
    FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
  );
COMMIT;
 
 
BEGIN;
CREATE TABLE logging_event_exception
  (
    event_id         BIGINT NOT NULL,
    i                SMALLINT NOT NULL,
    trace_line       VARCHAR(254) NOT NULL,
    PRIMARY KEY(event_id, i),
    FOREIGN KEY (event_id) REFERENCES logging_event(event_id)
  );
COMMIT;
  • No Sql
  • Console 控制台
  • 一般日志组件都可以自定义输出格式

6.日志配置

创建logback-spring.xm文件。一般放置于resources目录下

配置:
error级别保留三天,其余级别均保留一天

日志文件格式: yyyy-MM-dd- i − {i}- i−{level}.log

默认level级别为 info, 若想修改,在配置文件中配置 :

logging:
    level:
        org.springframework.web: debug
<?xml version="1.0" encoding="UTF-8"?>
<!--  日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出  -->
<!--  scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true  -->
<!--  scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
       当scan为true时,此属性生效。默认的时间间隔为1分钟。  -->
<!--  debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。  -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
    <contextName>logback</contextName>
    <!--  name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。  -->
    <springProperty scope="context" name="log.path" source="log.path"/>
    <!-- 0. 日志格式和颜色渲染  -->
    <!--  彩色日志依赖的渲染类  -->
    <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_PATTERN1"
              value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
    <!--普通日志格式-->
    <property name="CONSOLE_LOG_PATTERN2" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
    <!--dev环境配置-->
    <springProfile name="dev">
        <!--输出到控制台-->
        <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
            <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
            <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
                <level>debug</level>
            </filter>
            <encoder>
                <Pattern>${CONSOLE_LOG_PATTERN1}</Pattern>
                <charset>utf-8</charset>
            </encoder>
        </appender>
        <root level="info">
            <appender-ref ref="console"/>
        </root>
    </springProfile>


    <!--输出到debug-->
    <appender name="debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--  日志记录器的滚动策略,按日期,按大小记录  -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}-%i-debug.log</fileNamePattern>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
            <!-- 日志文档保留天数 -->
            <maxHistory>1</maxHistory>
            <!--
                      当日志文件超过maxFileSize指定的大小是,根据上面日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
                      -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN2}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印DEBUG日志 -->
            <level>DEBUG</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

    <!--输出到info-->
    <appender name="info" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!--  日志记录器的滚动策略,按日期,按大小记录  -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}-%i-info.log</fileNamePattern>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
            <maxHistory>1</maxHistory>
            <!--
                      当日志文件超过maxFileSize指定的大小是,根据上面日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
                      -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN2}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印INFO日志 -->
            <level>INFO</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--输出到warn-->
    <appender name="warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}-%i-warn.log</fileNamePattern>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
            <maxHistory>1</maxHistory>
            <!--
                      当日志文件超过maxFileSize指定的大小是,根据上面日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
                      -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>20MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN2}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印WARN日志 -->
            <level>WARN</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>
    <!--输出到error-->
    <appender name="error" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/%d{yyyy-MM-dd}-%i-error.log</fileNamePattern>
            <cleanHistoryOnStart>true</cleanHistoryOnStart>
            <maxHistory>3</maxHistory>
            <!--
                      当日志文件超过maxFileSize指定的大小是,根据上面日志文件滚动 注意此处配置SizeBasedTriggeringPolicy是无法实现按文件大小进行滚动的,必须配置timeBasedFileNamingAndTriggeringPolicy
                      -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <append>true</append>
        <encoder>
            <pattern>${CONSOLE_LOG_PATTERN2}</pattern>
            <charset>utf-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.LevelFilter"><!-- 只打印ERROR日志 -->
            <level>ERROR</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <!--
      root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
      level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
      不能设置为INHERITED或者同义词NULL。默认是DEBUG
      可以包含零个或多个元素,标识这个appender将会添加到这个logger。
     -->
    <root level="info">
        <appender-ref ref="debug"/>
        <appender-ref ref="info"/>
        <appender-ref ref="warn"/>
        <appender-ref ref="error"/>
    </root>
    <!--测试pre环境:输出到文档-->
    <springProfile name="pre">
        <root level="info">
            <appender-ref ref="debug"/>
            <appender-ref ref="info"/>
            <appender-ref ref="warn"/>
            <appender-ref ref="error"/>
        </root>
    </springProfile>
    <!--4.2 生产环境:输出到文档 -->
    <springProfile name="pro">
        <root level="info">
            <appender-ref ref="debug"/>
            <appender-ref ref="info"/>
            <appender-ref ref="warn"/>
            <appender-ref ref="error"/>
        </root>
    </springProfile>

</configuration>

7.使用方式

  1. 复制上文 logback-spring.xml 文件到 resource文件夹下
  2. 修改启动脚本start.sh ,指定log.path目录即可
nohup java  -Dlog.path="${logs_dir}" -Dserver.port="${port}" -Dlog.home="${logs_dir}" -Dapp.name="${appname}" -Dspring.profiles.active="${profile}" -Dspring.datasource.default.password="${pwd_ds1}" -Xms2g -Xmx2g -jar ${lib_dir}/${jarname} ${classname} > "${logs_dir}/${appname}.out" 2>&1 &
上一篇:JQuery获取对象


下一篇:数据库表介绍