#1224 Apply SQL bind values tracing configuration to db interceptors

This commit is contained in:
HyunGil Jeong
2015-11-19 19:18:08 +09:00
parent 5b0118eef2
commit 3402803fc2
7 changed files with 181 additions and 425 deletions
@@ -1,106 +1,121 @@
/*
* 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<Method> 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());
}
}
}
}
}
/*
* 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;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.*;
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.PreparedStatementBindVariableInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementExecuteQueryInterceptor;
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;
/**
* @author HyunGil Jeong
*/
public abstract class AbstractPreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final boolean traceBindValue;
public AbstractPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent, boolean traceBindValue) {
super(byteCodeInstrumentor, agent);
this.traceBindValue = traceBindValue;
}
protected abstract String getScope();
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass preparedStatementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
String scope = this.getScope();
for (String methodToIntercept : getMethodsToIntercept()) {
Interceptor executeMethodInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addScopeInterceptor(methodToIntercept, null, executeMethodInterceptor, scope);
}
addTraceValues(preparedStatementClass);
if (this.traceBindValue) {
bindVariableInterceptors(preparedStatementClass);
}
return preparedStatementClass.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
protected List<String> getMethodsToIntercept() {
return Arrays.asList("execute", "executeQuery", "executeUpdate");
}
protected void addTraceValues(InstrumentClass preparedStatementClass) throws InstrumentException {
preparedStatementClass.addTraceValue(DatabaseInfoTraceValue.class);
preparedStatementClass.addTraceValue(ParsingResultTraceValue.class);
preparedStatementClass.addTraceValue(BindValueTraceValue.class, "new java.util.HashMap();");
}
protected List<Method> getBindMethods() {
return PreparedStatementUtils.findBindVariableSetMethod();
}
protected void bindVariableInterceptors(InstrumentClass preparedStatement) throws InstrumentException {
List<Method> bindMethods = getBindMethods();
final Scope scope = super.byteCodeInstrumentor.getScope(this.getScope());
Interceptor interceptor = new ScopeDelegateStaticInterceptor(new PreparedStatementBindVariableInterceptor(), scope);
int interceptorId = -1;
for (Method method : bindMethods) {
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. Just some log will be enough.
if (logger.isDebugEnabled()) {
logger.debug("bindVariable api not found. method:{} param:{} Cause:{}", methodName, Arrays.toString(parameterType), e.getMessage());
}
}
}
}
}
@@ -16,97 +16,27 @@
package com.navercorp.pinpoint.profiler.modifier.db.cubrid;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.List;
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 com.navercorp.pinpoint.profiler.modifier.db.AbstractPreparedStatementModifier;
/**
* @author emeroad
*/
public class CubridPreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public class CubridPreparedStatementModifier extends AbstractPreparedStatementModifier {
public CubridPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
super(byteCodeInstrumentor, agent, agent.getProfilerConfig().isJdbcProfileCubridSqlBindValue());
}
@Override
public String getTargetClass() {
return "cubrid/jdbc/driver/CUBRIDPreparedStatement";
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {}", javassistClassName);
}
try {
InstrumentClass preparedStatementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor executeInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addScopeInterceptor("execute", null, executeInterceptor, CubridScope.SCOPE_NAME);
Interceptor executeQueryInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addScopeInterceptor("executeQuery", null, executeQueryInterceptor, CubridScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addScopeInterceptor("executeUpdate", null, executeUpdateInterceptor, CubridScope.SCOPE_NAME);
preparedStatementClass.addTraceValue(DatabaseInfoTraceValue.class);
preparedStatementClass.addTraceValue(ParsingResultTraceValue.class);
preparedStatementClass.addTraceValue(BindValueTraceValue.class, "new java.util.HashMap();");
bindVariableIntercept(preparedStatementClass, classLoader, protectedDomain);
return preparedStatementClass.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
@Override
protected String getScope() {
return CubridScope.SCOPE_NAME;
}
private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException {
List<Method> bindMethod = PreparedStatementUtils.findBindVariableSetMethod();
final Scope scope = byteCodeInstrumentor.getScope(CubridScope.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. Just some log will be enough.
if (logger.isDebugEnabled()) {
logger.debug("bindVariable api not found. method:{} param:{} Cause:{}", methodName, Arrays.toString(parameterType), e.getMessage());
}
}
}
}
}
@@ -18,97 +18,23 @@ package com.navercorp.pinpoint.profiler.modifier.db.jtds;
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.PreparedStatementBindVariableInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementExecuteQueryInterceptor;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import com.navercorp.pinpoint.profiler.util.PreparedStatementUtils;
import com.navercorp.pinpoint.profiler.modifier.db.AbstractPreparedStatementModifier;
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;
public class JtdsPreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public class JtdsPreparedStatementModifier extends AbstractPreparedStatementModifier {
public JtdsPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
super(byteCodeInstrumentor, agent, agent.getProfilerConfig().isJdbcProfileJtdsSqlBindValue());
}
@Override
public String getTargetClass() {
return "net/sourceforge/jtds/jdbc/JtdsPreparedStatement";
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {}", javassistClassName);
}
try {
InstrumentClass preparedStatementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor executeInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addScopeInterceptor("execute", null, executeInterceptor, JtdsScope.SCOPE_NAME);
Interceptor executeQueryInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addScopeInterceptor("executeQuery", null, executeQueryInterceptor, JtdsScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addScopeInterceptor("executeUpdate", null, executeUpdateInterceptor, JtdsScope.SCOPE_NAME);
preparedStatementClass.addTraceValue(DatabaseInfoTraceValue.class);
preparedStatementClass.addTraceValue(ParsingResultTraceValue.class);
preparedStatementClass.addTraceValue(BindValueTraceValue.class, "new java.util.HashMap();");
bindVariableIntercept(preparedStatementClass, classLoader, protectedDomain);
return preparedStatementClass.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
@Override
protected String getScope() {
return JtdsScope.SCOPE_NAME;
}
private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException {
List<Method> bindMethod = PreparedStatementUtils.findBindVariableSetMethod();
final Scope scope = byteCodeInstrumentor.getScope(JtdsScope.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());
}
}
}
}
}
@@ -20,84 +20,49 @@ 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.instrument.Type;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.profiler.interceptor.ScopeDelegateStaticInterceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementBindVariableInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.AbstractPreparedStatementModifier;
import com.navercorp.pinpoint.profiler.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author emeroad
*/
public class MySQLPreparedStatementJDBC4Modifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public class MySQLPreparedStatementJDBC4Modifier extends AbstractPreparedStatementModifier {
public MySQLPreparedStatementJDBC4Modifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
super(byteCodeInstrumentor, agent, agent.getProfilerConfig().isJdbcProfileMySqlSqlBindValue());
}
@Override
public String getTargetClass() {
return "com/mysql/jdbc/JDBC4PreparedStatement";
}
@Override
public byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {}", className);
}
try {
InstrumentClass preparedStatement = byteCodeInstrumentor.getClass(classLoader, className, classFileBuffer);
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;
}
protected String getScope() {
return MYSQLScope.SCOPE_NAME;
}
private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException {
// TODO Need to add parameter type to filter arguments
// Cannot specify methods without parameter type information because each JDBC driver has different API.
BindVariableFilter exclude = new IncludeBindVariableFilter(new String[]{"setRowId", "setNClob", "setSQLXML"});
List<Method> bindMethod = PreparedStatementUtils.findBindVariableSetMethod(exclude);
// TODO Do we have to utilize this logic?
// It would be better to create util api in bci package which adds interceptors to multiple methods.
final Scope scope = byteCodeInstrumentor.getScope(MYSQLScope.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, Type.after);
} else {
preparedStatement.reuseInterceptor(methodName, parameterType, interceptorId, Type.after);
}
} catch (NotFoundInstrumentException e) {
// Cannot find bind variable setter method. This is not an error. logging will be enough.
// Did not log stack trace intentionally
if (logger.isDebugEnabled()) {
logger.debug("bindVariable api not found. method:{} param:{} Cause:{}", methodName, Arrays.toString(parameterType), e.getMessage());
}
}
}
@Override
protected List<String> getMethodsToIntercept() {
// return nothing (taken care of in the parent class)
return Collections.emptyList();
}
@Override
protected void addTraceValues(InstrumentClass preparedStatementClass) throws InstrumentException {
// do nothing (taken care of in the parent class)
return;
}
@Override
protected List<Method> getBindMethods() {
BindVariableFilter excludedMethods = new IncludeBindVariableFilter(new String[]{"setRowId", "setNClob", "setSQLXML"});
return PreparedStatementUtils.findBindVariableSetMethod(excludedMethods);
}
}
@@ -18,101 +18,25 @@ package com.navercorp.pinpoint.profiler.modifier.db.mysql;
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.ExcludeBindVariableFilter;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import com.navercorp.pinpoint.profiler.util.PreparedStatementUtils;
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.profiler.modifier.db.AbstractPreparedStatementModifier;
/**
* @author emeroad
*/
public class MySQLPreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public class MySQLPreparedStatementModifier extends AbstractPreparedStatementModifier {
public MySQLPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
super(byteCodeInstrumentor, agent, agent.getProfilerConfig().isJdbcProfileMySqlSqlBindValue());
}
@Override
public String getTargetClass() {
return "com/mysql/jdbc/PreparedStatement";
}
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, MYSQLScope.SCOPE_NAME);
Interceptor executeQuery = new PreparedStatementExecuteQueryInterceptor();
preparedStatement.addScopeInterceptor("executeQuery", null, executeQuery, MYSQLScope.SCOPE_NAME);
Interceptor executeUpdate = new PreparedStatementExecuteQueryInterceptor();
preparedStatement.addScopeInterceptor("executeUpdate", null, executeUpdate, MYSQLScope.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;
}
@Override
protected String getScope() {
return MYSQLScope.SCOPE_NAME;
}
private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException {
ExcludeBindVariableFilter exclude = new ExcludeBindVariableFilter(new String[]{"setRowId", "setNClob", "setSQLXML"});
List<Method> bindMethod = PreparedStatementUtils.findBindVariableSetMethod(exclude);
final Scope scope = byteCodeInstrumentor.getScope(MYSQLScope.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());
}
}
}
}
}
@@ -20,8 +20,7 @@ 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;
import com.navercorp.pinpoint.profiler.modifier.db.AbstractPreparedStatementModifier;
/**
* For ojdbc library without OraclePreparedStatementWrapper.
@@ -29,13 +28,10 @@ import com.navercorp.pinpoint.profiler.modifier.ModifierDelegate;
*
* @author HyunGil Jeong
*/
public class OraclePreparedStatementModifier extends AbstractModifier {
private final ModifierDelegate delegate;
public class OraclePreparedStatementModifier extends AbstractPreparedStatementModifier {
public OraclePreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
this.delegate = new OraclePreparedStatementModifierDelegate(byteCodeInstrumentor);
super(byteCodeInstrumentor, agent, agent.getProfilerConfig().isJdbcProfileOracleSqlBindValue());
}
@Override
@@ -43,13 +39,18 @@ public class OraclePreparedStatementModifier extends AbstractModifier {
return OracleClassConstants.ORACLE_PREPARED_STATEMENT;
}
@Override
protected String getScope() {
return OracleScope.SCOPE_NAME;
}
@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);
return super.modify(classLoader, javassistClassName, protectedDomain, classFileBuffer);
}
}
@@ -16,32 +16,27 @@
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;
import com.navercorp.pinpoint.profiler.modifier.db.AbstractPreparedStatementModifier;
/**
* @author emeroad
*/
public class OraclePreparedStatementWrapperModifier extends AbstractModifier {
private final ModifierDelegate delegate;
public class OraclePreparedStatementWrapperModifier extends AbstractPreparedStatementModifier {
public OraclePreparedStatementWrapperModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
this.delegate = new OraclePreparedStatementModifierDelegate(byteCodeInstrumentor);
super(byteCodeInstrumentor, agent, agent.getProfilerConfig().isJdbcProfileOracleSqlBindValue());
}
@Override
public String getTargetClass() {
return OracleClassConstants.ORACLE_PREPARED_STATEMENT_WRAPPER;
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
return this.delegate.modify(classLoader, javassistClassName, protectedDomain, classFileBuffer);
protected String getScope() {
return OracleScope.SCOPE_NAME;
}
}