From 3f92ed5a07bef633de08ee82448fed5f4e1c0aaa Mon Sep 17 00:00:00 2001 From: Xylus Date: Thu, 26 Feb 2015 15:39:27 +0900 Subject: [PATCH 1/2] added API to check if a class exists in a given class loader's path --- .../bootstrap/instrument/ByteCodeInstrumentor.java | 2 ++ .../interceptor/bci/JavaAssistByteCodeInstrumentor.java | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/ByteCodeInstrumentor.java b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/ByteCodeInstrumentor.java index f3cbea0eb..32df40b1b 100644 --- a/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/ByteCodeInstrumentor.java +++ b/bootstrap/src/main/java/com/navercorp/pinpoint/bootstrap/instrument/ByteCodeInstrumentor.java @@ -26,6 +26,8 @@ import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; public interface ByteCodeInstrumentor { InstrumentClass getClass(ClassLoader classLoader, String jvmClassName, byte[] classFileBuffer) throws InstrumentException; + + boolean findClass(ClassLoader classLoader, String javassistClassName); Scope getScope(String scopeName); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java index 3d1e20337..6d85919fb 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/interceptor/bci/JavaAssistByteCodeInstrumentor.java @@ -30,8 +30,8 @@ import com.navercorp.pinpoint.bootstrap.interceptor.TargetClassLoader; import com.navercorp.pinpoint.profiler.interceptor.GlobalInterceptorRegistryBinder; import com.navercorp.pinpoint.profiler.interceptor.InterceptorRegistryBinder; import com.navercorp.pinpoint.profiler.util.ScopePool; - import com.navercorp.pinpoint.profiler.util.ThreadLocalScopePool; + import javassist.*; import org.slf4j.Logger; @@ -262,6 +262,12 @@ public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor { return true; } + @Override + public boolean findClass(ClassLoader classLoader, String javassistClassName) { + ClassPool classPool = findClassPool(classLoader); + return findClass(javassistClassName, classPool); + } + @Override public Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN) throws InstrumentException { Class aClass = this.defineClass(classLoader, interceptorFQCN, protectedDomain); From 882a810db12a1959eb6147cf68f860cc1e9edc74 Mon Sep 17 00:00:00 2001 From: Xylus Date: Thu, 26 Feb 2015 15:41:10 +0900 Subject: [PATCH 2/2] added support for older Oracle JDBC drivers (10.x) - fixes #193 --- .../modifier/AbstractModifierDelegate.java | 32 ++++++ .../modifier/DefaultModifierRegistry.java | 18 +-- .../profiler/modifier/ModifierDelegate.java | 24 ++++ .../PreparedStatementCreateInterceptor.java | 7 +- .../db/oracle/OracleClassConstants.java | 32 ++++++ .../OraclePreparedStatementModifier.java | 55 +++++++++ ...aclePreparedStatementModifierDelegate.java | 106 ++++++++++++++++++ ...raclePreparedStatementWrapperModifier.java | 82 ++------------ .../db/oracle/OracleStatementModifier.java | 55 +++++++++ .../OracleStatementModifierDelegate.java | 78 +++++++++++++ .../OracleStatementWrapperModifier.java | 55 ++------- 11 files changed, 413 insertions(+), 131 deletions(-) create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/AbstractModifierDelegate.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/ModifierDelegate.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleClassConstants.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifierDelegate.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifier.java create mode 100644 profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifierDelegate.java diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/AbstractModifierDelegate.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/AbstractModifierDelegate.java new file mode 100644 index 000000000..0c1816951 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/AbstractModifierDelegate.java @@ -0,0 +1,32 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.profiler.modifier; + +import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; + +/** + * @author HyunGil Jeong + */ +public abstract class AbstractModifierDelegate implements ModifierDelegate { + + protected final ByteCodeInstrumentor byteCodeInstrumentor; + + public AbstractModifierDelegate(ByteCodeInstrumentor byteCodeInstrumentor) { + this.byteCodeInstrumentor = byteCodeInstrumentor; + } + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java index 618eeb7f4..fe6527dd3 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/DefaultModifierRegistry.java @@ -61,7 +61,9 @@ import com.navercorp.pinpoint.profiler.modifier.db.mysql.MySQLPreparedStatementJ import com.navercorp.pinpoint.profiler.modifier.db.mysql.MySQLPreparedStatementModifier; import com.navercorp.pinpoint.profiler.modifier.db.mysql.MySQLStatementModifier; import com.navercorp.pinpoint.profiler.modifier.db.oracle.OracleDriverModifier; +import com.navercorp.pinpoint.profiler.modifier.db.oracle.OraclePreparedStatementModifier; import com.navercorp.pinpoint.profiler.modifier.db.oracle.OraclePreparedStatementWrapperModifier; +import com.navercorp.pinpoint.profiler.modifier.db.oracle.OracleStatementModifier; import com.navercorp.pinpoint.profiler.modifier.db.oracle.OracleStatementWrapperModifier; import com.navercorp.pinpoint.profiler.modifier.db.oracle.PhysicalConnectionModifier; import com.navercorp.pinpoint.profiler.modifier.method.MethodModifier; @@ -75,15 +77,9 @@ import com.navercorp.pinpoint.profiler.modifier.redis.JedisModifier; import com.navercorp.pinpoint.profiler.modifier.redis.JedisMultiKeyPipelineBaseModifier; import com.navercorp.pinpoint.profiler.modifier.redis.JedisPipelineBaseModifier; import com.navercorp.pinpoint.profiler.modifier.redis.JedisPipelineModifier; -import com.navercorp.pinpoint.profiler.modifier.servlet.HttpServletModifier; import com.navercorp.pinpoint.profiler.modifier.servlet.SpringFrameworkServletModifier; import com.navercorp.pinpoint.profiler.modifier.spring.beans.AbstractAutowireCapableBeanFactoryModifier; import com.navercorp.pinpoint.profiler.modifier.spring.orm.ibatis.SqlMapClientTemplateModifier; -import com.navercorp.pinpoint.profiler.modifier.tomcat.RequestFacadeModifier; -import com.navercorp.pinpoint.profiler.modifier.tomcat.StandardHostValveInvokeModifier; -import com.navercorp.pinpoint.profiler.modifier.tomcat.StandardServiceModifier; -import com.navercorp.pinpoint.profiler.modifier.tomcat.TomcatConnectorModifier; -import com.navercorp.pinpoint.profiler.modifier.tomcat.WebappLoaderModifier; /** * @author emeroad @@ -321,11 +317,15 @@ public class DefaultModifierRegistry implements ModifierRegistry { AbstractModifier oracleConnectionModifier = new PhysicalConnectionModifier(byteCodeInstrumentor, agent); addModifier(oracleConnectionModifier); - AbstractModifier oraclePreparedStatementModifier = new OraclePreparedStatementWrapperModifier(byteCodeInstrumentor, agent); + AbstractModifier oraclePreparedStatementWrapperModifier = new OraclePreparedStatementWrapperModifier(byteCodeInstrumentor, agent); + addModifier(oraclePreparedStatementWrapperModifier); + AbstractModifier oraclePreparedStatementModifier = new OraclePreparedStatementModifier(byteCodeInstrumentor, agent); addModifier(oraclePreparedStatementModifier); - AbstractModifier oracleStatement = new OracleStatementWrapperModifier(byteCodeInstrumentor, agent); - addModifier(oracleStatement); + AbstractModifier oracleStatementWrapperModifier = new OracleStatementWrapperModifier(byteCodeInstrumentor, agent); + addModifier(oracleStatementWrapperModifier); + AbstractModifier oracleStatementModifier = new OracleStatementModifier(byteCodeInstrumentor, agent); + addModifier(oracleStatementModifier); // // Modifier oracleResultSetModifier = new OracleResultSetModifier(byteCodeInstrumentor, agent); // addModifier(oracleResultSetModifier); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/ModifierDelegate.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/ModifierDelegate.java new file mode 100644 index 000000000..1b4fd5992 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/ModifierDelegate.java @@ -0,0 +1,24 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.profiler.modifier; + +/** + * @author HyunGil Jeong + */ +public interface ModifierDelegate extends Modifier { + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/interceptor/PreparedStatementCreateInterceptor.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/interceptor/PreparedStatementCreateInterceptor.java index d46a6379d..da450fb07 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/interceptor/PreparedStatementCreateInterceptor.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/interceptor/PreparedStatementCreateInterceptor.java @@ -76,9 +76,10 @@ public class PreparedStatementCreateInterceptor extends SpanEventSimpleAroundInt @Override public void doInAfterTrace(RecordableTrace trace, Object target, Object[] args, Object result, Throwable throwable) { - - ParsingResult parsingResult = ((ParsingResultTraceValue) result)._$PINPOINT$_getTraceParsingResult(); - trace.recordSqlParsingResult(parsingResult); + if (result instanceof ParsingResultTraceValue) { + ParsingResult parsingResult = ((ParsingResultTraceValue) result)._$PINPOINT$_getTraceParsingResult(); + trace.recordSqlParsingResult(parsingResult); + } trace.recordException(throwable); trace.recordApi(getMethodDescriptor()); diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleClassConstants.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleClassConstants.java new file mode 100644 index 000000000..ca3d5dff9 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleClassConstants.java @@ -0,0 +1,32 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.profiler.modifier.db.oracle; + +/** + * @author HyunGil Jeong + */ +public class OracleClassConstants { + + private OracleClassConstants() {} + + public static final String ORACLE_STATEMENT = "oracle/jdbc/driver/OracleStatement"; + public static final String ORACLE_STATEMENT_WRAPPER = "oracle/jdbc/driver/OracleStatementWrapper"; + + public static final String ORACLE_PREPARED_STATEMENT = "oracle/jdbc/driver/OraclePreparedStatement"; + public static final String ORACLE_PREPARED_STATEMENT_WRAPPER = "oracle/jdbc/driver/OraclePreparedStatementWrapper"; + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java new file mode 100644 index 000000000..47506daf0 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifier.java @@ -0,0 +1,55 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.profiler.modifier.db.oracle; + +import java.security.ProtectionDomain; + +import com.navercorp.pinpoint.bootstrap.Agent; +import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; +import com.navercorp.pinpoint.profiler.modifier.AbstractModifier; +import com.navercorp.pinpoint.profiler.modifier.ModifierDelegate; + +/** + * For ojdbc library without OraclePreparedStatementWrapper. + * eg. ojdbc-10.0.x + * + * @author HyunGil Jeong + */ +public class OraclePreparedStatementModifier extends AbstractModifier { + + private final ModifierDelegate delegate; + + public OraclePreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + this.delegate = new OraclePreparedStatementModifierDelegate(byteCodeInstrumentor); + } + + @Override + public String getTargetClass() { + return OracleClassConstants.ORACLE_PREPARED_STATEMENT; + } + + @Override + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + // Do not modify if wrapper exists + if (byteCodeInstrumentor.findClass(classLoader, OracleClassConstants.ORACLE_PREPARED_STATEMENT_WRAPPER)) { + return null; + } + return this.delegate.modify(classLoader, javassistClassName, protectedDomain, classFileBuffer); + } + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifierDelegate.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifierDelegate.java new file mode 100644 index 000000000..a5d8307bc --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementModifierDelegate.java @@ -0,0 +1,106 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.profiler.modifier.db.oracle; + +import java.lang.reflect.Method; +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; +import com.navercorp.pinpoint.bootstrap.instrument.NotFoundInstrumentException; +import com.navercorp.pinpoint.bootstrap.instrument.Scope; +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; +import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.BindValueTraceValue; +import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValue; +import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.ParsingResultTraceValue; +import com.navercorp.pinpoint.profiler.interceptor.ScopeDelegateStaticInterceptor; +import com.navercorp.pinpoint.profiler.modifier.AbstractModifierDelegate; +import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementBindVariableInterceptor; +import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementExecuteQueryInterceptor; +import com.navercorp.pinpoint.profiler.util.JavaAssistUtils; +import com.navercorp.pinpoint.profiler.util.PreparedStatementUtils; + +/** + * @author HyunGil Jeong + */ +public class OraclePreparedStatementModifierDelegate extends AbstractModifierDelegate { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + public OraclePreparedStatementModifierDelegate(ByteCodeInstrumentor byteCodeInstrumentor) { + super(byteCodeInstrumentor); + } + + @Override + public byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isInfoEnabled()) { + logger.info("Modifying. {}", className); + } + try { + InstrumentClass preparedStatement = byteCodeInstrumentor.getClass(classLoader, className, classFileBuffer); + + Interceptor execute = new PreparedStatementExecuteQueryInterceptor(); + preparedStatement.addScopeInterceptor("execute", null, execute, OracleScope.SCOPE_NAME); + Interceptor executeQuery = new PreparedStatementExecuteQueryInterceptor(); + preparedStatement.addScopeInterceptor("executeQuery", null, executeQuery, OracleScope.SCOPE_NAME); + Interceptor executeUpdate = new PreparedStatementExecuteQueryInterceptor(); + preparedStatement.addScopeInterceptor("executeUpdate", null, executeUpdate, OracleScope.SCOPE_NAME); + + preparedStatement.addTraceValue(DatabaseInfoTraceValue.class); + preparedStatement.addTraceValue(ParsingResultTraceValue.class); + preparedStatement.addTraceValue(BindValueTraceValue.class, "new java.util.HashMap();"); + bindVariableIntercept(preparedStatement, classLoader, protectedDomain); + + return preparedStatement.toBytecode(); + } catch (InstrumentException e) { + if (logger.isWarnEnabled()) { + logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e); + } + return null; + } + } + + private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException { + List bindMethod = PreparedStatementUtils.findBindVariableSetMethod(); + final Scope scope = byteCodeInstrumentor.getScope(OracleScope.SCOPE_NAME); + Interceptor interceptor = new ScopeDelegateStaticInterceptor(new PreparedStatementBindVariableInterceptor(), scope); + int interceptorId = -1; + for (Method method : bindMethod) { + String methodName = method.getName(); + String[] parameterType = JavaAssistUtils.getParameterType(method.getParameterTypes()); + try { + if (interceptorId == -1) { + interceptorId = preparedStatement.addInterceptor(methodName, parameterType, interceptor); + } else { + preparedStatement.reuseInterceptor(methodName, parameterType, interceptorId); + } + } catch (NotFoundInstrumentException e) { + // Cannot find bind variable setter method. This is not an error. logging will be enough. + if (logger.isDebugEnabled()) { + logger.debug("bindVariable api not found. method:{} param:{} Cause:{}", methodName, Arrays.toString(parameterType), e.getMessage()); + } + } + } + } + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementWrapperModifier.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementWrapperModifier.java index 37a8f2392..7e2f538bc 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementWrapperModifier.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OraclePreparedStatementWrapperModifier.java @@ -16,96 +16,32 @@ package com.navercorp.pinpoint.profiler.modifier.db.oracle; +import java.security.ProtectionDomain; + import com.navercorp.pinpoint.bootstrap.Agent; import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; -import com.navercorp.pinpoint.bootstrap.instrument.NotFoundInstrumentException; -import com.navercorp.pinpoint.bootstrap.instrument.Scope; -import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; -import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.BindValueTraceValue; -import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValue; -import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.ParsingResultTraceValue; -import com.navercorp.pinpoint.profiler.interceptor.ScopeDelegateStaticInterceptor; import com.navercorp.pinpoint.profiler.modifier.AbstractModifier; -import com.navercorp.pinpoint.profiler.modifier.db.interceptor.*; -import com.navercorp.pinpoint.profiler.util.JavaAssistUtils; -import com.navercorp.pinpoint.profiler.util.PreparedStatementUtils; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.Method; -import java.security.ProtectionDomain; -import java.util.Arrays; -import java.util.List; +import com.navercorp.pinpoint.profiler.modifier.ModifierDelegate; /** * @author emeroad */ public class OraclePreparedStatementWrapperModifier extends AbstractModifier { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final ModifierDelegate delegate; public OraclePreparedStatementWrapperModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { super(byteCodeInstrumentor, agent); + this.delegate = new OraclePreparedStatementModifierDelegate(byteCodeInstrumentor); } public String getTargetClass() { - return "oracle/jdbc/driver/OraclePreparedStatementWrapper"; + return OracleClassConstants.ORACLE_PREPARED_STATEMENT_WRAPPER; } + @Override public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isInfoEnabled()) { - logger.info("Modifing. {}", javassistClassName); - } - - try { - InstrumentClass preparedStatement = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer); - - Interceptor execute = new PreparedStatementExecuteQueryInterceptor(); - preparedStatement.addScopeInterceptor("execute", null, execute, OracleScope.SCOPE_NAME); - Interceptor executeQuery = new PreparedStatementExecuteQueryInterceptor(); - preparedStatement.addScopeInterceptor("executeQuery", null, executeQuery, OracleScope.SCOPE_NAME); - Interceptor executeUpdate = new PreparedStatementExecuteQueryInterceptor(); - preparedStatement.addScopeInterceptor("executeUpdate", null, executeUpdate, OracleScope.SCOPE_NAME); - - preparedStatement.addTraceValue(DatabaseInfoTraceValue.class); - preparedStatement.addTraceValue(ParsingResultTraceValue.class); - preparedStatement.addTraceValue(BindValueTraceValue.class, "new java.util.HashMap();"); - bindVariableIntercept(preparedStatement, classLoader, protectedDomain); - - return preparedStatement.toBytecode(); - } catch (InstrumentException e) { - if (logger.isWarnEnabled()) { - logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e); - } - return null; - } - - } - - private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException { - List bindMethod = PreparedStatementUtils.findBindVariableSetMethod(); - final Scope scope = byteCodeInstrumentor.getScope(OracleScope.SCOPE_NAME); - Interceptor interceptor = new ScopeDelegateStaticInterceptor(new PreparedStatementBindVariableInterceptor(), scope); - int interceptorId = -1; - for (Method method : bindMethod) { - String methodName = method.getName(); - String[] parameterType = JavaAssistUtils.getParameterType(method.getParameterTypes()); - try { - if (interceptorId == -1) { - interceptorId = preparedStatement.addInterceptor(methodName, parameterType, interceptor); - } else { - preparedStatement.reuseInterceptor(methodName, parameterType, interceptorId); - } - } catch (NotFoundInstrumentException e) { - // Cannot find bind variable setter method. This is not an error. logging will be enough. - if (logger.isDebugEnabled()) { - logger.debug("bindVariable api not found. method:{} param:{} Cause:{}", methodName, Arrays.toString(parameterType), e.getMessage()); - } - } - } - + return this.delegate.modify(classLoader, javassistClassName, protectedDomain, classFileBuffer); } } diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifier.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifier.java new file mode 100644 index 000000000..398acba97 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifier.java @@ -0,0 +1,55 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.profiler.modifier.db.oracle; + +import java.security.ProtectionDomain; + +import com.navercorp.pinpoint.bootstrap.Agent; +import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; +import com.navercorp.pinpoint.profiler.modifier.AbstractModifier; +import com.navercorp.pinpoint.profiler.modifier.ModifierDelegate; + +/** + * For ojdbc library without OracleStatementWrapper. + * eg. ojdbc-10.0.x + * + * @author HyunGil Jeong + */ +public class OracleStatementModifier extends AbstractModifier { + + private final ModifierDelegate delegate; + + public OracleStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { + super(byteCodeInstrumentor, agent); + this.delegate = new OracleStatementModifierDelegate(byteCodeInstrumentor); + } + + @Override + public String getTargetClass() { + return OracleClassConstants.ORACLE_STATEMENT; + } + + @Override + public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + // Do not modify if wrapper exists + if (byteCodeInstrumentor.findClass(classLoader, OracleClassConstants.ORACLE_STATEMENT_WRAPPER)) { + return null; + } + return this.delegate.modify(classLoader, javassistClassName, protectedDomain, classFileBuffer); + } + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifierDelegate.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifierDelegate.java new file mode 100644 index 000000000..9d6e71cf3 --- /dev/null +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementModifierDelegate.java @@ -0,0 +1,78 @@ +/* + * Copyright 2015 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.profiler.modifier.db.oracle; + +import java.security.ProtectionDomain; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; +import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; +import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValue; +import com.navercorp.pinpoint.profiler.modifier.AbstractModifierDelegate; +import com.navercorp.pinpoint.profiler.modifier.db.interceptor.StatementExecuteQueryInterceptor; +import com.navercorp.pinpoint.profiler.modifier.db.interceptor.StatementExecuteUpdateInterceptor; + +/** + * @author HyunGil Jeong + */ +public class OracleStatementModifierDelegate extends AbstractModifierDelegate { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + public OracleStatementModifierDelegate(ByteCodeInstrumentor byteCodeInstrumentor) { + super(byteCodeInstrumentor); + } + + @Override + public byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectedDomain, byte[] classFileBuffer) { + if (logger.isInfoEnabled()) { + logger.info("Modifying. {}", className); + } + try { + InstrumentClass statementClass = byteCodeInstrumentor.getClass(classLoader, className, classFileBuffer); + Interceptor executeQuery = new StatementExecuteQueryInterceptor(); + statementClass.addScopeInterceptor("executeQuery", new String[]{"java.lang.String"}, executeQuery, OracleScope.SCOPE_NAME); + + // FIXME + Interceptor executeUpdateInterceptor1 = new StatementExecuteUpdateInterceptor(); + statementClass.addScopeInterceptor("executeUpdate", new String[]{"java.lang.String"}, executeUpdateInterceptor1, OracleScope.SCOPE_NAME); + + + Interceptor executeUpdateInterceptor2 = new StatementExecuteUpdateInterceptor(); + statementClass.addScopeInterceptor("executeUpdate", new String[]{"java.lang.String", "int"}, executeUpdateInterceptor2, OracleScope.SCOPE_NAME); + + Interceptor executeInterceptor1 = new StatementExecuteUpdateInterceptor(); + statementClass.addScopeInterceptor("execute", new String[]{"java.lang.String"}, executeInterceptor1, OracleScope.SCOPE_NAME); + + Interceptor executeInterceptor2 = new StatementExecuteUpdateInterceptor(); + statementClass.addScopeInterceptor("execute", new String[]{"java.lang.String", "int"}, executeInterceptor2, OracleScope.SCOPE_NAME); + + statementClass.addTraceValue(DatabaseInfoTraceValue.class); + return statementClass.toBytecode(); + } catch (InstrumentException e) { + if (logger.isWarnEnabled()) { + logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e); + } + return null; + } + } + +} diff --git a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementWrapperModifier.java b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementWrapperModifier.java index f6f189061..c39a471ad 100644 --- a/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementWrapperModifier.java +++ b/profiler/src/main/java/com/navercorp/pinpoint/profiler/modifier/db/oracle/OracleStatementWrapperModifier.java @@ -16,70 +16,33 @@ package com.navercorp.pinpoint.profiler.modifier.db.oracle; +import java.security.ProtectionDomain; + import com.navercorp.pinpoint.bootstrap.Agent; import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; -import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; -import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor; -import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValue; import com.navercorp.pinpoint.profiler.modifier.AbstractModifier; -import com.navercorp.pinpoint.profiler.modifier.db.interceptor.StatementExecuteQueryInterceptor; -import com.navercorp.pinpoint.profiler.modifier.db.interceptor.StatementExecuteUpdateInterceptor; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.security.ProtectionDomain; +import com.navercorp.pinpoint.profiler.modifier.ModifierDelegate; /** * @author emeroad */ public class OracleStatementWrapperModifier extends AbstractModifier { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); + private final ModifierDelegate delegate; public OracleStatementWrapperModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) { super(byteCodeInstrumentor, agent); + this.delegate = new OracleStatementModifierDelegate(byteCodeInstrumentor); } + @Override public String getTargetClass() { - return "oracle/jdbc/driver/OracleStatementWrapper"; + return OracleClassConstants.ORACLE_STATEMENT_WRAPPER; } + @Override public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) { - if (logger.isInfoEnabled()) { - logger.info("Modifing. {}", javassistClassName); - } - - - try { - InstrumentClass statementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer); - Interceptor executeQuery = new StatementExecuteQueryInterceptor(); - statementClass.addScopeInterceptor("executeQuery", new String[]{"java.lang.String"}, executeQuery, OracleScope.SCOPE_NAME); - - // FIXME - Interceptor executeUpdateInterceptor1 = new StatementExecuteUpdateInterceptor(); - statementClass.addScopeInterceptor("executeUpdate", new String[]{"java.lang.String"}, executeUpdateInterceptor1, OracleScope.SCOPE_NAME); - - - Interceptor executeUpdateInterceptor2 = new StatementExecuteUpdateInterceptor(); - statementClass.addScopeInterceptor("executeUpdate", new String[]{"java.lang.String", "int"}, executeUpdateInterceptor2, OracleScope.SCOPE_NAME); - - Interceptor executeInterceptor1 = new StatementExecuteUpdateInterceptor(); - statementClass.addScopeInterceptor("execute", new String[]{"java.lang.String"}, executeInterceptor1, OracleScope.SCOPE_NAME); - - Interceptor executeInterceptor2 = new StatementExecuteUpdateInterceptor(); - statementClass.addScopeInterceptor("execute", new String[]{"java.lang.String", "int"}, executeInterceptor2, OracleScope.SCOPE_NAME); - - statementClass.addTraceValue(DatabaseInfoTraceValue.class); - return statementClass.toBytecode(); - } catch (InstrumentException e) { - if (logger.isWarnEnabled()) { - logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e); - } - return null; - } + return this.delegate.modify(classLoader, javassistClassName, protectedDomain, classFileBuffer); } - }