logback基础知识 DBAppend重写

 问题: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 plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <configuration>  
  3.     <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->    
  4.     <property name="LOG_HOME" value="c:/log" />    
  5.     <!-- 控制台输出 -->     
  6.     <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">  
  7.        <!-- 日志输出编码 -->    
  8.        <Encoding>UTF-8</Encoding>     
  9.         <layout class="ch.qos.logback.classic.PatternLayout">     
  10.              <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->   
  11.             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n     
  12.             </pattern>     
  13.         </layout>     
  14.     </appender>     
  15.     <!-- 按照每天生成日志文件 -->     
  16.     <appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">     
  17.         <Encoding>UTF-8</Encoding>     
  18.         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
  19.             <!--日志文件输出的文件名-->  
  20.             <FileNamePattern>${LOG_HOME}/myApp.log.%d{yyyy-MM-dd}.log</FileNamePattern>     
  21.             <MaxHistory>30</MaxHistory>  
  22.         </rollingPolicy>     
  23.         <layout class="ch.qos.logback.classic.PatternLayout">    
  24.             <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->   
  25.             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n     
  26.             </pattern>     
  27.        </layout>   
  28.         <!--日志文件最大的大小-->  
  29.        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">  
  30.          <MaxFileSize>10MB</MaxFileSize>  
  31.        </triggeringPolicy>  
  32.     </appender>   
  33.    <!-- show parameters for hibernate sql 专为 Hibernate 定制 -->    
  34.     <logger name="org.hibernate.type.descriptor.sql.BasicBinder"  level="TRACE" />    
  35.     <logger name="org.hibernate.type.descriptor.sql.BasicExtractor"  level="DEBUG" />    
  36.     <logger name="org.hibernate.SQL" level="DEBUG" />    
  37.     <logger name="org.hibernate.engine.QueryParameters" level="DEBUG" />    
  38.     <logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG" />    
  39.       
  40.     <!-- 日志输出级别 -->  
  41.     <root level="INFO">     
  42.         <appender-ref ref="STDOUT" />     
  43.         <appender-ref ref="FILE" />     
  44.     </root>   
  45.        
  46.      <!--日志异步到数据库 -->    
  47.     <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">  
  48.         <!--日志异步到数据库 -->   
  49.         <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">  
  50.            <!--连接池 -->   
  51.            <dataSource class="com.mchange.v2.c3p0.ComboPooledDataSource">  
  52.               <driverClass>com.mysql.jdbc.Driver</driverClass>  
  53.               <url>jdbc:mysql://127.0.0.1:3306/databaseName</url>  
  54.               <user>root</user>  
  55.               <password>root</password>  
  56.             </dataSource>  
  57.         </connectionSource>  
  58.   </appender> -->  
  59. </configuration>  

一:根节点 包含的属性:

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

例如:

<configuration scan="true" scanPeriod="60 seconds" debug="false">  
      <!-- 其他配置省略-->  
</configuration>

二:根节点 的子节点:

根节点<configuration>的子节点

2.1设置上下文名称:<contextName>

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

<configuration scan="true" scanPeriod="60 seconds" debug="false">  
      <contextName>myAppName</contextName>  
      <!-- 其他配置省略-->  
</configuration>

2.2设置变量: <property>

用来定义变量值的标签,<property> 有两个属性name和value;

  • name: 变量的名称
  • value: 的值时变量定义的值。

通过<property>定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。

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

<configuration scan="true" scanPeriod="60 seconds" debug="false">  
      <property name="APP_Name" value="myAppName" />   
      <contextName>${APP_Name}</contextName>  
      <!-- 其他配置省略-->  
</configuration>

2.3获取时间戳字符串:<timestamp>

两个属性:

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

例如将解析配置文件的时间作为上下文名称:

<configuration scan="true" scanPeriod="60 seconds" debug="false">  
      <timestamp key="bySecond" datePattern="yyyyMMdd'T'HHmmss"/>   
      <contextName>${bySecond}</contextName>  
      <!-- 其他配置省略-->  
</configuration>

2.4设置loger:

<loger>

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

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

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

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

<root>

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

  • level: 用来设置打印级别,大小写无关:TRACEDEBUGINFOWARNERRORALL 和 OFF,不能设置为INHERITED或者同义词NULL。 
    默认是DEBUG。

<loger><root>可以包含零个或多个<appender-ref>元素,标识这个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

<configuration>   

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">   
    <!-- encoder 默认配置为PatternLayoutEncoder -->   
    <encoder>   
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>   
    </encoder>   
  </appender>   

  <root level="INFO">             
    <appender-ref ref="STDOUT" />   
  </root>     

</configuration>

其中appender的配置表示打印到控制台(稍后详细讲解appender ); 
<root level="INFO">将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:

<configuration>   

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">   
    <!-- encoder 默认配置为PatternLayoutEncoder -->   
    <encoder>   
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>   
    </encoder>   
  </appender>   

  <!-- logback为java中的包 -->   
  <logger name="logback"/>   

  <root level="DEBUG">             
    <appender-ref ref="STDOUT" />   
  </root>     

</configuration>

其中appender的配置表示打印到控制台(稍后详细讲解appender ); 
<logger name="logback" />将控制logback包下的所有类的日志的打印,但是并没用设置打印级别,所以继承他的上级<root>的日志级别“DEBUG”; 
没有设置addtivity,默认为true,将此loger的打印信息向上级传递; 
没有设置appender,此loger本身不打印任何信息。 
<root level="DEBUG">将root的打印级别设置为“DEBUG”,指定了名字为“STDOUT”的appender。

当执行logback.LogbackDemo类的main方法时,因为LogbackDemo 在包logback中,所以首先执行<logger name="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:

<configuration>   
   <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">   
    <!-- encoder 默认配置为PatternLayoutEncoder -->   
    <encoder>   
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>   
    </encoder>   
  </appender>   

  <!-- logback为java中的包 -->   
  <logger name="logback"/>   
  <!--logback.LogbackDemo:类的全路径 -->   
  <logger name="logback.LogbackDemo" level="INFO" additivity="false">  
    <appender-ref ref="STDOUT"/>  
  </logger>   

  <root level="ERROR">             
    <appender-ref ref="STDOUT" />   
  </root>     
</configuration>

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

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

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

<root level="DEBUG">将root的打印级别设置为“ERROR”,指定了名字为“STDOUT”的appender。

当执行logback.LogbackDemo类的main方法时,先执行<logger name="logback.LogbackDemo" level="INFO" additivity="false">,将级别为“INFO”及大于“INFO”的日志信息交给此loger指定的名为“STDOUT”的appender处理,在控制台中打出日志,不再向次loger的上级 <logger name="logback"/> 传递打印信息; 
<logger name="logback"/>未接到任何打印信息,当然也不会给它的上级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://my.oschina.net/looly/blog/298675

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值