SpringBoot Logback 로그 가 데이터베이스 에 기록 되 는 실현 방법

로그 처리 에 있어 서 조건 에 맞 는 로 그 를 데이터베이스 에 계산 해 야 할 때 가 있 습 니 다.
pom 의존 추가

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--         ,    java.lang.ClassNotFoundException: org.apache.commons.dbcp.BasicDataSource-->
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
    </dependency>
2.logback 프로필 만 들 기

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
  <!--               LogBack           -->
  <property name="LOG_HOME" value="/home/admin" />

  <!--       -->
  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <!--     :%d    ,%thread     ,%-5level:      5     %msg:    ,%n    -->
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
  </appender>

  <!--            -->
  <appender name="application_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!--          -->
      <FileNamePattern>${LOG_HOME}/info/info.log.%d{yyyy-MM-dd}.log</FileNamePattern>
      <!--        -->
      <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <!--     :%d    ,%thread     ,%-5level:      5     %msg:    ,%n    -->
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
    <!--         -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <MaxFileSize>500MB</MaxFileSize>
    </triggeringPolicy>
  </appender>

  <!--        -->
  <appender name="error_file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!--          -->
      <FileNamePattern>${LOG_HOME}/error/error.log.%d{yyyy-MM-dd}.log</FileNamePattern>
      <!--        -->
      <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <!--     :%d    ,%thread     ,%-5level:      5     %msg:    ,%n    -->
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
    <!--         -->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
      <MaxFileSize>500MB</MaxFileSize>
    </triggeringPolicy>
    <!--         -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
      <level>error</level>
      <onMatch>ACCEPT</onMatch>
      <onMismatch>DENY</onMismatch>
    </filter>
  </appender>

  <!--       -->
  <appender name="db_classic_mysql_pool" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
      <dataSource class="org.apache.commons.dbcp.BasicDataSource">
        <driverClassName>com.mysql.cj.jdbc.Driver</driverClassName>
        <url>jdbc:mysql://127.0.0.1:3306/logdb?serverTimezone=Asia/Shanghai</url>
        <username>root</username>
        <password>123456</password>
      </dataSource>
    </connectionSource>
  </appender>

  <!--myibatis log configure-->
  <logger name="com.apache.ibatis" level="TRACE"/>
  <logger name="java.sql.Connection" level="DEBUG" />
  <logger name="java.sql.Statement" level="DEBUG"/>
  <logger name="java.sql.PreparedStatement" level="DEBUG"/>

  <!--        -->
  <root level="INFO">
    <appender-ref ref="stdout" />
    <appender-ref ref="application_file" />
    <appender-ref ref="error_file"/>
    <appender-ref ref="db_classic_mysql_pool" />
  </root>

</configuration>
3.데이터베이스 시트 만 들 기
ch.qos.logback.classic.db 패키지 에서 데이터베이스 에 대응 하 는 표 생 성 문 구 를 찾 을 수 있 습 니 다.

내 가 사용 하 는 my sql 데이터 베 이 스 는 먼저 스스로 라 이브 러 리 를 만 드 는 것 이 전제 이다.
mysql 데이터베이스 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;


생 성 된 시계
테스트
1.테스트 코드 작성

@RunWith(SpringRunner.class)
@SpringBootTest
public class Springboot02MybatisApplicationTests {

  private final Logger logger = LoggerFactory.getLogger(Springboot02MybatisApplicationTests.class);
  @Test
  public void contextLoads() {
    logger.info("     info");
    logger.error("     error");
  }
}

2.실행 결과

현재 단계 에 맞 는 모든 로그 기록 을 기본 으로 저장 합 니 다.
5.사용자 정의 데이터베이스 테이블 필드 와 저장 내용
물론 기본 표 필드 가 그렇게 많 고 많은 내용 을 저장 하지만 우 리 는 자신 이 인쇄 한 로그 내용 만 있 을 때 가 많 습 니 다.디스크 공간 을 절약 하기 위해 이 럴 때 저장 필드 와 저장 내용 을 사용자 정의 할 수 있 습 니 다.
단계:
1.데이터베이스 시트 만 들 기

DROP TABLE IF EXISTS `logging`;
CREATE TABLE `logging` (
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
 `message` VARCHAR(300) NOT NULL COMMENT '  ',
 `level_string` VARCHAR(254) NOT NULL COMMENT '  ',
 `created_time` DATETIME NOT NULL COMMENT '  ',
 `logger_name` VARCHAR(300) NOT NULL COMMENT '   ',
 PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='        '
2.재 작성 DBAppender 클래스 는 LogDBAppender 클래스 입 니 다.

package com.me.study.springboot02mybatis.config;

import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.db.DBAppenderBase;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;

@Configuration
public class LogDBAppender extends DBAppenderBase<ILoggingEvent> {

  protected static final Method GET_GENERATED_KEYS_METHOD;
  //  sql
  protected String insertSQL;
  // message     
  static final int MESSAGE = 1;
  // level_string
  static final int LEVEL_STRING = 2;
  // created_time   
  static final int CREATE_TIME = 3;
  // logger_name    
  static final int LOGGER_NAME = 4;

  static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

  static {
    // PreparedStatement.getGeneratedKeys() method was added in JDK 1.4
    Method getGeneratedKeysMethod;
    try {
      // the
      getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
    } catch (Exception ex) {
      getGeneratedKeysMethod = null;
    }
    GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
  }

  @Override
  public void start() {
    //     sql     insertSQL
    insertSQL = buildInsertSQL();
    super.start();
  }

  //      sql  
  private static String buildInsertSQL() {
    return "INSERT INTO `logging`(`message`,`level_string`,`created_time`,`logger_name`)" +
        "VALUES (?,?,?,?)";
  }

  @Override
  protected Method getGeneratedKeysMethod() {
    return GET_GENERATED_KEYS_METHOD;
  }

  @Override
  protected String getInsertSQL() {
    return insertSQL;
  }

  /**
   *        
   *
   * @param stmt
   * @param event
   * @throws SQLException
   */
  private void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException {
    // event.getFormattedMessage()       
    String message = event.getFormattedMessage();
    //              ,       :logger.info("- XXXX")
    if(message.startsWith("-")){ //            -    ,       
      stmt.setString(MESSAGE, message);
      // event.getLevel().toString()     
      stmt.setString(LEVEL_STRING, event.getLevel().toString());
      // new Timestamp(event.getTimeStamp())   
      stmt.setTimestamp(CREATE_TIME, new Timestamp(event.getTimeStamp()));
      // event.getLoggerName()    
      stmt.setString(LOGGER_NAME, event.getLoggerName());
    }

  }

  @Override
  protected void subAppend(ILoggingEvent eventObject, Connection connection, PreparedStatement statement) throws Throwable {
    bindLoggingEventWithInsertStatement(statement, eventObject);
    // This is expensive... should we do it every time?
    int updateCount = statement.executeUpdate();
    if (updateCount != 1) {
      addWarn("Failed to insert loggingEvent");
    }
  }

  @Override
  protected void secondarySubAppend(ILoggingEvent eventObject, Connection connection, long eventId) throws Throwable {
  }
}
3.logback 로그 파일 을 수정 하고 사용자 정의 LogDBAppender 클래스 를 참조 합 니 다.

  <!--       -->
  <appender name="db_classic_mysql_pool" class="com.me.study.springboot02mybatis.config.LogDBAppender">
    <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
      <dataSource class="org.apache.commons.dbcp.BasicDataSource">
        <driverClassName>com.mysql.cj.jdbc.Driver</driverClassName>
        <url>jdbc:mysql://127.0.0.1:3306/logdb?serverTimezone=Asia/Shanghai</url>
        <username>root</username>
        <password>admin</password>
      </dataSource>
    </connectionSource>
  </appender>
4.테스트 실행
1)테스트 코드 작성

  @Test
  public void contextLoads() {
    logger.info("-      info");
    logger.error("-      error");
    logger.info("    ‘-'   ,          ");
  }
2)실행 결과

데이터베이스 저장 결 과 는 사용자 정의 로그 기록 만 저장 되 어 있 습 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기