Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 自定义将管理记录器消息的appender_Java_Logback_Log4j2 - Fatal编程技术网

Java 自定义将管理记录器消息的appender

Java 自定义将管理记录器消息的appender,java,logback,log4j2,Java,Logback,Log4j2,我想创建三个appender:文件、控制台和数据库。此外,我在数据库中存储了三个变量:info、error和warn,它们的值是多少​​对应于上述附录之一 因此,当我运行以下语句时: Logger.info ("bla bla bla") 我需要动态获取数据库中信息的当前值,并在右侧的附加器(文件、控制台或数据库)上显示消息 使用回显: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration> <

我想创建三个appender:文件、控制台和数据库。此外,我在数据库中存储了三个变量:info、error和warn,它们的值是多少​​对应于上述附录之一

因此,当我运行以下语句时:

Logger.info ("bla bla bla")
我需要动态获取数据库中信息的当前值,并在右侧的附加器(文件、控制台或数据库)上显示消息

使用回显

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>

   <!-- Loads the datasource properties file -->
   <property resource="datasource.properties" />

   <!-- Directory where log files will be stored -->
   <property name="LOG_DIRECTORY" value="/tmp" />

   <!-- Appenders -->
   <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
      <filter class="com.myproject.logback.ConsoleFilter" />
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
      </encoder>
   </appender>

   <appender name="database" class="com.myproject.logback.CustomDBAppender">
      <filter class="com.myproject.logback.DBFilter" />
      <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
         <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <driverClass>${jdbc.driverClass}</driverClass>
            <jdbcUrl>${jdbc.jdbcUrl}</jdbcUrl>
            <databaseName>${jdbc.databaseName}</databaseName>
            <user>${jdbc.user}</user>
            <password>${jdbc.password}</password>
        </dataSource>
     </connectionSource>
  </appender>

  <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
     <filter class="com.myproject.logback.FileFilter" />
     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- Rollover daily -->
        <fileNamePattern>${LOG_DIRECTORY}/mylog-%d{yyyy-MM-dd}.txt</fileNamePattern>
        <!-- Keep 10 days of history -->
        <maxHistory>10</maxHistory>
     </rollingPolicy>
     <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
     </encoder>
  </appender>

  <!-- Logger for my project -->
  <logger name="com.myproject" additivity="false" level="all">
     <appender-ref ref="console" />
     <appender-ref ref="database" />
     <appender-ref ref="file" />
  </logger>

  <root level="info">
     <appender-ref ref="console" />
  </root>

</configuration>
public class CustomDBAppender extends DBAppenderBase<ILoggingEvent> {

    protected String insertSQL;

    // Indices of the fields of the table in which the logging information is stored
    private static final int EVENTTIME_INDEX     = 1;
    private static final int MESSAGE_INDEX       = 2;
    private static final int LOGGER_INDEX        = 3;
    private static final int LEVEL_INDEX         = 4;
    private static final int CALLER_CLASS_INDEX  = 5;
    private static final int CALLER_METHOD_INDEX = 6;
    private static final int CALLER_LINE_INDEX   = 7;
    private static final int TRACE_INDEX         = 8;

    static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    @Override
    public void append (ILoggingEvent eventObject) {

       Connection connection = null;
       PreparedStatement insertStatement = null;
       try {
          connection = connectionSource.getConnection();
          connection.setAutoCommit (false);

          insertStatement = connection.prepareStatement (getInsertSQL());

          // Inserting the event in database
          synchronized (this) {
             subAppend (eventObject, connection, insertStatement);
          }
          secondarySubAppend (eventObject, connection, 1);

          connection.commit();

       } catch (Throwable sqle) {
          addError("problem appending event", sqle);
       } finally {
          DBHelper.closeStatement (insertStatement);
          DBHelper.closeConnection (connection);
       }
    }

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

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

    @Override
    protected void secondarySubAppend (ILoggingEvent eventObject,
                       Connection connection, long eventId) throws Throwable {}

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

    @Override
    protected void subAppend (ILoggingEvent event, Connection connection,
                      PreparedStatement insertStatement) throws Throwable {

       bindLoggingEventWithInsertStatement (insertStatement, event);
       bindCallerDataWithPreparedStatement (insertStatement, event.getCallerData());

       int updateCount = insertStatement.executeUpdate();
       if (updateCount != 1) {
          addWarn("Failed to insert loggingEvent");
       }
    }

    void bindCallerDataWithPreparedStatement (PreparedStatement stmt,
            StackTraceElement[] callerDataArray) throws SQLException {

       StackTraceElement caller = extractFirstCaller (callerDataArray);

       stmt.setString (CALLER_CLASS_INDEX, caller.getClassName());
       stmt.setString (CALLER_METHOD_INDEX, caller.getMethodName());
       stmt.setString (CALLER_LINE_INDEX, Integer.toString (caller.getLineNumber()));
    }

    void bindLoggingEventWithInsertStatement (PreparedStatement stmt,
            ILoggingEvent event) throws SQLException {

       stmt.setTimestamp (EVENTTIME_INDEX, new Timestamp (event.getTimeStamp()));
       stmt.setString (MESSAGE_INDEX, event.getFormattedMessage());
       stmt.setString (LOGGER_INDEX, event.getLoggerName());
       stmt.setString (LEVEL_INDEX, event.getLevel().toString());

       if (event.getThrowableProxy() != null && 
           event.getThrowableProxy().getStackTraceElementProxyArray() != null)
          stmt.setString (TRACE_INDEX, ThrowableProxyUtil.asString (event.getThrowableProxy()));
       else
          stmt.setString (TRACE_INDEX, null);
    }

    private static String buildInsertSQL () {

       return "INSERT INTO mylogtable "
            + " (eventtime, message, logger, level, callerclass, callermethod, callerline, trace) "
            + "VALUES "
            + "(?, ?, ?, ?, ?, ?, ?, ?)";
    }

    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;
    }
 }
public class FileFilter extends Filter<ILoggingEvent> {

   @Override
   public FilterReply decide (ILoggingEvent event) {

      try {
         // I have in a database table something like this:
         //    Level   -   Appender
         //    ERROR         FILE
         //    DEBUG        CONSOLE
         //    ...

         // Here I check with a service if "the actual logger level"
         // [event.getLevel()] in the previous database table, is set
         // to record their messages with the "current appender"

         if (thePreviousCondition == true)
            return FilterReply.ACCEPT;

         return FilterReply.DENY;

      } catch (Exception e) {
         return FilterReply.DENY;
      }
   }
}
1。我需要创建一个完整的类(比如),因为我不想将信息存储在三个不同的表中(只存储在一个表中)

2.多亏了这一点,为信息捕获数据库的价值似乎很简单。因此,我可以在每个appender中包含过滤器,并根据info的值决定是否使用“当前appender”

使用Log4j 2

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>

   <!-- Loads the datasource properties file -->
   <property resource="datasource.properties" />

   <!-- Directory where log files will be stored -->
   <property name="LOG_DIRECTORY" value="/tmp" />

   <!-- Appenders -->
   <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
      <filter class="com.myproject.logback.ConsoleFilter" />
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
      </encoder>
   </appender>

   <appender name="database" class="com.myproject.logback.CustomDBAppender">
      <filter class="com.myproject.logback.DBFilter" />
      <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
         <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <driverClass>${jdbc.driverClass}</driverClass>
            <jdbcUrl>${jdbc.jdbcUrl}</jdbcUrl>
            <databaseName>${jdbc.databaseName}</databaseName>
            <user>${jdbc.user}</user>
            <password>${jdbc.password}</password>
        </dataSource>
     </connectionSource>
  </appender>

  <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
     <filter class="com.myproject.logback.FileFilter" />
     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- Rollover daily -->
        <fileNamePattern>${LOG_DIRECTORY}/mylog-%d{yyyy-MM-dd}.txt</fileNamePattern>
        <!-- Keep 10 days of history -->
        <maxHistory>10</maxHistory>
     </rollingPolicy>
     <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
     </encoder>
  </appender>

  <!-- Logger for my project -->
  <logger name="com.myproject" additivity="false" level="all">
     <appender-ref ref="console" />
     <appender-ref ref="database" />
     <appender-ref ref="file" />
  </logger>

  <root level="info">
     <appender-ref ref="console" />
  </root>

</configuration>
public class CustomDBAppender extends DBAppenderBase<ILoggingEvent> {

    protected String insertSQL;

    // Indices of the fields of the table in which the logging information is stored
    private static final int EVENTTIME_INDEX     = 1;
    private static final int MESSAGE_INDEX       = 2;
    private static final int LOGGER_INDEX        = 3;
    private static final int LEVEL_INDEX         = 4;
    private static final int CALLER_CLASS_INDEX  = 5;
    private static final int CALLER_METHOD_INDEX = 6;
    private static final int CALLER_LINE_INDEX   = 7;
    private static final int TRACE_INDEX         = 8;

    static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    @Override
    public void append (ILoggingEvent eventObject) {

       Connection connection = null;
       PreparedStatement insertStatement = null;
       try {
          connection = connectionSource.getConnection();
          connection.setAutoCommit (false);

          insertStatement = connection.prepareStatement (getInsertSQL());

          // Inserting the event in database
          synchronized (this) {
             subAppend (eventObject, connection, insertStatement);
          }
          secondarySubAppend (eventObject, connection, 1);

          connection.commit();

       } catch (Throwable sqle) {
          addError("problem appending event", sqle);
       } finally {
          DBHelper.closeStatement (insertStatement);
          DBHelper.closeConnection (connection);
       }
    }

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

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

    @Override
    protected void secondarySubAppend (ILoggingEvent eventObject,
                       Connection connection, long eventId) throws Throwable {}

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

    @Override
    protected void subAppend (ILoggingEvent event, Connection connection,
                      PreparedStatement insertStatement) throws Throwable {

       bindLoggingEventWithInsertStatement (insertStatement, event);
       bindCallerDataWithPreparedStatement (insertStatement, event.getCallerData());

       int updateCount = insertStatement.executeUpdate();
       if (updateCount != 1) {
          addWarn("Failed to insert loggingEvent");
       }
    }

    void bindCallerDataWithPreparedStatement (PreparedStatement stmt,
            StackTraceElement[] callerDataArray) throws SQLException {

       StackTraceElement caller = extractFirstCaller (callerDataArray);

       stmt.setString (CALLER_CLASS_INDEX, caller.getClassName());
       stmt.setString (CALLER_METHOD_INDEX, caller.getMethodName());
       stmt.setString (CALLER_LINE_INDEX, Integer.toString (caller.getLineNumber()));
    }

    void bindLoggingEventWithInsertStatement (PreparedStatement stmt,
            ILoggingEvent event) throws SQLException {

       stmt.setTimestamp (EVENTTIME_INDEX, new Timestamp (event.getTimeStamp()));
       stmt.setString (MESSAGE_INDEX, event.getFormattedMessage());
       stmt.setString (LOGGER_INDEX, event.getLoggerName());
       stmt.setString (LEVEL_INDEX, event.getLevel().toString());

       if (event.getThrowableProxy() != null && 
           event.getThrowableProxy().getStackTraceElementProxyArray() != null)
          stmt.setString (TRACE_INDEX, ThrowableProxyUtil.asString (event.getThrowableProxy()));
       else
          stmt.setString (TRACE_INDEX, null);
    }

    private static String buildInsertSQL () {

       return "INSERT INTO mylogtable "
            + " (eventtime, message, logger, level, callerclass, callermethod, callerline, trace) "
            + "VALUES "
            + "(?, ?, ?, ?, ?, ?, ?, ?)";
    }

    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;
    }
 }
public class FileFilter extends Filter<ILoggingEvent> {

   @Override
   public FilterReply decide (ILoggingEvent event) {

      try {
         // I have in a database table something like this:
         //    Level   -   Appender
         //    ERROR         FILE
         //    DEBUG        CONSOLE
         //    ...

         // Here I check with a service if "the actual logger level"
         // [event.getLevel()] in the previous database table, is set
         // to record their messages with the "current appender"

         if (thePreviousCondition == true)
            return FilterReply.ACCEPT;

         return FilterReply.DENY;

      } catch (Exception e) {
         return FilterReply.DENY;
      }
   }
}
1。我可以使用(而不必创建新类)

2.如何创建一个定制的数据库,用于获取数据库中信息的价值,并帮助我决定是否应该使用其中一个附件(文件、控制台或数据库)

问题是:

是否有任何方法可以简化“第一点回显”或执行“第二点回显”


提前感谢。

Log4j2支持过滤器,我相信与Logback非常类似。听起来您正在寻找基于级别的过滤,您可以使用


或者您正在寻找类似的内容(请参阅常见问题解答以获取详细信息)?这允许您配置多个appender,并根据ThreadContext映射将日志事件动态路由到不同的appender。

最后,我找到了问题的解决方案。在logback.xml文件中:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>

   <!-- Loads the datasource properties file -->
   <property resource="datasource.properties" />

   <!-- Directory where log files will be stored -->
   <property name="LOG_DIRECTORY" value="/tmp" />

   <!-- Appenders -->
   <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
      <filter class="com.myproject.logback.ConsoleFilter" />
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
      </encoder>
   </appender>

   <appender name="database" class="com.myproject.logback.CustomDBAppender">
      <filter class="com.myproject.logback.DBFilter" />
      <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
         <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <driverClass>${jdbc.driverClass}</driverClass>
            <jdbcUrl>${jdbc.jdbcUrl}</jdbcUrl>
            <databaseName>${jdbc.databaseName}</databaseName>
            <user>${jdbc.user}</user>
            <password>${jdbc.password}</password>
        </dataSource>
     </connectionSource>
  </appender>

  <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
     <filter class="com.myproject.logback.FileFilter" />
     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- Rollover daily -->
        <fileNamePattern>${LOG_DIRECTORY}/mylog-%d{yyyy-MM-dd}.txt</fileNamePattern>
        <!-- Keep 10 days of history -->
        <maxHistory>10</maxHistory>
     </rollingPolicy>
     <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
     </encoder>
  </appender>

  <!-- Logger for my project -->
  <logger name="com.myproject" additivity="false" level="all">
     <appender-ref ref="console" />
     <appender-ref ref="database" />
     <appender-ref ref="file" />
  </logger>

  <root level="info">
     <appender-ref ref="console" />
  </root>

</configuration>
public class CustomDBAppender extends DBAppenderBase<ILoggingEvent> {

    protected String insertSQL;

    // Indices of the fields of the table in which the logging information is stored
    private static final int EVENTTIME_INDEX     = 1;
    private static final int MESSAGE_INDEX       = 2;
    private static final int LOGGER_INDEX        = 3;
    private static final int LEVEL_INDEX         = 4;
    private static final int CALLER_CLASS_INDEX  = 5;
    private static final int CALLER_METHOD_INDEX = 6;
    private static final int CALLER_LINE_INDEX   = 7;
    private static final int TRACE_INDEX         = 8;

    static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    @Override
    public void append (ILoggingEvent eventObject) {

       Connection connection = null;
       PreparedStatement insertStatement = null;
       try {
          connection = connectionSource.getConnection();
          connection.setAutoCommit (false);

          insertStatement = connection.prepareStatement (getInsertSQL());

          // Inserting the event in database
          synchronized (this) {
             subAppend (eventObject, connection, insertStatement);
          }
          secondarySubAppend (eventObject, connection, 1);

          connection.commit();

       } catch (Throwable sqle) {
          addError("problem appending event", sqle);
       } finally {
          DBHelper.closeStatement (insertStatement);
          DBHelper.closeConnection (connection);
       }
    }

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

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

    @Override
    protected void secondarySubAppend (ILoggingEvent eventObject,
                       Connection connection, long eventId) throws Throwable {}

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

    @Override
    protected void subAppend (ILoggingEvent event, Connection connection,
                      PreparedStatement insertStatement) throws Throwable {

       bindLoggingEventWithInsertStatement (insertStatement, event);
       bindCallerDataWithPreparedStatement (insertStatement, event.getCallerData());

       int updateCount = insertStatement.executeUpdate();
       if (updateCount != 1) {
          addWarn("Failed to insert loggingEvent");
       }
    }

    void bindCallerDataWithPreparedStatement (PreparedStatement stmt,
            StackTraceElement[] callerDataArray) throws SQLException {

       StackTraceElement caller = extractFirstCaller (callerDataArray);

       stmt.setString (CALLER_CLASS_INDEX, caller.getClassName());
       stmt.setString (CALLER_METHOD_INDEX, caller.getMethodName());
       stmt.setString (CALLER_LINE_INDEX, Integer.toString (caller.getLineNumber()));
    }

    void bindLoggingEventWithInsertStatement (PreparedStatement stmt,
            ILoggingEvent event) throws SQLException {

       stmt.setTimestamp (EVENTTIME_INDEX, new Timestamp (event.getTimeStamp()));
       stmt.setString (MESSAGE_INDEX, event.getFormattedMessage());
       stmt.setString (LOGGER_INDEX, event.getLoggerName());
       stmt.setString (LEVEL_INDEX, event.getLevel().toString());

       if (event.getThrowableProxy() != null && 
           event.getThrowableProxy().getStackTraceElementProxyArray() != null)
          stmt.setString (TRACE_INDEX, ThrowableProxyUtil.asString (event.getThrowableProxy()));
       else
          stmt.setString (TRACE_INDEX, null);
    }

    private static String buildInsertSQL () {

       return "INSERT INTO mylogtable "
            + " (eventtime, message, logger, level, callerclass, callermethod, callerline, trace) "
            + "VALUES "
            + "(?, ?, ?, ?, ?, ?, ?, ?)";
    }

    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;
    }
 }
public class FileFilter extends Filter<ILoggingEvent> {

   @Override
   public FilterReply decide (ILoggingEvent event) {

      try {
         // I have in a database table something like this:
         //    Level   -   Appender
         //    ERROR         FILE
         //    DEBUG        CONSOLE
         //    ...

         // Here I check with a service if "the actual logger level"
         // [event.getLevel()] in the previous database table, is set
         // to record their messages with the "current appender"

         if (thePreviousCondition == true)
            return FilterReply.ACCEPT;

         return FilterReply.DENY;

      } catch (Exception e) {
         return FilterReply.DENY;
      }
   }
}

%d{yyyy-MM-dd HH:MM:ss}[%-5level.%msg-%class.%方法:%line]%n
${jdbc.driverClass}
${jdbc.jdbcUrl}
${jdbc.databaseName}
${jdbc.user}
${jdbc.password}
${LOG\u DIRECTORY}/mylog-%d{yyyy-MM-dd}.txt
10
%d{yyyy-MM-dd HH:MM:ss}[%-5level.%msg-%class.%方法:%line]%n
现在CustomDBAppender.java

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>

   <!-- Loads the datasource properties file -->
   <property resource="datasource.properties" />

   <!-- Directory where log files will be stored -->
   <property name="LOG_DIRECTORY" value="/tmp" />

   <!-- Appenders -->
   <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
      <filter class="com.myproject.logback.ConsoleFilter" />
      <encoder>
         <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
      </encoder>
   </appender>

   <appender name="database" class="com.myproject.logback.CustomDBAppender">
      <filter class="com.myproject.logback.DBFilter" />
      <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
         <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <driverClass>${jdbc.driverClass}</driverClass>
            <jdbcUrl>${jdbc.jdbcUrl}</jdbcUrl>
            <databaseName>${jdbc.databaseName}</databaseName>
            <user>${jdbc.user}</user>
            <password>${jdbc.password}</password>
        </dataSource>
     </connectionSource>
  </appender>

  <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
     <filter class="com.myproject.logback.FileFilter" />
     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- Rollover daily -->
        <fileNamePattern>${LOG_DIRECTORY}/mylog-%d{yyyy-MM-dd}.txt</fileNamePattern>
        <!-- Keep 10 days of history -->
        <maxHistory>10</maxHistory>
     </rollingPolicy>
     <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level.%msg - %class.%method : %line]%n</pattern>
     </encoder>
  </appender>

  <!-- Logger for my project -->
  <logger name="com.myproject" additivity="false" level="all">
     <appender-ref ref="console" />
     <appender-ref ref="database" />
     <appender-ref ref="file" />
  </logger>

  <root level="info">
     <appender-ref ref="console" />
  </root>

</configuration>
public class CustomDBAppender extends DBAppenderBase<ILoggingEvent> {

    protected String insertSQL;

    // Indices of the fields of the table in which the logging information is stored
    private static final int EVENTTIME_INDEX     = 1;
    private static final int MESSAGE_INDEX       = 2;
    private static final int LOGGER_INDEX        = 3;
    private static final int LEVEL_INDEX         = 4;
    private static final int CALLER_CLASS_INDEX  = 5;
    private static final int CALLER_METHOD_INDEX = 6;
    private static final int CALLER_LINE_INDEX   = 7;
    private static final int TRACE_INDEX         = 8;

    static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    @Override
    public void append (ILoggingEvent eventObject) {

       Connection connection = null;
       PreparedStatement insertStatement = null;
       try {
          connection = connectionSource.getConnection();
          connection.setAutoCommit (false);

          insertStatement = connection.prepareStatement (getInsertSQL());

          // Inserting the event in database
          synchronized (this) {
             subAppend (eventObject, connection, insertStatement);
          }
          secondarySubAppend (eventObject, connection, 1);

          connection.commit();

       } catch (Throwable sqle) {
          addError("problem appending event", sqle);
       } finally {
          DBHelper.closeStatement (insertStatement);
          DBHelper.closeConnection (connection);
       }
    }

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

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

    @Override
    protected void secondarySubAppend (ILoggingEvent eventObject,
                       Connection connection, long eventId) throws Throwable {}

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

    @Override
    protected void subAppend (ILoggingEvent event, Connection connection,
                      PreparedStatement insertStatement) throws Throwable {

       bindLoggingEventWithInsertStatement (insertStatement, event);
       bindCallerDataWithPreparedStatement (insertStatement, event.getCallerData());

       int updateCount = insertStatement.executeUpdate();
       if (updateCount != 1) {
          addWarn("Failed to insert loggingEvent");
       }
    }

    void bindCallerDataWithPreparedStatement (PreparedStatement stmt,
            StackTraceElement[] callerDataArray) throws SQLException {

       StackTraceElement caller = extractFirstCaller (callerDataArray);

       stmt.setString (CALLER_CLASS_INDEX, caller.getClassName());
       stmt.setString (CALLER_METHOD_INDEX, caller.getMethodName());
       stmt.setString (CALLER_LINE_INDEX, Integer.toString (caller.getLineNumber()));
    }

    void bindLoggingEventWithInsertStatement (PreparedStatement stmt,
            ILoggingEvent event) throws SQLException {

       stmt.setTimestamp (EVENTTIME_INDEX, new Timestamp (event.getTimeStamp()));
       stmt.setString (MESSAGE_INDEX, event.getFormattedMessage());
       stmt.setString (LOGGER_INDEX, event.getLoggerName());
       stmt.setString (LEVEL_INDEX, event.getLevel().toString());

       if (event.getThrowableProxy() != null && 
           event.getThrowableProxy().getStackTraceElementProxyArray() != null)
          stmt.setString (TRACE_INDEX, ThrowableProxyUtil.asString (event.getThrowableProxy()));
       else
          stmt.setString (TRACE_INDEX, null);
    }

    private static String buildInsertSQL () {

       return "INSERT INTO mylogtable "
            + " (eventtime, message, logger, level, callerclass, callermethod, callerline, trace) "
            + "VALUES "
            + "(?, ?, ?, ?, ?, ?, ?, ?)";
    }

    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;
    }
 }
public class FileFilter extends Filter<ILoggingEvent> {

   @Override
   public FilterReply decide (ILoggingEvent event) {

      try {
         // I have in a database table something like this:
         //    Level   -   Appender
         //    ERROR         FILE
         //    DEBUG        CONSOLE
         //    ...

         // Here I check with a service if "the actual logger level"
         // [event.getLevel()] in the previous database table, is set
         // to record their messages with the "current appender"

         if (thePreviousCondition == true)
            return FilterReply.ACCEPT;

         return FilterReply.DENY;

      } catch (Exception e) {
         return FilterReply.DENY;
      }
   }
}
public类CustomDBAppender扩展了DBAppenderBase{
受保护的字符串insertSQL;
//存储日志信息的表的字段索引
私有静态final int EVENTTIME_INDEX=1;
私有静态最终int消息_索引=2;
私有静态最终int LOGGER_索引=3;
私有静态最终整数级_索引=4;
私有静态final int CALLER_CLASS_INDEX=5;
私有静态final int CALLER_METHOD_INDEX=6;
私有静态最终整数调用方线索引=7;
私有静态final int TRACE_INDEX=8;
静态最终StackTraceeElement EMPTY_CALLER_DATA=CallerData.naInstance();
@凌驾
public void append(ilogingevent事件对象){
连接=空;
PreparedStatement insertStatement=null;
试一试{
connection=connectionSource.getConnection();
connection.setAutoCommit(false);
insertStatement=connection.prepareStatement(getInsertSQL());
//在数据库中插入事件
已同步(此){
子外观(eventObject、connection、insertStatement);
}
次要子外观(eventObject,connection,1);
commit();
}捕获(可丢弃的sqle){
加法器(“问题追加事件”,sqle);
}最后{
DBHelper.closeStatement(insertStatement);
DBHelper.closeConnection(连接);
}
}
@凌驾
受保护的方法getGeneratedKeysMethod(){
返回null;
}
@凌驾
受保护的字符串getInsertSQL(){
返回insertSQL;
}
@凌驾
受保护的void secondarySubAppend(ILOGingEvent事件对象,
连接,长事件ID)抛出可丢弃的{}
@凌驾
公开作废开始(){
insertSQL=CustomDBAppender.buildInsertSQL();
super.start();
}
@凌驾
受保护的无效子外观(ILoggingEvent事件、连接、,
PreparedStatement插入语句)抛出可丢弃的{
bindLoggingEventWithInsertStatement(insertStatement,事件);
bindCallerDataWithPreparedStatement(insertStatement,event.getCallerData());
int updateCount=insertStatement.executeUpdate();
如果(updateCount!=1){
addWarn(“未能插入loggingEvent”);
}
}
作废bindCallerDataWithPreparedStatement(PreparedStatement stmt,
StackTraceeElement[]callerDataArray)引发SQLException{
StackTraceElement调用者=extractFirstCaller(callerDataArray);
stmt.setString(CALLER_CLASS_索引,CALLER.getClassName());
stmt.setString(调用者\方法\索引,调用者.getMethodName());
stmt.setString(CALLER\u LINE\u索引,Integer.toString(CALLER.getLineNumber());
}
作废bindLoggingEventWithInsertStatement(PreparedStatement stmt,
ILOGingEvent事件)引发SQLException{
stmt.setTimestamp(EVENTTIME_索引,新的时间戳(event.getTimeStamp());
stmt.setString(消息索引,event.getFormattedMessage());
stmt.setString(LOGGER_索引,event.getLoggerName());
stmt.setString(LEVEL_索引,event.getLevel().toString());
if(event.getThrowableProxy()!=null&&
event.getThrowableProxy().getStackTraceElementProxyArray()!=null)
stmt.setString(TRACE_INDEX,ThrowableProxyUtil.asString(event.getThrowableProxy());
其他的
stmt.setString(跟踪输入)