Merge pull request #856 from jaehong-kim/redis

Redis
This commit is contained in:
Jaehong Kim
2015-08-20 17:10:34 +09:00
20 changed files with 549 additions and 269 deletions
+8 -1
View File
@@ -321,4 +321,11 @@ profiler.google.httpclient.enable=true
# Profile async.
profiler.google.httpclient.async=true
# Maximum anonymous innerclass number.
profiler.google.httpclient.async.innerclassname.max=3
profiler.google.httpclient.async.innerclassname.max=3
###########################################################
# redis
###########################################################
profiler.redis.pipeline
profiler.redis=true
profiler.redis.io=true
@@ -23,6 +23,6 @@ package com.navercorp.pinpoint.bootstrap.instrument;
public interface MethodFilter {
public static final boolean ACCEPT = true;
public static final boolean REJECT = false;
boolean accept(InstrumentMethod method);
boolean accept(InstrumentMethod method);
}
@@ -21,66 +21,72 @@ import java.util.Arrays;
*
*/
public class MethodFilters {
private MethodFilters() { }
public static final int SYNTHETIC = 0x00001000;
private MethodFilters() {
}
public static final MethodFilter ACCEPT_ALL = new MethodFilter() {
@Override
public boolean accept(InstrumentMethod method) {
return ACCEPT;
}
};
public static MethodFilter name(String... names) {
return new MethodNameFilter(names);
return new MethodNameFilter(null, names);
}
public static MethodFilter name(int[] rejectModifiers, String... names) {
return new MethodNameFilter(rejectModifiers, names);
}
public static MethodFilter modifier(int required) {
return modifier(required, 0);
}
public static MethodFilter modifierNot(int rejected) {
return modifier(0, rejected);
}
public static MethodFilter modifier(int required, int rejected) {
return new ModifierFilter(required, rejected);
}
public static MethodFilter argAt(int index, String type) {
return new ArgAtFilter(index, type);
}
public static MethodFilter args(String... types) {
return new ArgsFilter(types);
}
private static final class MethodNameFilter implements MethodFilter {
private final String[] names;
private final RejectModifiers modifiers;
public MethodNameFilter(String[] names) {
public MethodNameFilter(int[] rejectModifiers, String[] names) {
this.names = names;
this.modifiers = new RejectModifiers(rejectModifiers);
}
@Override
public boolean accept(InstrumentMethod method) {
for (String name : names) {
if (name.equals(method.getName())) {
return ACCEPT;
return modifiers.accept(method.getModifiers());
}
}
return REJECT;
}
}
private static final class ModifierFilter implements MethodFilter {
private final int required;
private final int rejected;
public ModifierFilter(int required, int rejected) {
this.required = required;
this.rejected = rejected;
@@ -92,11 +98,11 @@ public class MethodFilters {
return ((required & modifier) == required) && ((rejected & modifier) == 0);
}
}
private static final class ArgAtFilter implements MethodFilter {
private final int index;
private final String type;
public ArgAtFilter(int index, String type) {
this.index = index;
this.type = type;
@@ -105,15 +111,15 @@ public class MethodFilters {
@Override
public boolean accept(InstrumentMethod method) {
String[] paramTypes = method.getParameterTypes();
if (paramTypes.length < index + 1) {
return REJECT;
}
return type.equals(paramTypes[index]);
}
}
private static final class ArgsFilter implements MethodFilter {
private final String[] types;
@@ -127,4 +133,24 @@ public class MethodFilters {
return Arrays.equals(paramTypes, types);
}
}
}
private static class RejectModifiers {
private final int[] rejectModifiers;
public RejectModifiers(int[] rejectModifiers) {
this.rejectModifiers = rejectModifiers;
}
public boolean accept(int modifier) {
if (rejectModifiers != null) {
for (int rejectModifier : rejectModifiers) {
if (((rejectModifier & modifier) != 0)) {
return false;
}
}
}
return true;
}
}
}
@@ -0,0 +1,92 @@
/*
* 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.plugin.redis;
/**
*
* @author jaehong.kim
*
*/
public class CommandContext {
private long readBeginTime;
private long readEndTime;
private boolean readFail;
private long writeBeginTime;
private long writeEndTime;
private boolean writeFail;
public void setReadBeginTime(long readBeginTime) {
this.readBeginTime = readBeginTime;
}
public void setReadEndTime(long readEndTime) {
this.readEndTime = readEndTime;
}
public boolean isReadFail() {
return readFail;
}
public void setReadFail(boolean readFail) {
this.readFail = readFail;
}
public void setWriteBeginTime(long writeBeginTime) {
this.writeBeginTime = writeBeginTime;
}
public void setWriteEndTime(long writeEndTime) {
this.writeEndTime = writeEndTime;
}
public boolean isWriteFail() {
return writeFail;
}
public void setWriteFail(boolean writeFail) {
this.writeFail = writeFail;
}
public long getWriteElapsedTime() {
long result = writeEndTime - writeBeginTime;
return result > 0 ? result : 0;
}
public long getReadElapsedTime() {
long result = readEndTime - readBeginTime;
return result > 0 ? result : 0;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("{readBeginTime=");
builder.append(readBeginTime);
builder.append(", readEndTime=");
builder.append(readEndTime);
builder.append(", readFail=");
builder.append(readFail);
builder.append(", writeBeginTime=");
builder.append(writeBeginTime);
builder.append(", writeEndTime=");
builder.append(writeEndTime);
builder.append(", writeFail=");
builder.append(writeFail);
builder.append("}");
return builder.toString();
}
}
@@ -0,0 +1,6 @@
package com.navercorp.pinpoint.plugin.redis;
public interface EndPointAccessor {
public void _$PINPOINT$_setEndPoint(String endPoint);
public String _$PINPOINT$_getEndPoint();
}
@@ -14,11 +14,7 @@
* limitations under the License.
*/
package com.navercorp.pinpoint.plugin.redis.filter;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
package com.navercorp.pinpoint.plugin.redis;
/**
* Jedis method names
@@ -27,16 +23,9 @@ import java.util.Set;
*
*/
public class JedisMethodNames {
private static Set<String> names = null;
public static Set<String> get() {
if(names != null) {
return names;
}
final String[] methodNames = {
public static String[] get() {
return new String[] {
"get",
"type",
"append",
@@ -197,8 +186,5 @@ public class JedisMethodNames {
"slowlogGetBinary",
"info"
};
names = new HashSet<String>(Arrays.asList(methodNames));
return names;
}
}
@@ -14,10 +14,11 @@
* limitations under the License.
*/
package com.navercorp.pinpoint.plugin.redis.filter;
package com.navercorp.pinpoint.plugin.redis;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;
import java.util.List;
/**
* JedisPipeline method names
@@ -27,23 +28,17 @@ import java.util.Set;
*
*/
public class JedisPipelineMethodNames {
private static Set<String> names = null;
public static Set<String> get() {
if(names != null) {
return names;
}
public static String[] get() {
final String[] methodNames = {
"sync",
"syncAndReturnAll"
};
final Set<String> jedisMethodNames = JedisMethodNames.get();
jedisMethodNames.addAll(Arrays.asList(methodNames));
names = jedisMethodNames;
return names;
final List<String> names = new ArrayList<String>();
names.addAll(Arrays.asList(JedisMethodNames.get()));
names.addAll(Arrays.asList(methodNames));
return names.toArray(new String[names.size()]);
}
}
@@ -28,6 +28,7 @@ import com.navercorp.pinpoint.common.trace.ServiceType;
public interface RedisConstants {
public static final ServiceType REDIS = ServiceType.of(8200, "REDIS", FAST_SCHEMA, TERMINAL, RECORD_STATISTICS);
public static final String METADATA_END_POINT = "endPoint";
public static final String METADATA_DESTINATION_ID = "destinationId";
public static final String METADATA_END_POINT = "com.navercorp.pinpoint.plugin.redis.EndPointAccessor";
public static final String REDIS_SCOPE = "redisScope";
}
@@ -15,18 +15,19 @@
*/
package com.navercorp.pinpoint.plugin.redis;
import java.lang.reflect.Modifier;
import java.security.ProtectionDomain;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod;
import com.navercorp.pinpoint.bootstrap.instrument.MethodFilters;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginInstrumentContext;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassFileTransformerBuilder;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConstructorTransformerBuilder;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerBuilder;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerExceptionHandler;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerProperty;
import com.navercorp.pinpoint.plugin.redis.filter.JedisMethodNames;
import com.navercorp.pinpoint.plugin.redis.filter.JedisPipelineMethodNames;
import com.navercorp.pinpoint.plugin.redis.filter.NameBasedMethodFilter;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.PinpointClassFileTransformer;
/**
*
@@ -34,26 +35,6 @@ import com.navercorp.pinpoint.plugin.redis.filter.NameBasedMethodFilter;
*
*/
public class RedisPlugin implements ProfilerPlugin, RedisConstants {
private static final String STRING = "java.lang.String";
private static final String INT = "int";
private static final String URI = "java.net.URI";
private static final String JEDIS = "redis.clients.jedis.Jedis";
private static final String BINARY_JEDIS = "redis.clients.jedis.BinaryJedis";
private static final String JEDIS_CLIENT = "redis.clients.jedis.Client";
private static final String JEDIS_PIPELINE_BASE = "redis.clients.jedis.PipelineBase";
private static final String JEDIS_MULTIKEY_PIPELINE_BASE = "redis.clients.jedis.MultiKeyPipelineBase";
private static final String JEDIS_PIPELINE = "redis.clients.jedis.Pipeline";
private static final String JEDIS_SHARD_INFO = "redis.clients.jedis.JedisShardInfo";
private static final String JEDIS_CONSTRUCTOR_INTERCEPTOR = "com.navercorp.pinpoint.plugin.redis.interceptor.JedisConstructorInterceptor";
private static final String JEDIS_METHODS_INTERCEPTOR = "com.navercorp.pinpoint.plugin.redis.interceptor.JedisMethodInterceptor";
private static final String JEDIS_CLIENT_CONSTRUCTOR_INTERCEPTOR = "com.navercorp.pinpoint.plugin.redis.interceptor.JedisClientConstructorInterceptor";
private static final String JEDIS_PIPELINE_METHODS_INTERCEPTOR = "com.navercorp.pinpoint.plugin.redis.interceptor.JedisPipelineMethodInterceptor";
private static final String JEDIS_PIPELINE_SET_CLIENT_METHOD_INTERCEPTOR = "com.navercorp.pinpoint.plugin.redis.interceptor.JedisPipelineSetClientMethodInterceptor";
private static final String JEDIS_PIPELINE_CONSTRUCTOR_INTERCEPTOR = "com.navercorp.pinpoint.plugin.redis.interceptor.JedisPipelineConstructorInterceptor";
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
@Override
@@ -65,6 +46,7 @@ public class RedisPlugin implements ProfilerPlugin, RedisConstants {
if (enabled) {
// jedis
addJedisClassEditors(context, config);
addProtocolClassEditor(context, config);
if (pipelineEnabled) {
// jedis pipeline
@@ -76,102 +58,161 @@ public class RedisPlugin implements ProfilerPlugin, RedisConstants {
// Jedis & BinaryJedis
private void addJedisClassEditors(ProfilerPluginSetupContext context, RedisPluginConfig config) {
final ClassFileTransformerBuilder classEditorBuilder = addJedisExtendedClassEditor(context, config, BINARY_JEDIS);
classEditorBuilder.injectMetadata(METADATA_END_POINT);
context.addClassFileTransformer(classEditorBuilder.build());
addJedisExtendedClassEditor(context, config, "redis.clients.jedis.BinaryJedis", new TransformHandler() {
// Jedis extends BinaryJedis
context.addClassFileTransformer(addJedisExtendedClassEditor(context, config, JEDIS).build());
}
private ClassFileTransformerBuilder addJedisExtendedClassEditor(ProfilerPluginSetupContext context, RedisPluginConfig config, final String targetClassName) {
final ClassFileTransformerBuilder classEditorBuilder = context.getClassFileTransformerBuilder(targetClassName);
final ConstructorTransformerBuilder constructorEditorBuilderArg1 = classEditorBuilder.editConstructor(STRING);
constructorEditorBuilderArg1.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilderArg1.injectInterceptor(JEDIS_CONSTRUCTOR_INTERCEPTOR);
final ConstructorTransformerBuilder constructorEditorBuilderArg2 = classEditorBuilder.editConstructor(STRING, INT);
constructorEditorBuilderArg2.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilderArg2.injectInterceptor(JEDIS_CONSTRUCTOR_INTERCEPTOR);
final ConstructorTransformerBuilder constructorEditorBuilderArg3 = classEditorBuilder.editConstructor(STRING, INT, INT);
constructorEditorBuilderArg3.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilderArg3.injectInterceptor(JEDIS_CONSTRUCTOR_INTERCEPTOR);
final ConstructorTransformerBuilder constructorEditorBuilderArg4 = classEditorBuilder.editConstructor(URI);
constructorEditorBuilderArg4.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilderArg4.injectInterceptor(JEDIS_CONSTRUCTOR_INTERCEPTOR);
final ConstructorTransformerBuilder constructorEditorBuilderArg5 = classEditorBuilder.editConstructor(JEDIS_SHARD_INFO);
constructorEditorBuilderArg5.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilderArg5.injectInterceptor(JEDIS_CONSTRUCTOR_INTERCEPTOR);
final MethodTransformerBuilder methodEditorBuilder = classEditorBuilder.editMethods(new NameBasedMethodFilter(JedisMethodNames.get()));
methodEditorBuilder.exceptionHandler(new MethodTransformerExceptionHandler() {
@Override
public void handle(String targetClassName, String targetMethodName, String[] targetMethodParameterTypes, Throwable exception) throws Exception {
if (logger.isWarnEnabled()) {
logger.warn("Unsupported method " + targetClassName + "." + targetMethodName, exception);
}
public void handle(InstrumentClass target) throws InstrumentException {
target.addField(METADATA_END_POINT);
}
});
methodEditorBuilder.injectInterceptor(JEDIS_METHODS_INTERCEPTOR);
return classEditorBuilder;
// Jedis extends BinaryJedis
addJedisExtendedClassEditor(context, config, "redis.clients.jedis.Jedis", null);
}
private void addJedisExtendedClassEditor(ProfilerPluginSetupContext context, final RedisPluginConfig config, final String targetClassName, final TransformHandler handler) {
context.addClassFileTransformer(targetClassName, new PinpointClassFileTransformer() {
@Override
public byte[] transform(ProfilerPluginInstrumentContext instrumentContext, ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentContext.getInstrumentClass(classLoader, className, classfileBuffer);
if (handler != null) {
handler.handle(target);
}
final InstrumentMethod constructorEditorBuilderArg1 = target.getConstructor("java.lang.String");
if (constructorEditorBuilderArg1 != null) {
constructorEditorBuilderArg1.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisConstructorInterceptor");
}
final InstrumentMethod constructorEditorBuilderArg2 = target.getConstructor("java.lang.String", "int");
if (constructorEditorBuilderArg2 != null) {
constructorEditorBuilderArg2.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisConstructorInterceptor");
}
final InstrumentMethod constructorEditorBuilderArg3 = target.getConstructor("java.lang.String", "int", "int");
if (constructorEditorBuilderArg3 != null) {
constructorEditorBuilderArg3.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisConstructorInterceptor");
}
final InstrumentMethod constructorEditorBuilderArg4 = target.getConstructor("java.net.URI");
if (constructorEditorBuilderArg4 != null) {
constructorEditorBuilderArg4.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisConstructorInterceptor");
}
final InstrumentMethod constructorEditorBuilderArg5 = target.getConstructor("redis.clients.jedis.JedisShardInfo");
if (constructorEditorBuilderArg5 != null) {
constructorEditorBuilderArg5.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisConstructorInterceptor");
}
for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name(new int[] { MethodFilters.SYNTHETIC }, JedisMethodNames.get()))) {
try {
method.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisMethodInterceptor", config.isIo());
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Unsupported method " + method, e);
}
}
}
return target.toBytecode();
}
});
}
// Client
private void addJedisClientClassEditor(ProfilerPluginSetupContext context, RedisPluginConfig config) {
final ClassFileTransformerBuilder classEditorBuilder = context.getClassFileTransformerBuilder(JEDIS_CLIENT);
classEditorBuilder.injectMetadata(METADATA_END_POINT);
context.addClassFileTransformer("redis.clients.jedis.Client", new PinpointClassFileTransformer() {
final ConstructorTransformerBuilder constructorEditorBuilderArg1 = classEditorBuilder.editConstructor(STRING);
constructorEditorBuilderArg1.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilderArg1.injectInterceptor(JEDIS_CLIENT_CONSTRUCTOR_INTERCEPTOR);
final ConstructorTransformerBuilder constructorEditorBuilderArg2 = classEditorBuilder.editConstructor(STRING, INT);
constructorEditorBuilderArg2.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilderArg2.injectInterceptor(JEDIS_CLIENT_CONSTRUCTOR_INTERCEPTOR);
@Override
public byte[] transform(ProfilerPluginInstrumentContext instrumentContext, ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentContext.getInstrumentClass(classLoader, className, classfileBuffer);
target.addField(METADATA_END_POINT);
context.addClassFileTransformer(classEditorBuilder.build());
final InstrumentMethod constructorEditorBuilderArg1 = target.getConstructor("java.lang.String");
if (constructorEditorBuilderArg1 != null) {
constructorEditorBuilderArg1.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisClientConstructorInterceptor");
}
final InstrumentMethod constructorEditorBuilderArg2 = target.getConstructor("java.lang.String", "int");
if (constructorEditorBuilderArg2 != null) {
constructorEditorBuilderArg2.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisClientConstructorInterceptor");
}
return target.toBytecode();
}
});
}
private void addProtocolClassEditor(ProfilerPluginSetupContext context, RedisPluginConfig config) {
context.addClassFileTransformer("redis.clients.jedis.Protocol", new PinpointClassFileTransformer() {
@Override
public byte[] transform(ProfilerPluginInstrumentContext instrumentContext, ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentContext.getInstrumentClass(classLoader, className, classfileBuffer);
for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name(new int[] { Modifier.PRIVATE }, "sendCommand", "read"))) {
method.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.ProtocolSendCommandAndReadMethodInterceptor");
}
return target.toBytecode();
}
});
}
// Pipeline
private void addJedisPipelineClassEditors(ProfilerPluginSetupContext context, RedisPluginConfig config) {
context.addClassFileTransformer(addJedisPipelineBaseExtendedClassEditor(context, config, JEDIS_PIPELINE_BASE).build());
addJedisPipelineBaseExtendedClassEditor(context, config, "redis.clients.jedis.PipelineBase", null);
// MultikeyPipellineBase extends PipelineBase
context.addClassFileTransformer(addJedisPipelineBaseExtendedClassEditor(context, config, JEDIS_MULTIKEY_PIPELINE_BASE).build());
addJedisPipelineBaseExtendedClassEditor(context, config, "redis.clients.jedis.MultiKeyPipelineBase", null);
// Pipeline extends PipelineBase
final ClassFileTransformerBuilder classEditorBuilder = addJedisPipelineBaseExtendedClassEditor(context, config, JEDIS_PIPELINE);
classEditorBuilder.injectMetadata(METADATA_END_POINT);
final MethodTransformerBuilder setClientMethodEditorBuilder = classEditorBuilder.editMethod("setClient", JEDIS_CLIENT);
setClientMethodEditorBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
setClientMethodEditorBuilder.injectInterceptor(JEDIS_PIPELINE_SET_CLIENT_METHOD_INTERCEPTOR);
addJedisPipelineBaseExtendedClassEditor(context, config, "redis.clients.jedis.Pipeline", new TransformHandler() {
final ConstructorTransformerBuilder constructorEditorBuilder = classEditorBuilder.editConstructor(JEDIS_CLIENT);
constructorEditorBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorEditorBuilder.injectInterceptor(JEDIS_PIPELINE_CONSTRUCTOR_INTERCEPTOR);
context.addClassFileTransformer(classEditorBuilder.build());
}
private ClassFileTransformerBuilder addJedisPipelineBaseExtendedClassEditor(ProfilerPluginSetupContext context, RedisPluginConfig config, String targetClassName) {
final ClassFileTransformerBuilder classEditorBuilder = context.getClassFileTransformerBuilder(targetClassName);
final MethodTransformerBuilder methodEditorBuilder = classEditorBuilder.editMethods(new NameBasedMethodFilter(JedisPipelineMethodNames.get()));
methodEditorBuilder.exceptionHandler(new MethodTransformerExceptionHandler() {
@Override
public void handle(String targetClassName, String targetMethodName, String[] targetMethodParameterTypes, Throwable exception) throws Exception {
if (logger.isWarnEnabled()) {
logger.warn("Unsupported method " + targetClassName + "." + targetMethodName, exception);
public void handle(InstrumentClass target) throws InstrumentException {
target.addField(METADATA_END_POINT);
final InstrumentMethod setClientMethodEditorBuilder = target.getDeclaredMethod("setClient", "redis.clients.jedis.Client");
if (setClientMethodEditorBuilder != null) {
setClientMethodEditorBuilder.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisPipelineSetClientMethodInterceptor");
}
final InstrumentMethod constructorEditorBuilder = target.getConstructor("redis.clients.jedis.Client");
if (constructorEditorBuilder != null) {
constructorEditorBuilder.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisPipelineConstructorInterceptor");
}
}
});
methodEditorBuilder.injectInterceptor(JEDIS_PIPELINE_METHODS_INTERCEPTOR);
}
return classEditorBuilder;
private void addJedisPipelineBaseExtendedClassEditor(ProfilerPluginSetupContext context, final RedisPluginConfig config, String targetClassName, final TransformHandler handler) {
context.addClassFileTransformer(targetClassName, new PinpointClassFileTransformer() {
@Override
public byte[] transform(ProfilerPluginInstrumentContext instrumentContext, ClassLoader classLoader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentContext.getInstrumentClass(classLoader, className, classfileBuffer);
if (handler != null) {
handler.handle(target);
}
for (InstrumentMethod method : target.getDeclaredMethods(MethodFilters.name(new int[] { MethodFilters.SYNTHETIC }, JedisPipelineMethodNames.get()))) {
try {
method.addInterceptor("com.navercorp.pinpoint.plugin.redis.interceptor.JedisPipelineMethodInterceptor", config.isIo());
} catch (Exception e) {
if (logger.isWarnEnabled()) {
logger.warn("Unsupported method " + method, e);
}
}
}
return target.toBytecode();
}
});
}
private interface TransformHandler {
void handle(InstrumentClass target) throws InstrumentException;
}
}
@@ -26,10 +26,12 @@ public class RedisPluginConfig {
private boolean enabled = true;
private boolean pipelineEnabled = true;
private boolean io = true;
public RedisPluginConfig(ProfilerConfig src) {
enabled = src.readBoolean("profiler.redis", true);
pipelineEnabled = src.readBoolean("profiler.redis.pipeline", true);
io = src.readBoolean("profiler.redis.io", true);
}
public boolean isEnabled() {
@@ -40,6 +42,10 @@ public class RedisPluginConfig {
return pipelineEnabled;
}
public boolean isIo() {
return io;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
@@ -47,7 +53,9 @@ public class RedisPluginConfig {
builder.append(enabled);
builder.append(", pipelineEnabled=");
builder.append(pipelineEnabled);
builder.append(", io=");
builder.append(io);
builder.append("}");
return builder.toString();
}
}
}
@@ -18,10 +18,12 @@ package com.navercorp.pinpoint.plugin.redis;
import com.navercorp.pinpoint.common.trace.TraceMetadataProvider;
import com.navercorp.pinpoint.common.trace.TraceMetadataSetupContext;
import static com.navercorp.pinpoint.common.trace.AnnotationKeyMatcher.*;
public class RedisTypeProvider implements TraceMetadataProvider, RedisConstants{
@Override
public void setup(TraceMetadataSetupContext context) {
context.addServiceType(REDIS);
context.addServiceType(REDIS, ARGS_MATCHER);
}
}
@@ -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.plugin.redis.filter;
import java.lang.reflect.Modifier;
import java.util.Set;
import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter;
import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod;
/**
* Name based on method filter
*
* @author jaehong.kim
*
*/
public class NameBasedMethodFilter implements MethodFilter {
private static final int SYNTHETIC = 0x00001000;
private final Set<String> methodNames;
public NameBasedMethodFilter(final Set<String> methodNames) {
this.methodNames = methodNames;
}
@Override
public boolean accept(InstrumentMethod ctMethod) {
final int modifiers = ctMethod.getModifiers();
if (isSynthetic(modifiers) || !Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) {
return REJECT;
}
if (methodNames.contains(ctMethod.getName())) {
return ACCEPT;
}
return REJECT;
}
private boolean isSynthetic(int mod) {
return (mod & SYNTHETIC) != 0;
}
}
@@ -16,13 +16,12 @@
package com.navercorp.pinpoint.plugin.redis.interceptor;
import com.navercorp.pinpoint.bootstrap.MetadataAccessor;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
import com.navercorp.pinpoint.plugin.redis.EndPointAccessor;
import com.navercorp.pinpoint.plugin.redis.RedisConstants;
/**
@@ -36,10 +35,7 @@ public class JedisClientConstructorInterceptor implements SimpleAroundIntercepto
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private MetadataAccessor endPointAccessor;
public JedisClientConstructorInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(METADATA_END_POINT) MetadataAccessor endPointAccessor) {
this.endPointAccessor = endPointAccessor;
public JedisClientConstructorInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor) {
}
@Override
@@ -64,7 +60,7 @@ public class JedisClientConstructorInterceptor implements SimpleAroundIntercepto
// set default port
endPoint.append(":").append(6379);
}
endPointAccessor.set(target, endPoint.toString());
((EndPointAccessor)target)._$PINPOINT$_setEndPoint(endPoint.toString());
} catch (Throwable t) {
logger.warn("Failed to BEFORE process. {}", t.getMessage(), t);
}
@@ -81,8 +77,8 @@ public class JedisClientConstructorInterceptor implements SimpleAroundIntercepto
return false;
}
if (!endPointAccessor.isApplicable(target)) {
logger.debug("Invalid target object. Need metadata accessor({}).", METADATA_DESTINATION_ID);
if (!(target instanceof EndPointAccessor)) {
logger.debug("Invalid target object. Need field accessor({}).", METADATA_END_POINT);
return false;
}
@@ -17,13 +17,12 @@ package com.navercorp.pinpoint.plugin.redis.interceptor;
import redis.clients.jedis.Client;
import com.navercorp.pinpoint.bootstrap.MetadataAccessor;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
import com.navercorp.pinpoint.plugin.redis.EndPointAccessor;
import com.navercorp.pinpoint.plugin.redis.RedisConstants;
/**
@@ -35,10 +34,7 @@ public abstract class JedisClientMetadataAttchInterceptor implements SimpleAroun
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private MetadataAccessor endPointAccessor;
public JedisClientMetadataAttchInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(METADATA_END_POINT) MetadataAccessor endPointAccessor) {
this.endPointAccessor = endPointAccessor;
public JedisClientMetadataAttchInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor) {
}
@Override
@@ -52,9 +48,9 @@ public abstract class JedisClientMetadataAttchInterceptor implements SimpleAroun
return;
}
final String endPoint = endPointAccessor.get(args[0]);
final String endPoint = ((EndPointAccessor) args[0])._$PINPOINT$_getEndPoint();
if (endPoint != null) {
endPointAccessor.set(target, endPoint);
((EndPointAccessor) target)._$PINPOINT$_setEndPoint(endPoint);
}
} catch (Throwable t) {
logger.warn("Failed to BEFORE process. {}", t.getMessage(), t);
@@ -72,8 +68,13 @@ public abstract class JedisClientMetadataAttchInterceptor implements SimpleAroun
return false;
}
if (!endPointAccessor.isApplicable(target)) {
logger.debug("Invalid target object. Need metadata accessor({}).", METADATA_END_POINT);
if (!(args[0] instanceof EndPointAccessor)) {
logger.debug("Invalid args[0] object. Need field accessor({}).", METADATA_END_POINT);
return false;
}
if (!(target instanceof EndPointAccessor)) {
logger.debug("Invalid target object. Need field accessor({}).", METADATA_END_POINT);
return false;
}
@@ -20,13 +20,12 @@ import java.net.URI;
import redis.clients.jedis.JedisShardInfo;
import com.navercorp.pinpoint.bootstrap.MetadataAccessor;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
import com.navercorp.pinpoint.plugin.redis.EndPointAccessor;
import com.navercorp.pinpoint.plugin.redis.RedisConstants;
/**
@@ -41,10 +40,7 @@ public class JedisConstructorInterceptor implements SimpleAroundInterceptor, Red
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private MetadataAccessor endPointAccessor;
public JedisConstructorInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(METADATA_END_POINT) MetadataAccessor endPointAccessor) {
this.endPointAccessor = endPointAccessor;
public JedisConstructorInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor) {
}
@Override
@@ -80,8 +76,7 @@ public class JedisConstructorInterceptor implements SimpleAroundInterceptor, Red
endPoint.append(":");
endPoint.append(info.getPort());
}
endPointAccessor.set(target, endPoint.toString());
((EndPointAccessor)target)._$PINPOINT$_setEndPoint(endPoint.toString());
} catch (Throwable t) {
if (logger.isWarnEnabled()) {
logger.warn("Failed to BEFORE process. {}", t.getMessage(), t);
@@ -95,8 +90,8 @@ public class JedisConstructorInterceptor implements SimpleAroundInterceptor, Red
return false;
}
if (!endPointAccessor.isApplicable(target)) {
logger.debug("Invalid target object. Need metadata accessor({}).", METADATA_END_POINT);
if (!(target instanceof EndPointAccessor)) {
logger.debug("Invalid target object. Need field accessor({}).", METADATA_END_POINT);
return false;
}
@@ -16,12 +16,17 @@
package com.navercorp.pinpoint.plugin.redis.interceptor;
import com.navercorp.pinpoint.bootstrap.MetadataAccessor;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.instrument.AttachmentFactory;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroup;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group;
import com.navercorp.pinpoint.common.trace.AnnotationKey;
import com.navercorp.pinpoint.plugin.redis.CommandContext;
import com.navercorp.pinpoint.plugin.redis.EndPointAccessor;
import com.navercorp.pinpoint.plugin.redis.RedisConstants;
/**
@@ -30,26 +35,59 @@ import com.navercorp.pinpoint.plugin.redis.RedisConstants;
* @author jaehong.kim
*
*/
@Group(value = RedisConstants.REDIS_SCOPE)
public class JedisMethodInterceptor extends SpanEventSimpleAroundInterceptorForPlugin implements RedisConstants {
private MetadataAccessor endPointAccessor;
private InterceptorGroup interceptorGroup;
private boolean io;
public JedisMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(METADATA_END_POINT) MetadataAccessor endPointAccessor) {
public JedisMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, InterceptorGroup interceptorGroup, boolean io) {
super(traceContext, methodDescriptor);
this.endPointAccessor = endPointAccessor;
this.interceptorGroup = interceptorGroup;
this.io = io;
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
final InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
if (invocation != null) {
final CommandContext callContext = (CommandContext) invocation.getOrCreateAttachment(new AttachmentFactory() {
@Override
public Object createAttachment() {
return new CommandContext();
}
});
invocation.setAttachment(callContext);
}
}
@Override
public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
String endPoint = null;
if (endPointAccessor.isApplicable(target)) {
endPoint = endPointAccessor.get(target);
if (target instanceof EndPointAccessor) {
endPoint = ((EndPointAccessor) target)._$PINPOINT$_getEndPoint();
}
final InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
if (invocation != null && invocation.getAttachment() != null) {
final CommandContext commandContext = (CommandContext) invocation.getAttachment();
logger.debug("Check command context {}", commandContext);
if (io) {
final StringBuilder sb = new StringBuilder();
sb.append("write=").append(commandContext.getWriteElapsedTime());
if (commandContext.isWriteFail()) {
sb.append("(fail)");
}
sb.append(", read=").append(commandContext.getReadElapsedTime());
if (commandContext.isReadFail()) {
sb.append("(fail)");
}
recorder.recordAttribute(AnnotationKey.ARGS0, sb.toString());
}
// clear
invocation.removeAttachment();
}
recorder.recordApi(getMethodDescriptor());
@@ -16,10 +16,8 @@
package com.navercorp.pinpoint.plugin.redis.interceptor;
import com.navercorp.pinpoint.bootstrap.MetadataAccessor;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
/**
* Jedis Pipeline(redis client) constructor interceptor
@@ -30,7 +28,7 @@ import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
*/
public class JedisPipelineConstructorInterceptor extends JedisClientMetadataAttchInterceptor {
public JedisPipelineConstructorInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(METADATA_END_POINT) MetadataAccessor endPointAccessor) {
super(traceContext, methodDescriptor, endPointAccessor);
public JedisPipelineConstructorInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor) {
super(traceContext, methodDescriptor);
}
}
@@ -16,12 +16,17 @@
package com.navercorp.pinpoint.plugin.redis.interceptor;
import com.navercorp.pinpoint.bootstrap.MetadataAccessor;
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.instrument.AttachmentFactory;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroup;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group;
import com.navercorp.pinpoint.common.trace.AnnotationKey;
import com.navercorp.pinpoint.plugin.redis.CommandContext;
import com.navercorp.pinpoint.plugin.redis.EndPointAccessor;
import com.navercorp.pinpoint.plugin.redis.RedisConstants;
/**
@@ -30,26 +35,60 @@ import com.navercorp.pinpoint.plugin.redis.RedisConstants;
* @author jaehong.kim
*
*/
@Group(value = RedisConstants.REDIS_SCOPE)
public class JedisPipelineMethodInterceptor extends SpanEventSimpleAroundInterceptorForPlugin implements RedisConstants {
private MetadataAccessor endPointAccessor;
public JedisPipelineMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(METADATA_END_POINT) MetadataAccessor endPointAccessor) {
private InterceptorGroup interceptorGroup;
private boolean io;
public JedisPipelineMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, InterceptorGroup interceptorGroup, boolean io) {
super(traceContext, methodDescriptor);
this.endPointAccessor = endPointAccessor;
this.interceptorGroup = interceptorGroup;
this.io = io;
}
@Override
public void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
final InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
if (invocation != null) {
final CommandContext callContext = (CommandContext) invocation.getOrCreateAttachment(new AttachmentFactory() {
@Override
public Object createAttachment() {
return new CommandContext();
}
});
invocation.setAttachment(callContext);
}
}
@Override
public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
String endPoint = null;
if (endPointAccessor.isApplicable(target)) {
endPoint = endPointAccessor.get(target);
if (target instanceof EndPointAccessor) {
endPoint = ((EndPointAccessor)target)._$PINPOINT$_getEndPoint();
}
final InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
if (invocation != null && invocation.getAttachment() != null) {
final CommandContext commandContext = (CommandContext) invocation.getAttachment();
logger.debug("Check command context {}", commandContext);
if (io) {
final StringBuilder sb = new StringBuilder();
sb.append("write=").append(commandContext.getWriteElapsedTime());
if (commandContext.isWriteFail()) {
sb.append("(fail)");
}
sb.append(", read=").append(commandContext.getReadElapsedTime());
if (commandContext.isReadFail()) {
sb.append("(fail)");
}
recorder.recordAttribute(AnnotationKey.ARGS0, sb.toString());
}
// clear
invocation.removeAttachment();
}
recorder.recordApi(getMethodDescriptor());
recorder.recordEndPoint(endPoint != null ? endPoint : "Unknown");
recorder.recordDestinationId(REDIS.getName());
@@ -16,10 +16,8 @@
package com.navercorp.pinpoint.plugin.redis.interceptor;
import com.navercorp.pinpoint.bootstrap.MetadataAccessor;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
/**
* Jedis pipeline (redis client) setClient method interceptor
@@ -29,7 +27,7 @@ import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name;
*/
public class JedisPipelineSetClientMethodInterceptor extends JedisClientMetadataAttchInterceptor {
public JedisPipelineSetClientMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(METADATA_END_POINT) MetadataAccessor endPointAccessor) {
super(traceContext, methodDescriptor, endPointAccessor);
public JedisPipelineSetClientMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor) {
super(traceContext, methodDescriptor);
}
}
@@ -0,0 +1,108 @@
/*
* 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.plugin.redis.interceptor;
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.interceptor.MethodDescriptor;
import com.navercorp.pinpoint.bootstrap.interceptor.SimpleAroundInterceptor;
import com.navercorp.pinpoint.bootstrap.interceptor.group.ExecutionPolicy;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroup;
import com.navercorp.pinpoint.bootstrap.interceptor.group.InterceptorGroupInvocation;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;
import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group;
import com.navercorp.pinpoint.plugin.redis.CommandContext;
import com.navercorp.pinpoint.plugin.redis.RedisConstants;
/**
* RedisConnection(nBase-ARC client) constructor interceptor - trace endPoint
*
* @author jaehong.kim
*
*/
@Group(value = RedisConstants.REDIS_SCOPE, executionPolicy = ExecutionPolicy.INTERNAL)
public class ProtocolSendCommandAndReadMethodInterceptor implements SimpleAroundInterceptor, RedisConstants {
private final PLogger logger = PLoggerFactory.getLogger(this.getClass());
private final boolean isDebug = logger.isDebugEnabled();
private TraceContext traceContext;
private MethodDescriptor methodDescriptor;
private InterceptorGroup interceptorGroup;
public ProtocolSendCommandAndReadMethodInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, InterceptorGroup interceptorGroup) {
this.traceContext = traceContext;
this.methodDescriptor = methodDescriptor;
this.interceptorGroup = interceptorGroup;
}
@Override
public void before(Object target, Object[] args) {
if (isDebug) {
logger.beforeInterceptor(target, args);
}
final Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
try {
final InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
if (invocation != null && invocation.getAttachment() != null) {
final CommandContext commandContext = (CommandContext) invocation.getAttachment();
if (methodDescriptor.getMethodName().equals("sendCommand")) {
commandContext.setWriteBeginTime(System.currentTimeMillis());
} else {
commandContext.setReadBeginTime(System.currentTimeMillis());
}
logger.debug("Set command context {}", commandContext);
}
} catch (Throwable t) {
logger.warn("Failed to BEFORE process. {}", t.getMessage(), t);
}
}
@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
if (isDebug) {
logger.afterInterceptor(target, methodDescriptor.getClassName(), methodDescriptor.getMethodName(), "", args, result, throwable);
}
final Trace trace = traceContext.currentTraceObject();
if (trace == null) {
return;
}
try {
final InterceptorGroupInvocation invocation = interceptorGroup.getCurrentInvocation();
if (invocation != null && invocation.getAttachment() != null) {
final CommandContext commandContext = (CommandContext) invocation.getAttachment();
if (methodDescriptor.getMethodName().equals("sendCommand")) {
commandContext.setWriteEndTime(System.currentTimeMillis());
commandContext.setWriteFail(throwable != null);
} else {
commandContext.setReadEndTime(System.currentTimeMillis());
commandContext.setReadFail(throwable != null);
}
logger.debug("Set command context {}", commandContext);
}
} catch (Throwable t) {
logger.warn("Failed to AFTER process. {}", t.getMessage(), t);
}
}
}