• 关于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>
  • 相关阅读:
    Codeforces 631D Messenger KMP
    Google Codejam 2016 Round1A Problem C BFFs 简单图论
    ACM常用数论知识 总结
    C++ 虚函数表
    HDU 5661 Claris and XOR 贪心
    2013亚洲区域赛长沙站 ZOJ 3732 Graph Reconstruction
    [C++] upper_bound和lower_bound
    2015合肥网络赛 HDU 5489 Removed Interval LIS+线段树(树状数组)
    hdu 3532 Max Angle(atan2的使用)
    poj 1106 Transmitters (计算几何,叉积||极角排序)
  • 原文地址:https://www.cnblogs.com/zimublog/p/12923786.html
Copyright © 2020-2023  润新知