当前位置:   article > 正文

logback日志自定义DBAppender_logback自定义dbappenderbase

logback自定义dbappenderbase
  1. 日志配置文件logback-spring-prod.xml 日志配置文件名称尽量避免默认的,否则有可能读取不到yaml的属性

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
  3. <!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
  4. <!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
  5. 当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
  6. <!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
  7. <configuration scan="true" scanPeriod="10 seconds">
  8. <!--0. 日志格式和颜色渲染 -->
  9. <!-- 彩色日志依赖的渲染类 -->
  10. <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
  11. <conversionRule conversionWord="wex"
  12. converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
  13. <conversionRule conversionWord="wEx"
  14. converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
  15. <!-- 彩色日志格式 -->
  16. <property name="CONSOLE_LOG_PATTERN"
  17. 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}}"/>
  18. <!--1. 输出到控制台-->
  19. <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
  20. <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
  21. <encoder>
  22. <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
  23. <!-- 设置字符集 -->
  24. <charset>UTF-8</charset>
  25. </encoder>
  26. </appender>
  27. <springProperty scope="context" name="springAppName" source="spring.application.name"/>
  28. <springProperty scope="context" name="serverName" source="logging.serverName"/>
  29. <springProperty scope="context" name="post" source="logging.post"/>
  30. <springProperty scope="context" name="dbName" source="logging.dbName"/>
  31. <springProperty scope="context" name="userName" source="logging.userName"/>
  32. <springProperty scope="context" name="password" source="logging.password"/>
  33. <springProperty scope="context" name="logLevel" source="logging.logLevel"/>
  34. <!--日志异步到数据库 -->
  35. <appender name="dbAppender" class="com.xx.common.extension.CustomDBAppender">
  36. <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
  37. <level>${logLevel}</level>
  38. </filter>
  39. <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
  40. <dataSource class="org.apache.commons.dbcp.BasicDataSource">
  41. <driverClassName>com.mysql.cj.jdbc.Driver</driverClassName>
  42. <url>jdbc:mysql://${serverName}:${post}/${dbName}?useUnicode=true;characterEncoding=UTF-8;useSSL=false;serverTimezone=Asia/Shanghai</url>
  43. <username>${userName}</username>
  44. <password>${password}</password>
  45. </dataSource>
  46. </connectionSource>
  47. </appender>
  48. <springProperty scope="context" name="loggerName" source="logging.logName"/>
  49. <!-- root的默认level是DEBUG -->
  50. <root level="INFO">
  51. <appender-ref ref="CONSOLE"/>
  52. <appender-ref ref="dbAppender"/>
  53. </root>
  54. </configuration>
  1. yaml配置

  1. logging:
  2. config: classpath:logback-spring-prod.xml
  3. serverName: xx.xx.xx.xx
  4. post: 3306
  5. dbName: dbName
  6. userName: userName
  7. password: password
  8. logLevel: ERROR
  1. CustomDBAppender 复制DBAppender的代码,根据自己的需求修改  

  1. public class CustomDBAppender extends DBAppenderBase<ILoggingEvent> {
  2. protected String insertExceptionSQL;
  3. protected String insertSQL;
  4. protected static final Method GET_GENERATED_KEYS_METHOD;
  5. private DBNameResolver dbNameResolver;
  6. static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();
  7. public CustomDBAppender() {
  8. }
  9. public void setDbNameResolver(DBNameResolver dbNameResolver) {
  10. this.dbNameResolver = dbNameResolver;
  11. }
  12. @Override
  13. public void start() {
  14. if (this.dbNameResolver == null) {
  15. this.dbNameResolver = new DefaultDBNameResolver();
  16. }
  17. this.insertExceptionSQL = SQLBuilder.buildInsertExceptionSQL(this.dbNameResolver);
  18. this.insertSQL = SQLBuilder.buildInsertSQL(this.dbNameResolver);
  19. super.start();
  20. }
  21. @Override
  22. protected void subAppend(ILoggingEvent event, Connection connection, PreparedStatement insertStatement) throws Throwable {
  23. this.bindLoggingEventWithInsertStatement(insertStatement, event);
  24. this.bindLoggingEventArgumentsWithPreparedStatement(insertStatement, event.getArgumentArray());
  25. StackTraceElement[] stackTraceElements = event.getCallerData();
  26. if (event.getThrowableProxy() != null) {
  27. if (event.getThrowableProxy().getCause()!=null){
  28. StackTraceElementProxy[] stackTraceElementProxies = event.getThrowableProxy().getCause().getStackTraceElementProxyArray();
  29. if (stackTraceElementProxies!=null&&stackTraceElementProxies.length>0) {
  30. for (StackTraceElementProxy item : stackTraceElementProxies
  31. ) {
  32. if (item.getStackTraceElement().getClassName().indexOf("com.xx") >= 0 && item.getStackTraceElement().getLineNumber() > 0) {
  33. stackTraceElements[0] = item.getStackTraceElement();
  34. break;
  35. }
  36. }
  37. }
  38. }
  39. }
  40. this.bindCallerDataWithPreparedStatement(insertStatement, stackTraceElements);
  41. int updateCount = insertStatement.executeUpdate();
  42. if (updateCount != 1) {
  43. this.addWarn("Failed to insert loggingEvent");
  44. }
  45. }
  46. @Override
  47. protected void secondarySubAppend(ILoggingEvent event, Connection connection, long eventId) throws Throwable {
  48. /*Map<String, String> mergedMap = this.mergePropertyMaps(event);
  49. this.insertProperties(mergedMap, connection, eventId);*/
  50. if (event.getThrowableProxy() != null) {
  51. this.insertThrowable(event.getThrowableProxy(), connection, eventId);
  52. }
  53. }
  54. void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException {
  55. stmt.setLong(1, event.getTimeStamp());
  56. stmt.setString(2, event.getFormattedMessage());
  57. stmt.setString(3, event.getLoggerName());
  58. stmt.setString(4, event.getLevel().toString());
  59. stmt.setString(5, event.getThreadName());
  60. stmt.setShort(6, DBHelper.computeReferenceMask(event));
  61. }
  62. void bindLoggingEventArgumentsWithPreparedStatement(PreparedStatement stmt, Object[] argArray) throws SQLException {
  63. int arrayLen = argArray != null ? argArray.length : 0;
  64. int i;
  65. for(i = 0; i < arrayLen && i < 4; ++i) {
  66. stmt.setString(7 + i, this.asStringTruncatedTo254(argArray[i]));
  67. }
  68. if (arrayLen < 4) {
  69. for(i = arrayLen; i < 4; ++i) {
  70. stmt.setString(7 + i, (String)null);
  71. }
  72. }
  73. }
  74. String asStringTruncatedTo254(Object o) {
  75. String s = null;
  76. if (o != null) {
  77. s = o.toString();
  78. }
  79. if (s == null) {
  80. return null;
  81. } else {
  82. return s.length() <= 254 ? s : s.substring(0, 254);
  83. }
  84. }
  85. void bindCallerDataWithPreparedStatement(PreparedStatement stmt, StackTraceElement[] callerDataArray) throws SQLException {
  86. StackTraceElement caller = this.extractFirstCaller(callerDataArray);
  87. stmt.setString(11, caller.getFileName());
  88. stmt.setString(12, caller.getClassName());
  89. stmt.setString(13, caller.getMethodName());
  90. stmt.setString(14, Integer.toString(caller.getLineNumber()));
  91. }
  92. private StackTraceElement extractFirstCaller(StackTraceElement[] callerDataArray) {
  93. StackTraceElement caller = EMPTY_CALLER_DATA;
  94. if (this.hasAtLeastOneNonNullElement(callerDataArray)) {
  95. caller = callerDataArray[0];
  96. }
  97. return caller;
  98. }
  99. private boolean hasAtLeastOneNonNullElement(StackTraceElement[] callerDataArray) {
  100. return callerDataArray != null && callerDataArray.length > 0 && callerDataArray[0] != null;
  101. }
  102. @Override
  103. protected Method getGeneratedKeysMethod() {
  104. return GET_GENERATED_KEYS_METHOD;
  105. }
  106. @Override
  107. protected String getInsertSQL() {
  108. return this.insertSQL;
  109. }
  110. void updateExceptionStatement(PreparedStatement exceptionStatement, String txt, short i, long eventId) throws SQLException {
  111. exceptionStatement.setLong(1, eventId);
  112. exceptionStatement.setShort(2, i);
  113. exceptionStatement.setString(3, txt);
  114. if (this.cnxSupportsBatchUpdates) {
  115. exceptionStatement.addBatch();
  116. } else {
  117. exceptionStatement.execute();
  118. }
  119. }
  120. short buildExceptionStatement(IThrowableProxy tp, short baseIndex, PreparedStatement insertExceptionStatement, long eventId) throws SQLException {
  121. try{
  122. StringBuilder buf = new StringBuilder();
  123. ThrowableProxyUtil.subjoinFirstLine(buf, tp);
  124. this.updateExceptionStatement(insertExceptionStatement, buf.toString(), baseIndex++, eventId);
  125. int commonFrames = tp.getCommonFrames();
  126. StackTraceElementProxy[] stepArray = tp.getStackTraceElementProxyArray();
  127. for(int i = 0; i < stepArray.length; ++i) {
  128. StringBuilder sb = new StringBuilder();
  129. sb.append('\t');
  130. ThrowableProxyUtil.subjoinSTEP(sb, stepArray[i]);
  131. this.updateExceptionStatement(insertExceptionStatement, sb.toString(), baseIndex++, eventId);
  132. }
  133. }catch (Exception e){
  134. System.out.println("11");
  135. }
  136. return baseIndex;
  137. }
  138. protected void insertThrowable(IThrowableProxy tp, Connection connection, long eventId) throws SQLException {
  139. PreparedStatement exceptionStatement = null;
  140. try {
  141. exceptionStatement = connection.prepareStatement(this.insertExceptionSQL);
  142. short baseIndex = 0;
  143. while(true) {
  144. if (tp == null) {
  145. if (this.cnxSupportsBatchUpdates) {
  146. exceptionStatement.executeBatch();
  147. }
  148. break;
  149. }
  150. if (tp.getCause()!=null){
  151. tp = tp.getCause();
  152. }
  153. baseIndex = this.buildExceptionStatement(tp, baseIndex, exceptionStatement, eventId);
  154. tp = tp.getCause();
  155. }
  156. } finally {
  157. ch.qos.logback.core.db.DBHelper.closeStatement(exceptionStatement);
  158. }
  159. }
  160. static {
  161. Method getGeneratedKeysMethod;
  162. try {
  163. getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[])null);
  164. } catch (Exception var2) {
  165. getGeneratedKeysMethod = null;
  166. }
  167. GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
  168. }
  169. }
  1. SQLBuilder

  1. public class SQLBuilder {
  2. public SQLBuilder() {
  3. }
  4. static String buildInsertPropertiesSQL(DBNameResolver dbNameResolver) {
  5. StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");
  6. sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT_PROPERTY)).append(" (");
  7. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.EVENT_ID)).append(", ");
  8. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.MAPPED_KEY)).append(", ");
  9. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.MAPPED_VALUE)).append(") ");
  10. sqlBuilder.append("VALUES (?, ?, ?)");
  11. return sqlBuilder.toString();
  12. }
  13. static String buildInsertExceptionSQL(DBNameResolver dbNameResolver) {
  14. StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");
  15. sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT_EXCEPTION)).append(" (");
  16. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.EVENT_ID)).append(", ");
  17. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.I)).append(", ");
  18. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.TRACE_LINE)).append(") ");
  19. sqlBuilder.append("VALUES (?, ?, ?)");
  20. return sqlBuilder.toString();
  21. }
  22. static String buildInsertSQL(DBNameResolver dbNameResolver) {
  23. StringBuilder sqlBuilder = new StringBuilder("INSERT INTO ");
  24. sqlBuilder.append(dbNameResolver.getTableName(TableName.LOGGING_EVENT)).append(" (");
  25. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.TIMESTMP)).append(", ");
  26. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.FORMATTED_MESSAGE)).append(", ");
  27. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LOGGER_NAME)).append(", ");
  28. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.LEVEL_STRING)).append(", ");
  29. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.THREAD_NAME)).append(", ");
  30. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.REFERENCE_FLAG)).append(", ");
  31. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG0)).append(", ");
  32. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG1)).append(", ");
  33. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG2)).append(", ");
  34. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.ARG3)).append(", ");
  35. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_FILENAME)).append(", ");
  36. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_CLASS)).append(", ");
  37. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_METHOD)).append(", ");
  38. sqlBuilder.append(dbNameResolver.getColumnName(ColumnName.CALLER_LINE)).append(") ");
  39. sqlBuilder.append("VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
  40. return sqlBuilder.toString();
  41. }
  42. }

表结构 logging_event.sql

  1. SET NAMES utf8mb4;
  2. SET FOREIGN_KEY_CHECKS = 0;
  3. -- ----------------------------
  4. -- Table structure for logging_event
  5. -- ----------------------------
  6. DROP TABLE IF EXISTS `logging_event`;
  7. CREATE TABLE `logging_event` (
  8. `timestmp` bigint(20) NOT NULL,
  9. `formatted_message` longtext CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  10. `logger_name` varchar(254) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  11. `level_string` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  12. `thread_name` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  13. `reference_flag` smallint(6) DEFAULT NULL,
  14. `arg0` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  15. `arg1` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  16. `arg2` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  17. `arg3` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci DEFAULT NULL,
  18. `caller_filename` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  19. `caller_class` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  20. `caller_method` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  21. `caller_line` char(4) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  22. `event_id` bigint(20) NOT NULL AUTO_INCREMENT,
  23. `create_time` datetime(0) DEFAULT CURRENT_TIMESTAMP,
  24. PRIMARY KEY (`event_id`) USING BTREE
  25. ) ENGINE = InnoDB AUTO_INCREMENT = 504 CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
  26. SET FOREIGN_KEY_CHECKS = 1;

表结构 logging_event_exception.sql

  1. SET NAMES utf8mb4;
  2. SET FOREIGN_KEY_CHECKS = 0;
  3. -- ----------------------------
  4. -- Table structure for logging_event_exception
  5. -- ----------------------------
  6. DROP TABLE IF EXISTS `logging_event_exception`;
  7. CREATE TABLE `logging_event_exception` (
  8. `event_id` bigint(20) NOT NULL,
  9. `i` smallint(6) NOT NULL,
  10. `trace_line` varchar(254) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
  11. PRIMARY KEY (`event_id`, `i`) USING BTREE,
  12. CONSTRAINT `logging_event_exception_ibfk_1` FOREIGN KEY (`event_id`) REFERENCES `logging_event` (`event_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
  13. ) ENGINE = InnoDB CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Dynamic;
  14. SET FOREIGN_KEY_CHECKS = 1;
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/312774
推荐阅读
相关标签
  

闽ICP备14008679号