logback的DBAppender重写

问题:logback的DBAppender只能写入4个参数,而且参数名字固定,保存数据的表名固定,因此解决以上问题,需要重写DBAppender;
而且还自己从数据库定义各种类型的日志级别

方案:除logback的三张表外,其它再增加2张表,分别为分类表和需要定义的package或class,logback的表名可以进行修改
1、修改表名和列名:logback的表名可以修改成你需要的表名,只需要在AppDBNameResolver里面修改getTableName方法的返回值;
列名也是一样的,只需要修改getColumnName的返回值;
如下:
public class MyDBNameResolver implements DBNameResolver {

private String tableNamePrefix = “s_” ;

private String tableNameSuffix = “” ;

private String columnNamePrefix = “” ;

private String columnNameSuffix = “” ;

//修改表名
  public <N extends Enum<?>> String getTableName(N tableName) {
    System.out.println( " getTableName " + tableName );
    return tableNamePrefix + tableName .name().toLowerCase() + tableNameSuffix;
  }

//修改列名
  public <N extends Enum<?>> String getColumnName(N columnName) {
    System.out.println( " getColumnName " + columnName + " " + columnName.name().toLowerCase() );
    if(“arg0”.equals( columnName.name().toLowerCase())){
      return “log_type”;
    }else
    return columnNamePrefix + columnName .name().toLowerCase() + columnNameSuffix;
  }

logback.xml中增加如下:
< dbNameResolver class=“com.javacodegeeks.examples.logbackmdcexample.MyDBNameResolver”/>增加到< appender>中

2、增加参数
需要重写DBAppender,主要在以下地方:
 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   ARG4_INDEX = 11;//增加的一个参数

bindLoggingEventArgumentsWithPreparedStatement方法中修改:对应的数字4改成你增加到的数字
void bindLoggingEventArgumentsWithPreparedStatement (PreparedStatement stmt ,
      Object[] argArray) throws SQLException {

int arrayLen = argArray != null ? argArray .length : 0;

for(int i = 0; i < arrayLen && i < 5; i++) {
      stmt.setString( ARG0_INDEX+i , asStringTruncatedTo254(argArray[i]));
    }
    if(arrayLen < 5) {
      for(int i = arrayLen; i < 5; i++) {
        stmt.setString( ARG0_INDEX+i , null);
      }
    }
  }

如果还增加了其它字段到数据库且,可以修改bindCallerDataWithPreparedStatement方法
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()));
//增加的字段
       stmt.setString(15, “logger add column”);
  }

最后修改SQLBuilder,增加你增加的字段
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. ARG4)).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(“logger_type”).append( ") ");//增加自己的列
    sqlBuilder.append( “VALUES (?, ?, ? ,?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?, ?, ?)” );//增加两个占位符
    return sqlBuilder.toString();
  }

logback.xml中修改如下:
< appender name =“db” class=“com.javacodegeeks.examples.logbackmdcexample.MyDBAppender”>,改成自己的DBAppender

logback基础详解:
log日志级别:TRACE < DEBUG < INFO < WARN < ERROR

Logback默认配置的步骤

(1). 尝试在 classpath 下查找文件 logback-test.xml;

(2). 如果文件不存在,则查找文件 logback.xml;

(3). 如果两个文件都不存在,logback 用 Bas icConfigurator 自动对自己进行配置,这会导致记录输出到控制台。

Logback.xml 文件

[html] view plaincopy

<?xml version="1.0" encoding="UTF-8"?>                                                               UTF-8                                                  %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n                                                                             UTF-8                                             ${LOG_HOME}/myApp.log.%d{yyyy-MM-dd}.log                  30                                                           %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n                                                                  10MB                                                                                                                                                                                                                                      com.mysql.jdbc.Driver                 jdbc:mysql://127.0.0.1:3306/databaseName                 root                 root                                -->     

一:根节点 包含的属性:
scan: 
当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
scanPeriod: 
设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
debug: 
当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
例如:

二:根节点 的子节点:

2.1设置上下文名称:
每个logger都关联到logger上下文,默认上下文名称为default。但可以使用设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。

myAppName 2.2设置变量:  用来定义变量值的标签, 有两个属性name和value;

name: 变量的名称
value: 的值时变量定义的值。
通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。

例如使用定义上下文名称,然后在设置logger上下文时使用。

${APP_Name} 2.3获取时间戳字符串: 两个属性:

key: 标识此 的名字;
datePattern: 设置将当前时间(解析配置文件的时间)转换为字符串的模式,遵循java.txt.SimpleDateFormat的格式。
例如将解析配置文件的时间作为上下文名称:

${bySecond} 2.4设置loger: 用来设置某一个包或者具体的某一个类的日志打印级别、以及指定。仅有一个name属性,一个可选的level和一个可选的addtivity属性。

name: 
用来指定受此loger约束的某一个包或者具体的某一个类。

level: 
用来设置打印级别,大小写无关:TRACE, DEBUG, INFO,WARN,ERROR,ALL和OFF,还有一个特俗值INHERITED或者同义词NULL`,代表强制执行上级的级别。 
如果未设置此属性,那么当前loger将会继承上级的级别。

addtivity: 
是否向上级loger传递打印信息。默认是true。

也是 元素,但是它是根loger。只有一个level属性,应为已经被命名为"root”.

level: 用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,不能设置为INHERITED或者同义词NULL。 
默认是DEBUG。
和可以包含零个或多个元素,标识这个appender将会添加到这个loger。

例如: 
LogbackDemo.java类

package logback;

import org.slf4j.Logger; import org.slf4j.LoggerFactory;

public class LogbackDemo {
private static Logger log = LoggerFactory.getLogger(LogbackDemo.class);
public static void main(String[] args) {
log.trace("======trace");
log.debug("======debug");
log.info("======info");
log.warn("======warn");
log.error("======error");
}
}
三、logback.xml配置文件
第1种:只配置root

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 其中appender的配置表示打印到控制台(稍后详细讲解appender );  将root的打印级别设置为“INFO”,指定了名字为“STDOUT”的appender。

当执行logback.LogbackDemo类的main方法时,root将级别为“INFO”及大于“INFO”的日志信息交给已经配置好的名为“STDOUT”的appender处理,“STDOUT”appender将信息打印到控制台;

打印结果如下:

13:30:38.484 [main] INFO logback.LogbackDemo - ======info
13:30:38.500 [main] WARN logback.LogbackDemo - ======warn
13:30:38.500 [main] ERROR logback.LogbackDemo - ======error
第2种:带有loger的配置,不指定级别,不指定appender:

%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 其中appender的配置表示打印到控制台(稍后详细讲解appender );  将控制logback包下的所有类的日志的打印,但是并没用设置打印级别,所以继承他的上级的日志级别“DEBUG”;  没有设置addtivity,默认为true,将此loger的打印信息向上级传递;  没有设置appender,此loger本身不打印任何信息。  将root的打印级别设置为“DEBUG”,指定了名字为“STDOUT”的appender。

当执行logback.LogbackDemo类的main方法时,因为LogbackDemo 在包logback中,所以首先执行,将级别为“DEBUG”及大于“DEBUG”的日志信息传递给root,本身并不打印; 
root接到下级传递的信息,交给已经配置好的名为“STDOUT”的appender处理,“STDOUT”appender将信息打印到控制台;

打印结果如下:

13:19:15.406 [main] DEBUG logback.LogbackDemo - ======debug
13:19:15.406 [main] INFO logback.LogbackDemo - ======info
13:19:15.406 [main] WARN logback.LogbackDemo - ======warn
13:19:15.406 [main] ERROR logback.LogbackDemo - ======error
第3种:带有多个loger的配置,指定级别,指定appender:




%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n

其中appender的配置表示打印到控制台(稍后详细讲解appender );

将控制logback包下的所有类的日志的打印,但是并没用设置打印级别,所以继承他的上级的日志级别“DEBUG”; 
没有设置addtivity,默认为true,将此loger的打印信息向上级传递; 
没有设置appender,此loger本身不打印任何信息。

控制logback.LogbackDemo类的日志打印,打印级别为“INFO”; 
additivity属性为false,表示此loger的打印信息不再向上级传递, 
指定了名字为“STDOUT”的appender。

将root的打印级别设置为“ERROR”,指定了名字为“STDOUT”的appender。

当执行logback.LogbackDemo类的main方法时,先执行,将级别为“INFO”及大于“INFO”的日志信息交给此loger指定的名为“STDOUT”的appender处理,在控制台中打出日志,不再向次loger的上级  传递打印信息; 
未接到任何打印信息,当然也不会给它的上级root传递任何打印信息;

打印结果如下:

14:09:01.531 [main] INFO logback.LogbackDemo - ======info
14:09:01.531 [main] INFO logback.LogbackDemo - ======info
14:09:01.531 [main] WARN logback.LogbackDemo - ======warn
14:09:01.531 [main] WARN logback.LogbackDemo - ======warn
14:09:01.531 [main] ERROR logback.LogbackDemo - ======error
14:09:01.531 [main] ERROR logback.LogbackDemo - ======error

参考:http://blog.csdn.net/chunming8302/article/details/7321338
          http://my.oschina.net/looly/blog/298675

作者:DannyDaiChn
来源:CSDN
原文:https://blog.csdn.net/qq352345425/article/details/46982683
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值