`
Donald_Draper
  • 浏览: 984883 次
社区版块
存档分类
最新评论

P6Spy源码分析-Connection获取,日志打印

阅读更多
P6Spy使用:http://donald-draper.iteye.com/blog/2319646
P6Spy源码分析-属性文件加载:http://donald-draper.iteye.com/admin/blogs/2319851
使用P6Spy的时候用到这一句我们来看这一句的内涵:
P6DataSource p6DSource = new P6DataSource(cpDSource)
// p6DSource = new P6DataSource(cpDSource)
public class P6DataSource extends P6Base
    implements DataSource, Referenceable, Serializable
{
    //source是通过构造传入的数据源c3p0或Druid
    public P6DataSource(DataSource source)
    {
        rds = source;
    }
    //初始化驱动及日志模块
    public static void initMethod()
    {
        P6SpyDriverCore.initMethod((com.p6spy.engine.spy.P6SpyDriver.class).getName());
    }
    //获取Connection
     public Connection getConnection()
        throws SQLException
    {
        if(rds == null)
            bindDataSource();
        return P6SpyDriverCore.wrapConnection(rds.getConnection());
    }
    protected DataSource rds;
    protected String rdsName;
    //通过static语句块调用初始化方法
    static 
    {
        initMethod();
    }
}

日志线路解析:
P6DataSource,的getConnection方法通过 P6SpyDriverCore.wrapConnection(rds.getConnection())获取连接;
再来看看P6SpyDriverCore的wrapConnection的方法都做了什么事情
public abstract class P6SpyDriverCore
    implements Driver
{
    public static synchronized void initMethod(String spydriver)
    {
        if(initialized)
            return;
        String path = P6SpyProperties.getPropertiesPath();
        if(path == null)
        {
            foundSpyProperties = false;
            return;
        }
        foundSpyProperties = true;
	//初始化spy.properties属性文件
        P6SpyProperties properties = new P6SpyProperties();
        P6SpyOptions coreOptions = new P6SpyOptions();
        OptionReloader.add(coreOptions, properties);
        String className = "no class";
        String classType = "driver";
        try
        {
	    //realdriver
            ArrayList driverNames = null;
	    //日志模块
            ArrayList modules = null;
	    //获取驱动名
            driverNames = P6SpyOptions.allDriverNames();
	    //获取所有日志模块
            modules = P6SpyOptions.allModules();
            boolean hasModules = modules.size() > 0;
            Iterator i = null;
            classType = "driver";
            Driver realDriver;
            for(i = driverNames.iterator(); i.hasNext(); P6LogQuery.logDebug("Registered driver: " + className + ", realdriver: " + realDriver))
            {
                P6SpyDriver spy = null;
                if(hasModules)
                {
                    spy = new P6SpyDriver();
                    DriverManager.registerDriver(spy);
                }
                className = (String)i.next();
                deregister(className);
                realDriver = (Driver)P6Util.forName(className).newInstance();
                if(P6SpyOptions.getDeregisterDrivers())
		    //注册驱动realdriver=com.mysql.jdbc.Driver
                    DriverManager.registerDriver(realDriver);
                if(hasModules)
                {
                    spy.setPassthru(realDriver);
                    realDrivers.add(realDriver);
                }
            }

            if(hasModules)
            {
                factories = new ArrayList();
                classType = "factory";
                com.p6spy.engine.common.P6Options options;
                for(i = modules.iterator(); i.hasNext(); P6LogQuery.logDebug("Registered factory: " + className + " with options: " + options))
                {
                    className = (String)i.next();
		    //module.log=com.p6spy.engine.logging.P6LogFactory
                    //module.outage=com.p6spy.engine.outage.P6OutageFactory
                    P6Factory factory = (P6Factory)P6Util.forName(className).newInstance();
                    factories.add(factory);
                    options = factory.getOptions();
                    if(options != null)
                        OptionReloader.add(options, properties);
                }

            }
            initialized = true;
            for(Enumeration e = DriverManager.getDrivers(); e.hasMoreElements(); P6LogQuery.logDebug("Driver manager reporting driver registered: " + e.nextElement()));
        }
        catch(Exception e)
        {
            String err = "Error registering " + classType + "  [" + className + "]\nCaused By: " + e.toString();
            P6LogQuery.logError(err);
            throw new P6DriverNotFoundError(err);
        }
    }
//P6DataSource的getConnection方法条用P6SpyDriverCore的wrapConnection(Connection realConnection)方法
public static Connection wrapConnection(Connection realConnection)
        throws SQLException
    {
        Connection con = realConnection;
        if(factories != null)
        {
            for(Iterator it = factories.iterator(); it.hasNext();)
            {
                P6Factory factory = (P6Factory)it.next();
		//这里是重点,这里是通过P6Factory来获取连接,P6SpyDriverCore
		//在初始化initMethod已经P6LogFactory,P6OutageFactory
		//module.log=com.p6spy.engine.logging.P6LogFactory
                //module.outage=com.p6spy.engine.outage.P6OutageFactory
                con = factory.getConnection(con);
            }

        }
        return con;
    }
    protected Driver passthru;
    protected static boolean initialized = false;
    protected static ArrayList factories;
    protected static ArrayList realDrivers = new ArrayList();
    protected static boolean foundSpyProperties;
}

这一句很重要:con = factory.getConnection(con),这个factory实际上是P6LogFactory或P6OutageFactory
再来看看P6LogFactory的getConnection()的方法
public class P6LogFactory extends P6CoreFactory
{
    //返回的是P6LogConnection
    public Connection getConnection(Connection conn)
        throws SQLException
    {
        return new P6LogConnection(this, conn);
    }
    //返回的是P6LogPreparedStatement
    public PreparedStatement getPreparedStatement(PreparedStatement real, P6Connection conn, String p0)
        throws SQLException
    {
        return new P6LogPreparedStatement(this, real, conn, p0);
    }
}
再来看看P6LogConnection实现了Connection同时继承了P6Connection
public class P6LogConnection extends P6Connection
    implements Connection
{

    public P6LogConnection(P6Factory factory, Connection conn)
        throws SQLException
    {
        super(factory, conn);
    }
    //事务提交
    public void commit()
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
        try
        {
            passthru.commit();
        }
        finally
        {
            P6LogQuery.logElapsed(getId(), startTime, "commit", "", "");
        }
    }
   //事务回滚
    public void rollback()
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
        try
        {
            passthru.rollback();
        }
        finally
        {
            P6LogQuery.logElapsed(getId(), startTime, "rollback", "", "");
        }
    }
   //回滚的指定点
    public void rollback(Savepoint p0)
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
        try
        {
            passthru.rollback(p0);
        }
        finally
        {
            P6LogQuery.logElapsed(getId(), startTime, "rollback", "", "");
        }
    }
}

再看P6Connection
public class P6Connection extends P6Base
    implements Connection
{
   获取预编译Statement,看到这是不是很熟悉的JDBC的Connection.prepareStatement(String sql)
public PreparedStatement prepareStatement(String p0)
        throws SQLException
    {
        这里条用的实际就是P6LogFactory的getPreparedStatement的方法
        return getP6Factory().getPreparedStatement(passthru.prepareStatement(p0), this, p0);
    }
}
再看P6LogFactory的getPreparedStatement方法
public class P6LogFactory extends P6CoreFactory
{
    //返回的是P6LogPreparedStatement
    public PreparedStatement getPreparedStatement(PreparedStatement real, P6Connection conn, String p0)
        throws SQLException
    {
        return new P6LogPreparedStatement(this, real, conn, p0);
    }
}

再看P6LogPreparedStatement
public class P6LogPreparedStatement extends P6PreparedStatement
    implements PreparedStatement
{

    public P6LogPreparedStatement(P6Factory factory, PreparedStatement statement, P6Connection conn, String query)
    {
        super(factory, statement, conn, query);
    }
    //插入
     public boolean execute()
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
        boolean flag;
        try
        {
            flag = prepStmtPassthru.execute();
        }
        finally
        {   
	    //打印日志
            P6LogQuery.logElapsed(connection.getId(), startTime, "statement", preparedQuery, getQueryFromPreparedStatement());
        }
        return flag;
    }
    //查询
    public ResultSet executeQuery()
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
        ResultSet resultset;
        try
        {
            resultset = getP6Factory().getResultSet(prepStmtPassthru.executeQuery(), this, preparedQuery, getQueryFromPreparedStatement());
        }
        finally
        {
	    //打印日志
            P6LogQuery.logElapsed(connection.getId(), startTime, "statement", preparedQuery, getQueryFromPreparedStatement());
        }
        return resultset;
    }
    //更新
    public int executeUpdate()
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
        int i;
        try
        {
            i = prepStmtPassthru.executeUpdate();
        }
        finally
        {
	    //打印日志
            P6LogQuery.logElapsed(connection.getId(), startTime, "statement", preparedQuery, getQueryFromPreparedStatement());
        }
        return i;
    }

日志打印类P6LogQuery:
public class P6LogQuery
{
    public static synchronized void initMethod()
    {
        //日志appender信息
        String appender = P6SpyOptions.getAppender();
        if(appender == null)
            appender = "com.p6spy.engine.logging.appender.FileLogger";
        try
        {
            logger = (P6Logger)P6Util.forName(appender).newInstance();
        }
        catch(Exception e1)
        {
            try
            {
                ClassLoader loader = ClassLoader.getSystemClassLoader();
                logger = (P6Logger)loader.loadClass(appender).newInstance();
            }
            catch(Exception e)
            {
                System.err.println("Cannot instantiate " + appender + ", even on second attempt.  Logging to file log4jaux.log: " + e);
            }
        }
        if(logger != null && (logger instanceof FileLogger))
        {
            String logfile = P6SpyOptions.getLogfile();
            logfile = logfile != null ? logfile : "spy.log";
            ((FileLogger)logger).setLogfile(logfile);
        }
        if(P6SpyOptions.getFilter())
        {
            includeTables = parseCSVList(P6SpyOptions.getInclude());
            excludeTables = parseCSVList(P6SpyOptions.getExclude());
        }
        includeCategories = parseCSVList(P6SpyOptions.getIncludecategories());
        excludeCategories = parseCSVList(P6SpyOptions.getExcludecategories());
    }
    //打印log
 public static void logElapsed(int connectionId, long startTime, String category, String prepared, String sql)
    {
        logElapsed(connectionId, startTime, System.currentTimeMillis(), category, prepared, sql);
    }

    public static void logElapsed(int connectionId, long startTime, long endTime, String category, String prepared, String sql)
    {
        if(logger != null && meetsThresholdRequirement(endTime - startTime) && isLoggable(sql) && isCategoryOk(category))
            doLogElapsed(connectionId, startTime, endTime, category, prepared, sql);
        else
        if(isDebugOn())
            logDebug("P6Spy intentionally did not log category: " + category + ", statement: " + sql + "  Reason: logger=" + logger + ", isLoggable=" + isLoggable(sql) + ", isCategoryOk=" + isCategoryOk(category));
    }
    protected static void doLogElapsed(int connectionId, long startTime, long endTime, String category, String prepared, String sql)
    {
        doLog(connectionId, endTime - startTime, category, prepared, sql);
    }
    //打印log
    protected static synchronized void doLog(int connectionId, long elapsed, String category, String prepared, String sql)
    {
        if(logger != null)
        {
            Date now = P6Util.timeNow();
            SimpleDateFormat sdf = P6SpyOptions.getDateformatter();
            String stringNow;
            if(sdf == null)
                stringNow = Long.toString(now.getTime());
            else
                stringNow = sdf.format(new Date(now.getTime())).trim();
            logger.logSQL(connectionId, stringNow, elapsed, category, prepared, sql);
            boolean stackTrace = P6SpyOptions.getStackTrace();
            String stackTraceClass = P6SpyOptions.getStackTraceClass();
            if(stackTrace)
            {
                Exception e = new Exception();
                if(stackTraceClass != null)
                {
                    StringWriter sw = new StringWriter();
                    PrintWriter pw = new PrintWriter(sw);
                    e.printStackTrace(pw);
                    String stack = sw.toString();
                    if(stack.indexOf(stackTraceClass) != -1)
                        lastStack = stack;
                    else
                        e = null;
                }
                if(e != null)
                    logger.logException(e);
            }
        }
    }
public static void logInfo(String sql)
    {
        if(logger != null && isCategoryOk("info"))
            doLog(-1L, "info", "", sql);
    }

    public static boolean isDebugOn()
    {
        return isCategoryOk("debug");
    }

    public static void logDebug(String sql)
    {
        if(isDebugOn())
            if(logger != null)
                doLog(-1L, "debug", "", sql);
            else
                System.err.println(sql);
    }

    public static void logError(String sql)
    {
        System.err.println("Warning: " + sql);
        if(logger != null)
            doLog(-1L, "error", "", sql);
    }

    protected static PrintStream qlog;
    protected static String includeTables[];
    protected static String excludeTables[];
    protected static String includeCategories[];
    protected static String excludeCategories[];
    protected static String lastStack;
    //log打印类
    protected static P6Logger logger;
   //通过静态语句块调用出事化方法
    static 
    {
        initMethod();
    }
}

P6Logger类:

public interface P6Logger
{

    public abstract void logSQL(int i, String s, long l, String s1, String s2, String s3);

    public abstract void logException(Exception exception);

    public abstract void logText(String s);

    public abstract String getLastEntry();
}

P6Logger实现类:
log4j日志
public class Log4jLogger extends FormattedLogger
    implements P6Logger
{

    public Log4jLogger()
    {
        level = Level.INFO;
        P6SpyProperties properties = new P6SpyProperties();
        PropertyConfigurator.configure(properties.forceReadProperties());
        log = Logger.getLogger("p6spy");
        log.setAdditivity(false);
    }
    public void logException(Exception e)
    {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        logText(sw.toString());
    }

    public void logText(String text)
    {
        log.log(level, text);
        setLastEntry(text);
    }

    public Level getLevel()
    {
        return level;
    }

    public void setLevel(Level inVar)
    {
        level = inVar;
    }

    protected Level level;
    protected String lastEntry;
    private static Logger log;
}

标准控制输出
public class StdoutLogger extends FormattedLogger
    implements P6Logger
{

    public StdoutLogger()
    {
        qlog = System.out;
    }

    public void logException(Exception e)
    {
        e.printStackTrace(qlog);
    }

    public void logText(String text)
    {
        qlog.println(text);
        setLastEntry(text);
    }

    protected PrintStream qlog;
}

FormattedLogger类
public abstract class FormattedLogger
{

    public FormattedLogger()
    {
    }
    //日志打印
    public void logSQL(int connectionId, String now, long elapsed, String category, String prepared, String sql)
    {
        String logEntry = now + "|" + elapsed + "|" + (connectionId != -1 ? String.valueOf(connectionId) : "") + "|" + category + "|" + prepared + "|" + sql;
        logText(logEntry);
    }

    public abstract void logText(String s);

    public void setLastEntry(String inVar)
    {
        lastEntry = inVar;
    }

    public String getLastEntry()
    {
        return lastEntry;
    }

    protected String lastEntry;
}

总结:
通过以上的分析,相信大家对P6Spy如何属性配置,connection获取,日志打印有了初步的了解,主要点是利用static语句块,初始化属性,利用工场模式获取connection,日志的打印主要通过封装实现jdbc的statement来嵌入。
0
0
分享到:
评论

相关推荐

    p6spy精简版-跟踪sql工具

    压缩包中的"p6spy-syj"可能是一个包含了精简版p6spy的源码和说明文档的文件。源码可以用于学习和二次开发,说明文档则能指导用户如何正确安装和使用这个工具。对于非开发人员,理解文档中的步骤和配置说明至关重要,...

    p6spy-spring-boot-starter:弹簧启动启动器p6spy

    p6spy-spring-boot-starter p6spy弹簧启动器说明基于p6spy的Spring Boot Starter实现玛文< dependency>< groupId>com.github.hiwepy</ groupId>< artifactId>p6spy-spring-boot-starter</ artifactId>< version>${...

    p6spy的maven工程源码

    **P6Spy 知识点详解** P6Spy 是一个开源的 Java 库,它专为监控和分析数据库应用的 SQL 活动...本版本的 "p6spy-maven工程源码" 提供了一个可以直接导入并运行的 Maven 项目,方便开发者快速体验和利用 P6Spy 的功能。

    下载 p6spy.jar (内含使用步骤)

    1. **SQL日志记录**:P6Spy 可以捕获并记录应用程序执行的所有SQL语句,包括参数和执行时间,这对于调试和性能分析非常有用。 2. **格式化输出**:P6Spy 提供了自定义的日志格式,可以按照开发者的需求定制输出信息...

    数据插入监控 p6spy

    1. **添加依赖**:首先,你需要将P6Spy的JAR文件(如`p6spy-2.1.0.jar`)添加到项目的类路径中。如果是Maven项目,可以在`pom.xml`中添加对应的依赖条目。 2. **配置代理驱动**:在`jdbc.properties`或类似配置文件...

    myeclipse配置p6spy以及导入源码

    具体来说,可以从SourceForge网站上找到P6Spy的官方下载页面,下载对应版本的源码压缩包p6spy-src.zip。下载完成后,将该压缩包解压,然后将解压得到的源码文件导入到MyEclipse的源码项目中。在导入源码之后,用户就...

    p6spy-sql监控

    1. **SQL日志记录**:P6Spy可以捕获并记录所有执行的SQL语句,包括原始的SQL、执行时间、返回结果等,这对于追踪数据库操作和性能分析非常有用。 2. **日志格式自定义**:P6Spy允许用户通过配置文件定制日志输出...

    使用P6spy打印ibatis执行的SQL语句

    本文将详细探讨如何使用P6Spy来打印iBatis(现为MyBatis)执行的SQL语句,以便进行性能分析和调试。 首先,我们需要了解P6Spy的工作原理。P6Spy通过替换JDBC驱动,将自己插入到应用程序和数据库之间,监听所有的SQL...

    P6SPY JDBC拦截打印sql语句 非常好的调试工具

    P6spy是一个JDBC Driver的包装工具,p6spy通过对JDBC Driver的封装以达到对SQL语句的监听和分析,以达到各种目的。 p6spy的安装步骤: 1. 下载p6spy的安装包 2. 把p6spy的jar包放到Classpath中,如果是WEB App...

    借鉴p6spy,实现自己的SQL执行监控器项目源代码

    P6Spy的工作原理是通过代理JDBC驱动,拦截所有的SQL语句,然后在执行前后添加额外的操作,如日志记录、性能分析等。为了实现自己的SQL执行控制器,我们需要理解以下几个关键知识点: 1. **JDBC驱动代理**:JDBC驱动...

    采用p6spy完整显示hibernate的SQL语句

    通过P6Spy,我们可以得到诸如SQL语句的原始格式、执行时间、异常信息等详细信息,这对于分析和优化数据库性能至关重要。例如,你可以找出导致高延迟的SQL语句,或者检查是否有未优化的查询。此外,P6Spy还支持自定义...

    p6spy 在weblogic中的配置 以及使用sqlprofiler监控

    通过在WebLogic中配置P6Spy并使用SQLProfiler,我们可以获取详细的SQL执行信息,从而优化数据库性能。这个过程涉及到对WebLogic数据源的配置、P6Spy代理驱动的使用以及`spy.properties`的定制。理解这些知识点对于...

    p6spy简介显示hibernate配置

    2. **格式化输出**:P6Spy可以按照自定义的格式输出SQL日志,使其更易于阅读和分析。 3. **性能监控**:通过记录SQL执行时间和其他相关信息,P6Spy可以帮助识别性能瓶颈,从而优化数据库操作。 4. **无需代码修改*...

    p6spy-3.7.0.zip

    P6Spy 是一个开源的数据库监视工具,它允许开发者在不修改应用程序代码的情况下,对数据库访问进行监听、记录和分析。P6Spy 的3.7.0版本为开发者提供了更强大的功能和改进,使得数据库性能调优变得更加便捷。 ### ...

    spring-boot-data-source-decorator:与p6spy,datasource-proxy,flexy-pool和spring-cloud-sleuth集成的Spring Boot

    用于分布式跟踪的库(如果在classpath中找到)可启用jdbc连接和查询跟踪(仅适用于p6spy或datasource-proxy) 为什么不将DataSource包装在配置中? 除了使用库之外,您还可以手动包装DataSource ,但是该库还提供了...

    p6spy使用说明.doc

    P6Spy产生的日志文件包含了详细的SQL执行信息,包括执行时间、参数等,这对于性能分析和优化非常有帮助。日志格式通常包括模块信息、时间戳、SQL语句以及执行时长等,可以通过调整配置参数来控制日志的详细程度和...

    p6spy java 使用

    1. 性能监控:通过分析 P6Spy 的日志,可以找出执行慢的 SQL,进而优化数据库查询。 2. 问题排查:当遇到数据库相关的问题时,查看 P6Spy 的日志可以帮助定位问题所在,因为它们提供了完整的 SQL 语句及其执行上下文...

    p6spy install

    - **结合日志分析工具**:P6Spy 输出的日志可以导入到像 Logstash、Splunk 这样的日志分析工具,以获取更强大的分析功能。 - **调整日志级别**:根据需要调整 `logLevel`,在调试时使用 `DEBUG` 模式,生产环境中...

    p6spy_sqlprofiler-0.3-bin.zip

    `p6spy-install.zip`包含了一些额外的安装和配置指南,可能包括了如何在不同的数据库驱动中配置P6Spy的说明。`README.txt`、`APACHE.txt`和`LICENSE.txt`文件则分别提供了软件的使用说明、Apache许可协议和版权信息...

    P6Spy 提供数据库性能监控和剖析工具

    通过 P6Spy 我们可以对 SQL 语句进行拦截,相当于一个 SQL 语句的记录器,这样我们可以用它来作相关的分析,比如性能分析。P6Spy 用 Log4J 来记录 JDBC 调用的日记信息。 自从 2003 年 11 月 30 日 P6Spy 版本 1.3 ...

Global site tag (gtag.js) - Google Analytics