关于springboot默认日志框架Slf4j+logback,自定义Appender问题

第一种:

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.StackTraceElementProxy; import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.UnsynchronizedAppenderBase; import ch.qos.logback.core.helpers.Transform; import com.test.domain.ErrorLog; import com.test.service.ErrorLogService; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.Date; @Component public class DbErrorLogAppender extends UnsynchronizedAppenderBase<ILoggingEvent> { /** * 错误日志数据库增删改查服务 */ @Autowired private ErrorLogService errorLogService;  /** * DbErrorLogAppender初始化 */ @PostConstruct public void init() { LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); ThresholdFilter filter = new ThresholdFilter(); filter.setLevel("ERROR"); filter.setContext(context); filter.start(); this.addFilter(filter); this.setContext(context); context.getLogger("ROOT").addAppender(DbErrorLogAppender.this); super.start(); } /** * 错误日志拼装成实体类,写入数据库 */ @Override protected void append(ILoggingEvent loggingEvent) { IThrowableProxy tp = loggingEvent.getThrowableProxy(); // ErrorLogPO数据表实体类 ErrorLog errorLog = new ErrorLog(); errorLog.setLevel(1); errorLog.setReason("reason"); errorLog.setClassName("setClassName"); errorLog.setContent("content"); errorLog.setCreateTime(new Date(loggingEvent.getTimeStamp())); try { // 错误日志实体类写入数据库  errorLogService.addErrorLog(errorLog); } catch (Exception ex) { this.addError("上报错误日志失败:" + ex.getMessage()); } }  }

该类会在报错之后调用,无需配置,写入数据库,直接继承UnsynchronizedAppenderBase<ILoggingEvent>。

 第二种:

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.core.db.DBAppenderBase;
import org.springframework.stereotype.Component;

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

@Component
public class LogDBAppender extends DBAppenderBase<ILoggingEvent> {

    protected static final Method GET_GENERATED_KEYS_METHOD;

    //插入sql
    protected String insertSQL;

    static final int LEVEL = 1;

    static final int REASON = 2;

    static final int CLASS_NAME = 3;

    static final int CONTENT = 4;

    static final int CREATE_TIME = 5;

    //static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    static {
        Method getGeneratedKeysMethod;
        try {
            getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
        } catch (Exception ex) {
            getGeneratedKeysMethod = null;
        }
        GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
    }

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

    private static String buildInsertSQL() {
        return "INSERT INTO `error_log`(`level`,`reason`,`class_name`,`content`,`create_time`) 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 {
        String message = event.getFormattedMessage();
        Object[] argumentArray = event.getArgumentArray();
//        stmt.setString(LEVELevent.getLevel().toString());
        if(argumentArray.length>0){
            stmt.setString(LEVEL, String.valueOf(argumentArray[0]));
            stmt.setString(REASON, String.valueOf(argumentArray[1]));
        }else{
            stmt.setString(LEVEL, "未填写");
            stmt.setString(REASON, "未填写");
        }
        stmt.setString(CLASS_NAME, event.getLoggerName());
        IThrowableProxy throwableProxy = event.getThrowableProxy();
        if(throwableProxy!=null){
            StringBuffer s = new StringBuffer(throwableProxy.getClassName());
            s.append(throwableProxy.getMessage());
            stmt.setString(CONTENT, s.toString());
        }else{
            stmt.setString(CONTENT, "未传入异常");
        }
        stmt.setTimestamp(CREATE_TIME, new Timestamp(event.getTimeStamp()));
    }

    @Override
    protected void subAppend(ILoggingEvent eventObject, Connection connection, PreparedStatement statement) throws Throwable {
        bindLoggingEventWithInsertStatement(statement, eventObject);
        int updateCount = statement.executeUpdate();
        if (updateCount != 1) {
            addWarn("Failed to insert loggingEvent");
        }
    }

    @Override
    protected void secondarySubAppend(ILoggingEvent eventObject, Connection connection, long eventId) throws Throwable {
    }
}
继承DBAppenderBase<ILoggingEvent>,需配置logback.xml
<configuration scan="true" scanPeriod="60 seconds" debug="false">

    <property name="LOG_HOME" value="D:/test_log"/>
    <property name="LOG_NAME" value="testLog"/>

    <!--输出到控制台-->
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} : %msg%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>
    <appender name="error_db_appender" class="com.test.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://localhost:3306/test</url>
                <username>root</username>
                <password>****</password>
            </dataSource>
        </connectionSource>
        <!-- 只打印错误日志 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>


    <!--根节点-->
    <root level="INFO">
        <appender-ref ref="console"/>
        <appender-ref ref="error_db_appender" />
    </root>

</configuration>

猜你喜欢

转载自www.cnblogs.com/zimublog/p/12923786.html