Remove modifier api

This commit is contained in:
Jongho Moon
2015-09-17 11:51:10 +09:00
parent 8b35dae8e5
commit 2ed79b570e
92 changed files with 0 additions and 7168 deletions
@@ -1,47 +0,0 @@
/*
* Copyright 2014 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.bootstrap.instrument;
import java.security.ProtectionDomain;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
/**
* @author emeroad
*/
@Deprecated
public interface ByteCodeInstrumentor {
InstrumentClass getClass(ClassLoader classLoader, String jvmClassName, byte[] classFileBuffer) throws NotFoundInstrumentException;
boolean findClass(ClassLoader classLoader, String javassistClassName);
@Deprecated
InterceptorGroupInvocation getInterceptorGroupTransaction(String scopeName);
@Deprecated
InterceptorGroupInvocation getInterceptorGroupTransaction(InterceptorGroupDefinition scopeDefinition);
@Deprecated
Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN) throws InstrumentException;
// TargetMethod newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN, Object[] params) throws InstrumentException;
@Deprecated
Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN, Object[] params, Class[] paramClazz) throws InstrumentException;
}
@@ -1,238 +0,0 @@
/*
* Copyright 2014 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.interceptor.bci;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.NotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.DefaultInterceptorGroupDefinition;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException;
import com.navercorp.pinpoint.bootstrap.instrument.InterceptorGroupDefinition;
import com.navercorp.pinpoint.bootstrap.instrument.NotFoundInstrumentException;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.common.util.Asserts;
import com.navercorp.pinpoint.profiler.DefaultAgent;
import com.navercorp.pinpoint.profiler.plugin.DefaultProfilerPluginContext;
import com.navercorp.pinpoint.profiler.util.ScopePool;
import com.navercorp.pinpoint.profiler.util.ThreadLocalScopePool;
/**
* @author emeroad
*/
public class JavaAssistByteCodeInstrumentor implements ByteCodeInstrumentor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final boolean isInfo = logger.isInfoEnabled();
private final boolean isDebug = logger.isDebugEnabled();
private final JavassistClassPool classPool;
private Agent agent;
private final ScopePool scopePool = new ThreadLocalScopePool();
private final ClassLoadChecker classLoadChecker = new ClassLoadChecker();
private final DefaultProfilerPluginContext globalContext;
public JavaAssistByteCodeInstrumentor(Agent agent, JavassistClassPool classPool) {
Asserts.notNull(agent, "agent");
Asserts.notNull(classPool, "classPool");
this.agent = agent;
this.classPool = classPool;
this.globalContext = new DefaultProfilerPluginContext((DefaultAgent)agent, new LegacyProfilerPluginClassLoader(getClass().getClassLoader()));
}
public Agent getAgent() {
return agent;
}
@Override
public InterceptorGroupInvocation getInterceptorGroupTransaction(String scopeName) {
final InterceptorGroupDefinition scopeDefinition = new DefaultInterceptorGroupDefinition(scopeName);
return getInterceptorGroupTransaction(scopeDefinition);
}
public InterceptorGroupInvocation getInterceptorGroupTransaction(InterceptorGroupDefinition scopeDefinition) {
if (scopeDefinition == null) {
throw new NullPointerException("scopeDefinition must not be null");
}
return this.scopePool.getScope(scopeDefinition);
}
@Override
@Deprecated
public InstrumentClass getClass(ClassLoader classLoader, String jvmInternalClassName, byte[] classFileBuffer) throws NotFoundInstrumentException {
return classPool.getClass(globalContext, classLoader, jvmInternalClassName, classFileBuffer);
}
@Deprecated
public InstrumentClass getClass(DefaultProfilerPluginContext pluginContext, ClassLoader classLoader, String jvmInternalClassName, byte[] classFileBuffer) throws NotFoundInstrumentException {
return classPool.getClass(pluginContext, classLoader, jvmInternalClassName, classFileBuffer);
}
@Deprecated
public CtClass getClass(ClassLoader classLoader, String className) throws NotFoundInstrumentException {
return classPool.getClass(classLoader, className);
}
@Deprecated
public NamedClassPool getClassPool(ClassLoader classLoader) {
return classPool.getClassPool(classLoader);
}
public Class<?> defineClass(ClassLoader classLoader, String defineClass, ProtectionDomain protectedDomain) throws InstrumentException {
if (isInfo) {
logger.info("defineClass class:{}, cl:{}", defineClass, classLoader);
}
try {
if (classLoader == null) {
classLoader = ClassLoader.getSystemClassLoader();
}
final NamedClassPool classPool = getClassPool(classLoader);
// It's safe to synchronize on classLoader because current thread already hold lock on classLoader.
// Without lock, maybe something could go wrong.
synchronized (classLoader) {
if (this.classLoadChecker.exist(classLoader, defineClass)) {
return classLoader.loadClass(defineClass);
} else {
final CtClass clazz = classPool.get(defineClass);
checkTargetClassInterface(clazz);
defineAbstractSuperClass(clazz, classLoader, protectedDomain);
defineNestedClass(clazz, classLoader, protectedDomain);
return clazz.toClass(classLoader, protectedDomain);
}
}
} catch (NotFoundException e) {
throw new InstrumentException(defineClass + " class not found. Cause:" + e.getMessage(), e);
} catch (CannotCompileException e) {
throw new InstrumentException(defineClass + " class define fail. cl:" + classLoader + " Cause:" + e.getMessage(), e);
} catch (ClassNotFoundException e) {
throw new InstrumentException(defineClass + " class not found. Cause:" + e.getMessage(), e);
}
}
private void checkTargetClassInterface(CtClass clazz) throws NotFoundException, InstrumentException {
final String name = TargetClassLoader.class.getName();
final CtClass[] interfaces = clazz.getInterfaces();
for (CtClass anInterface : interfaces) {
if (name.equals(anInterface.getName())) {
return;
}
}
throw new InstrumentException("newInterceptor() not support. " + clazz.getName());
}
private void defineAbstractSuperClass(CtClass clazz, ClassLoader classLoader, ProtectionDomain protectedDomain) throws NotFoundException, CannotCompileException {
final CtClass superClass = clazz.getSuperclass();
if (superClass == null) {
// maybe java.lang.Object
return;
}
final int modifiers = superClass.getModifiers();
if (Modifier.isAbstract(modifiers)) {
if (this.classLoadChecker.exist(classLoader, superClass.getName())) {
// We have to check if abstract super classes is already loaded because it could be used by other classes unlike nested classes.
return;
}
if (isInfo) {
logger.info("defineAbstractSuperClass class:{} cl:{}", superClass.getName(), classLoader);
}
// If it was more strict we had to make a recursive call to check super class of super class.
// But it seems like too much. We'll check direct super class only.
superClass.toClass(classLoader, protectedDomain);
}
}
private void defineNestedClass(CtClass clazz, ClassLoader classLoader, ProtectionDomain protectedDomain) throws NotFoundException, CannotCompileException {
CtClass[] nestedClasses = clazz.getNestedClasses();
if (nestedClasses.length == 0) {
return;
}
for (CtClass nested : nestedClasses) {
// load from inner-most to outer.
defineNestedClass(nested, classLoader, protectedDomain);
if (isInfo) {
logger.info("defineNestedClass class:{} cl:{}", nested.getName(), classLoader);
}
nested.toClass(classLoader, protectedDomain);
}
}
@Deprecated
public boolean findClass(String classBinaryName, ClassPool classPool) {
return this.classPool.hasClass(classBinaryName, classPool);
}
@Override
@Deprecated
public boolean findClass(ClassLoader classLoader, String classBinaryName) {
return classPool.hasClass(classLoader, classBinaryName);
}
@Override
public Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN) throws InstrumentException {
Class<?> aClass = this.defineClass(classLoader, interceptorFQCN, protectedDomain);
try {
return (Interceptor) aClass.newInstance();
} catch (InstantiationException e) {
throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e);
}
}
@Override
public Interceptor newInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, String interceptorFQCN, Object[] params, Class[] paramClazz) throws InstrumentException {
Class<?> aClass = this.defineClass(classLoader, interceptorFQCN, protectedDomain);
try {
Constructor<?> constructor = aClass.getConstructor(paramClazz);
return (Interceptor) constructor.newInstance(params);
} catch (InstantiationException e) {
throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e);
} catch (NoSuchMethodException e) {
throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e);
} catch (InvocationTargetException e) {
throw new InstrumentException(aClass + " instance create fail Cause:" + e.getMessage(), e);
}
}
}
@@ -1,71 +0,0 @@
/*
* Copyright 2014 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.Agent;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchable;
/**
* @author emeroad
*/
public abstract class AbstractModifier implements Modifier, Matchable {
protected final ByteCodeInstrumentor byteCodeInstrumentor;
private final ProfilerConfig profilerConfig;
@Deprecated
public AbstractModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
this(byteCodeInstrumentor, assertAgent(agent));
}
private static ProfilerConfig assertAgent(Agent agent) {
if (agent == null) {
throw new NullPointerException("agent must not be null");
}
return agent.getProfilerConfig();
}
public AbstractModifier(ByteCodeInstrumentor byteCodeInstrumentor, ProfilerConfig profilerConfig) {
if (byteCodeInstrumentor == null) {
throw new NullPointerException("byteCodeInstrumentor must not be null");
}
if (profilerConfig == null) {
throw new NullPointerException("profilerConfig must not be null");
}
this.byteCodeInstrumentor = byteCodeInstrumentor;
this.profilerConfig = profilerConfig;
}
public AbstractModifier(ByteCodeInstrumentor byteCodeInstrumentor) {
if (byteCodeInstrumentor == null) {
throw new NullPointerException("byteCodeInstrumentor must not be null");
}
this.byteCodeInstrumentor = byteCodeInstrumentor;
this.profilerConfig = null;
}
// public abstract String getTargetClass();
public ProfilerConfig getProfilerConfig() {
return profilerConfig;
}
}
@@ -1,26 +0,0 @@
/*
* Copyright 2014 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 java.security.ProtectionDomain;
/**
* @author emeroad
*/
public interface Modifier {
byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectedDomain, byte[] classFileBuffer);
}
@@ -1,72 +0,0 @@
/*
* Copyright 2014 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.profiler.util.JavaAssistUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
/**
* @author emeroad
*/
@Deprecated
public class ModifierTransformAdaptor implements ClassFileTransformer {
private final Modifier modifier;
public ModifierTransformAdaptor(Modifier modifier) {
if (modifier == null) {
throw new NullPointerException("modifier must not be null");
}
this.modifier = modifier;
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
final String jvmClassName = JavaAssistUtils.jvmNameToJavaName(className);
return modifier.modify(loader, jvmClassName, protectionDomain, classfileBuffer);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ModifierTransformAdaptor{");
sb.append("modifier=").append(modifier);
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ModifierTransformAdaptor that = (ModifierTransformAdaptor) o;
return !(modifier != null ? !modifier.equals(that.modifier) : that.modifier != null);
}
@Override
public int hashCode() {
return modifier != null ? modifier.hashCode() : 0;
}
}
@@ -1,27 +0,0 @@
/*
* Copyright 2014 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.connector;
/**
*
*/
public class HttpHostParser {
public static String parseUrl(String url) {
return null;
}
}
@@ -1,69 +0,0 @@
/*
* Copyright 2014 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.connector.asynchttpclient;
import java.security.ProtectionDomain;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.interceptor.Interceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
/**
*
* https://github.com/AsyncHttpClient/async-http-client modifier
*
* @author netspider
*
*/
public class AsyncHttpClientModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public AsyncHttpClientModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("com/ning/http/client/AsyncHttpClient");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass aClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor executeRequestInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.navercorp.pinpoint.profiler.modifier.connector.asynchttpclient.interceptor.ExecuteRequestInterceptor");
aClass.addInterceptor("executeRequest", new String[] { "com.ning.http.client.Request", "com.ning.http.client.AsyncHandler" }, executeRequestInterceptor);
return aClass.toBytecode();
} catch (Throwable e) {
logger.warn("httpClient4 modifier error. Caused:{}", e.getMessage(), e);
return null;
}
}
}
@@ -1,26 +0,0 @@
/*
* Copyright 2014 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.context.DatabaseInfo;
/**
* @author emeroad
*/
public interface ConnectionStringParser {
DatabaseInfo parse(String url);
}
@@ -1,115 +0,0 @@
/*
* Copyright 2014 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.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import java.util.List;
/**
* @author emeroad
*/
public class DefaultDatabaseInfo implements DatabaseInfo {
private ServiceType type = ServiceType.UNKNOWN_DB;
private ServiceType executeQueryType = ServiceType.UNKNOWN_DB_EXECUTE_QUERY;
private String databaseId;
private String realUrl; // URL BEFORE refinement
private String normalizedUrl;
private List<String> host;
private String multipleHost;
public DefaultDatabaseInfo(ServiceType type, ServiceType executeQueryType, String realUrl, String normalizedUrl, List<String> host, String databaseId) {
if (type == null) {
throw new NullPointerException("type must not be null");
}
if (executeQueryType == null) {
throw new NullPointerException("executeQueryType must not be null");
}
this.type = type;
this.executeQueryType = executeQueryType;
this.realUrl = realUrl;
this.normalizedUrl = normalizedUrl;
this.host = host;
this.multipleHost = merge(host);
this.databaseId = databaseId;
}
private String merge(List<String> host) {
if (host.isEmpty()) {
return "";
}
String single = host.get(0);
StringBuilder sb = new StringBuilder();
sb.append(single);
for(int i =1; i<host.size(); i++) {
sb.append(',');
sb.append(host.get(i));
}
return sb.toString();
}
@Override
public List<String> getHost() {
// With replication, this is not simple because there could be multiple hosts or ports.
return host;
}
@Override
public String getMultipleHost() {
return multipleHost;
}
@Override
public String getDatabaseId() {
return databaseId;
}
@Override
public String getRealUrl() {
return realUrl;
}
@Override
public String getUrl() {
return normalizedUrl;
}
@Override
public ServiceType getType() {
return type;
}
@Override
public ServiceType getExecuteQueryType() {
return executeQueryType;
}
@Override
public String toString() {
return "DatabaseInfo{" +
"type=" + type +
", executeQueryType=" + executeQueryType +
", databaseId='" + databaseId + '\'' +
", realUrl='" + realUrl + '\'' +
", normalizedUrl='" + normalizedUrl + '\'' +
", host=" + host +
'}';
}
}
@@ -1,121 +0,0 @@
/*
* Copyright 2014 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 java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.modifier.db.cubrid.CubridConnectionStringParser;
import com.navercorp.pinpoint.profiler.modifier.db.jtds.JtdsConnectionStringParser;
import com.navercorp.pinpoint.profiler.modifier.db.mysql.MySqlConnectionStringParser;
import com.navercorp.pinpoint.profiler.modifier.db.oracle.OracleConnectionStringParser;
/**
* @author emeroad
*/
public class JDBCUrlParser {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final ConcurrentMap<String, DatabaseInfo> cache = new ConcurrentHashMap<String, DatabaseInfo>();
//http://www.petefreitag.com/articles/jdbc_urls/
public DatabaseInfo parse(String url) {
final DatabaseInfo hit = cache.get(url);
if (hit != null) {
logger.debug("database url cache hit:{} {}", url, hit);
return hit;
}
final DatabaseInfo databaseInfo = doParse(url);
final DatabaseInfo old = cache.putIfAbsent(url, databaseInfo);
if (old != null) {
return old;
}
return databaseInfo;
}
private DatabaseInfo doParse(String url) {
// check jdbc
String lowCaseURL = url.toLowerCase().trim();
if (!lowCaseURL.startsWith("jdbc:")) {
return createUnknownDataBase(url);
}
if (driverTypeCheck(lowCaseURL, "mysql")) {
return parseMysql(url);
}
if (driverTypeCheck(lowCaseURL, "oracle")) {
return parseOracle(url);
}
if (driverTypeCheck(lowCaseURL, "jtds:sqlserver")) {
return parseJtds(url);
}
if (driverTypeCheck(lowCaseURL, "cubrid")) {
return parseCubrid(url);
}
return createUnknownDataBase(url);
}
private boolean driverTypeCheck(String lowCaseURL, String type) {
final int jdbcNextIndex = 5;
return lowCaseURL.startsWith(type, jdbcNextIndex);
}
private DatabaseInfo parseOracle(String url) {
OracleConnectionStringParser parser = new OracleConnectionStringParser();
return parser.parse(url);
}
public static DatabaseInfo createUnknownDataBase(String url) {
return createUnknownDataBase(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url);
}
public static DatabaseInfo createUnknownDataBase(ServiceType type, ServiceType executeQueryType, String url) {
List<String> list = new ArrayList<String>();
list.add("error");
return new DefaultDatabaseInfo(type, executeQueryType, url, url, list, "error");
}
private DatabaseInfo parseMysql(String url) {
final ConnectionStringParser parser = new MySqlConnectionStringParser();
return parser.parse(url);
}
private DatabaseInfo parseJtds(String url) {
final JtdsConnectionStringParser parser = new JtdsConnectionStringParser();
return parser.parse(url);
}
private DatabaseInfo parseCubrid(String url) {
final ConnectionStringParser parser = new CubridConnectionStringParser();
return parser.parse(url);
}
}
@@ -1,387 +0,0 @@
/*
* Copyright 2014 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;
/**
* copy lucy 1.5
*/
public class StringMaker {
/**
* The value.
*/
private String value;
/**
* The indexing.
*/
private String indexing;
/**
* The begin.
*/
private int begin;
/**
* The end.
*/
private int end;
/**
* Instantiates a new string maker.
*
* @param value the value
*/
public StringMaker(String value) {
this.value = value;
this.indexing = value;
this.end = value.length();
}
/**
* Instantiates a new string maker.
*
* @param value the value
* @param begin the begin
* @param end the end
*/
private StringMaker(String value, int begin, int end) {
this.value = value;
this.indexing = value;
this.begin = begin;
this.end = end;
}
/**
* Lower.
*
* @return the string maker
*/
public StringMaker lower() {
indexing = indexing.toLowerCase();
return this;
}
/**
* Upper.
*
* @return the string maker
*/
public StringMaker upper() {
indexing = indexing.toUpperCase();
return this;
}
/**
* Reset.
*
* @return the string maker
*/
public StringMaker reset() {
indexing = value;
return this;
}
/**
* After.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker after(char ch) {
int index = indexing.indexOf(ch, begin);
if (index < 0 || index > end) {
return this;
}
begin = index + 1 > end ? end : index + 1;
return this;
}
/**
* After.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker after(String ch) {
int index = indexing.indexOf(ch, begin);
if (index < 0 || index > end) {
return this;
}
begin = index + ch.length() > end ? end : index + ch.length();
return this;
}
/**
* Before.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker before(char ch) {
int index = indexing.indexOf(ch, begin);
if (index < 0 || index > end) {
return this;
}
end = index < begin ? begin : index;
return this;
}
public StringMaker before(char ch1, char ch2) {
int index = indexOf(ch1, ch2);
// int index = indexing.indexOf(ch1, begin);
if (index < 0 || index > end) {
return this;
}
end = index < begin ? begin : index;
return this;
}
private int indexOf(char ch1, char ch2) {
for(int i = begin; i< indexing.length(); i++) {
final char c = indexing.charAt(i);
if (c == ch1 || c == ch2) {
return i;
}
}
return -1;
}
/**
* Before.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker before(String ch) {
int index = indexing.indexOf(ch, begin);
if (index < 0 || index > end) {
return this;
}
end = index < begin ? begin : index;
return this;
}
/**
* After last.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker afterLast(char ch) {
int index = indexing.lastIndexOf(ch, end);
if (index < begin) {
return this;
}
begin = index + 1 > end ? end : index + 1;
return this;
}
public int getBeginIndex() {
return begin;
}
public int getEndIndex() {
return end;
}
/**
* Find last ch1 or ch2
* @param ch1
* @param ch2
* @return
*/
public StringMaker afterLast(char ch1, char ch2) {
int index = lastIndexOf(indexing, end, ch1, ch2);
if (index < begin) {
return this;
}
begin = index + 1 > end ? end : index + 1;
return this;
}
int lastIndexOf(String string, int end, char ch1, char ch2) {
int i = end;
for (; i >= begin; i--) {
final char c = string.charAt(i - 1);
if (ch1 == c || ch2 == c) {
return i-1;
}
}
// Not found
return -1;
}
/**
* After last.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker afterLast(String ch) {
int index = indexing.lastIndexOf(ch, end);
if (index < begin) {
return this;
}
begin = index + ch.length() > end ? end : index + ch.length();
return this;
}
/**
* Before last.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker beforeLast(char ch) {
int index = indexing.lastIndexOf(ch, end);
if (index < begin) {
return this;
}
//end = index < begin ? begin : index;
//for Klocwork
end = index;
return this;
}
public StringMaker beforeLast(char ch1, char ch2) {
int index = lastIndexOf(indexing, end, ch1, ch2);
if (index < begin) {
return this;
}
//end = index < begin ? begin : index;
//for Klocwork
end = index;
return this;
}
/**
* Before last.
*
* @param ch the ch
* @return the string maker
*/
public StringMaker beforeLast(String ch) {
int index = indexing.lastIndexOf(ch, end);
if (index < begin) {
return this;
}
//end = index < begin ? begin : index;
//for Klocwork
end = index;
return this;
}
/**
* Prev.
*
* @return the string maker
*/
public StringMaker prev() {
this.end = begin;
this.begin = 0;
return this;
}
/**
* Next.
*
* @return the string maker
*/
public StringMaker next() {
this.begin = end;
this.end = indexing.length();
return this;
}
/**
* Clear.
*
* @return the string maker
*/
public StringMaker clear() {
begin = 0;
end = indexing.length();
return this;
}
/**
* Checks if is empty.
*
* @return true, if is empty
*/
public boolean isEmpty() {
return begin == end;
}
/**
* Value.
*
* @return the string
*/
public String value() {
return value.substring(begin, end);
}
/**
* Duplicate.
*
* @return the string maker
*/
public StringMaker duplicate() {
return new StringMaker(value, begin, end);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
/**
* To string.
*
* @return value() String
*/
public String toString() {
return value();
}
}
@@ -1,118 +0,0 @@
/*
* Copyright 2014 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.cubrid;
import java.security.ProtectionDomain;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author emeroad
*/
public class CubridConnectionModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public CubridConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("cubrid/jdbc/driver/CUBRIDConnection");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass cubridConnection = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
cubridConnection.addTraceValue(DatabaseInfoTraceValue.class);
Interceptor connectionCloseInterceptor = new ConnectionCloseInterceptor();
cubridConnection.addGroupInterceptor("close", null, connectionCloseInterceptor, CubridScope.SCOPE_NAME);
Interceptor statementCreateInterceptor1 = new StatementCreateInterceptor();
cubridConnection.addGroupInterceptor("createStatement", null, statementCreateInterceptor1, CubridScope.SCOPE_NAME);
Interceptor statementCreateInterceptor2 = new StatementCreateInterceptor();
cubridConnection.addGroupInterceptor("createStatement", new String[]{"int", "int"}, statementCreateInterceptor2, CubridScope.SCOPE_NAME);
Interceptor statementCreateInterceptor3 = new StatementCreateInterceptor();
cubridConnection.addGroupInterceptor("createStatement", new String[]{"int", "int", "int"}, statementCreateInterceptor3, CubridScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor1 = new PreparedStatementCreateInterceptor();
cubridConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String"}, preparedStatementCreateInterceptor1, CubridScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor2 = new PreparedStatementCreateInterceptor();
cubridConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int"}, preparedStatementCreateInterceptor2, CubridScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor3 = new PreparedStatementCreateInterceptor();
cubridConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int[]"}, preparedStatementCreateInterceptor3, CubridScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor4 = new PreparedStatementCreateInterceptor();
cubridConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "java.lang.String[]"}, preparedStatementCreateInterceptor4, CubridScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor5 = new PreparedStatementCreateInterceptor();
cubridConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int"}, preparedStatementCreateInterceptor5, CubridScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor6 = new PreparedStatementCreateInterceptor();
cubridConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int", "int"}, preparedStatementCreateInterceptor6, CubridScope.SCOPE_NAME);
// final ProfilerConfig profilerConfig = this.getProfilerConfig();
// if (profilerConfig.isJdbcProfileCubridSetAutoCommit()) {
// Interceptor setAutoCommit = new TransactionSetAutoCommitInterceptor();
// cubridConnection.addGroupInterceptor("setAutoCommit", new String[]{"boolean"}, setAutoCommit, CubridScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileCubridCommit()) {
// Interceptor commit = new TransactionCommitInterceptor();
// cubridConnection.addGroupInterceptor("commit", null, commit, CubridScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileCubridRollback()) {
// Interceptor rollback = new TransactionRollbackInterceptor();
// cubridConnection.addGroupInterceptor("rollback", null, rollback, CubridScope.SCOPE_NAME);
// }
if (this.logger.isInfoEnabled()) {
this.logger.info("{} class is converted.", javassistClassName);
}
return cubridConnection.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,128 +0,0 @@
/*
* Copyright 2014 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.cubrid;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.modifier.db.ConnectionStringParser;
import com.navercorp.pinpoint.profiler.modifier.db.DefaultDatabaseInfo;
import com.navercorp.pinpoint.profiler.modifier.db.JDBCUrlParser;
import com.navercorp.pinpoint.profiler.modifier.db.StringMaker;
/**
* @author emeroad
*/
public class CubridConnectionStringParser implements ConnectionStringParser {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public static final String DEFAULT_HOSTNAME = "localhost";
public static final int DEFAULT_PORT = 30000;
public static final String DEFAULT_USER = "public";
public static final String DEFAULT_PASSWORD = "";
private static final String URL_PATTERN = "jdbc:cubrid(-oracle|-mysql)?:([a-zA-Z_0-9\\.-]*):([0-9]*):([^:]+):([^:]*):([^:]*):(\\?[a-zA-Z_0-9]+=[^&=?]+(&[a-zA-Z_0-9]+=[^&=?]+)*)?";
private static final Pattern PATTERN = Pattern.compile(URL_PATTERN, Pattern.CASE_INSENSITIVE);
@Override
public DatabaseInfo parse(String url) {
if (url == null) {
return JDBCUrlParser.createUnknownDataBase(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, null);
}
final Matcher matcher = PATTERN.matcher(url);
if (!matcher.find()) {
logger.warn("Cubrid connectionString parse fail. url:{}", url);
return JDBCUrlParser.createUnknownDataBase(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url);
}
String host = matcher.group(2);
String portString = matcher.group(3);
String db = matcher.group(4);
String user = matcher.group(5);
// String pass = matcher.group(6);
// String prop = matcher.group(7);
int port = DEFAULT_PORT;
// String resolvedUrl;
if (host == null || host.length() == 0) {
host = DEFAULT_HOSTNAME;
}
if (portString == null || portString.length() == 0) {
port = DEFAULT_PORT;
} else {
try {
port = Integer.parseInt(portString);
} catch (NumberFormatException e) {
logger.warn("cubrid portString parsing fail. portString:{}, url:{}", portString, url);
}
}
if (user == null) {
user = DEFAULT_USER;
}
// if (pass == null) {
// pass = DEFAULT_PASSWORD;
// }
// resolvedUrl = "jdbc:cubrid:" + host + ":" + port + ":" + db + ":" + user + ":********:";
StringMaker maker = new StringMaker(url);
String normalizedUrl = maker.clear().before('?').value();
List<String> hostList = new ArrayList<String>(1);
final String hostAndPort = host + ":" + portString;
hostList.add(hostAndPort);
// skip alt host
return new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url, normalizedUrl, hostList, db);
}
/*
private DatabaseInfo parseCubrid(String url) {
// jdbc:cubrid:10.20.30.40:12345:pinpoint:::
StringMaker maker = new StringMaker(url);
maker.after("jdbc:cubrid:");
// 10.11.12.13:3306 In case of replication driver could have multiple values
// We have to consider mm db too.
String host = maker.after("//").before('/').value();
List<String> hostList = new ArrayList<String>(1);
hostList.add(host);
// String port = maker.next().after(':').before('/').value();
String databaseId = maker.next().afterLast('/').before('?').value();
String normalizedUrl = maker.clear().before('?').value();
return new DatabaseInfo(ServiceType.CUBRID, ServiceType.CUBRID_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId);
}
*/
}
@@ -1,69 +0,0 @@
/*
* Copyright 2014 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.cubrid;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.DriverConnectInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CubridDriverModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public CubridDriverModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("cubrid/jdbc/driver/CUBRIDDriver");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass mysqlConnection = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
final InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(CubridScope.SCOPE_NAME);
DriverConnectInterceptor driverConnectInterceptor = new DriverConnectInterceptor(scope);
mysqlConnection.addInterceptor("connect", new String[]{"java.lang.String", "java.util.Properties"}, driverConnectInterceptor);
if (this.logger.isInfoEnabled()) {
this.logger.info("{} class is converted.", javassistClassName);
}
return mysqlConnection.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,115 +0,0 @@
/*
* Copyright 2014 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.cubrid;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.List;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
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.GroupDelegateStaticInterceptor;
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;
/**
* @author emeroad
*/
public class CubridPreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public CubridPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("cubrid/jdbc/driver/CUBRIDPreparedStatement");
}
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);
Interceptor executeInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addGroupInterceptor("execute", null, executeInterceptor, CubridScope.SCOPE_NAME);
Interceptor executeQueryInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addGroupInterceptor("executeQuery", null, executeQueryInterceptor, CubridScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addGroupInterceptor("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;
}
}
private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException {
List<Method> bindMethod = PreparedStatementUtils.findBindVariableSetMethod();
final InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(CubridScope.SCOPE_NAME);
Interceptor interceptor = new GroupDelegateStaticInterceptor(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());
}
}
}
}
}
@@ -1,51 +0,0 @@
/*
* Copyright 2014 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.cubrid;
import java.security.ProtectionDomain;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author emeroad
*/
public class CubridResultSetModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public CubridResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("cubrid/jdbc/driver/CUBRIDResultSet");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
return null;
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2014 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.cubrid;
/**
* @author emeroad
*/
public class CubridScope {
public static final String SCOPE_NAME = "JDBCScope.cubrid";
}
@@ -1,83 +0,0 @@
/*
* Copyright 2014 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.cubrid;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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;
/**
* @author emeroad
*/
public class CubridStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public CubridStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("cubrid/jdbc/driver/CUBRIDStatement");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass statementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor executeQueryInterceptor = new StatementExecuteQueryInterceptor();
statementClass.addGroupInterceptor("executeQuery", new String[]{"java.lang.String"}, executeQueryInterceptor, CubridScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor1 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String"}, executeUpdateInterceptor1, CubridScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor2 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String", "int"}, executeUpdateInterceptor2, CubridScope.SCOPE_NAME);
Interceptor executeInterceptor1 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("execute", new String[]{"java.lang.String"}, executeInterceptor1, CubridScope.SCOPE_NAME);
Interceptor executeInterceptor2 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("execute", new String[]{"java.lang.String", "int"}, executeInterceptor2, CubridScope.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;
}
}
}
@@ -1,65 +0,0 @@
/*
* Copyright 2014 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.cubrid;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Not used anymore.
*
* @author emeroad
*/
public class CubridUStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public CubridUStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("cubrid/jdbc/jci/UStatement");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass ustatementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
return ustatementClass.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,72 +0,0 @@
/*
* Copyright 2014 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.dbcp;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.DataSourceGetConnectionInterceptor;
/**
* @author emeroad
*/
public class DBCPBasicDataSourceModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public DBCPBasicDataSourceModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("org/apache/commons/dbcp/BasicDataSource");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass basicDataSource = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor getConnection0 = new DataSourceGetConnectionInterceptor();
basicDataSource.addGroupInterceptor("getConnection", null, getConnection0, DBCPScope.SCOPE_NAME);
Interceptor getConnection1 = new DataSourceGetConnectionInterceptor();
basicDataSource.addGroupInterceptor("getConnection", new String[] {"java.lang.String", "java.lang.String"}, getConnection1, DBCPScope.SCOPE_NAME);
return basicDataSource.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,72 +0,0 @@
/*
* Copyright 2014 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.dbcp;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.DataSourceCloseInterceptor;
/**
* @author emeroad
*/
public class DBCPPoolGuardConnectionWrapperModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public DBCPPoolGuardConnectionWrapperModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("org/apache/commons/dbcp/PoolingDataSource$PoolGuardConnectionWrapper");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
return changeMethod(classLoader, javassistClassName, classFileBuffer);
}
private byte[] changeMethod(ClassLoader classLoader, String javassistClassName, byte[] classFileBuffer) {
try {
InstrumentClass wrapper = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor close = new DataSourceCloseInterceptor();
wrapper.addGroupInterceptor("close", null, close, DBCPScope.SCOPE_NAME);
return wrapper.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2014 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.dbcp;
/**
* @author emeroad
*/
public class DBCPScope {
public static final String SCOPE_NAME = "JDBCScope.dbcp";
}
@@ -1,97 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.util.StringUtils;
import java.util.Map;
/**
* @author emeroad
*/
public final class BindValueUtils {
private BindValueUtils() {
}
public static String bindValueToString(final Map<Integer, String> bindValueMap, int limit) {
if (bindValueMap == null) {
return "";
}
if (bindValueMap.isEmpty()) {
return "";
}
final int maxParameterIndex = getMaxParameterIndex(bindValueMap);
if (maxParameterIndex <= 0) {
return "";
}
final String[] temp = new String[maxParameterIndex];
for (Map.Entry<Integer, String> entry : bindValueMap.entrySet()) {
final int parameterIndex = entry.getKey() - 1;
if (parameterIndex < 0) {
// invalid index. PreparedStatement first parameterIndex is 1
continue;
}
if (temp.length <= parameterIndex) {
continue;
}
temp[parameterIndex] = entry.getValue();
}
return bindValueToString(temp, limit);
}
private static int getMaxParameterIndex(Map<Integer, String> bindValueMap) {
int maxIndex = 0;
for (Integer idx : bindValueMap.keySet()) {
maxIndex = Math.max(maxIndex, idx);
}
return maxIndex;
}
public static String bindValueToString(String[] bindValueArray, int limit) {
if (bindValueArray == null) {
return "";
}
final StringBuilder sb = new StringBuilder(32);
final int length = bindValueArray.length;
final int end = length - 1;
for (int i = 0; i < length; i++) {
if (sb.length() >= limit) {
// Appending omission postfix makes generating binded sql difficult. But without this, we cannot say if it's omitted or not.
appendLength(sb, length);
break;
}
final String bindValue = StringUtils.defaultString(bindValueArray[i], "");
StringUtils.appendDrop(sb, bindValue, limit);
if (i < end) {
sb.append(", ");
}
}
return sb.toString();
}
private static void appendLength(StringBuilder sb, int length) {
sb.append("...(");
sb.append(length);
sb.append(')');
}
public static String bindValueToString(String[] stringArray) {
return bindValueToString(stringArray, Integer.MAX_VALUE);
}
}
@@ -1,45 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
/**
* @author emeroad
*/
public class ConnectionCloseInterceptor implements SimpleAroundInterceptor {
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
// In case of close, we have to delete data even if the invocation failed.
DatabaseInfoTraceValueUtils.__setTraceDatabaseInfo(target, null);
}
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
}
}
@@ -1,46 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.RecordableTrace;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.common.trace.ServiceType;
/**
* Maybe we should trace get of Datasource.
* @author emeroad
*/
public class DataSourceCloseInterceptor extends SpanEventSimpleAroundInterceptor {
public DataSourceCloseInterceptor() {
super(DataSourceCloseInterceptor.class);
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, final Object target, Object[] args) {
}
@Override
public void doInAfterTrace(SpanEventRecorder trace, Object target, Object[] args, Object result, Throwable throwable) {
trace.recordServiceType(ServiceType.UNKNOWN);
trace.recordApi(getMethodDescriptor());
trace.recordException(throwable);
}
}
@@ -1,51 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.common.trace.ServiceType;
/**
* Maybe we should trace get of Datasource.
* @author emeroad
*/
public class DataSourceGetConnectionInterceptor extends SpanEventSimpleAroundInterceptor {
// private final DepthScope scope = JDBCScope.SCOPE;
public DataSourceGetConnectionInterceptor() {
super(DataSourceGetConnectionInterceptor.class);
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, final Object target, Object[] args) {
}
@Override
public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
recorder.recordServiceType(ServiceType.UNKNOWN);
if (args == null) {
// getConnection() without any arguments
recorder.recordApi(getMethodDescriptor());
} else if(args.length == 2) {
// skip args[1] because it's a password.
recorder.recordApi(getMethodDescriptor(), args[0], 0);
}
recorder.recordException(throwable);
}
}
@@ -1,117 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.group.ExecutionPolicy;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils;
/**
* @author emeroad
*/
public class DriverConnectInterceptor extends SpanEventSimpleAroundInterceptor {
private final InterceptorGroupInvocation scope;
private final boolean recordConnection;
public DriverConnectInterceptor(InterceptorGroupInvocation scope) {
this(true, scope);
}
public DriverConnectInterceptor(boolean recordConnection, InterceptorGroupInvocation scope) {
super(DriverConnectInterceptor.class);
if (scope == null) {
throw new NullPointerException("scope must not be null");
}
// option for mysql loadbalance only. Destination is recorded at lower implementations.
this.recordConnection = recordConnection;
this.scope = scope;
}
@Override
protected void logBeforeInterceptor(Object target, Object[] args) {
// Must not log args because it contains a password
logger.beforeInterceptor(target, null);
}
@Override
protected void prepareBeforeTrace(Object target, Object[] args) {
scope.tryEnter(ExecutionPolicy.BOUNDARY);
}
@Override
protected void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
}
@Override
protected void logAfterInterceptor(Object target, Object[] args, Object result, Throwable throwable) {
logger.afterInterceptor(target, null, result, throwable);
}
@Override
protected void prepareAfterTrace(Object target, Object[] args, Object result, Throwable throwable) {
// Must not check if current transaction is trace target or not. Connection can be made by other thread.
if (scope.canLeave(ExecutionPolicy.BOUNDARY)) {
scope.leave(ExecutionPolicy.BOUNDARY);
}
final boolean success = InterceptorUtils.isSuccess(throwable);
// Must not check if current transaction is trace target or not. Connection can be made by other thread.
final String driverUrl = (String) args[0];
DatabaseInfo databaseInfo = createDatabaseInfo(driverUrl);
if (success) {
if (recordConnection) {
DatabaseInfoTraceValueUtils.__setTraceDatabaseInfo(result, databaseInfo);
}
}
}
@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
if (recordConnection) {
final DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(result, UnKnownDatabaseInfo.INSTANCE);
// Count database connect too because it's very heavy operation
recorder.recordServiceType(databaseInfo.getExecuteQueryType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
}
final String driverUrl = (String) args[0];
// Invoking databaseInfo.getRealUrl() here is dangerous. It doesn't return real URL if it's a loadbalance connection.
recorder.recordApiCachedString(getMethodDescriptor(), driverUrl, 0);
recorder.recordException(throwable);
}
private DatabaseInfo createDatabaseInfo(String url) {
if (url == null) {
return UnKnownDatabaseInfo.INSTANCE;
}
final DatabaseInfo databaseInfo = getTraceContext().parseJdbcUrl(url);
if (isDebug) {
logger.debug("parse DatabaseInfo:{}", databaseInfo);
}
return databaseInfo;
}
}
@@ -1,82 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import java.util.Map;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.StaticAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.BindValueTraceValue;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.util.NumberUtils;
import com.navercorp.pinpoint.profiler.util.bindvalue.BindValueConverter;
/**
* @author emeroad
*/
public class PreparedStatementBindVariableInterceptor implements StaticAroundInterceptor, TraceContextSupport {
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private TraceContext traceContext;
@Override
public void before(Object target, String className, String methodName, String parameterDescription, Object[] args) {
}
@Override
public void after(Object target, String className, String methodName, String parameterDescription, Object[] args, Object result, Throwable throwable) {
if (isDebug) {
logger.afterInterceptor(target, className, methodName, parameterDescription, args, result, throwable);
}
final Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
Map<Integer, String> bindList = null;
if (target instanceof BindValueTraceValue) {
bindList = ((BindValueTraceValue)target)._$PINPOINT$_getTraceBindValue();
}
if (bindList == null) {
if (logger.isWarnEnabled()) {
logger.warn("bindValue is null");
}
return;
}
Integer index = NumberUtils.toInteger(args[0]);
if (index == null) {
// something is wrong
return;
}
String value = BindValueConverter.convert(methodName, args);
bindList.put(index, value);
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
}
@@ -1,84 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValue;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.ParsingResultTraceValue;
import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils;
import com.navercorp.pinpoint.bootstrap.context.ParsingResult;
/**
* @author emeroad
*/
public class PreparedStatementCreateInterceptor extends SpanEventSimpleAroundInterceptor {
public PreparedStatementCreateInterceptor() {
super(PreparedStatementCreateInterceptor.class);
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
final DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
recorder.recordServiceType(databaseInfo.getType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
}
@Override
protected void prepareAfterTrace(Object target, Object[] args, Object result, Throwable throwable) {
final boolean success = InterceptorUtils.isSuccess(throwable);
if (success) {
if (target instanceof DatabaseInfoTraceValue) {
// set databaseInfo to PreparedStatement only when preparedStatement is generated successfully.
DatabaseInfo databaseInfo = ((DatabaseInfoTraceValue) target)._$PINPOINT$_getTraceDatabaseInfo();
if (databaseInfo != null) {
if (result instanceof DatabaseInfoTraceValue) {
((DatabaseInfoTraceValue) result)._$PINPOINT$_setTraceDatabaseInfo(databaseInfo);
}
}
}
if (result instanceof ParsingResultTraceValue) {
// 1. Don't check traceContext. preparedStatement can be created in other thread.
// 2. While sampling is active, the thread which creates preparedStatement could not be a sampling target. So record sql anyway.
String sql = (String) args[0];
ParsingResult parsingResult = getTraceContext().parseSql(sql);
if (parsingResult != null) {
((ParsingResultTraceValue)result)._$PINPOINT$_setTraceParsingResult(parsingResult);
} else {
if (logger.isErrorEnabled()) {
logger.error("sqlParsing fail. parsingResult is null sql:{}", sql);
}
}
}
}
}
@Override
public void doInAfterTrace(SpanEventRecorder trace, Object target, Object[] args, Object result, Throwable throwable) {
if (result instanceof ParsingResultTraceValue) {
ParsingResult parsingResult = ((ParsingResultTraceValue) result)._$PINPOINT$_getTraceParsingResult();
trace.recordSqlParsingResult(parsingResult);
}
trace.recordException(throwable);
trace.recordApi(getMethodDescriptor());
}
}
@@ -1,144 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import java.util.HashMap;
import java.util.Map;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.ByteCodeMethodDescriptorSupport;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.BindValueTraceValue;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.ParsingResultTraceValue;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.context.ParsingResult;
/**
* @author emeroad
*/
public class PreparedStatementExecuteQueryInterceptor implements SimpleAroundInterceptor, ByteCodeMethodDescriptorSupport, TraceContextSupport {
private static final int DEFAULT_BIND_VALUE_LENGTH = 1024;
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private MethodDescriptor descriptor;
private TraceContext traceContext;
private int maxSqlBindValueLength = DEFAULT_BIND_VALUE_LENGTH;
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
SpanEventRecorder recorder = trace.traceBlockBegin();
try {
DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
recorder.recordServiceType(databaseInfo.getExecuteQueryType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
ParsingResult parsingResult = null;
if (target instanceof ParsingResultTraceValue) {
parsingResult = ((ParsingResultTraceValue) target)._$PINPOINT$_getTraceParsingResult();
}
Map<Integer, String> bindValue = null;
if (target instanceof BindValueTraceValue) {
bindValue = ((BindValueTraceValue)target)._$PINPOINT$_getTraceBindValue();
}
if (bindValue != null) {
String bindString = toBindVariable(bindValue);
recorder.recordSqlParsingResult(parsingResult, bindString);
} else {
recorder.recordSqlParsingResult(parsingResult);
}
recorder.recordApi(descriptor);
// trace.recordApi(apiId);
// Need to change where to invoke clean().
// There is cleanParameters method but it's not necessary to intercept that method.
// iBatis intentionally does not invoke it in most cases.
clean(target);
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn(e.getMessage(), e);
}
}
}
private void clean(Object target) {
if (target instanceof BindValueTraceValue) {
((BindValueTraceValue) target)._$PINPOINT$_setTraceBindValue(new HashMap<Integer, String>());
}
}
private String toBindVariable(Map<Integer, String> bindValue) {
return BindValueUtils.bindValueToString(bindValue, maxSqlBindValueLength);
}
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
if (isDebug) {
logger.afterInterceptor(target, args, result, throwable);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
try {
SpanEventRecorder recorder = trace.currentSpanEventRecorder();
// TODO Test if it's success. if failed terminate. else calculate resultset fetch too. we'd better make resultset fetch optional.
recorder.recordException(throwable);
} finally {
trace.traceBlockEnd();
}
}
@Override
public void setMethodDescriptor(MethodDescriptor descriptor) {
this.descriptor = descriptor;
traceContext.cacheApi(descriptor);
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
// this.maxSqlBindValueLength = traceContext.getProfilerConfig().getJdbcMaxSqlBindValueSize();
}
}
@@ -1,72 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils;
import java.sql.Connection;
/**
* @author emeroad
*/
public class StatementCreateInterceptor implements SimpleAroundInterceptor, TraceContextSupport {
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private TraceContext traceContext;
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
}
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
if (isDebug) {
logger.afterInterceptor(target, args, result, throwable);
}
if (InterceptorUtils.isThrowable(throwable)) {
return;
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
if (target instanceof Connection) {
final DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
DatabaseInfoTraceValueUtils.__setTraceDatabaseInfo(result, databaseInfo);
}
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
}
@@ -1,63 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
/**
* @author netspider
* @author emeroad
*/
public class StatementExecuteQueryInterceptor extends SpanEventSimpleAroundInterceptor {
public StatementExecuteQueryInterceptor() {
super(StatementExecuteQueryInterceptor.class);
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, final Object target, Object[] args) {
/**
* If method was not called by request handler, we skip tagging.
*/
DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
recorder.recordServiceType(databaseInfo.getExecuteQueryType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
}
@Override
public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
recorder.recordApi(getMethodDescriptor());
if (args.length > 0) {
Object arg = args[0];
if (arg instanceof String) {
recorder.recordSqlInfo((String) arg);
// TODO more parsing result processing
}
}
recorder.recordException(throwable);
}
}
@@ -1,59 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.RecordableTrace;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
/**
* protected int executeUpdate(String sql, boolean isBatch, boolean returnGeneratedKeys)
*
* @author netspider
* @author emeroad
*/
public class StatementExecuteUpdateInterceptor extends SpanEventSimpleAroundInterceptor {
public StatementExecuteUpdateInterceptor() {
super(StatementExecuteUpdateInterceptor.class);
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
recorder.recordServiceType(databaseInfo.getExecuteQueryType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
recorder.recordApi(getMethodDescriptor());
if (args != null && args.length > 0) {
Object arg = args[0];
if (arg instanceof String) {
recorder.recordSqlInfo((String) arg);
}
}
}
@Override
public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
recorder.recordException(throwable);
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.RecordableTrace;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
/**
* @author emeroad
*/
public class TransactionCommitInterceptor extends SpanEventSimpleAroundInterceptor {
public TransactionCommitInterceptor() {
super(TransactionCommitInterceptor.class);
}
@Override
protected void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
}
@Override
public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
recorder.recordServiceType(databaseInfo.getType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
recorder.recordApi(getMethodDescriptor());
recorder.recordException(throwable);
}
}
@@ -1,58 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
/**
* @author emeroad
*/
public class TransactionRollbackInterceptor extends SpanEventSimpleAroundInterceptor {
public TransactionRollbackInterceptor() {
super(TransactionRollbackInterceptor.class);
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
}
@Override
public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
recorder.recordServiceType(databaseInfo.getType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
recorder.recordApi(getMethodDescriptor());
// boolean success = InterceptorUtils.isSuccess(result);
// if (success) {
// trace.recordAttribute("Transaction", "rollback");
// } else {
// trace.recordAttribute("Transaction", "rollback fail");
// }
recorder.recordException(throwable);
}
}
@@ -1,52 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.RecordableTrace;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValueUtils;
/**
* @author emeroad
*/
public class TransactionSetAutoCommitInterceptor extends SpanEventSimpleAroundInterceptor {
public TransactionSetAutoCommitInterceptor() {
super(TransactionSetAutoCommitInterceptor.class);
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
}
@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
DatabaseInfo databaseInfo = DatabaseInfoTraceValueUtils.__getTraceDatabaseInfo(target, UnKnownDatabaseInfo.INSTANCE);
recorder.recordServiceType(databaseInfo.getType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
recorder.recordApi(getMethodDescriptor(), args);
recorder.recordException(throwable);
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2014 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.interceptor;
import java.util.ArrayList;
import java.util.List;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.modifier.db.DefaultDatabaseInfo;
/**
* @author emeroad
*/
public class UnKnownDatabaseInfo {
public static final DatabaseInfo INSTANCE;
static{
final List<String> urls = new ArrayList<String>();
urls.add("unknown");
INSTANCE = new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, "unknown", "unknown", urls, "unknown");
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2014 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.jtds;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
/**
* 1.2.x -> jdk 1.5
* @author emeroad
*/
public class Jdbc2ConnectionModifier extends JtdsConnectionModifier {
public Jdbc2ConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("net/sourceforge/jtds/jdbc/ConnectionJDBC2");
}
}
@@ -1,37 +0,0 @@
/*
* Copyright 2014 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.jtds;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
/**
* 1.3.x -> jdk 1.7
* @author emeroad
*/
public class Jdbc4_1ConnectionModifier extends JtdsConnectionModifier {
public Jdbc4_1ConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("net/sourceforge/jtds/jdbc/JtdsConnection");
}
}
@@ -1,117 +0,0 @@
/*
* Copyright 2014 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.jtds;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
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.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.ProtectionDomain;
public abstract class JtdsConnectionModifier extends AbstractModifier {
private static final String SCOPE_NAME = JtdsScope.SCOPE_NAME;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public JtdsConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass jtdsConnection = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
jtdsConnection.addTraceValue(DatabaseInfoTraceValue.class);
Interceptor closeConnection = new ConnectionCloseInterceptor();
jtdsConnection.addGroupInterceptor("close", null, closeConnection, SCOPE_NAME);
Interceptor statementCreateInterceptor1 = new StatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("createStatement", null, statementCreateInterceptor1, SCOPE_NAME);
Interceptor statementCreateInterceptor2 = new StatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("createStatement", new String[]{"int", "int"}, statementCreateInterceptor2, SCOPE_NAME);
Interceptor statementCreateInterceptor3 = new StatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("createStatement", new String[]{"int", "int", "int"}, statementCreateInterceptor3, SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor1 = new PreparedStatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String"}, preparedStatementCreateInterceptor1, SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor2 = new PreparedStatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int"}, preparedStatementCreateInterceptor2, SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor3 = new PreparedStatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int[]"}, preparedStatementCreateInterceptor3, SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor4 = new PreparedStatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "java.lang.String[]"}, preparedStatementCreateInterceptor4, SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor5 = new PreparedStatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int"}, preparedStatementCreateInterceptor5, SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor6 = new PreparedStatementCreateInterceptor();
jtdsConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int", "int"}, preparedStatementCreateInterceptor6, SCOPE_NAME);
// final ProfilerConfig profilerConfig = this.getProfilerConfig();
// if (profilerConfig.isJdbcProfileJtdsSetAutoCommit()) {
// Interceptor setAutocommit = new TransactionSetAutoCommitInterceptor();
// jtdsConnection.addGroupInterceptor("setAutoCommit", new String[]{"boolean"}, setAutocommit, SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileJtdsCommit()) {
// Interceptor commit = new TransactionCommitInterceptor();
// jtdsConnection.addGroupInterceptor("commit", null, commit, SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileJtdsRollback()) {
// Interceptor rollback = new TransactionRollbackInterceptor();
// jtdsConnection.addGroupInterceptor("rollback", null, rollback, SCOPE_NAME);
// }
if (this.logger.isInfoEnabled()) {
this.logger.info("{} class is converted.", javassistClassName);
}
return jtdsConnection.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,79 +0,0 @@
/*
* Copyright 2014 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.jtds;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.modifier.db.ConnectionStringParser;
import com.navercorp.pinpoint.profiler.modifier.db.DefaultDatabaseInfo;
import com.navercorp.pinpoint.profiler.modifier.db.JDBCUrlParser;
import com.navercorp.pinpoint.profiler.modifier.db.StringMaker;
/**
* @author emeroad
*/
public class JtdsConnectionStringParser implements ConnectionStringParser {
public static final int DEFAULT_PORT = 1433;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public DatabaseInfo parse(String url) {
if (url == null) {
return JDBCUrlParser.createUnknownDataBase(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, null);
}
// jdbc:jtds:sqlserver://10.xx.xx.xx:1433;DatabaseName=CAFECHAT;sendStringParametersAsUnicode=false;useLOBs=false;loginTimeout=3
// jdbc:jtds:sqlserver://server[:port][/database][;property=value[;...]]
// jdbc:jtds:sqlserver://server/db;user=userName;password=password
StringMaker maker = new StringMaker(url);
maker.lower().after("jdbc:jtds:sqlserver:");
StringMaker before = maker.after("//").before(';');
final String hostAndPortAndDataBaseString = before.value();
String databaseId = "";
String hostAndPortString = "";
final int databaseIdIndex = hostAndPortAndDataBaseString.indexOf('/');
if (databaseIdIndex != -1) {
hostAndPortString = hostAndPortAndDataBaseString.substring(0, databaseIdIndex);
databaseId = hostAndPortAndDataBaseString.substring(databaseIdIndex+1, hostAndPortAndDataBaseString.length());
} else {
hostAndPortString = hostAndPortAndDataBaseString;
}
List<String> hostList = new ArrayList<String>(1);
hostList.add(hostAndPortString);
// option properties search
if (databaseId.isEmpty()) {
databaseId = maker.next().after("databasename=").before(';').value();
}
String normalizedUrl = maker.clear().before(";").value();
return new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId);
}
}
@@ -1,76 +0,0 @@
/*
* Copyright 2014 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.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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.DriverConnectInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.ProtectionDomain;
/**
* @author emeroad
*/
public class JtdsDriverModifier extends AbstractModifier {
// oracle.jdbc.driver
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public JtdsDriverModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("net/sourceforge/jtds/jdbc/Driver");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass jtdsDriver = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
final InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(JtdsScope.SCOPE_NAME);
Interceptor createConnection = new DriverConnectInterceptor(scope);
String[] params = new String[]{ "java.lang.String", "java.util.Properties" };
jtdsDriver.addInterceptor("connect", params, createConnection);
if (logger.isInfoEnabled()) {
logger.info("{} class is converted.", javassistClassName);
}
return jtdsDriver.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn(this.getClass().getSimpleName() + " modify fail. Cause:" + e.getMessage(), e);
}
return null;
}
}
}
@@ -1,116 +0,0 @@
/*
* Copyright 2014 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.jtds;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.List;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
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.GroupDelegateStaticInterceptor;
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;
public class JtdsPreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public JtdsPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("net/sourceforge/jtds/jdbc/JtdsPreparedStatement");
}
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);
Interceptor executeInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addGroupInterceptor("execute", null, executeInterceptor, JtdsScope.SCOPE_NAME);
Interceptor executeQueryInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addGroupInterceptor("executeQuery", null, executeQueryInterceptor, JtdsScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor = new PreparedStatementExecuteQueryInterceptor();
preparedStatementClass.addGroupInterceptor("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;
}
}
private void bindVariableIntercept(InstrumentClass preparedStatement, ClassLoader classLoader, ProtectionDomain protectedDomain) throws InstrumentException {
List<Method> bindMethod = PreparedStatementUtils.findBindVariableSetMethod();
final InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(JtdsScope.SCOPE_NAME);
Interceptor interceptor = new GroupDelegateStaticInterceptor(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());
}
}
}
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2014 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.jtds;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JtdsResultSetModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public JtdsResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("net/sourceforge/jtds/jdbc/JtdsResultSet");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
return null;
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2014 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.jtds;
/**
* @author emeroad
*/
public final class JtdsScope {
public static final String SCOPE_NAME = "Jtds";
}
@@ -1,81 +0,0 @@
/*
* Copyright 2014 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.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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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 java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class JtdsStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public JtdsStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("net/sourceforge/jtds/jdbc/JtdsStatement");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass statementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor executeQuery = new StatementExecuteQueryInterceptor();
statementClass.addGroupInterceptor("executeQuery", new String[]{"java.lang.String"}, executeQuery, JtdsScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor1 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String"}, executeUpdateInterceptor1, JtdsScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor2 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String", "int"}, executeUpdateInterceptor2, JtdsScope.SCOPE_NAME);
Interceptor executeInterceptor1 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("execute", new String[]{"java.lang.String"}, executeInterceptor1, JtdsScope.SCOPE_NAME);
Interceptor executeInterceptor2 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("execute", new String[]{"java.lang.String", "int"}, executeInterceptor2, JtdsScope.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;
}
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2014 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.mysql;
/**
* @author emeroad
*/
public class MYSQLScope {
public static final String SCOPE_NAME = "JDBCScope.mysql";
}
@@ -1,138 +0,0 @@
/*
* Copyright 2014 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.mysql;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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.ConnectionCloseInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementCreateInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.StatementCreateInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.TransactionCommitInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.TransactionRollbackInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.TransactionSetAutoCommitInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.mysql.interceptor.MySQLConnectionCreateInterceptor;
/**
* @author emeroad
*/
public class MySQLConnectionImplModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySQLConnectionImplModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("com/mysql/jdbc/ConnectionImpl");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass mysqlConnection = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
mysqlConnection.addTraceValue(DatabaseInfoTraceValue.class);
// If you want to make this common intercepter class, it has to be loaded to system.
// TargetMethod createConnection = new ConnectionCreateInterceptor();
// String[] params = new String[] {
// "java.lang.String", "int", "java.util.Properties", "java.lang.String", "java.lang.String"
// };
// mysqlConnection.addInterceptor("getInstance", params, createConnection);
Interceptor connectionUrlBindInterceptor = new MySQLConnectionCreateInterceptor();
mysqlConnection.addConstructorInterceptor(new String[]{"java.lang.String", "int",
"java.util.Properties", "java.lang.String", "java.lang.String" }, connectionUrlBindInterceptor);
Interceptor closeConnection = new ConnectionCloseInterceptor();
mysqlConnection.addGroupInterceptor("close", null, closeConnection, MYSQLScope.SCOPE_NAME);
Interceptor statementCreateInterceptor1 = new StatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("createStatement", null, statementCreateInterceptor1, MYSQLScope.SCOPE_NAME);
Interceptor statementCreateInterceptor2 = new StatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("createStatement", new String[]{"int", "int"}, statementCreateInterceptor2, MYSQLScope.SCOPE_NAME);
Interceptor statementCreateInterceptor3 = new StatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("createStatement", new String[]{"int", "int", "int"}, statementCreateInterceptor3, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor1 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String"}, preparedStatementCreateInterceptor1, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor2 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int"}, preparedStatementCreateInterceptor2, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor3 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int[]"}, preparedStatementCreateInterceptor3, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor4 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "java.lang.String[]"}, preparedStatementCreateInterceptor4, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor5 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int"}, preparedStatementCreateInterceptor5, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor6 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int", "int"}, preparedStatementCreateInterceptor6, MYSQLScope.SCOPE_NAME);
// final ProfilerConfig profilerConfig = this.getProfilerConfig();
// if (profilerConfig.isJdbcProfileMySqlSetAutoCommit()) {
// Interceptor setAutocommit = new TransactionSetAutoCommitInterceptor();
// mysqlConnection.addGroupInterceptor("setAutoCommit", new String[]{"boolean"}, setAutocommit, MYSQLScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileMySqlCommit()) {
// Interceptor commit = new TransactionCommitInterceptor();
// mysqlConnection.addGroupInterceptor("commit", null, commit, MYSQLScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileMySqlRollback()) {
// Interceptor rollback = new TransactionRollbackInterceptor();
// mysqlConnection.addGroupInterceptor("rollback", null, rollback, MYSQLScope.SCOPE_NAME);
// }
if (this.logger.isInfoEnabled()) {
this.logger.info("{} class is converted.", javassistClassName);
}
return mysqlConnection.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,142 +0,0 @@
/*
* Copyright 2014 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.mysql;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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.ConnectionCloseInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementCreateInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.StatementCreateInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.TransactionCommitInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.TransactionRollbackInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.TransactionSetAutoCommitInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.mysql.interceptor.MySQLConnectionCreateInterceptor;
/**
* @author emeroad
*/
public class MySQLConnectionModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySQLConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
// Connection has implementation in old versions of MySQL
return Matchers.newClassNameMatcher("com/mysql/jdbc/Connection");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass mysqlConnection = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
if (mysqlConnection.isInterface()) {
// Newer version of MySQL
return null;
}
mysqlConnection.addTraceValue(DatabaseInfoTraceValue.class);
// If you want to make this common intercepter class, it has to be loaded to system.
// TargetMethod createConnection = new ConnectionCreateInterceptor();
// String[] params = new String[] {
// "java.lang.String", "int", "java.util.Properties", "java.lang.String", "java.lang.String"
// };
// mysqlConnection.addInterceptor("getInstance", params, createConnection);
Interceptor connectionUrlBindInterceptor = new MySQLConnectionCreateInterceptor();
mysqlConnection.addConstructorInterceptor(new String[]{"java.lang.String", "int",
"java.util.Properties", "java.lang.String", "java.lang.String" }, connectionUrlBindInterceptor);
Interceptor closeConnection = new ConnectionCloseInterceptor();
mysqlConnection.addGroupInterceptor("close", null, closeConnection, MYSQLScope.SCOPE_NAME);
Interceptor statementCreateInterceptor1 = new StatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("createStatement", null, statementCreateInterceptor1, MYSQLScope.SCOPE_NAME);
Interceptor statementCreateInterceptor2 = new StatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("createStatement", new String[]{"int", "int"}, statementCreateInterceptor2, MYSQLScope.SCOPE_NAME);
Interceptor statementCreateInterceptor3 = new StatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("createStatement", new String[]{"int", "int", "int"}, statementCreateInterceptor3, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor1 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String"}, preparedStatementCreateInterceptor1, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor2 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int"}, preparedStatementCreateInterceptor2, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor3 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int[]"}, preparedStatementCreateInterceptor3, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor4 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "java.lang.String[]"}, preparedStatementCreateInterceptor4, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor5 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int"}, preparedStatementCreateInterceptor5, MYSQLScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor6 = new PreparedStatementCreateInterceptor();
mysqlConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int", "int"}, preparedStatementCreateInterceptor6, MYSQLScope.SCOPE_NAME);
// final ProfilerConfig profilerConfig = this.getProfilerConfig();
// if (profilerConfig.isJdbcProfileMySqlSetAutoCommit()) {
// Interceptor setAutocommit = new TransactionSetAutoCommitInterceptor();
// mysqlConnection.addGroupInterceptor("setAutoCommit", new String[]{"boolean"}, setAutocommit, MYSQLScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileMySqlCommit()) {
// Interceptor commit = new TransactionCommitInterceptor();
// mysqlConnection.addGroupInterceptor("commit", null, commit, MYSQLScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileMySqlRollback()) {
// Interceptor rollback = new TransactionRollbackInterceptor();
// mysqlConnection.addGroupInterceptor("rollback", null, rollback, MYSQLScope.SCOPE_NAME);
// }
if (this.logger.isInfoEnabled()) {
this.logger.info("{} class is converted.", javassistClassName);
}
return mysqlConnection.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,78 +0,0 @@
/*
* Copyright 2014 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.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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.DriverConnectInterceptor;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author emeroad
*/
public class MySQLNonRegisteringDriverModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySQLNonRegisteringDriverModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("com/mysql/jdbc/NonRegisteringDriver");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass mysqlConnection = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
final InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(MYSQLScope.SCOPE_NAME);
Interceptor createConnection = new DriverConnectInterceptor(false, scope);
String[] params = new String[]{
"java.lang.String", "java.util.Properties"
};
// Don't use scope at Driver. Connection can be made at thread which is not being traced.
mysqlConnection.addInterceptor("connect", params, createConnection);
if (this.logger.isInfoEnabled()) {
this.logger.info("{} class is converted.", javassistClassName);
}
return mysqlConnection.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,109 +0,0 @@
/*
* Copyright 2014 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.mysql;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.List;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.interceptor.InterceptPoint;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.profiler.interceptor.GroupDelegateStaticInterceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementBindVariableInterceptor;
import com.navercorp.pinpoint.profiler.util.BindVariableFilter;
import com.navercorp.pinpoint.profiler.util.IncludeBindVariableFilter;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import com.navercorp.pinpoint.profiler.util.PreparedStatementUtils;
/**
* @author emeroad
*/
public class MySQLPreparedStatementJDBC4Modifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySQLPreparedStatementJDBC4Modifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("com/mysql/jdbc/JDBC4PreparedStatement");
}
@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);
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 {
// 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 InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(MYSQLScope.SCOPE_NAME);
Interceptor interceptor = new GroupDelegateStaticInterceptor(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, InterceptPoint.AFTER);
} else {
preparedStatement.reuseInterceptor(methodName, parameterType, interceptorId, InterceptPoint.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());
}
}
}
}
}
@@ -1,121 +0,0 @@
/*
* Copyright 2014 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.mysql;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.List;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
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.GroupDelegateStaticInterceptor;
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.ExcludeBindVariableFilter;
import com.navercorp.pinpoint.profiler.util.JavaAssistUtils;
import com.navercorp.pinpoint.profiler.util.PreparedStatementUtils;
/**
* @author emeroad
*/
public class MySQLPreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySQLPreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("com/mysql/jdbc/PreparedStatement");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass preparedStatement = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor execute = new PreparedStatementExecuteQueryInterceptor();
preparedStatement.addGroupInterceptor("execute", null, execute, MYSQLScope.SCOPE_NAME);
Interceptor executeQuery = new PreparedStatementExecuteQueryInterceptor();
preparedStatement.addGroupInterceptor("executeQuery", null, executeQuery, MYSQLScope.SCOPE_NAME);
Interceptor executeUpdate = new PreparedStatementExecuteQueryInterceptor();
preparedStatement.addGroupInterceptor("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;
}
}
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 InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(MYSQLScope.SCOPE_NAME);
Interceptor interceptor = new GroupDelegateStaticInterceptor(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());
}
}
}
}
}
@@ -1,53 +0,0 @@
/*
* Copyright 2014 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.mysql;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author emeroad
*/
public class MySQLResultSetModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySQLResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("com/mysql/jdbc/ResultSetImpl");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
return null;
}
}
@@ -1,86 +0,0 @@
/*
* Copyright 2014 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.mysql;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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;
/**
* @author emeroad
*/
public class MySQLStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MySQLStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("com/mysql/jdbc/StatementImpl");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass statementClass = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor interceptor = new StatementExecuteQueryInterceptor();
statementClass.addGroupInterceptor("executeQuery", new String[]{"java.lang.String"}, interceptor, MYSQLScope.SCOPE_NAME);
// FIXME
Interceptor executeUpdateInterceptor1 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String"}, executeUpdateInterceptor1, MYSQLScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor2 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String", "int"}, executeUpdateInterceptor2, MYSQLScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor3 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("execute", new String[]{"java.lang.String"}, executeUpdateInterceptor3, MYSQLScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor4 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("execute", new String[]{"java.lang.String", "int"}, executeUpdateInterceptor4, MYSQLScope.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;
}
}
}
@@ -1,87 +0,0 @@
/*
* Copyright 2014 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.mysql;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.modifier.db.ConnectionStringParser;
import com.navercorp.pinpoint.profiler.modifier.db.DefaultDatabaseInfo;
import com.navercorp.pinpoint.profiler.modifier.db.JDBCUrlParser;
import com.navercorp.pinpoint.profiler.modifier.db.StringMaker;
/**
* @author emeroad
*/
public class MySqlConnectionStringParser implements ConnectionStringParser {
// jdbc:mysql:loadbalance://10.22.33.44:3306,10.22.33.55:3306/MySQL?characterEncoding=UTF-8
private static final String JDBC_MYSQL_LOADBALANCE = "jdbc:mysql:loadbalance:";
@Override
public DatabaseInfo parse(String url) {
if (url == null) {
return JDBCUrlParser.createUnknownDataBase(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, null);
}
if (isLoadbalanceUrl(url)) {
return parseLoadbalancedUrl(url);
}
return parseNormal(url);
}
private DatabaseInfo parseLoadbalancedUrl(String url) {
// jdbc:mysql://1.2.3.4:5678/test_db
StringMaker maker = new StringMaker(url);
maker.after("jdbc:mysql:");
// 1.2.3.4:5678 In case of replication driver could have multiple values
// We have to consider mm db too.
String host = maker.after("//").before('/').value();
// Decided not to cache regex. This is not invoked often so don't waste memory.
String[] parsedHost = host.split(",");
List<String> hostList = Arrays.asList(parsedHost);
String databaseId = maker.next().afterLast('/').before('?').value();
String normalizedUrl = maker.clear().before('?').value();
return new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId);
}
private boolean isLoadbalanceUrl(String url) {
return url.regionMatches(true, 0, JDBC_MYSQL_LOADBALANCE, 0, JDBC_MYSQL_LOADBALANCE.length());
}
private DatabaseInfo parseNormal(String url) {
// jdbc:mysql://1.2.3.4:5678/test_db
StringMaker maker = new StringMaker(url);
maker.after("jdbc:mysql:");
// 1.2.3.4:5678 In case of replication driver could have multiple values
// We have to consider mm db too.
String host = maker.after("//").before('/').value();
List<String> hostList = new ArrayList<String>(1);
hostList.add(host);
// String port = maker.next().after(':').before('/').value();
String databaseId = maker.next().afterLast('/').before('?').value();
String normalizedUrl = maker.clear().before('?').value();
return new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url, normalizedUrl, hostList, databaseId);
}
}
@@ -1,107 +0,0 @@
/*
* Copyright 2014 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.mysql.interceptor;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.interceptor.tracevalue.DatabaseInfoTraceValue;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils;
import com.navercorp.pinpoint.common.trace.ServiceType;
/**
* @author emeroad
*/
public class MySQLConnectionCreateInterceptor implements SimpleAroundInterceptor, TraceContextSupport {
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private TraceContext traceContext;
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
if (isDebug) {
logger.afterInterceptor(target, args, result, throwable);
}
if (args == null || args.length != 5) {
return;
}
final String hostToConnectTo = getString(args[0]);
final Integer portToConnectTo = getInteger(args[1]);
final String databaseId = getString(args[3]);
// In case of loadbalance, connectUrl is modified.
// final String url = getString(args[4]);
DatabaseInfo databaseInfo = null;
if (hostToConnectTo != null && portToConnectTo != null && databaseId != null) {
// It's dangerous to use this url directly
databaseInfo = traceContext.createDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, hostToConnectTo, portToConnectTo, databaseId);
if (InterceptorUtils.isSuccess(throwable)) {
// Set only if connection is success.
if (target instanceof DatabaseInfoTraceValue) {
((DatabaseInfoTraceValue)target)._$PINPOINT$_setTraceDatabaseInfo(databaseInfo);
}
}
}
final Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
SpanEventRecorder recorder = trace.currentSpanEventRecorder();
// We must do this if current transaction is being recorded.
if (databaseInfo != null) {
recorder.recordServiceType(databaseInfo.getExecuteQueryType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
}
}
private String getString(Object value) {
if (value instanceof String) {
return (String) value;
}
return null;
}
private Integer getInteger(Object value) {
if (value instanceof Integer) {
return (Integer) value;
}
return null;
}
@Override
public void before(Object target, Object[] args) {
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
}
@@ -1,32 +0,0 @@
/*
* 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";
}
@@ -1,124 +0,0 @@
/*
* Copyright 2014 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.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.modifier.db.ConnectionStringParser;
import com.navercorp.pinpoint.profiler.modifier.db.DefaultDatabaseInfo;
import com.navercorp.pinpoint.profiler.modifier.db.JDBCUrlParser;
import com.navercorp.pinpoint.profiler.modifier.db.StringMaker;
import com.navercorp.pinpoint.profiler.modifier.db.oracle.parser.Description;
import com.navercorp.pinpoint.profiler.modifier.db.oracle.parser.KeyValue;
import com.navercorp.pinpoint.profiler.modifier.db.oracle.parser.OracleConnectionStringException;
import com.navercorp.pinpoint.profiler.modifier.db.oracle.parser.OracleNetConnectionDescriptorParser;
/**
* @author emeroad
*/
public class OracleConnectionStringParser implements ConnectionStringParser {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public DatabaseInfo parse(String url) {
StringMaker maker = new StringMaker(url);
maker.after("jdbc:oracle:").after(":");
String description = maker.after('@').value().trim();
if (description.startsWith("(")) {
return parseNetConnectionUrl(url);
} else {
return parseSimpleUrl(url, maker);
}
}
// rac url.
// jdbc:oracle:thin:@(Description=(LOAD_BALANCE=on)" +
// "(ADDRESS=(PROTOCOL=TCP)(HOST=1.2.3.4) (PORT=1521))" +
// "(ADDRESS=(PROTOCOL=TCP)(HOST=1.2.3.5) (PORT=1521))" +
// "(CONNECT_DATA=(SERVICE_NAME=service)))"
//
// thin driver url
// jdbc:oracle:thin:@hostname:port:SID
// "jdbc:oracle:thin:MYWORKSPACE/qwerty@localhost:1521:XE";
// With proper indentation and line break,
// jdbc:oracle:thin:
// @(
// Description=(LOAD_BALANCE=on)
// (
// ADDRESS=(PROTOCOL=TCP)(HOST=1.2.3.4) (PORT=1521)
// )
// (
// ADDRESS=(PROTOCOL=TCP)(HOST=1.2.3.5) (PORT=1521)
// )
// (
// CONNECT_DATA=(SERVICE_NAME=service)
// )
// )
private DatabaseInfo parseNetConnectionUrl(String url) {
try {
// oracle new URL : for rac
OracleNetConnectionDescriptorParser parser = new OracleNetConnectionDescriptorParser(url);
KeyValue keyValue = parser.parse();
// TODO Need to handle oci driver. It's more popular.
// parser.getDriverType();
return createOracleDatabaseInfo(keyValue, url);
} catch (OracleConnectionStringException ex) {
logger.warn("OracleConnectionString parse error. url:{} Caused:", url, ex.getMessage(), ex);
// Log error and just create unknownDataBase
return JDBCUrlParser.createUnknownDataBase(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url);
} catch (Throwable ex) {
// If we throw exception more precisely later, catch OracleConnectionStringException only.
logger.warn("OracleConnectionString parse error. url:{} Caused:", url, ex.getMessage(), ex);
// Log error and just create unknownDataBase
return JDBCUrlParser.createUnknownDataBase(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url);
}
}
private DefaultDatabaseInfo parseSimpleUrl(String url, StringMaker maker) {
// thin driver
// jdbc:oracle:thin:@hostname:port:SID
// "jdbc:oracle:thin:MYWORKSPACE/qwerty@localhost:1521:XE";
// jdbc:oracle:thin:@//hostname:port/serviceName
String host = maker.before(':').value();
String port = maker.next().after(':').before(':', '/').value();
String databaseId = maker.next().afterLast(':', '/').value();
List<String> hostList = new ArrayList<String>(1);
hostList.add(host + ":" + port);
return new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url, url, hostList, databaseId);
}
private DatabaseInfo createOracleDatabaseInfo(KeyValue keyValue, String url) {
Description description = new Description(keyValue);
List<String> jdbcHost = description.getJdbcHost();
return new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, url, url, jdbcHost, description.getDatabaseId());
}
}
@@ -1,76 +0,0 @@
/*
* Copyright 2014 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 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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.DriverConnectInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.security.ProtectionDomain;
/**
* @author emeroad
*/
public class OracleDriverModifier extends AbstractModifier {
// oracle.jdbc.driver
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public OracleDriverModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("oracle/jdbc/driver/OracleDriver");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass oracleDriver = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
final InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(OracleScope.SCOPE_NAME);
Interceptor createConnection = new DriverConnectInterceptor(scope);
String[] params = new String[]{ "java.lang.String", "java.util.Properties" };
oracleDriver.addInterceptor("connect", params, createConnection);
if (logger.isInfoEnabled()) {
logger.info("{} class is converted.", javassistClassName);
}
return oracleDriver.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn(this.getClass().getSimpleName() + " modify fail. Cause:" + e.getMessage(), e);
}
return null;
}
}
}
@@ -1,127 +0,0 @@
/*
* 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 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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
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.GroupDelegateStaticInterceptor;
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;
/**
* For ojdbc library without OraclePreparedStatementWrapper.
* eg. ojdbc-10.0.x
*
* @author HyunGil Jeong
*/
public class OraclePreparedStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public OraclePreparedStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public Matcher getMatcher() {
List<String> preparedStatement = Arrays.asList(OracleClassConstants.ORACLE_PREPARED_STATEMENT, OracleClassConstants.ORACLE_PREPARED_STATEMENT_WRAPPER);
return Matchers.newMultiClassNameMatcher(preparedStatement);
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
// Do not modify if wrapper exists
if (OracleClassConstants.ORACLE_PREPARED_STATEMENT.equals(javassistClassName)) {
if (byteCodeInstrumentor.findClass(classLoader, OracleClassConstants.ORACLE_PREPARED_STATEMENT_WRAPPER)) {
return null;
}
}
return this.modifyStatement(classLoader, javassistClassName, protectedDomain, classFileBuffer);
}
public byte[] modifyStatement(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.addGroupInterceptor("execute", null, execute, OracleScope.SCOPE_NAME);
Interceptor executeQuery = new PreparedStatementExecuteQueryInterceptor();
preparedStatement.addGroupInterceptor("executeQuery", null, executeQuery, OracleScope.SCOPE_NAME);
Interceptor executeUpdate = new PreparedStatementExecuteQueryInterceptor();
preparedStatement.addGroupInterceptor("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 InterceptorGroupInvocation scope = byteCodeInstrumentor.getInterceptorGroupTransaction(OracleScope.SCOPE_NAME);
Interceptor interceptor = new GroupDelegateStaticInterceptor(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());
}
}
}
}
}
@@ -1,55 +0,0 @@
/*
* Copyright 2014 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 com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author emeroad
*/
public class OracleResultSetModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public OracleResultSetModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("oracle/jdbc/driver/OracleResultSetImpl");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
return null;
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2014 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 emeroad
*/
public class OracleScope {
public static final String SCOPE_NAME = "JDBCScope.oracle";
}
@@ -1,97 +0,0 @@
/*
* 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.bootstrap.instrument.InstrumentClass;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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;
/**
* For ojdbc library without OracleStatementWrapper.
* eg. ojdbc-10.0.x
*
* @author HyunGil Jeong
*/
public class OracleStatementModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public OracleStatementModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public Matcher getMatcher() {
return Matchers.newMultiClassNameMatcher(OracleClassConstants.ORACLE_STATEMENT, OracleClassConstants.ORACLE_STATEMENT_WRAPPER);
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
// Do not modify if wrapper exists
if(OracleClassConstants.ORACLE_STATEMENT.equals(javassistClassName)) {
if (byteCodeInstrumentor.findClass(classLoader, OracleClassConstants.ORACLE_STATEMENT_WRAPPER)) {
return null;
}
}
return this.modifyStatement(classLoader, javassistClassName, protectedDomain, classFileBuffer);
}
public byte[] modifyStatement(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.addGroupInterceptor("executeQuery", new String[]{"java.lang.String"}, executeQuery, OracleScope.SCOPE_NAME);
// FIXME
Interceptor executeUpdateInterceptor1 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String"}, executeUpdateInterceptor1, OracleScope.SCOPE_NAME);
Interceptor executeUpdateInterceptor2 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("executeUpdate", new String[]{"java.lang.String", "int"}, executeUpdateInterceptor2, OracleScope.SCOPE_NAME);
Interceptor executeInterceptor1 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("execute", new String[]{"java.lang.String"}, executeInterceptor1, OracleScope.SCOPE_NAME);
Interceptor executeInterceptor2 = new StatementExecuteUpdateInterceptor();
statementClass.addGroupInterceptor("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;
}
}
}
@@ -1,132 +0,0 @@
/*
* Copyright 2014 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.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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
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.ConnectionCloseInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.PreparedStatementCreateInterceptor;
import com.navercorp.pinpoint.profiler.modifier.db.interceptor.StatementCreateInterceptor;
/**
* @author emeroad
*/
public class PhysicalConnectionModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public PhysicalConnectionModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
// There is a common super class of T4C, T2C (OCI subclasses T2C), which is based on PhysicalConnection.
// So modifying PhysicalConnection will be enough.
return Matchers.newClassNameMatcher("oracle/jdbc/driver/PhysicalConnection");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass oracleConnection = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
oracleConnection.addTraceValue(DatabaseInfoTraceValue.class);
// If we make this as common interceptor, it has to be loaded to system.
// TargetMethod createConnection = new ConnectionCreateInterceptor();
// String[] params = new String[] {
// "java.lang.String", "int", "java.util.Properties", "java.lang.String", "java.lang.String"
// };
// mysqlConnection.addInterceptor("getInstance", params, createConnection);
Interceptor closeConnection = new ConnectionCloseInterceptor();
oracleConnection.addGroupInterceptor("close", null, closeConnection, OracleScope.SCOPE_NAME);
Interceptor statementCreateInterceptor1 = new StatementCreateInterceptor();
oracleConnection.addGroupInterceptor("createStatement", null, statementCreateInterceptor1, OracleScope.SCOPE_NAME);
Interceptor statementCreateInterceptor2 = new StatementCreateInterceptor();
oracleConnection.addGroupInterceptor("createStatement", new String[]{"int", "int"}, statementCreateInterceptor2, OracleScope.SCOPE_NAME);
Interceptor statementCreateInterceptor3 = new StatementCreateInterceptor();
oracleConnection.addGroupInterceptor("createStatement", new String[]{"int", "int", "int"}, statementCreateInterceptor3, OracleScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor1 = new PreparedStatementCreateInterceptor();
oracleConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String"}, preparedStatementCreateInterceptor1, OracleScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor2 = new PreparedStatementCreateInterceptor();
oracleConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int"}, preparedStatementCreateInterceptor2, OracleScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor3 = new PreparedStatementCreateInterceptor();
oracleConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int[]"}, preparedStatementCreateInterceptor3, OracleScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor4 = new PreparedStatementCreateInterceptor();
oracleConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "java.lang.String[]"}, preparedStatementCreateInterceptor4, OracleScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor5 = new PreparedStatementCreateInterceptor();
oracleConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int"}, preparedStatementCreateInterceptor5, OracleScope.SCOPE_NAME);
Interceptor preparedStatementCreateInterceptor6 = new PreparedStatementCreateInterceptor();
oracleConnection.addGroupInterceptor("prepareStatement", new String[]{"java.lang.String", "int", "int", "int"}, preparedStatementCreateInterceptor6, OracleScope.SCOPE_NAME);
// final ProfilerConfig profilerConfig = this.getProfilerConfig();
// if (profilerConfig.isJdbcProfileOracleSetAutoCommit()) {
// Interceptor setAutocommit = new TransactionSetAutoCommitInterceptor();
// oracleConnection.addGroupInterceptor("setAutoCommit", new String[]{"boolean"}, setAutocommit, OracleScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileOracleCommit()) {
// Interceptor commit = new TransactionCommitInterceptor();
// oracleConnection.addGroupInterceptor("commit", null, commit, OracleScope.SCOPE_NAME);
// }
// if (profilerConfig.isJdbcProfileOracleRollback()) {
// Interceptor rollback = new TransactionRollbackInterceptor();
// oracleConnection.addGroupInterceptor("rollback", null, rollback, OracleScope.SCOPE_NAME);
// }
if (this.logger.isInfoEnabled()) {
this.logger.info("{} class is converted.", javassistClassName);
}
return oracleConnection.toBytecode();
} catch (InstrumentException e) {
if (logger.isWarnEnabled()) {
logger.warn("{} modify fail. Cause:{}", this.getClass().getSimpleName(), e.getMessage(), e);
}
return null;
}
}
}
@@ -1,92 +0,0 @@
/*
* Copyright 2014 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.parser;
/**
* @author emeroad
*/
public class Address {
private String protocol;
private String host;
private String port;
public Address(String protocol, String host, String port) {
this.protocol = protocol;
this.host = host;
this.port = port;
}
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Address address = (Address) o;
if (host != null ? !host.equals(address.host) : address.host != null) return false;
if (port != null ? !port.equals(address.port) : address.port != null) return false;
if (protocol != null ? !protocol.equals(address.protocol) : address.protocol != null) return false;
return true;
}
@Override
public int hashCode() {
int result = protocol != null ? protocol.hashCode() : 0;
result = 31 * result + (host != null ? host.hashCode() : 0);
result = 31 * result + (port != null ? port.hashCode() : 0);
return result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Address");
sb.append("{protocol='").append(protocol).append('\'');
sb.append(", host='").append(host).append('\'');
sb.append(", port='").append(port).append('\'');
sb.append('}');
return sb.toString();
}
}
@@ -1,165 +0,0 @@
/*
* Copyright 2014 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.parser;
import java.util.ArrayList;
import java.util.List;
/**
* @author emeroad
*/
public class Description {
private String serviceName;
private String sid;
private ArrayList<Address> addressList = new ArrayList<Address>();
public Description() {
}
public Description(KeyValue keyValue) {
if (keyValue == null) {
throw new NullPointerException("keyValue");
}
mapping(keyValue);
}
private void mapping(KeyValue keyValue) {
if (!compare("description", keyValue)) {
throw new OracleConnectionStringException("description node not found");
}
for (KeyValue kv : keyValue.getKeyValueList()) {
if (compare("address", kv)) {
String host = null;
String port = null;
String protocol = null;
for (KeyValue address : kv.getKeyValueList()) {
if (compare("host", address)) {
host = address.getValue();
} else if (compare("port", address)) {
port = address.getValue();
} else if(compare("protocol", address)) {
protocol = address.getValue();
}
}
this.addAddress(protocol, host, port);
} else if(compare("connect_data", kv)) {
for (KeyValue connectData : kv.getKeyValueList()) {
if (compare("service_name", connectData)) {
this.serviceName = connectData.getValue();
} else if(compare("sid", connectData)) {
// sid also needed to check compatibility.
this.sid = connectData.getValue();
}
}
}
}
}
private boolean compare(String value, KeyValue kv) {
if (kv == null) {
return false;
}
return value.equals(kv.getKey());
}
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public List<String> getJdbcHost() {
List<String> hostList = new ArrayList<String>();
for(Address address : addressList) {
String host = address.getHost();
String port = address.getPort();
if(port == null) {
// set default port
port = "1521";
}
hostList.add(host + ":" + port);
}
return hostList;
}
public String getDatabaseId() {
// Find serviceName first
String serviceName = getServiceName();
if(serviceName != null) {
return serviceName;
}
// Use sid if serviceName is not available
String sid = getSid();
if (sid != null) {
return sid;
}
return "oracleDatabaseId not found";
}
public void addAddress(String protocol, String host, String port) {
this.addressList.add(new Address(protocol, host, port));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Description that = (Description) o;
if (addressList != null ? !addressList.equals(that.addressList) : that.addressList != null) return false;
if (serviceName != null ? !serviceName.equals(that.serviceName) : that.serviceName != null) return false;
if (sid != null ? !sid.equals(that.sid) : that.sid != null) return false;
return true;
}
@Override
public int hashCode() {
int result = serviceName != null ? serviceName.hashCode() : 0;
result = 31 * result + (sid != null ? sid.hashCode() : 0);
result = 31 * result + (addressList != null ? addressList.hashCode() : 0);
return result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Description");
sb.append("{serviceName='").append(serviceName).append('\'');
sb.append(", sid='").append(sid).append('\'');
sb.append(", addressList=").append(addressList);
sb.append('}');
return sb.toString();
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2014 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.parser;
/**
* @author emeroad
*/
public enum DriverType {
THIN, OCI
}
@@ -1,98 +0,0 @@
/*
* Copyright 2014 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.parser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author emeroad
*/
public class KeyValue {
public String key;
public String value;
public List<KeyValue> keyValueList;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public List<KeyValue> getKeyValueList() {
if (keyValueList == null) {
return Collections.emptyList();
}
return keyValueList;
}
public void addKeyValueList(KeyValue keyValue) {
if (keyValueList == null) {
keyValueList = new ArrayList<KeyValue>();
}
this.keyValueList.add(keyValue);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("{key='").append(key).append('\'');
if (value != null) {
sb.append(", value='").append(value).append('\'');
}
if (keyValueList != null) {
sb.append(", keyValueList=").append(keyValueList);
}
sb.append('}');
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
KeyValue keyValue = (KeyValue) o;
if (key != null ? !key.equals(keyValue.key) : keyValue.key != null) return false;
if (keyValueList != null ? !keyValueList.equals(keyValue.keyValueList) : keyValue.keyValueList != null) return false;
if (value != null ? !value.equals(keyValue.value) : keyValue.value != null) return false;
return true;
}
@Override
public int hashCode() {
int result = key != null ? key.hashCode() : 0;
result = 31 * result + (value != null ? value.hashCode() : 0);
result = 31 * result + (keyValueList != null ? keyValueList.hashCode() : 0);
return result;
}
}
@@ -1,40 +0,0 @@
/*
* Copyright 2014 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.parser;
import com.navercorp.pinpoint.exception.PinpointException;
/**
* @author emeroad
*/
public class OracleConnectionStringException extends PinpointException {
public OracleConnectionStringException() {
}
public OracleConnectionStringException(String message) {
super(message);
}
public OracleConnectionStringException(String message, Throwable cause) {
super(message, cause);
}
public OracleConnectionStringException(Throwable cause) {
super(cause);
}
}
@@ -1,148 +0,0 @@
/*
* Copyright 2014 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.parser;
/**
* @author emeroad
*/
public class OracleNetConnectionDescriptorParser {
private static String THIN = "jdbc:oracle:thin";
private static String OCI = "jdbc:oracle:oci";
private String url;
private String normalizedUrl;
private DriverType driverType;
private OracleNetConnectionDescriptorTokenizer tokenizer;
public OracleNetConnectionDescriptorParser(String url) {
this.url = url;
this.normalizedUrl = url.toLowerCase();
this.tokenizer = new OracleNetConnectionDescriptorTokenizer(normalizedUrl);
}
public KeyValue parse() {
// You can find driver spec here: http://docs.oracle.com/cd/B14117_01/java.101/b10979/urls.htm
// It's for 10g but maybe 11g would be same.
int position;
if (normalizedUrl.startsWith(THIN)) {
position = nextPosition(THIN);
driverType = DriverType.THIN;
} else if(normalizedUrl.startsWith(OCI)) {
position = nextPosition(OCI);
driverType = DriverType.OCI;
} else {
throw new IllegalArgumentException("invalid oracle jdbc url. expected token:(" + THIN + " or " + OCI + ") url:" + url);
}
// skip thin string
this.tokenizer.setPosition(position);
this.tokenizer.parse();
KeyValue keyValue = parseKeyValue();
checkEof();
return keyValue;
}
private void checkEof() {
Token eof = this.tokenizer.nextToken();
if (eof == null) {
throw new OracleConnectionStringException("parsing error. expected token:'EOF' token:null");
}
if (eof != OracleNetConnectionDescriptorTokenizer.TOKEN_EOF_OBJECT) {
throw new OracleConnectionStringException("parsing error. expected token:'EOF' token:" + eof);
}
}
public DriverType getDriverType() {
return driverType;
}
private int nextPosition(String driverUrl) {
final int thinLength = driverUrl.length();
if (normalizedUrl.startsWith(":@", thinLength)) {
return thinLength + 2;
} else if(normalizedUrl.startsWith("@", thinLength)) {
return thinLength + 1;
} else {
throw new OracleConnectionStringException("invalid oracle jdbc url:" + driverUrl);
}
}
private KeyValue parseKeyValue() {
// start
this.tokenizer.checkStartToken();
KeyValue keyValue = new KeyValue();
// key
Token literalToken = this.tokenizer.getLiteralToken();
keyValue.setKey(literalToken.getToken());
// =
this.tokenizer.checkEqualToken();
// value compare reduce
boolean nonTerminalValue = false;
while(true) {
final Token token = this.tokenizer.lookAheadToken();
if (token == null) {
// Abnormal termination.
throw new OracleConnectionStringException("Syntax error. lookAheadToken is null");
}
if (token.getType() == OracleNetConnectionDescriptorTokenizer.TYPE_KEY_START) {
nonTerminalValue = true;
KeyValue child = parseKeyValue();
keyValue.addKeyValueList(child);
// if next token is ')', value is completed.
Token endCheck = this.tokenizer.lookAheadToken();
if (endCheck == OracleNetConnectionDescriptorTokenizer.TOKEN_KEY_END_OBJECT) {
this.tokenizer.nextPosition();
return keyValue;
}
} else if(token.getType() == OracleNetConnectionDescriptorTokenizer.TYPE_LITERAL) {
if (nonTerminalValue) {
throw new OracleConnectionStringException("Syntax error. expected token:'(' or ')' :" + token.getToken());
}
// We already have checked current token by lookAheadToken(). Proceed to next token.
this.tokenizer.nextPosition();
keyValue.setValue(token.getToken());
this.tokenizer.checkEndToken();
return keyValue;
} else if(token.getType() == OracleNetConnectionDescriptorTokenizer.TYPE_KEY_END){
this.tokenizer.nextPosition();
// This could happen if value is empty.
// Does it allow empty value?
return keyValue;
} else {
// Cannot reach here because we checked all those possible cases, START, END and LITERAL.
// Adding new token type could cause error.
// In case of syntax error, EOF can come to here.
throw new OracleConnectionStringException("Syntax error. " + token.getToken());
}
}
}
}
@@ -1,241 +0,0 @@
/*
* Copyright 2014 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.parser;
import java.util.ArrayList;
import java.util.List;
/**
* @author emeroad
*/
public class OracleNetConnectionDescriptorTokenizer {
public static final char TOKEN_EQUAL = '=';
public static final char TOKEN_KEY_START = '(';
public static final char TOKEN_KEY_END = ')';
// Connection methodDescriptor can contain below tokens too.
// But we don't support them right now.
private static final char TOKEN_COMMA = ',';
private static final char TOKEN_BKSLASH = '\\';
private static final char TOKEN_DQUOTE = '"';
private static final char TOKEN_SQUOTE = '\'';
public static final int TYPE_KEY_START = 0;
public static final Token TOKEN_KEY_START_OBJECT = new Token(String.valueOf(TOKEN_KEY_START), TYPE_KEY_START);
public static final int TYPE_KEY_END = 1;
public static final Token TOKEN_KEY_END_OBJECT = new Token(String.valueOf(TOKEN_KEY_END), TYPE_KEY_END);
public static final int TYPE_EQUAL = 2;
public static final Token TOKEN_EQUAL_OBJECT = new Token(String.valueOf(TOKEN_EQUAL), TYPE_EQUAL);
public static final int TYPE_LITERAL = 3;
public static final int TYPE_EOF = -1;
public static final Token TOKEN_EOF_OBJECT = new Token("EOF", TYPE_EOF);
private final List<Token> tokenList = new ArrayList<Token>();
private int tokenPosition = 0;
private final String connectionString;
private int position = 0;
public OracleNetConnectionDescriptorTokenizer(String connectionString) {
if (connectionString == null) {
throw new NullPointerException("connectionString");
}
this.connectionString = connectionString;
}
public void parse() {
final int length = connectionString.length();
for (; position < length; position++) {
final char ch = connectionString.charAt(position);
if (isWhiteSpace(ch)) {
continue;
}
switch (ch) {
case TOKEN_KEY_START:
this.tokenList.add(TOKEN_KEY_START_OBJECT);
break;
case TOKEN_EQUAL:
this.tokenList.add(TOKEN_EQUAL_OBJECT);
break;
case TOKEN_KEY_END:
this.tokenList.add(TOKEN_KEY_END_OBJECT);
break;
case TOKEN_COMMA:
case TOKEN_BKSLASH:
case TOKEN_DQUOTE:
case TOKEN_SQUOTE:
// TODO handle these tokens.
// Need to study how these tokens are used.
throw new OracleConnectionStringException("unsupported token:" + ch);
default:
String literal = parseLiteral();
addToken(literal, TYPE_LITERAL);
}
}
this.tokenList.add(TOKEN_EOF_OBJECT);
}
String parseLiteral() {
int start = trimLeft();
for (position = start; position < connectionString.length(); position++) {
final char ch = connectionString.charAt(position);
switch (ch) {
case TOKEN_EQUAL:
case TOKEN_KEY_START:
case TOKEN_KEY_END:
int end = trimRight(position);
// step back position because last seen character is not part of this literal.
position--;
return connectionString.substring(start, end);
default:
}
}
// end of the string.
int end = trimRight(position);
return connectionString.substring(start, end);
}
int trimRight(int index) {
int end = index;
for (; end > 0 ; end--) {
final char ch = connectionString.charAt(end-1);
if (!isWhiteSpace(ch)) {
return end;
}
}
return end;
}
int trimLeft() {
final int length = connectionString.length();
int start = position;
for (; start < length; start++) {
final char ch = connectionString.charAt(start);
if (!isWhiteSpace(ch)) {
return start;
}
}
return start;
}
private void addToken(String tokenString, int type) {
Token token = new Token(tokenString, type);
this.tokenList.add(token);
}
private boolean isWhiteSpace(char ch) {
return (ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r');
}
public Token nextToken() {
if (tokenList.size() <= tokenPosition) {
return null;
}
Token token = tokenList.get(tokenPosition);
tokenPosition++;
return token;
}
public void nextPosition() {
if (tokenList.size() <= tokenPosition) {
return;
}
tokenPosition++;
}
public Token lookAheadToken() {
if (tokenList.size() <= tokenPosition) {
return null;
}
return tokenList.get(tokenPosition);
}
public void setPosition(int position) {
this.position = position;
}
public void checkStartToken() {
Token token = this.nextToken();
if (token == null) {
throw new OracleConnectionStringException("parse error. token is null");
}
// We can check by == because the token object is singleton.
if (!(token == TOKEN_KEY_START_OBJECT)) {
throw new OracleConnectionStringException("syntax error. Expected token='(' :" + token.getToken());
}
}
public void checkEqualToken() {
Token token = this.nextToken();
if (token == null) {
throw new OracleConnectionStringException("parse error. token is null. Expected token='='");
}
// We can check by == because the token object is singleton.
if (!(token == TOKEN_EQUAL_OBJECT)) {
throw new OracleConnectionStringException("Syntax error. Expected token='=' :" + token.getToken());
}
}
public void checkEndToken() {
Token token = this.nextToken();
if (token == null) {
throw new OracleConnectionStringException("parse error. token is null. Expected token=')");
}
// We can check by == because the token object is singleton.
if (!(token == TOKEN_KEY_END_OBJECT)) {
throw new OracleConnectionStringException("Syntax error. Expected token=')' :" + token.getToken());
}
}
public Token getLiteralToken() {
Token token = this.nextToken();
if (token == null) {
throw new OracleConnectionStringException("parse error. token is null. Expected token='LITERAL'");
}
// We can check by == because the token object is singleton.
if (!(token.getType() == TYPE_LITERAL)) {
throw new OracleConnectionStringException("Syntax error. Expected token='LITERAL'' :" + token.getToken());
}
return token;
}
public Token getLiteralToken(String expectedValue) {
Token token = this.nextToken();
if (token == null) {
throw new OracleConnectionStringException("parse error. token is null. Expected token='LITERAL'");
}
// We can check by == because the token object is singleton.
if (!(token.getType() == TYPE_LITERAL)) {
throw new OracleConnectionStringException("Syntax error. Expected token='LITERAL' :" + token.getToken());
}
if (!expectedValue.equals(token.getToken())) {
throw new OracleConnectionStringException("Syntax error. Expected token=" + expectedValue + "' :" + token.getToken());
}
return token;
}
}
@@ -1,57 +0,0 @@
/*
* Copyright 2014 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.parser;
/**
* @author emeroad
*/
public class Token {
private String token;
private int type;
public Token(String token, int type) {
this.token = token;
this.type = type;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Token");
sb.append("{token='").append(token).append('\'');
sb.append(", type=").append(type);
sb.append('}');
return sb.toString();
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2014 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.log;
/**
* @author minwoo.jung
*/
public class MdcKey {
public static final String TRANSACTION_ID = "PtxId";
public static final String SPAN_ID = "PspanId";
}
@@ -1,96 +0,0 @@
/*
* Copyright 2014 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.log.log4j;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
/**
* This modifier support log4j 1.2.14 version, or greater.
* Because under 1.2.14 version is not exist MDC function and the number of constructor is different
* and under 1.2.14 version is too old.
* By the way 1.2.13 version release on Dec. 2005.
* Refer to url http://mvnrepository.com/artifact/log4j/log4j for detail.
*
* @author minwoo.jung
*/
public class LoggingEventOfLog4jModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public LoggingEventOfLog4jModifier(ByteCodeInstrumentor byteCodeInstrumentor,Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass mdcClass = byteCodeInstrumentor.getClass(classLoader, "org.apache.log4j.MDC", classFileBuffer);
if (!mdcClass.hasMethod("put", new String[]{"java.lang.String", "java.lang.Object"})) {
logger.warn("modify fail. Because put method does not existed org.apache.log4j.MDC class.");
return null;
}
if (!mdcClass.hasMethod("remove", new String[]{"java.lang.String"})) {
logger.warn("modify fail. Because remove method does not existed org.apache.log4j.MDC class.");
return null;
}
} catch (InstrumentException e) {
logger.warn("modify fail. Because org.apache.log4j.MDC does not existed. Cause:" + e.getMessage(), e);
return null;
}
try {
InstrumentClass loggingEvent = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor interceptor1 = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.navercorp.pinpoint.profiler.modifier.log.log4j.interceptor.LoggingEventOfLog4jInterceptor");
loggingEvent.addConstructorInterceptor(new String[]{"java.lang.String", "org.apache.log4j.Category", "org.apache.log4j.Priority", "java.lang.Object", "java.lang.Throwable"}, interceptor1);
Interceptor interceptor2 = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.navercorp.pinpoint.profiler.modifier.log.log4j.interceptor.LoggingEventOfLog4jInterceptor");
loggingEvent.addConstructorInterceptor(new String[]{"java.lang.String", "org.apache.log4j.Category", "long", "org.apache.log4j.Priority", "java.lang.Object", "java.lang.Throwable"}, interceptor2);
Interceptor interceptor3 = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.navercorp.pinpoint.profiler.modifier.log.log4j.interceptor.LoggingEventOfLog4jInterceptor");
loggingEvent.addConstructorInterceptor(new String[]{"java.lang.String", "org.apache.log4j.Category", "long", "org.apache.log4j.Level", "java.lang.Object", "java.lang.String", "org.apache.log4j.spi.ThrowableInformation", "java.lang.String", "org.apache.log4j.spi.LocationInfo", "java.util.Map"}, interceptor3);
return loggingEvent.toBytecode();
} catch (InstrumentException e) {
logger.warn("modify fail. Cause:" + e.getMessage(), e);
return null;
}
}
@Override
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("org/apache/log4j/spi/LoggingEvent");
}
}
@@ -1,57 +0,0 @@
/*
* Copyright 2014 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.log.log4j.interceptor;
import org.apache.log4j.MDC;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.navercorp.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.navercorp.pinpoint.profiler.modifier.log.MdcKey;
/**
* @author minwoo.jung
*/
public class LoggingEventOfLog4jInterceptor implements SimpleAroundInterceptor, TraceContextSupport, TargetClassLoader {
private TraceContext traceContext;
@Override
public void before(Object target, Object[] args) {
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
MDC.remove(MdcKey.TRANSACTION_ID);
MDC.remove(MdcKey.SPAN_ID);
return;
} else {
MDC.put(MdcKey.TRANSACTION_ID, trace.getTraceId().getTransactionId());
MDC.put(MdcKey.SPAN_ID, String.valueOf(trace.getTraceId().getSpanId()));
}
}
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
}
@@ -1,93 +0,0 @@
/*
* Copyright 2014 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.log.logback;
import java.security.ProtectionDomain;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.profiler.modifier.AbstractModifier;
/**
* This modifier support slf4j 1.4.1 version and logback 0.9.8 version, or greater.
* Because package name of MDC class is different on under those version
* and under those version is too old.
* By the way slf4j 1.4.0 version release on May 2007.
* Refer to url http://mvnrepository.com/artifact/org.slf4j/slf4j-api for detail.
*
* @author minwoo.jung
*/
public class LoggingEventOfLogbackModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public LoggingEventOfLogbackModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass mdcClass = byteCodeInstrumentor.getClass(classLoader, "org.slf4j.MDC", classFileBuffer);
if (!mdcClass.hasMethod("put", new String[]{"java.lang.String", "java.lang.String"})) {
logger.warn("modify fail. Because put method does not existed org.slf4j.MDC class.");
return null;
}
if (!mdcClass.hasMethod("remove", new String[]{"java.lang.String"})) {
logger.warn("modify fail. Because remove method does not existed org.slf4j.MDC class.");
return null;
}
} catch (InstrumentException e) {
logger.warn("modify fail. Because org.slf4j.MDC does not existed. Cause:" + e.getMessage(), e);
return null;
}
try {
InstrumentClass loggingEvent = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
Interceptor interceptor1 = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.navercorp.pinpoint.profiler.modifier.log.logback.interceptor.LoggingEventOfLogbackInterceptor");
loggingEvent.addConstructorInterceptor(new String[]{"java.lang.String", "ch.qos.logback.classic.Logger", "ch.qos.logback.classic.Level", "java.lang.String", "java.lang.Throwable", "java.lang.Object[]"}, interceptor1);
Interceptor interceptor2 = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.navercorp.pinpoint.profiler.modifier.log.logback.interceptor.LoggingEventOfLogbackInterceptor");
loggingEvent.addConstructorInterceptor(new String[]{}, interceptor2);
return loggingEvent.toBytecode();
} catch (InstrumentException e) {
logger.warn("modify fail. Cause:" + e.getMessage(), e);
return null;
}
}
@Override
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("ch/qos/logback/classic/spi/LoggingEvent");
}
}
@@ -1,57 +0,0 @@
/*
* Copyright 2014 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.log.logback.interceptor;
import org.slf4j.MDC;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.TargetClassLoader;
import com.navercorp.pinpoint.bootstrap.interceptor.TraceContextSupport;
import com.navercorp.pinpoint.profiler.modifier.log.MdcKey;
/**
* @author minwoo.jung
*/
public class LoggingEventOfLogbackInterceptor implements SimpleAroundInterceptor, TraceContextSupport, TargetClassLoader {
private TraceContext traceContext;
@Override
public void before(Object target, Object[] args) {
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
MDC.remove(MdcKey.TRANSACTION_ID);
MDC.remove(MdcKey.SPAN_ID);
return;
} else {
MDC.put(MdcKey.TRANSACTION_ID, trace.getTraceId().getTransactionId());
MDC.put(MdcKey.SPAN_ID, String.valueOf(trace.getTraceId().getSpanId()));
}
}
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2014 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.method;
import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod;
/**
* @author emeroad
*/
public class EmptyMethodFilter implements MethodFilter {
public static final MethodFilter FILTER = new EmptyMethodFilter();
@Override
public boolean accept(InstrumentMethod ctMethod) {
return ACCEPT;//ctMethod.isEmpty();
}
}
@@ -1,81 +0,0 @@
/*
* Copyright 2014 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.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.InstrumentMethod;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.method.interceptor.MethodInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author netspider
* @author emeroad
*
*/
public class MethodModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public MethodModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("*");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
InstrumentClass clazz = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
if (!clazz.isInterceptable()) {
return null;
}
List<InstrumentMethod> methodList = clazz.getDeclaredMethods(EmptyMethodFilter.FILTER);
for (InstrumentMethod method : methodList) {
final Interceptor interceptor = new MethodInterceptor();
if (logger.isTraceEnabled()) {
logger.trace("### c={}, m={}, params={}", javassistClassName, method.getName(), Arrays.toString(method.getParameterTypes()));
}
clazz.addInterceptor(method.getName(), method.getParameterTypes(), interceptor);
}
return clazz.toBytecode();
} catch (Exception e) {
logger.warn("modify fail. Cause:{}", e.getMessage(), e);
return null;
}
}
}
@@ -1,100 +0,0 @@
/*
* Copyright 2014 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.method.interceptor;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.*;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.common.trace.ServiceType;
/**
*
* @author netspider
* @author emeroad
*/
public class MethodInterceptor implements SimpleAroundInterceptor, ServiceTypeSupport, ByteCodeMethodDescriptorSupport, TraceContextSupport {
private final PLogger logger = PLoggerFactory.getLogger(MethodInterceptor.class);
private final boolean isDebug = logger.isDebugEnabled();
private MethodDescriptor descriptor;
private TraceContext traceContext;
private ServiceType serviceType = ServiceType.INTERNAL_METHOD;
public MethodInterceptor(TraceContext traceContext, MethodDescriptor descriptor, ServiceType serviceType) {
this.descriptor = descriptor;
this.traceContext = traceContext;
this.serviceType = serviceType;
}
public MethodInterceptor() {
// empty
}
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
SpanEventRecorder recorder = trace.traceBlockBegin();
recorder.recordServiceType(serviceType);
}
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
if (isDebug) {
logger.afterInterceptor(target, args);
}
Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
try {
SpanEventRecorder recorder = trace.currentSpanEventRecorder();
recorder.recordApi(descriptor);
recorder.recordException(throwable);
} finally {
trace.traceBlockEnd();
}
}
public void setServiceType(ServiceType serviceType) {
this.serviceType = serviceType;
}
@Override
public void setMethodDescriptor(MethodDescriptor descriptor) {
this.descriptor = descriptor;
this.traceContext.cacheApi(descriptor);
}
@Override
public void setTraceContext(TraceContext traceContext) {
this.traceContext = traceContext;
}
}
@@ -1,84 +0,0 @@
/*
* Copyright 2014 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.servlet;
import java.security.ProtectionDomain;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.ServiceTypeSupport;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import com.navercorp.pinpoint.profiler.modifier.method.interceptor.MethodInterceptor;
/**
*
* @author netspider
* @author emeroad
*/
public class SpringFrameworkServletModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public SpringFrameworkServletModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
public Matcher getMatcher() {
return Matchers.newClassNameMatcher("org/springframework/web/servlet/FrameworkServlet");
}
public byte[] modify(ClassLoader classLoader, String javassistClassName, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifying. {}", javassistClassName);
}
try {
Interceptor doGetInterceptor = new MethodInterceptor();
setServiceType(doGetInterceptor, ServiceType.UNKNOWN);
Interceptor doPostInterceptor = new MethodInterceptor();
setServiceType(doPostInterceptor, ServiceType.UNKNOWN);
InstrumentClass servlet = byteCodeInstrumentor.getClass(classLoader, javassistClassName, classFileBuffer);
servlet.addInterceptor("doGet", new String[] { "javax.servlet.http.HttpServletRequest", "javax.servlet.http.HttpServletResponse" }, doGetInterceptor);
servlet.addInterceptor("doPost", new String[] { "javax.servlet.http.HttpServletRequest", "javax.servlet.http.HttpServletResponse" }, doPostInterceptor);
return servlet.toBytecode();
} catch (InstrumentException e) {
logger.warn("modify fail. Cause:{}", e.getMessage(), e);
return null;
}
}
private void setServiceType(Interceptor interceptor, ServiceType serviceType) {
if (interceptor instanceof ServiceTypeSupport) {
((ServiceTypeSupport)interceptor).setServiceType(serviceType);
}
}
}
@@ -1,50 +0,0 @@
/*
* Copyright 2014 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.plugin;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.MatchableClassFileTransformer;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
public class ClassFileTransformerAdaptor extends AbstractModifier {
private final MatchableClassFileTransformer transformer;
public ClassFileTransformerAdaptor(ByteCodeInstrumentor byteCodeInstrumentor, MatchableClassFileTransformer transformer) {
super(byteCodeInstrumentor);
this.transformer = transformer;
}
@Override
public byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
try {
return transformer.transform(classLoader, className, null, protectionDomain, classfileBuffer);
} catch (IllegalClassFormatException e) {
throw new PinpointException("Fail to transform class: " + className, e);
}
}
@Override
public Matcher getMatcher() {
return transformer.getMatcher();
}
}
@@ -1,32 +0,0 @@
/*
* Copyright 2014 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.test;
import com.navercorp.pinpoint.profiler.modifier.Modifier;
import com.navercorp.pinpoint.test.util.BytecodeUtils;
public class ClassTransformHelper {
public static Class<?> transformClass(ClassLoader classLoader, String className, Modifier modifier) {
final byte[] original = BytecodeUtils.getClassFile(classLoader, className);
final byte[] transformed = modifier.modify(classLoader, className, null, original);
return BytecodeUtils.defineClass(classLoader, className, transformed);
}
}
@@ -1,72 +0,0 @@
/*
* Copyright 2014 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.test;
import com.navercorp.pinpoint.bootstrap.Agent;
import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchable;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matcher;
import com.navercorp.pinpoint.bootstrap.instrument.matcher.Matchers;
import com.navercorp.pinpoint.bootstrap.interceptor.Interceptor;
import com.navercorp.pinpoint.profiler.modifier.AbstractModifier;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;
/**
* @author emeroad
*/
public abstract class TestModifier extends AbstractModifier {
private String targetClass;
public final List<Interceptor> interceptorList = new ArrayList<Interceptor>();
public TestModifier(ByteCodeInstrumentor byteCodeInstrumentor, ProfilerConfig profilerConfig) {
super(byteCodeInstrumentor, profilerConfig);
}
public void setTargetClass(String targetClass) {
this.targetClass = targetClass;
}
@Override
public Matcher getMatcher() {
return Matchers.newClassNameMatcher(targetClass);
}
public void addInterceptor(Interceptor interceptor) {
this.interceptorList.add(interceptor);
}
public List<Interceptor> getInterceptorList() {
return interceptorList;
}
public Interceptor getInterceptor(int index) {
return interceptorList.get(index);
}
@Override
public abstract byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectedDomain, byte[] classFileBuffer);
}
@@ -1,63 +0,0 @@
/*
* Copyright 2014 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.mysql;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerBinder;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.profiler.logging.Slf4jLoggerBinder;
import com.navercorp.pinpoint.test.MockAgent;
import com.navercorp.pinpoint.test.TestClassLoader;
import org.junit.After;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author emeroad
*/
public class MySQLConnectionImplTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private TestClassLoader loader;
private PLoggerBinder binder = new Slf4jLoggerBinder();
private MockAgent agent;
// @Before
public void setUp() throws Exception {
PLoggerFactory.initialize(new Slf4jLoggerBinder());
agent = MockAgent.of("pinpoint.config");
loader = new TestClassLoader(agent.getProfilerConfig(), agent.getByteCodeInstrumentor(), agent.getClassFileTransformer());
loader.initialize();
}
@After
public void tearDown() throws Exception {
if (agent != null) {
agent.stop();
}
PLoggerFactory.unregister(binder);
}
// @Test
public void test() throws Throwable {
// This is an example of test which loads test class indirectly.
// loader.runTest("com.navercorp.pinpoint.profiler.modifier.db.mysql.MySQLConnectionImplModifierTest", "testModify");
}
}
@@ -1,153 +0,0 @@
/*
* Copyright 2014 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.tomcat;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.util.Enumeration;
import java.util.List;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardHost;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.navercorp.pinpoint.bootstrap.context.Header;
import com.navercorp.pinpoint.common.bo.SpanBo;
import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.common.util.TransactionIdUtils;
import com.navercorp.pinpoint.test.junit4.BasePinpointTest;
import com.navercorp.pinpoint.test.junit4.IsRootSpan;
/**
* @author hyungil.jeong
*/
public class StandardHostValveInvokeModifierTest extends BasePinpointTest {
// private static final ServiceType SERVICE_TYPE = ServiceType.TOMCAT;
private static final String REQUEST_URI = "testRequestUri";
private static final String SERVER_NAME = "serverForTest";
private static final int SERVER_PORT = 19999;
private static final String REMOTE_ADDRESS = "1.1.1.1";
private static final Enumeration<String> EMPTY_PARAM_KEYS = new Enumeration<String>() {
@Override
public boolean hasMoreElements() {
return false;
}
@Override
public String nextElement() {
return null;
}
};
private StandardHost host;
@Mock
private Request mockRequest;
@Mock
private Response mockResponse;
@Before
public void setUp() throws Exception {
// MockitoAnnotations.initMocks(this);
// initMockRequest();
// // StandardHost's default constructor sets StandardHostValve as the first item in the pipeline.
// host = new StandardHost();
}
private void initMockRequest() {
when(mockRequest.getRequestURI()).thenReturn(REQUEST_URI);
when(mockRequest.getServerName()).thenReturn(SERVER_NAME);
when(mockRequest.getServerPort()).thenReturn(SERVER_PORT);
when(mockRequest.getRemoteAddr()).thenReturn(REMOTE_ADDRESS);
when(mockRequest.getParameterNames()).thenReturn(EMPTY_PARAM_KEYS);
}
@Test
@IsRootSpan
public void invokeShouldBeTraced() throws Exception {
// // Given
// // When
// host.invoke(mockRequest, mockResponse);
// // Then
// final List<SpanBo> rootSpans = getCurrentRootSpans();
// assertEquals(rootSpans.size(), 1);
//
// final SpanBo rootSpan = rootSpans.get(0);
// assertEquals(rootSpan.getParentSpanId(), -1);
// assertEquals(rootSpan.getServiceType(), SERVICE_TYPE.getCode());
// assertEquals(rootSpan.getRpc(), REQUEST_URI);
// assertEquals(rootSpan.getEndPoint(), SERVER_NAME + ":" + SERVER_PORT);
// assertEquals(rootSpan.getRemoteAddr(), REMOTE_ADDRESS);
}
@Test
@IsRootSpan
public void invokeShouldTraceExceptions() throws Exception {
// // Given
// when(mockRequest.getContext()).thenThrow(new RuntimeException("expected exception."));
// // When
// try {
// host.invoke(mockRequest, mockResponse);
// assertTrue(false);
// } catch (RuntimeException e) {
// // Then
// final List<SpanBo> rootSpans = getCurrentRootSpans();
// assertEquals(rootSpans.size(), 1);
//
// final SpanBo rootSpan = rootSpans.get(0);
// assertEquals(rootSpan.getParentSpanId(), -1);
// assertEquals(rootSpan.getServiceType(), SERVICE_TYPE.getCode());
// assertTrue(rootSpan.hasException());
// }
}
@Test
@IsRootSpan
public void invokeShouldContinueTracingFromRequest() throws Exception {
// // Given
// // Set Transaction ID from remote source.
// final String sourceAgentId = "agentId";
// final long sourceAgentStartTime = 1234567890123L;
// final long sourceTransactionSequence = 12345678L;
// final String sourceTransactionId = TransactionIdUtils.formatString(sourceAgentId, sourceAgentStartTime, sourceTransactionSequence);
// when(mockRequest.getHeader(Header.HTTP_TRACE_ID.toString())).thenReturn(sourceTransactionId);
// // Set parent Span ID from remote source.
// final long sourceParentId = 99999;
// when(mockRequest.getHeader(Header.HTTP_PARENT_SPAN_ID.toString())).thenReturn(String.valueOf(sourceParentId));
// // When
// host.invoke(mockRequest, mockResponse);
// // Then
// final List<SpanBo> rootSpans = getCurrentRootSpans();
// assertEquals(rootSpans.size(), 1);
//
// final SpanBo rootSpan = rootSpans.get(0);
// // Check Transaction ID from remote source.
// assertEquals(rootSpan.getTransactionId(), sourceTransactionId);
// assertEquals(rootSpan.getTraceAgentId(), sourceAgentId);
// assertEquals(rootSpan.getTraceAgentStartTime(), sourceAgentStartTime);
// assertEquals(rootSpan.getTraceTransactionSequence(), sourceTransactionSequence);
// // Check parent Span ID from remote source.
// assertEquals(rootSpan.getParentSpanId(), sourceParentId);
}
}