美文网首页
springboot oracle 日志输出到数据库

springboot oracle 日志输出到数据库

作者: 爱吃菜的流浪狗 | 来源:发表于2020-07-11 16:33 被阅读0次

    1.配置logback.xml文件

    在logback文件下,配置数据源
    mysql 5.0.7 版本以上支持

       <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
            <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
                <driverClass>com.mysql.cj.jdbc.Driver</driverClass>
                <url>*******i</url>
                <user>***</user>
                <password>****</password>
            </connectionSource>
        </appender>
    

    oralce 14版本以上支持

    <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">
            <driverClass>oracle.jdbc.OracleDriver</driverClass>
            <user>******</user>
            <password>********</password>
            <url>*******</url>
        </connectionSource>
    </appender>
    

    带数据库连接池版本
    连接池版本 com.alibaba:druid-spring-boot-starter:1.1.10

     <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">
        <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
            <dataSource class="com.alibaba.druid.pool.DruidDataSource">
                <driverClassName>oracle.jdbc.OracleDriver</driverClassName>
                <username>*******</username>
                <password>*******</password>
                <url>*******</url>
            </dataSource>
        </connectionSource>
    </appender>
    

    2.重写 logback 写入DBAppender方法

    重写的DBAppender方法

    /**
     * The DBAppender inserts logging events into three database tables in a format
     * independent of the Java programming language.
     *
     * For more information about this appender, please refer to the online manual
     * at http://logback.qos.ch/manual/appenders.html#DBAppender
     *
     * @author Ceki G&uuml;lc&uuml;
     * @author Ray DeCampo
     * @author S&eacute;bastien Pennec
     */
    public class LogAppender extends DBAppenderBase<ILoggingEvent> {
        protected String insertPropertiesSQL;
        protected String insertExceptionSQL;
        protected String insertSQL;
        protected static final Method GET_GENERATED_KEYS_METHOD;
    
        private DBNameResolver dbNameResolver;
    
        static final int TIMESTMP_INDEX = 1;
        static final int FORMATTED_MESSAGE_INDEX = 2;
        static final int LOGGER_NAME_INDEX = 3;
        static final int LEVEL_STRING_INDEX = 4;
        static final int THREAD_NAME_INDEX = 5;
        static final int REFERENCE_FLAG_INDEX = 6;
        static final int ARG0_INDEX = 7;
        static final int ARG1_INDEX = 8;
        static final int ARG2_INDEX = 9;
        static final int ARG3_INDEX = 10;
        static final int CALLER_FILENAME_INDEX = 11;
        static final int CALLER_CLASS_INDEX = 12;
        static final int CALLER_METHOD_INDEX = 13;
        static final int CALLER_LINE_INDEX = 14;
        static final int EVENT_ID_INDEX = 15;
    
        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;
        }
    
        public void setDbNameResolver(DBNameResolver dbNameResolver) {
            this.dbNameResolver = dbNameResolver;
        }
    
        @Override
        public void start() {
            if (dbNameResolver == null)
                dbNameResolver = new DefaultDBNameResolver();
            insertExceptionSQL = buildInsertExceptionSQL(dbNameResolver);
            insertPropertiesSQL = buildInsertPropertiesSQL(dbNameResolver);
            insertSQL = buildInsertSQL(dbNameResolver);
            super.start();
        }
    
        static String buildInsertPropertiesSQL(DBNameResolver dbNameResolver) {
            StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");
            sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT_PROPERTY)).append(" (");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.EVENT_ID)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.MAPPED_KEY)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.MAPPED_VALUE)).append(") ");
            sqlBuilder.append("VALUES (?, ?, ?)");
            return sqlBuilder.toString();
        }
    
        static String buildInsertExceptionSQL(DBNameResolver dbNameResolver) {
            StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");
            sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT_EXCEPTION)).append(" (");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.EVENT_ID)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.I)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.TRACE_LINE)).append(") ");
            sqlBuilder.append("VALUES (?, ?, ?)");
            return sqlBuilder.toString();
        }
    
        static String buildInsertSQL(DBNameResolver dbNameResolver) {
            StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");
            sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT)).append(" (");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.TIMESTMP)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.FORMATTED_MESSAGE)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LOGGER_NAME)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LEVEL_STRING)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.THREAD_NAME)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.REFERENCE_FLAG)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG0)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG1)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG2)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG3)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_FILENAME)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_CLASS)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_METHOD)).append(", ");
            sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_LINE)).append(") ");
            sqlBuilder.append("VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
            return sqlBuilder.toString();
        }
    
        @Override
        protected void subAppend(ILoggingEvent event, Connection connection,
                                 PreparedStatement insertStatement) throws Throwable {
            Integer logSwitch = (Integer) Constant.getCacheMap().get("logSwitch");
            if (logSwitch != null && logSwitch != 0) {
                bindLoggingEventWithInsertStatement(insertStatement, event);
                bindLoggingEventArgumentsWithPreparedStatement(insertStatement, event.getArgumentArray());
    
                // This is expensive... should we do it every time?
                bindCallerDataWithPreparedStatement(insertStatement, event.getCallerData());
    
                int updateCount = insertStatement.executeUpdate();
                if (updateCount != 1) {
                    addWarn("Failed to insert loggingEvent");
                }
            }
        }
    
        protected void secondarySubAppend(ILoggingEvent event, Connection connection,
                                          long eventId) throws Throwable {
            Map<String, String> mergedMap = mergePropertyMaps(event);
            insertProperties(mergedMap, connection, eventId);
    
            if (event.getThrowableProxy() != null) {
                insertThrowable(event.getThrowableProxy(), connection, eventId);
            }
        }
    
        void bindLoggingEventWithInsertStatement(PreparedStatement stmt,
                                                 ILoggingEvent event) throws SQLException {
            stmt.setLong(TIMESTMP_INDEX, event.getTimeStamp());
            stmt.setString(FORMATTED_MESSAGE_INDEX, event.getFormattedMessage());
            stmt.setString(LOGGER_NAME_INDEX, event.getLoggerName());
            stmt.setString(LEVEL_STRING_INDEX, event.getLevel().toString());
            stmt.setString(THREAD_NAME_INDEX, event.getThreadName());
            stmt.setShort(REFERENCE_FLAG_INDEX, DBHelper.computeReferenceMask(event));
        }
    
        void bindLoggingEventArgumentsWithPreparedStatement(PreparedStatement stmt,
                                                            Object[] argArray) throws SQLException {
    
            int arrayLen = argArray != null ? argArray.length : 0;
    
            for (int i = 0; i < arrayLen && i < 4; i++) {
                stmt.setString(ARG0_INDEX + i, asStringTruncatedTo254(argArray[i]));
            }
            if (arrayLen < 4) {
                for (int i = arrayLen; i < 4; i++) {
                    stmt.setString(ARG0_INDEX + i, null);
                }
            }
        }
    
        String asStringTruncatedTo254(Object o) {
            String s = null;
            if (o != null) {
                s = o.toString();
            }
    
            if (s == null) {
                return null;
            }
            if (s.length() <= 254) {
                return s;
            } else {
                return s.substring(0, 254);
            }
        }
    
        void bindCallerDataWithPreparedStatement(PreparedStatement stmt,
                                                 StackTraceElement[] callerDataArray) throws SQLException {
    
            StackTraceElement caller = extractFirstCaller(callerDataArray);
    
            stmt.setString(CALLER_FILENAME_INDEX, caller.getFileName());
            stmt.setString(CALLER_CLASS_INDEX, caller.getClassName());
            stmt.setString(CALLER_METHOD_INDEX, caller.getMethodName());
            stmt.setString(CALLER_LINE_INDEX, Integer.toString(caller.getLineNumber()));
        }
    
        private StackTraceElement extractFirstCaller(StackTraceElement[] callerDataArray) {
            StackTraceElement caller = EMPTY_CALLER_DATA;
            if (hasAtLeastOneNonNullElement(callerDataArray))
                caller = callerDataArray[0];
            return caller;
        }
    
        private boolean hasAtLeastOneNonNullElement(StackTraceElement[] callerDataArray) {
            return callerDataArray != null && callerDataArray.length > 0 && callerDataArray[0] != null;
        }
    
        Map<String, String> mergePropertyMaps(ILoggingEvent event) {
            Map<String, String> mergedMap = new HashMap<String, String>();
            // we add the context properties first, then the event properties, since
            // we consider that event-specific properties should have priority over
            // context-wide properties.
            Map<String, String> loggerContextMap = event.getLoggerContextVO()
                    .getPropertyMap();
            Map<String, String> mdcMap = event.getMDCPropertyMap();
            if (loggerContextMap != null) {
                mergedMap.putAll(loggerContextMap);
            }
            if (mdcMap != null) {
                mergedMap.putAll(mdcMap);
            }
    
            return mergedMap;
        }
    
        @Override
        protected Method getGeneratedKeysMethod() {
            return GET_GENERATED_KEYS_METHOD;
        }
    
        @Override
        protected String getInsertSQL() {
            return insertSQL;
        }
    
        protected void insertProperties(Map<String, String> mergedMap,
                                        Connection connection, long eventId) throws SQLException {
            Set<String> propertiesKeys = mergedMap.keySet();
            if (propertiesKeys.size() > 0) {
                PreparedStatement insertPropertiesStatement = null;
                try {
                    insertPropertiesStatement = connection
                            .prepareStatement(insertPropertiesSQL);
    
                    for (String key : propertiesKeys) {
                        String value = mergedMap.get(key);
    
                        insertPropertiesStatement.setLong(1, eventId);
                        insertPropertiesStatement.setString(2, key);
                        insertPropertiesStatement.setString(3, value);
    
                        if (cnxSupportsBatchUpdates) {
                            insertPropertiesStatement.addBatch();
                        } else {
                            insertPropertiesStatement.execute();
                        }
                    }
    
                    if (cnxSupportsBatchUpdates) {
                        insertPropertiesStatement.executeBatch();
                    }
                } finally {
                    closeStatement(insertPropertiesStatement);
                }
            }
        }
    
        /**
         * Add an exception statement either as a batch or execute immediately if
         * batch updates are not supported.
         */
        void updateExceptionStatement(PreparedStatement exceptionStatement,
                                      String txt, short i, long eventId) throws SQLException {
            exceptionStatement.setLong(1, eventId);
            exceptionStatement.setShort(2, i);
            exceptionStatement.setString(3, txt);
            if (cnxSupportsBatchUpdates) {
                exceptionStatement.addBatch();
            } else {
                exceptionStatement.execute();
            }
        }
    
        short buildExceptionStatement(IThrowableProxy tp, short baseIndex,
                                      PreparedStatement insertExceptionStatement, long eventId)
                throws SQLException {
    
            StringBuilder buf = new StringBuilder();
            ThrowableProxyUtil.subjoinFirstLine(buf, tp);
            updateExceptionStatement(insertExceptionStatement, buf.toString(),
                    baseIndex++, eventId);
    
            int commonFrames = tp.getCommonFrames();
            StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();
            for (int i = 0; i < stepArray.length - commonFrames; i++) {
                StringBuilder sb = new StringBuilder();
                sb.append(CoreConstants.TAB);
                ThrowableProxyUtil.subjoinSTEP(sb, stepArray[i]);
                updateExceptionStatement(insertExceptionStatement, sb.toString(),
                        baseIndex++, eventId);
            }
    
            if (commonFrames > 0) {
                StringBuilder sb = new StringBuilder();
                sb.append(CoreConstants.TAB).append("... ").append(commonFrames).append(
                        " common frames omitted");
                updateExceptionStatement(insertExceptionStatement, sb.toString(),
                        baseIndex++, eventId);
            }
    
            return baseIndex;
        }
    
        protected void insertThrowable(IThrowableProxy tp, Connection connection,
                                       long eventId) throws SQLException {
    
            PreparedStatement exceptionStatement = null;
            try {
                exceptionStatement = connection.prepareStatement(insertExceptionSQL);
    
                short baseIndex = 0;
                while (tp != null) {
                    baseIndex = buildExceptionStatement(tp, baseIndex, exceptionStatement,
                            eventId);
                    tp = tp.getCause();
                }
    
                if (cnxSupportsBatchUpdates) {
                    exceptionStatement.executeBatch();
                }
            } finally {
                closeStatement(exceptionStatement);
            }
        }
    }
    

    在数据库创建连接表
    在logback.classic jar包中ch.qos.logback.classic.db.script下找对应的文件sql文件
    否则容易出现触发器出发不了的问题


    image.png

    oralce数据库中创建表sql

    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for logging_event
    -- ----------------------------
    DROP TABLE IF EXISTS `logging_event`;
    CREATE TABLE `logging_event` (
      `timestmp` bigint(20) NOT NULL,
      `formatted_message` text NOT NULL,
      `logger_name` varchar(254) NOT NULL,
      `level_string` varchar(254) NOT NULL,
      `thread_name` varchar(254) DEFAULT NULL,
      `reference_flag` smallint(6) DEFAULT NULL,
      `arg0` varchar(254) DEFAULT NULL,
      `arg1` varchar(254) DEFAULT NULL,
      `arg2` varchar(254) DEFAULT NULL,
      `arg3` varchar(254) DEFAULT NULL,
      `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(20) NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (`event_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5245 DEFAULT CHARSET=latin1;
    >SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for logging_event_exception
    -- ----------------------------
    DROP TABLE IF EXISTS `logging_event_exception`;
    CREATE TABLE `logging_event_exception` (
      `event_id` bigint(20) NOT NULL,
      `i` smallint(6) NOT NULL,
      `trace_line` varchar(254) NOT NULL,
      PRIMARY KEY (`event_id`,`i`),
      CONSTRAINT `logging_event_exception_ibfk_1` FOREIGN KEY (`event_id`) REFERENCES `logging_event` (`event_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    >SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for logging_event_property
    -- ----------------------------
    DROP TABLE IF EXISTS `logging_event_property`;
    CREATE TABLE `logging_event_property` (
      `event_id` bigint(20) NOT NULL,
      `mapped_key` varchar(254) NOT NULL,
      `mapped_value` text,
      PRIMARY KEY (`event_id`,`mapped_key`),
      CONSTRAINT `logging_event_property_ibfk_1` FOREIGN KEY (`event_id`) REFERENCES `logging_event` (`event_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;
    

    3.根据自己内容修改DBAppender方法

    1) 修改插入语句
    在DBappender中 ,通过获取XML配置中的connection链接


    数组库字段映射.png

    拼接sql


    image.png
    可对应修改插入字段,自定义数据库表
    2)修改插入方法
    image.png

    相关文章

      网友评论

          本文标题:springboot oracle 日志输出到数据库

          本文链接:https://www.haomeiwen.com/subject/snwkkctx.html