mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-21 18:56:11 +10:00
@@ -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
|
||||
|
||||
+2
-2
@@ -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);
|
||||
}
|
||||
|
||||
+47
-21
@@ -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();
|
||||
}
|
||||
+3
-17
@@ -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;
|
||||
}
|
||||
}
|
||||
+9
-14
@@ -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";
|
||||
}
|
||||
|
||||
+141
-100
@@ -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;
|
||||
}
|
||||
}
|
||||
+9
-1
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
-57
@@ -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;
|
||||
}
|
||||
}
|
||||
+5
-9
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+11
-10
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+5
-10
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+45
-7
@@ -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());
|
||||
|
||||
+2
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
+48
-9
@@ -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());
|
||||
|
||||
+2
-4
@@ -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);
|
||||
}
|
||||
}
|
||||
+108
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user