- 浏览: 983923 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
P6Spy使用:http://donald-draper.iteye.com/blog/2319646
P6Spy源码分析-属性文件加载:http://donald-draper.iteye.com/admin/blogs/2319851
使用P6Spy的时候用到这一句我们来看这一句的内涵:
P6DataSource p6DSource = new P6DataSource(cpDSource)
日志线路解析:
P6DataSource,的getConnection方法通过 P6SpyDriverCore.wrapConnection(rds.getConnection())获取连接;
再来看看P6SpyDriverCore的wrapConnection的方法都做了什么事情
这一句很重要:con = factory.getConnection(con),这个factory实际上是P6LogFactory或P6OutageFactory
再来看看P6LogFactory的getConnection()的方法
再看P6Connection
再看P6LogPreparedStatement
日志打印类P6LogQuery:
P6Logger类:
P6Logger实现类:
log4j日志
标准控制输出
FormattedLogger类
总结:
通过以上的分析,相信大家对P6Spy如何属性配置,connection获取,日志打印有了初步的了解,主要点是利用static语句块,初始化属性,利用工场模式获取connection,日志的打印主要通过封装实现jdbc的statement来嵌入。
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来嵌入。
相关推荐
压缩包中的"p6spy-syj"可能是一个包含了精简版p6spy的源码和说明文档的文件。源码可以用于学习和二次开发,说明文档则能指导用户如何正确安装和使用这个工具。对于非开发人员,理解文档中的步骤和配置说明至关重要,...
p6spy-spring-boot-starter p6spy弹簧启动器说明基于p6spy的Spring Boot Starter实现玛文< dependency>< groupId>com.github.hiwepy</ groupId>< artifactId>p6spy-spring-boot-starter</ artifactId>< version>${...
**P6Spy 知识点详解** P6Spy 是一个开源的 Java 库,它专为监控和分析数据库应用的 SQL 活动...本版本的 "p6spy-maven工程源码" 提供了一个可以直接导入并运行的 Maven 项目,方便开发者快速体验和利用 P6Spy 的功能。
1. **SQL日志记录**:P6Spy 可以捕获并记录应用程序执行的所有SQL语句,包括参数和执行时间,这对于调试和性能分析非常有用。 2. **格式化输出**:P6Spy 提供了自定义的日志格式,可以按照开发者的需求定制输出信息...
1. **添加依赖**:首先,你需要将P6Spy的JAR文件(如`p6spy-2.1.0.jar`)添加到项目的类路径中。如果是Maven项目,可以在`pom.xml`中添加对应的依赖条目。 2. **配置代理驱动**:在`jdbc.properties`或类似配置文件...
具体来说,可以从SourceForge网站上找到P6Spy的官方下载页面,下载对应版本的源码压缩包p6spy-src.zip。下载完成后,将该压缩包解压,然后将解压得到的源码文件导入到MyEclipse的源码项目中。在导入源码之后,用户就...
1. **SQL日志记录**:P6Spy可以捕获并记录所有执行的SQL语句,包括原始的SQL、执行时间、返回结果等,这对于追踪数据库操作和性能分析非常有用。 2. **日志格式自定义**:P6Spy允许用户通过配置文件定制日志输出...
本文将详细探讨如何使用P6Spy来打印iBatis(现为MyBatis)执行的SQL语句,以便进行性能分析和调试。 首先,我们需要了解P6Spy的工作原理。P6Spy通过替换JDBC驱动,将自己插入到应用程序和数据库之间,监听所有的SQL...
P6spy是一个JDBC Driver的包装工具,p6spy通过对JDBC Driver的封装以达到对SQL语句的监听和分析,以达到各种目的。 p6spy的安装步骤: 1. 下载p6spy的安装包 2. 把p6spy的jar包放到Classpath中,如果是WEB App...
P6Spy的工作原理是通过代理JDBC驱动,拦截所有的SQL语句,然后在执行前后添加额外的操作,如日志记录、性能分析等。为了实现自己的SQL执行控制器,我们需要理解以下几个关键知识点: 1. **JDBC驱动代理**:JDBC驱动...
通过P6Spy,我们可以得到诸如SQL语句的原始格式、执行时间、异常信息等详细信息,这对于分析和优化数据库性能至关重要。例如,你可以找出导致高延迟的SQL语句,或者检查是否有未优化的查询。此外,P6Spy还支持自定义...
通过在WebLogic中配置P6Spy并使用SQLProfiler,我们可以获取详细的SQL执行信息,从而优化数据库性能。这个过程涉及到对WebLogic数据源的配置、P6Spy代理驱动的使用以及`spy.properties`的定制。理解这些知识点对于...
2. **格式化输出**:P6Spy可以按照自定义的格式输出SQL日志,使其更易于阅读和分析。 3. **性能监控**:通过记录SQL执行时间和其他相关信息,P6Spy可以帮助识别性能瓶颈,从而优化数据库操作。 4. **无需代码修改*...
P6Spy 是一个开源的数据库监视工具,它允许开发者在不修改应用程序代码的情况下,对数据库访问进行监听、记录和分析。P6Spy 的3.7.0版本为开发者提供了更强大的功能和改进,使得数据库性能调优变得更加便捷。 ### ...
用于分布式跟踪的库(如果在classpath中找到)可启用jdbc连接和查询跟踪(仅适用于p6spy或datasource-proxy) 为什么不将DataSource包装在配置中? 除了使用库之外,您还可以手动包装DataSource ,但是该库还提供了...
P6Spy产生的日志文件包含了详细的SQL执行信息,包括执行时间、参数等,这对于性能分析和优化非常有帮助。日志格式通常包括模块信息、时间戳、SQL语句以及执行时长等,可以通过调整配置参数来控制日志的详细程度和...
1. 性能监控:通过分析 P6Spy 的日志,可以找出执行慢的 SQL,进而优化数据库查询。 2. 问题排查:当遇到数据库相关的问题时,查看 P6Spy 的日志可以帮助定位问题所在,因为它们提供了完整的 SQL 语句及其执行上下文...
- **结合日志分析工具**:P6Spy 输出的日志可以导入到像 Logstash、Splunk 这样的日志分析工具,以获取更强大的分析功能。 - **调整日志级别**:根据需要调整 `logLevel`,在调试时使用 `DEBUG` 模式,生产环境中...
`p6spy-install.zip`包含了一些额外的安装和配置指南,可能包括了如何在不同的数据库驱动中配置P6Spy的说明。`README.txt`、`APACHE.txt`和`LICENSE.txt`文件则分别提供了软件的使用说明、Apache许可协议和版权信息...
通过 P6Spy 我们可以对 SQL 语句进行拦截,相当于一个 SQL 语句的记录器,这样我们可以用它来作相关的分析,比如性能分析。P6Spy 用 Log4J 来记录 JDBC 调用的日记信息。 自从 2003 年 11 月 30 日 P6Spy 版本 1.3 ...