log4jdbc源码解析(1)

        log4jdbc是用来记录数据库sql的jar包。需要与log类.jar一起使用。之前我们公司使用的是log4j。但是据说log4j有性能问题。最后我们换用了现在比较流行的logback日志框架。但是,中间需要用适配的jar包,所以组合为log4jdbc+log4j-over-slfj+logback。

一、如何配置

    数据库连接配置修改如下:

#driver需要配置为适配的log4jdbc的驱动类
dataSource.driverClass=net.sf.log4jdbc.sql.jdbcapi.DriverSpy

#jdbcUrl需要增加前面的head:jdbc\:log4
dataSource.jdbcUrl=jdbc\:log4jdbc\:jtds\:sybase\://ip\:port/db;charset\=UTF-8;appname\=appname;

    log4jdbc特有的配置-log4jdbc.log4j2.properties:

#配置真实的数据库驱动
log4jdbc.drivers=net.sourceforge.jtds.jdbc.Driver
#
log4jdbc.dump.fulldebugstacktrace=false
#配置为需要记录的包或类匹配路径
log4jdbc.debug.stack.prefix=
#sql的最大占行长度
log4jdbc.dump.sql.maxlinelength=150
#spy日志处理类
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
#warn级别的日志,时间耗时超过配置值的会打印出来
log4jdbc.sqltiming.warn.threshold=100 
    logback配置:
<appender name="jdbcfile"
		class="ch.qos.logback.core.rolling.RollingFileAppender">
		<File>${baseHome}/${appname}_jdbc_${ip}_${port}.log</File>
		<encoder>
			<pattern>%d{yyyy-MM-dd HH:mm:ss} [%-5level] [%-5thread] %logger{20} -
				%msg%n</pattern>
		</encoder>
		<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
			<level>warn</level>
		</filter>
		<append>true</append>
		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
			<fileNamePattern>${baseHome}/${appname}_jdbc_${ip}_${port}.%d{yyyy-MM-dd}(%i).log</fileNamePattern>
			<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
			     <maxFileSize>200MB</maxFileSize>
			</timeBasedFileNamingAndTriggeringPolicy>
		</rollingPolicy>
	</appender>

	<logger name="jdbc.sqltiming" level="warn" additivity="false">
		<appender-ref ref="jdbcfile" />
	</logger>
 二、源码跟踪

    首先,我们先看看代理的驱动类--net.sf.log4jdbc.sql.jdbcapi.DriverSpy

  1.为什么jdbcUrl需要增加前面的head:jdbc\:log4?

	/**
	 * A <code>String</code> representing the prefix of URL 
	 * to use log4jdbc. 
	 */
	static final private String log4jdbcUrlPrefix = "jdbc:log4";
        /**
	 * Get the actual URL that the real driver expects 
	 * (strip off <code>#log4jdbcUrlPrefix</code> from <code>url</code>).
	 * 
	 * @param url 	A <code>String</code> corresponding to a JDBC url for log4jdbc. 
	 * @return 		A <code>String</code> representing url 
	 * 				with <code>#log4jdbcUrlPrefix</code> stripped off. 
	 */
	private String getRealUrl(String url)
	{
		return url.substring(log4jdbcUrlPrefix.length());
	}
 2.log4jdbc.log4j.properties只有这几个属性吗?

 不止呢@~@

//你可以知道的远不止这些
public final class Properties 
{
	private static volatile SpyLogDelegator log;

	/**
	 * A <code>String</code> representing the name of the class implementing 
	 * <code>SpyLogDelegator</code> to use. It is used by {@link SpyLogFactory} 
	 * to determine which class to load. 
	 * Default is <code>net.sf.log4jdbc.log4j2.Log4j2SpyLogDelegator</code> 
	 * 
	 * @see SpyLogFactory
	 */
	static final String SpyLogDelegatorName;	//这里就先列一个想看的自己看看properties
   
       /**
	 * Static initializer. 
	 */
	static 
	{
        //first we init the logger
		log = null;
		
		//then we need the properties to define which logger to use
		java.util.Properties props = getProperties();
		SpyLogDelegatorName = props.getProperty("log4jdbc.spylogdelegator.name");//。。。。。
          }
          
private static java.util.Properties getProperties()
	{
		java.util.Properties props = new java.util.Properties(System.getProperties());
    	//try to get the properties file.
    	//default name is log4jdbc.log4j2.properties
    	//check first if an alternative name has been provided in the System properties
    	String propertyFile = props.getProperty("log4jdbc.log4j2.properties.file", 
    			"/log4jdbc.log4j2.properties");
		if (log != null) {
		    log.debug("Trying to use properties file " + propertyFile);
		}
    	InputStream propStream = Properties.class.getResourceAsStream(propertyFile);
    	if (propStream != null) {
    		try {
    			props.load(propStream);
    		} catch (IOException e) {
    			if (log != null) {
    			    log.debug("Error when loading log4jdbc.log4j2.properties from classpath: " + 
    			        e.getMessage());
    			}
    		} finally {
    			try {
    				propStream.close();
    			} catch (IOException e) {
    				if (log != null) {
    				    log.debug("Error when closing log4jdbc.log4j2.properties file" + 
    			            e.getMessage());
    				}
    			}
    		}
    		if (log != null) {
    		    log.debug("log4jdbc.logj2.properties loaded from classpath");
    		}
    	} else {
    		if (log != null) {
    		    log.debug("log4jdbc.logj2.properties not found in classpath. Using System properties.");
    		}
    	}
    	return props;
	}
 }
 3.是哪调用的log4jdbc的connect方法呢?

    java.sql.DriverManager的getConnection方法

                try {
                    println("    trying " + aDriver.driver.getClass().getName());
                    Connection con = aDriver.driver.connect(url, info);
                    if (con != null) {
                        // Success!
                        println("getConnection returning " + aDriver.driver.getClass().getName());
                        return (con);
                    }
                } catch (SQLException ex) {
                    if (reason == null) {
                        reason = ex;
                    }
                }
 4.什么时候记录的日志的?

 

 这些都是检测的sql_spy类:

public boolean execute(String sql, String[] columnNames) throws SQLException
	{
		String methodCall = "execute(" + sql + ", " + columnNames + ")";
		this.sql = sql;
		reportStatementSql(sql, methodCall); //这个地方开始调用Slf4jSpyLogDelegator
		long tstart = System.currentTimeMillis();
		try
		{
			boolean result = realStatement.execute(sql, columnNames);
			reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);//2
			return reportReturn(methodCall, result);//3
		}
		catch (SQLException s)
		{
			reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
			throw s;
		}
	}
 以下是打印sql的处理类,如果你想按照你的标准或是日志级别分配的话,你可以实现接口SpyLogDelegator:

 

 以上是我的全部内容。我是游走在IT届的小女子,有人问你想在IT走多远?我想说,别人能走多远,我同样能!没有终点!

   

    

 

       

猜你喜欢

转载自itwork4liu.iteye.com/blog/2344286