Merge branch 'master' of kimjh008/pinpoint

from pull-request 127

* refs/heads/master:
  #70 remove unused code
  #70 redis&nBase-ARC interceptor master merge
  Merge commit 'e337411e0a98d8bd2c2d577d6b04457905b260b2'
  Merge branch 'master' of http://yobi.navercorp.com/pinpoint/pinpoint
  #7 add super class interceptor
  Merge branch '1.0.3'
  Merge branch '1.0.3' of kimjh008/pinpoint
  #70 redis&nBase-ARC interceptor
  Merge branch '#67_add_api_getDeclaredMethodsForce' of emeroad/pinpoint
  [#67] add api getDeclaredMethodsForce
  [#58] change collector server domain address (nhncorp.com -> navercorp.com)
  Merge branch '1.0.3' of kimjh008/pinpoint
  #65 add chkLibrary
  Merge branch 'master' of pinpoint/pinpoint
This commit is contained in:
Jaehong Kim
2014-11-03 18:24:17 +09:00
24 changed files with 616 additions and 125 deletions
@@ -61,13 +61,19 @@ import com.nhn.pinpoint.profiler.modifier.orm.ibatis.SqlMapClientImplModifier;
import com.nhn.pinpoint.profiler.modifier.orm.ibatis.SqlMapSessionImplModifier;
import com.nhn.pinpoint.profiler.modifier.orm.mybatis.DefaultSqlSessionModifier;
import com.nhn.pinpoint.profiler.modifier.orm.mybatis.SqlSessionTemplateModifier;
import com.nhn.pinpoint.profiler.modifier.redis.BinaryJedisModifier;
import com.nhn.pinpoint.profiler.modifier.redis.BinaryRedisClusterModifier;
import com.nhn.pinpoint.profiler.modifier.redis.BinaryTriplesRedisClusterModifier;
import com.nhn.pinpoint.profiler.modifier.redis.GatewayModifier;
import com.nhn.pinpoint.profiler.modifier.redis.GatewayServerModifier;
import com.nhn.pinpoint.profiler.modifier.redis.JedisClientModifier;
import com.nhn.pinpoint.profiler.modifier.redis.JedisModifier;
import com.nhn.pinpoint.profiler.modifier.redis.JedisMultiKeyPipelineBaseModifier;
import com.nhn.pinpoint.profiler.modifier.redis.JedisPipelineBaseModifier;
import com.nhn.pinpoint.profiler.modifier.redis.JedisPipelineModifier;
import com.nhn.pinpoint.profiler.modifier.redis.RedisClusterModifier;
import com.nhn.pinpoint.profiler.modifier.redis.RedisClusterPipelineModifier;
import com.nhn.pinpoint.profiler.modifier.redis.TriplesRedisClusterModifier;
import com.nhn.pinpoint.profiler.modifier.servlet.HttpServletModifier;
import com.nhn.pinpoint.profiler.modifier.servlet.SpringFrameworkServletModifier;
import com.nhn.pinpoint.profiler.modifier.spring.beans.AbstractAutowireCapableBeanFactoryModifier;
@@ -388,11 +394,14 @@ public class DefaultModifierRegistry implements ModifierRegistry {
public void addRedisSupport() {
if(profilerConfig.isRedisEnabled()) {
addModifier(new BinaryJedisModifier(byteCodeInstrumentor, agent));
addModifier(new JedisModifier(byteCodeInstrumentor, agent));
}
if(profilerConfig.isRedisPipelineEnabled()) {
addModifier(new JedisClientModifier(byteCodeInstrumentor, agent));
addModifier(new JedisPipelineBaseModifier(byteCodeInstrumentor, agent));
addModifier(new JedisMultiKeyPipelineBaseModifier(byteCodeInstrumentor, agent));
addModifier(new JedisPipelineModifier(byteCodeInstrumentor, agent));
}
}
@@ -404,6 +413,9 @@ public class DefaultModifierRegistry implements ModifierRegistry {
if(profilerConfig.isNbaseArcEnabled()) {
addModifier(new RedisClusterModifier(byteCodeInstrumentor, agent));
addModifier(new BinaryRedisClusterModifier(byteCodeInstrumentor, agent));
addModifier(new TriplesRedisClusterModifier(byteCodeInstrumentor, agent));
addModifier(new BinaryTriplesRedisClusterModifier(byteCodeInstrumentor, agent));
}
if(profilerConfig.isNbaseArcPipelineEnabled()) {
@@ -0,0 +1,34 @@
package com.nhn.pinpoint.profiler.modifier.redis;
import java.security.ProtectionDomain;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentException;
import com.nhn.pinpoint.bootstrap.instrument.NotFoundInstrumentException;
import com.nhn.pinpoint.bootstrap.interceptor.tracevalue.MapTraceValue;
/**
* jedis(redis client) modifier
*
* @author jaehong.kim
*
*/
public class BinaryJedisModifier extends JedisModifier {
public BinaryJedisModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "redis/clients/jedis/BinaryJedis";
}
@Override
protected void beforeAddInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
// trace endPoint.
instrumentClass.addTraceValue(MapTraceValue.class);
}
}
@@ -0,0 +1,22 @@
package com.nhn.pinpoint.profiler.modifier.redis;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
/**
* RedisCluster(nBase-ARC client) modifier
*
* @author jaehong.kim
*
*/
public class BinaryRedisClusterModifier extends RedisClusterModifier {
public BinaryRedisClusterModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "com/nhncorp/redis/cluster/BinaryRedisCluster";
}
}
@@ -0,0 +1,34 @@
package com.nhn.pinpoint.profiler.modifier.redis;
import java.security.ProtectionDomain;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentException;
import com.nhn.pinpoint.bootstrap.instrument.NotFoundInstrumentException;
import com.nhn.pinpoint.bootstrap.interceptor.tracevalue.MapTraceValue;
/**
* RedisCluster(nBase-ARC client) modifier
*
* @author jaehong.kim
*
*/
public class BinaryTriplesRedisClusterModifier extends RedisClusterModifier {
public BinaryTriplesRedisClusterModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "com/nhncorp/redis/cluster/triples/BinaryTriplesRedisCluster";
}
@Override
protected void beforeAddInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
// trace destinationId, endPoint
instrumentClass.addTraceValue(MapTraceValue.class);
}
}
@@ -61,7 +61,7 @@ public class GatewayModifier extends AbstractModifier {
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("redis.GatewayModifier(nBase-ARC) fail. Target class is " + getTargetClass() + ", Caused " + e.getMessage(), e);
logger.warn("Failed to modifier. caused={}", e.getMessage(), e);
}
}
@@ -59,7 +59,7 @@ public class GatewayServerModifier extends AbstractModifier {
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("redis.GatewayServerModifier(nBase-ARC) fail. Target class is " + getTargetClass() + ", Caused " + e.getMessage(), e);
logger.warn("Failed to modifier. caused={}", e.getMessage(), e);
}
}
@@ -52,7 +52,7 @@ public class JedisClientModifier extends AbstractModifier {
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("redis.JedisClientModifier(Jedis) fail. Target class is " + getTargetClass() + ". Caused " + e.getMessage(), e);
logger.warn("Failed to modifier. caused={}", e.getMessage(), e);
}
}
@@ -9,12 +9,13 @@ import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentException;
import com.nhn.pinpoint.bootstrap.instrument.MethodInfo;
import com.nhn.pinpoint.bootstrap.instrument.NotFoundInstrumentException;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.bootstrap.interceptor.tracevalue.MapTraceValue;
import com.nhn.pinpoint.profiler.modifier.AbstractModifier;
import com.nhn.pinpoint.profiler.modifier.redis.filter.NameBasedMethodFilter;
import com.nhn.pinpoint.profiler.modifier.redis.filter.JedisMethodNames;
import com.nhn.pinpoint.profiler.modifier.redis.filter.NameBasedMethodFilter;
/**
* jedis(redis client) modifier
@@ -24,7 +25,7 @@ import com.nhn.pinpoint.profiler.modifier.redis.filter.JedisMethodNames;
*/
public class JedisModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
public JedisModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
@@ -45,34 +46,49 @@ public class JedisModifier extends AbstractModifier {
try {
final InstrumentClass instrumentClass = byteCodeInstrumentor.getClass(className);
// trace endPoint
instrumentClass.addTraceValue(MapTraceValue.class);
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisConstructorInterceptor");
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String" }, constructorInterceptor);
try {
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int", "int" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.net.URI" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "redis.clients.jedis.JedisShardInfo" }, constructorInterceptor);
} catch (Exception ignored) {
// backward compatibility error
}
beforeAddInterceptor(classLoader, protectedDomain, instrumentClass);
// method
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(JedisMethodNames.get()));
for (MethodInfo method : declaredMethods) {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
}
// add constructor
addConstructorInterceptor(classLoader, protectedDomain, instrumentClass);
// add method
addMethodInterceptor(classLoader, protectedDomain, instrumentClass);
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("redis.JedisModifier(Jedis) fail. Target class is " + getTargetClass() + ". Caused " + e.getMessage(), e);
logger.warn("Failed to modifier. caused={}", e.getMessage(), e);
}
}
return null;
}
}
protected void beforeAddInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
// nothing
}
protected void addConstructorInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws InstrumentException, NotFoundInstrumentException {
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisConstructorInterceptor");
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String" }, constructorInterceptor);
try {
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int", "int" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.net.URI" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "redis.clients.jedis.JedisShardInfo" }, constructorInterceptor);
} catch (Exception e) {
// backward compatibility error
if (logger.isWarnEnabled()) {
logger.warn("Failed to add constructor interceptor('not found redis.clients.jedis.JedisShardInfo' is compatibility error). caused={}", e.getMessage(), e);
}
}
}
protected void addMethodInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(JedisMethodNames.get()));
for (MethodInfo method : declaredMethods) {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
}
}
}
@@ -0,0 +1,22 @@
package com.nhn.pinpoint.profiler.modifier.redis;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
/**
* jedis(redis client) pipeline modifier
*
* @author jaehong.kim
*
*/
public class JedisMultiKeyPipelineBaseModifier extends JedisPipelineBaseModifier {
public JedisMultiKeyPipelineBaseModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "redis/clients/jedis/MultiKeyPipelineBase";
}
}
@@ -0,0 +1,75 @@
package com.nhn.pinpoint.profiler.modifier.redis;
import java.security.ProtectionDomain;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentException;
import com.nhn.pinpoint.bootstrap.instrument.MethodInfo;
import com.nhn.pinpoint.bootstrap.instrument.NotFoundInstrumentException;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.profiler.modifier.AbstractModifier;
import com.nhn.pinpoint.profiler.modifier.redis.filter.JedisPipelineMethodNames;
import com.nhn.pinpoint.profiler.modifier.redis.filter.NameBasedMethodFilter;
/**
* jedis(redis client) pipeline modifier
*
* @author jaehong.kim
*
*/
public class JedisPipelineBaseModifier extends AbstractModifier {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
public JedisPipelineBaseModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "redis/clients/jedis/PipelineBase";
}
@Override
public byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {}", className);
}
byteCodeInstrumentor.checkLibrary(classLoader, className);
try {
final InstrumentClass instrumentClass = byteCodeInstrumentor.getClass(className);
beforeAddInterceptor(classLoader, protectedDomain, instrumentClass);
// method
addMethodInterceptor(classLoader, protectedDomain, instrumentClass);
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to modifier. caused={}", e.getMessage(), e);
}
}
return null;
}
protected void beforeAddInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
// nothing
}
protected void addMethodInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(JedisPipelineMethodNames.get()));
for (MethodInfo method : declaredMethods) {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisPipelineMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
}
}
}
@@ -1,20 +1,15 @@
package com.nhn.pinpoint.profiler.modifier.redis;
import java.security.ProtectionDomain;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentException;
import com.nhn.pinpoint.bootstrap.instrument.MethodInfo;
import com.nhn.pinpoint.bootstrap.instrument.NotFoundInstrumentException;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.bootstrap.interceptor.tracevalue.MapTraceValue;
import com.nhn.pinpoint.profiler.modifier.AbstractModifier;
import com.nhn.pinpoint.profiler.modifier.redis.filter.JedisPipelineMethodNames;
import com.nhn.pinpoint.profiler.modifier.redis.filter.NameBasedMethodFilter;
/**
* jedis(redis client) pipeline modifier
@@ -22,9 +17,7 @@ import com.nhn.pinpoint.profiler.modifier.redis.filter.NameBasedMethodFilter;
* @author jaehong.kim
*
*/
public class JedisPipelineModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public class JedisPipelineModifier extends JedisPipelineBaseModifier {
public JedisPipelineModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
@@ -35,50 +28,34 @@ public class JedisPipelineModifier extends AbstractModifier {
return "redis/clients/jedis/Pipeline";
}
@Override
public byte[] modify(ClassLoader classLoader, String className, ProtectionDomain protectedDomain, byte[] classFileBuffer) {
if (logger.isInfoEnabled()) {
logger.info("Modifing. {}", className);
}
protected void beforeAddInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
// trace endPoint
instrumentClass.addTraceValue(MapTraceValue.class);
byteCodeInstrumentor.checkLibrary(classLoader, className);
try {
final InstrumentClass instrumentClass = byteCodeInstrumentor.getClass(className);
// trace endPoint
instrumentClass.addTraceValue(MapTraceValue.class);
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisPipelineConstructorInterceptor");
try {
// jedis 1.x
instrumentClass.addConstructorInterceptor(new String[] { "redis.clients.jedis.Client" }, constructorInterceptor);
} catch (Exception ignored) {
// backward compatibility error
}
for (MethodInfo method : instrumentClass.getDeclaredMethods()) {
if (method.getName().equals("setClient")) {
// jedis 2.x
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisPipelineSetClientMethodInterceptor");
instrumentClass.addInterceptor("setClient", new String[] { "redis.clients.jedis.Client" }, methodInterceptor);
}
}
// method
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(JedisPipelineMethodNames.get()));
for (MethodInfo method : declaredMethods) {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisPipelineMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
}
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("redis.JedisPipelineModifier(Jedis) fail. Target class is " + getTargetClass() + ". Caused " + e.getMessage(), e);
}
}
return null;
addConstructorInterceptor(classLoader, protectedDomain, instrumentClass);
addSetClientMethodInterceptor(classLoader, protectedDomain, instrumentClass);
}
}
private void addSetClientMethodInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws NotFoundInstrumentException, InstrumentException {
for (MethodInfo method : instrumentClass.getDeclaredMethods()) {
if (method.getName().equals("setClient")) {
// jedis 2.x
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisPipelineSetClientMethodInterceptor");
instrumentClass.addInterceptor("setClient", new String[] { "redis.clients.jedis.Client" }, methodInterceptor);
}
}
}
private void addConstructorInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws InstrumentException {
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.JedisPipelineConstructorInterceptor");
try {
// jedis 1.x
instrumentClass.addConstructorInterceptor(new String[] { "redis.clients.jedis.Client" }, constructorInterceptor);
} catch (Exception e) {
// backward compatibility error
if (logger.isWarnEnabled()) {
logger.warn("Failed to add constructor interceptor(only jedis 1.x). caused={}", e.getMessage(), e);
}
}
}
}
@@ -9,9 +9,10 @@ import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentException;
import com.nhn.pinpoint.bootstrap.instrument.MethodInfo;
import com.nhn.pinpoint.bootstrap.instrument.NotFoundInstrumentException;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.bootstrap.interceptor.tracevalue.MapTraceValue;
import com.nhn.pinpoint.profiler.modifier.AbstractModifier;
import com.nhn.pinpoint.profiler.modifier.redis.filter.NameBasedMethodFilter;
import com.nhn.pinpoint.profiler.modifier.redis.filter.RedisClusterMethodNames;
@@ -23,8 +24,7 @@ import com.nhn.pinpoint.profiler.modifier.redis.filter.RedisClusterMethodNames;
*
*/
public class RedisClusterModifier extends AbstractModifier {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
public RedisClusterModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
@@ -45,28 +45,47 @@ public class RedisClusterModifier extends AbstractModifier {
try {
final InstrumentClass instrumentClass = byteCodeInstrumentor.getClass(className);
// trace destinationId, endPoint
instrumentClass.addTraceValue(MapTraceValue.class);
beforeAddInterceptor(classLoader, protectedDomain, instrumentClass);
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterConstructorInterceptor");
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int", "int" }, constructorInterceptor);
// add constructor
addConstructorInterceptor(classLoader, protectedDomain, instrumentClass);
// method
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(RedisClusterMethodNames.get()));
for (MethodInfo method : declaredMethods) {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
}
addMethodInterceptor(classLoader, protectedDomain, instrumentClass);
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("redis.RedisClusterModifier(nBase-ARC) fail. Target class is " + getTargetClass() + ", Caused " + e.getMessage(), e);
logger.warn("Failed to modifier. caused={}", e.getMessage(), e);
}
}
return null;
}
protected void beforeAddInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws InstrumentException {
// nothing
}
protected void addMethodInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws InstrumentException {
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(RedisClusterMethodNames.get()));
for (MethodInfo method : declaredMethods) {
try {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to add method interceptor('not found ...' is jedis compatibility error). caused={}", e.getMessage(), e);
}
}
}
}
protected void addConstructorInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws InstrumentException, NotFoundInstrumentException {
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterConstructorInterceptor");
instrumentClass.addConstructorInterceptor(new String[]{"java.lang.String"}, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int" }, constructorInterceptor);
instrumentClass.addConstructorInterceptor(new String[] { "java.lang.String", "int", "int" }, constructorInterceptor);
}
}
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentClass;
import com.nhn.pinpoint.bootstrap.instrument.InstrumentException;
import com.nhn.pinpoint.bootstrap.instrument.MethodInfo;
import com.nhn.pinpoint.bootstrap.interceptor.Interceptor;
import com.nhn.pinpoint.bootstrap.interceptor.tracevalue.MapTraceValue;
@@ -47,28 +48,45 @@ public class RedisClusterPipelineModifier extends AbstractModifier {
// trace destinationId, endPoint
instrumentClass.addTraceValue(MapTraceValue.class);
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterPipelineConstructorInterceptor");
try {
instrumentClass.addConstructorInterceptor(new String[] { "com.nhncorp.redis.cluster.gateway.GatewayServer" }, constructorInterceptor);
} catch (Exception ignored) {
// backward compatibility error
}
addConstructorInterceptor(classLoader, protectedDomain, instrumentClass);
// method
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(RedisClusterPipelineMethodNames.get()));
for (MethodInfo method : declaredMethods) {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterPipelineMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
}
addMethodInterceptor(classLoader, protectedDomain, instrumentClass);
return instrumentClass.toBytecode();
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("redis.RedisClusterPipelineModifier(nBase-ARC) fail. Target class is " + getTargetClass() + ", Caused " + e.getMessage(), e);
logger.warn("Failed to modifier. caused={}", e.getMessage(), e);
}
}
return null;
}
protected void addConstructorInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws InstrumentException {
final Interceptor constructorInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterPipelineConstructorInterceptor");
try {
instrumentClass.addConstructorInterceptor(new String[] { "com.nhncorp.redis.cluster.gateway.GatewayServer" }, constructorInterceptor);
} catch (Exception e) {
// backward compatibility error
if (logger.isWarnEnabled()) {
logger.warn("Failed to add constructor interceptor. caused={}", e.getMessage(), e);
}
}
}
protected void addMethodInterceptor(ClassLoader classLoader, ProtectionDomain protectedDomain, final InstrumentClass instrumentClass) throws InstrumentException {
final List<MethodInfo> declaredMethods = instrumentClass.getDeclaredMethods(new NameBasedMethodFilter(RedisClusterPipelineMethodNames.get()));
for (MethodInfo method : declaredMethods) {
try {
final Interceptor methodInterceptor = byteCodeInstrumentor.newInterceptor(classLoader, protectedDomain, "com.nhn.pinpoint.profiler.modifier.redis.interceptor.RedisClusterPipelineMethodInterceptor");
instrumentClass.addInterceptor(method.getName(), method.getParameterTypes(), methodInterceptor);
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to add method interceptor('not found ...' is jedis compatibility error). caused={}", e.getMessage(), e);
}
}
}
}
}
@@ -0,0 +1,22 @@
package com.nhn.pinpoint.profiler.modifier.redis;
import com.nhn.pinpoint.bootstrap.Agent;
import com.nhn.pinpoint.bootstrap.instrument.ByteCodeInstrumentor;
/**
* RedisCluster(nBase-ARC client) modifier
*
* @author jaehong.kim
*
*/
public class TriplesRedisClusterModifier extends RedisClusterModifier {
public TriplesRedisClusterModifier(ByteCodeInstrumentor byteCodeInstrumentor, Agent agent) {
super(byteCodeInstrumentor, agent);
}
@Override
public String getTargetClass() {
return "com/nhncorp/redis/cluster/triples/TriplesRedisCluster";
}
}
@@ -13,16 +13,18 @@ import com.nhn.pinpoint.bootstrap.instrument.MethodFilter;
*
*/
public class NameBasedMethodFilter implements MethodFilter {
private static final int SYNTHETIC = 0x00001000;
private final Set<String> methodNames;
public NameBasedMethodFilter(Set<String> methodNames) {
public NameBasedMethodFilter(final Set<String> methodNames) {
this.methodNames = methodNames;
}
@Override
public boolean filter(MethodInfo ctMethod) {
final int modifiers = ctMethod.getModifiers();
if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
if (isSynthetic(modifiers) || !Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
return true;
}
@@ -32,4 +34,8 @@ public class NameBasedMethodFilter implements MethodFilter {
return true;
}
private boolean isSynthetic(int mod) {
return (mod & SYNTHETIC) != 0;
}
}
@@ -11,8 +11,7 @@ import com.nhn.pinpoint.bootstrap.logging.PLoggerFactory;
import com.nhncorp.redis.cluster.gateway.GatewayConfig;
/**
* Gateway(nBase-ARC client) constructor interceptor
* - trace destinationId
* Gateway(nBase-ARC client) constructor interceptor - trace destinationId
*
* @author jaehong.kim
*
@@ -43,8 +42,11 @@ public class GatewayConstructorInterceptor implements SimpleAroundInterceptor, T
// over 1.1.x
traceValue.put("destinationId", config.getClusterName());
}
} catch (Exception ignored) {
} catch (Exception e) {
// backward compatibility error or expect 'class not found exception - GatewayConfig'
if (logger.isWarnEnabled()) {
logger.warn("Failed to trace destinationId('not found getClusterName' is compatibility error). caused={}", e.getMessage(), e);
}
}
((MapTraceValue) target).__setTraceBindValue(traceValue);
@@ -58,8 +58,11 @@ public class JedisConstructorInterceptor implements SimpleAroundInterceptor, Tar
endPoint.append(":");
endPoint.append(info.getPort());
}
} catch (Exception ignored) {
} catch (Exception e) {
// expect 'class not found exception - JedisShardInfo'
if (logger.isWarnEnabled()) {
logger.warn("Failed to trace endPoint('not found JedisShardInfo' is compatibility error). caused={}", e.getMessage(), e);
}
}
final Map<String, Object> traceValue = new HashMap<String, Object>();
@@ -11,8 +11,7 @@ import com.nhn.pinpoint.bootstrap.logging.PLoggerFactory;
import com.nhncorp.redis.cluster.gateway.GatewayServer;
/**
* RedisCluster pipeline(nBase-ARC client) constructor interceptor
* - trace destinationId & endPoint
* RedisCluster pipeline(nBase-ARC client) constructor interceptor - trace destinationId & endPoint
*
* @author jaehong.kim
*
@@ -39,8 +38,11 @@ public class RedisClusterPipelineConstructorInterceptor implements SimpleAroundI
try {
final GatewayServer server = (GatewayServer) args[0];
traceValue.put("endPoint", server.getAddress().getHost() + ":" + server.getAddress().getPort());
} catch(Exception ignored) {
} catch (Exception e) {
// expect 'class not found exception - GatewayServer'
if (logger.isWarnEnabled()) {
logger.warn("Failed to trace endPoint('not found GatewayServer' is compatibility error). caused={}", e.getMessage(), e);
}
}
if (args[0] instanceof MapTraceValue) {
@@ -41,8 +41,137 @@ public final class JavaAssistUtils {
return sb.toString();
}
public static String[] parseParameterDescriptor(String descriptor) {
if (descriptor == null) {
throw new NullPointerException("descriptor must not be null");
}
final String[] parameterDesc = splitParameterDesc(descriptor);
final String[] objectType = new String[parameterDesc.length];
for (int i = 0; i < parameterDesc.length; i++) {
String description = parameterDesc[i];
objectType[i] = byteCodeDescToObjectType(description);
}
return objectType;
}
public static String[] getParameterType(Class[] paramsClass) {
private static String byteCodeDescToObjectType(String description) {
final char scheme = description.charAt(0);
switch (scheme) {
case 'B':
return "byte";
case 'C':
return "char";
case 'D':
return "double";
case 'F':
return "float";
case 'I':
return "int";
case 'J':
return "long";
case 'S':
return "short";
case 'V':
return "void";
case 'Z':
return "boolean";
case 'L':
return toObjectType(description, 1);
case '[': {
return toArrayType(description);
}
}
throw new IllegalArgumentException("invalid description :" + description);
}
private static String toArrayType(String description) {
final int arraySize = getArraySize(description);
final char scheme = description.charAt(arraySize);
switch (scheme) {
case 'B':
return arrayType("byte", arraySize);
case 'C':
return arrayType("char", arraySize);
case 'D':
return arrayType("double", arraySize);
case 'F':
return arrayType("float", arraySize);
case 'I':
return arrayType("int", arraySize);
case 'J':
return arrayType("long", arraySize);
case 'S':
return arrayType("short", arraySize);
case 'V':
return arrayType("void", arraySize);
case 'Z':
return arrayType("boolean", arraySize);
case 'L':
final String objectType = toObjectType(description, arraySize + 1);
return arrayType(objectType, arraySize);
case '[': {
throw new IllegalArgumentException("invalid description" + description);
}
}
throw new IllegalArgumentException("invalid description :" + description);
}
private static String arrayType(String objectType, int arraySize) {
final String array = "[]";
final int arrayStringLength = array.length() * arraySize;
StringBuilder sb = new StringBuilder(objectType.length() + arrayStringLength);
sb.append(objectType);
for (int i = 0; i < arraySize; i++) {
sb.append(array);
}
return sb.toString();
}
private static int getArraySize(String description) {
int arraySize = 0;
for (int i = 0; i < description.length(); i++) {
final char c = description.charAt(i);
if (c == '[') {
arraySize++;
} else {
break;
}
}
return arraySize;
}
private static String toObjectType(String description, int startIndex) {
final String assistClass = description.substring(startIndex, description.length());
final String objectName = assistClass.replace('/', '.');
if (objectName.isEmpty()) {
throw new IllegalArgumentException("invalid description. objectName not found :" + description);
}
return objectName;
}
private static String[] splitParameterDesc(String descriptor) {
final String parameterDesc = getParameterDesc(descriptor);
if (parameterDesc.isEmpty()) {
return EMPTY_STRING_ARRAY;
}
return parameterDesc.split(";");
}
private static String getParameterDesc(String descriptor) {
final int start = descriptor.indexOf('(');
if (start == -1) {
throw new IllegalArgumentException("'(' not found. descriptor:" + descriptor);
}
final int end = descriptor.indexOf(')', start + 1);
if (end == -1) {
throw new IllegalArgumentException("')' not found. descriptor:" + descriptor);
}
return descriptor.substring(start + 1, end);
}
public static String[] getParameterType(Class[] paramsClass) {
if (paramsClass == null) {
return null;
}
@@ -50,6 +50,22 @@ public class JedisModifierTest extends BasePinpointTest {
assertNull(event.getExceptionMessage());
}
@Test
public void traceBinaryMethod() {
// get 명령을 실행하고 event 결과를 확인한다.
jedis.get("foo".getBytes());
final List<SpanEventBo> spanEvents = getCurrentSpanEvents();
assertEquals(1, spanEvents.size());
SpanEventBo event = spanEvents.get(0);
assertEquals(HOST + ":" + PORT, event.getEndPoint());
assertEquals("REDIS", event.getDestinationId());
assertEquals(ServiceType.REDIS, event.getServiceType());
assertNull(event.getExceptionMessage());
}
@Test
public void traceMethodThrowException() {
// 에러가 발생한 경우에 대한 event 결과를 확인한다.
@@ -66,4 +82,4 @@ public class JedisModifierTest extends BasePinpointTest {
assertNotNull(event.getExceptionMessage());
}
}
}
@@ -37,7 +37,25 @@ public class JedisPipelineModifierTest extends BasePinpointTest {
}
@Test
public void traceMethod() {
public void traceMultikeyMethod() {
// get 명령을 실행하고 event 결과를 확인한다.
Pipeline pipeline = jedis.pipelined();
pipeline.mget("foo");
pipeline.syncAndReturnAll();
final List<SpanEventBo> spanEvents = getCurrentSpanEvents();
assertEquals(2, spanEvents.size());
SpanEventBo event = spanEvents.get(0);
System.out.println(event);
assertEquals(HOST + ":" + PORT, event.getEndPoint());
assertEquals("REDIS", event.getDestinationId());
assertEquals(ServiceType.REDIS, event.getServiceType());
assertNull(event.getExceptionMessage());
}
@Test
public void traceBaseMethod() {
// get 명령을 실행하고 event 결과를 확인한다.
Pipeline pipeline = jedis.pipelined();
pipeline.get("foo");
@@ -46,13 +64,14 @@ public class JedisPipelineModifierTest extends BasePinpointTest {
final List<SpanEventBo> spanEvents = getCurrentSpanEvents();
assertEquals(2, spanEvents.size());
SpanEventBo event = spanEvents.get(0);
System.out.println(event);
assertEquals(HOST + ":" + PORT, event.getEndPoint());
assertEquals("REDIS", event.getDestinationId());
assertEquals(ServiceType.REDIS, event.getServiceType());
assertNull(event.getExceptionMessage());
}
@Test
public void traceMethodThrowException() {
// 에러가 발생한 경우에 대한 event 결과를 확인한다.
@@ -29,7 +29,6 @@ public class RedisClusterModifierTest extends BasePinpointTest {
@Before
public void before() {
redis = new RedisCluster(HOST, PORT);
}
@Test
@@ -45,6 +44,20 @@ public class RedisClusterModifierTest extends BasePinpointTest {
assertEquals(ServiceType.NBASE_ARC, event.getServiceType());
assertNull(event.getExceptionMessage());
}
@Test
public void traceBinaryMethod() {
redis.get("foo".getBytes());
final List<SpanEventBo> spanEvents = getCurrentSpanEvents();
assertEquals(1, spanEvents.size());
SpanEventBo event = spanEvents.get(0);
assertEquals("NBASE_ARC", event.getDestinationId());
assertEquals(HOST + ":" + PORT, event.getEndPoint());
assertEquals(ServiceType.NBASE_ARC, event.getServiceType());
assertNull(event.getExceptionMessage());
}
@Test
public void traceDestinationId() {
@@ -51,6 +51,25 @@ public class RedisClusterPipelineModifierTest extends BasePinpointTest {
assertNull(event.getExceptionMessage());
}
@Test
public void traceBinaryMethod() {
pipeline.get("foo".getBytes());
pipeline.syncAndReturnAll();
final List<SpanEventBo> spanEvents = getCurrentSpanEvents();
for (SpanEventBo bo : spanEvents) {
System.out.println("### " + bo);
}
assertEquals(2, spanEvents.size());
SpanEventBo event = spanEvents.get(0);
assertEquals("NBASE_ARC", event.getDestinationId());
assertEquals(HOST + ":" + PORT, event.getEndPoint());
assertEquals(ServiceType.NBASE_ARC, event.getServiceType());
assertNull(event.getExceptionMessage());
}
@Test
public void traceDestinationId() {
GatewayConfig config = new GatewayConfig();
@@ -33,8 +33,39 @@ public class JavaAssistUtilsTest {
String clsDescription = JavaAssistUtils.getParameterDescription(new Class[]{int.class});
logger.info(clsDescription);
Assert.assertEquals(ctDescription, clsDescription);
}
@Test
public void testParseParameterDescriptor() throws Exception {
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("()V"), new String[]{});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(I)I"), new String[]{"int"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(I;D)I"), new String[]{"int", "double"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(B;F;S)I"), new String[]{"byte", "float", "short"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(Ljava/lang/String)I"), new String[]{"java.lang.String"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(Ljava/lang/String;J)I"), new String[]{"java.lang.String", "long"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(J;Ljava/lang/Object;Z)I"), new String[]{"long", "java.lang.Object", "boolean"});
}
@Test
public void testParseParameterDescriptor_array() throws Exception {
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("([I)I"), new String[]{"int[]"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("([I;J)I"), new String[]{"int[]", "long"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("([J;[I)I"), new String[]{"long[]", "int[]"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("([Ljava/lang/String)"), new String[]{"java.lang.String[]"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(Ljava/lang/String;[[J)"), new String[]{"java.lang.String", "long[][]"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("(Ljava/lang/Object;[[Ljava/lang/String)"), new String[]{"java.lang.Object", "java.lang.String[][]"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("([[[Ljava/lang/String)"), new String[]{"java.lang.String[][][]"});
Assert.assertArrayEquals(JavaAssistUtils.parseParameterDescriptor("([[[I)"), new String[]{"int[][][]"});
}
@Test