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

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

 
阅读更多
P6Spy使用:http://donald-draper.iteye.com/blog/2319646
P6Spy源码分析-属性文件加载:http://donald-draper.iteye.com/admin/blogs/2319851
P6Spy源码分析-Connection获取,日志打印:http://donald-draper.iteye.com/admin/blogs/2319873
使用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
再来看看P6OutageFactory的getConnection()的方法
public class P6OutageFactory extends P6CoreFactory
{   //返回P6OutageConnection
public Connection getConnection(Connection conn)
        throws SQLException
    {
        return new P6OutageConnection(this, conn);
    }
    //返回P6OutagePreparedStatement
    public PreparedStatement getPreparedStatement(PreparedStatement real, P6Connection conn, String p0)
        throws SQLException
    {
        return new P6OutagePreparedStatement(this, real, conn, p0);
    }
}

再看P6OutageConnection
public class P6OutageConnection extends P6Connection
    implements Connection
{
   //提交
    public void commit()
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
	//outagedetection=true
        if(P6OutageOptions.getOutageDetection())
	//P6OutageDetector,注册statement行为commit事件
            P6OutageDetector.getInstance().registerInvocation(this, startTime, "commit", "", "");
        try
        {
            passthru.commit();
        }
        finally
        {
            if(P6OutageOptions.getOutageDetection())
                P6OutageDetector.getInstance().unregisterInvocation(this);
        }
    }
}

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

再看P6OutagePreparedStatement
public class P6OutagePreparedStatement extends P6PreparedStatement
    implements PreparedStatement
{

    public boolean execute()
        throws SQLException
    {
        long startTime = System.currentTimeMillis();
        //outagedetection=true
        if(P6OutageOptions.getOutageDetection())
	    //将statement注册到P6OutageDetector(statement超时探测器)
            P6OutageDetector.getInstance().registerInvocation(this, startTime, "statement", preparedQuery, getQueryFromPreparedStatement());
        boolean flag;
        try
        {
            flag = prepStmtPassthru.execute();
        }
        finally
        {
	    //outagedetection=true
            if(P6OutageOptions.getOutageDetection())
	        //当statement执行完毕,将statement从P6OutageDetector(statement超时探测器)移除
                P6OutageDetector.getInstance().unregisterInvocation(this);
        }
        return flag;
    }
}

再看P6OutageOptions
//超时属性配置
//outagedetection=true
//outagedetectioninterval=5
public class P6OutageOptions extends P6Options
{
    public static boolean getOutageDetection()
    {
        return outageDetection;
    }

    public static void setOutageDetection(String _outagedetection)
    {
        outageDetection = P6Util.isTrue(_outagedetection, false);
    }

    public static long getOutageDetectionInterval()
    {
        return outageDetectionInterval;
    }

    public static long getOutageDetectionIntervalMS()
    {
        return outageMs;
    }

    public static void setOutageDetectionInterval(String _outagedetectioninterval)
    {
        outageDetectionInterval = P6Util.parseLong(_outagedetectioninterval, -1L);
        outageMs = outageDetectionInterval * 1000L;
    }

    protected static boolean outageDetection;
    protected static long outageDetectionInterval;
    protected static long outageMs;
}

再看P6OutageDetector(statement超时探测器)
//实际上是一个线程
public class P6OutageDetector
    implements Runnable
{

    protected P6OutageDetector()
    {
        pendingMessages = null;
        haltThread = false;
        pendingMessages = new Hashtable();
        P6LogQuery.logDebug("P6Spy - P6OutageDetector has been invoked.");
        P6LogQuery.logDebug("P6Spy - P6OutageOptions.getOutageDetectionIntervalMS() = " + P6OutageOptions.getOutageDetectionIntervalMS());
    }
    //单例模式获取探测器实例
    public static synchronized P6OutageDetector getInstance()
    {
        if(instance == null)
        {
            instance = new P6OutageDetector();
            ThreadGroup group = new ThreadGroup("P6SpyThreadGroup");
	    //放在后再运行
            group.setDaemon(true);
            Thread outageThread = new Thread(group, instance, "P6SpyOutageThread");
            outageThread.start();
        }
        return instance;
    }

    public void run()
    {
        while(!haltThread) 
        {
            detectOutage();
            try
            {
	        //睡眠outagedetectioninterval=5秒
                Thread.sleep(P6OutageOptions.getOutageDetectionIntervalMS());
            }
            catch(Exception e) { }
        }
    }

    public void shutdown()
    {
        haltThread = true;
    }
    //将statement注册到探测器
    public void registerInvocation(Object jdbcObject, long startTime, String category, String ps, String sql)
    {
	//pendingMessages其实是一个HashMap,private Hashtable pendingMessages;
        pendingMessages.put(jdbcObject, new InvocationInfo(startTime, category, ps, sql));
    }
    //将statement从探测器移除
    public void unregisterInvocation(Object jdbcObject)
    {
        pendingMessages.remove(jdbcObject);
    }
    //探测是否有超时的statement
    private void detectOutage()
    {
        int listSize = pendingMessages.size();
        if(listSize == 0)
            return;
        P6LogQuery.logDebug("P6Spy - detectOutage.pendingMessage.size = " + listSize);
        long currentTime = System.currentTimeMillis();
        long threshold = P6OutageOptions.getOutageDetectionIntervalMS();
        Set keys = pendingMessages.keySet();
        for(Iterator keyIter = keys.iterator(); keyIter.hasNext();)
        {
	    
            InvocationInfo ii = (InvocationInfo)pendingMessages.get(keyIter.next());
	   //判断statement是否超时
            if(ii != null && currentTime - ii.startTime > threshold)
            {
		//打印日志
                P6LogQuery.logDebug("P6Spy - statement exceeded threshold - check log.");
                logOutage(ii);
            }
        }

    }
    //打印日志
    private void logOutage(InvocationInfo ii)
    {
        P6LogQuery.logElapsed(-1, ii.startTime, "OUTAGE", ii.preparedStmt, ii.sql);
    }

    private Hashtable pendingMessages;
    private boolean haltThread;
    private static P6OutageDetector instance = null;
    private static final boolean debug = true;

}

P6LogQuery类,这里就不分析了,在前面已经说过了
总结:
通过以上的分析,相信大家对P6Spy超时探测,connection获取,日志打印有了
初步的了解,主要 点,static语句块,初始化类,利用工场模式获取connection,
单例模式获取探测器,日志的打印主要通过封装实现jdbc的statement来嵌入。
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics