Skip to content

Commit

Permalink
pinpoint-apm#329 added profiling support for asynchronous processor o…
Browse files Browse the repository at this point in the history
…perations
  • Loading branch information
Xylus committed May 29, 2015
1 parent 0032397 commit 357e185
Show file tree
Hide file tree
Showing 8 changed files with 592 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,16 @@ public interface ThriftConstants {
public static final String UNKNOWN_ADDRESS = "Unknown";

public static final Pattern PROCESSOR_PATTERN = Pattern.compile("\\$Processor");
public static final Pattern ASYNC_PROCESSOR_PATTERN = Pattern.compile("\\$AsyncProcessor");
public static final Pattern CLIENT_PATTERN = Pattern.compile("\\$Client");

public static final String ATTRIBUTE_CONFIG = "thriftPluginConfig";

public static final String METADATA_SOCKET = "transportSocket";
public static final String METADATA_SERVER_MARKER = "serverTraceMarker";
public static final String METADATA_ASYNC_MARKER = "asyncMarker";

public static final String FIELD_FRAME_BUFFER_IN_TRANSPORT = "trans_";
public static final String FIELD_FRAME_BUFFER_IN_TRANSPORT_WRAPPER = "inTrans_";

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin;
import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginContext;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassConditions;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassFileTransformerBuilder;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConditionalClassFileTransformerBuilder;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConditionalClassFileTransformerSetup;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.ConstructorTransformerBuilder;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerBuilder;
import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerProperty;
Expand All @@ -49,6 +52,7 @@ public void setup(ProfilerPluginContext context) {

if (traceProcessor) {
addInterceptorsForSynchronousProcessors(context);
addInterceptorsForAsynchronousProcessors(context);
}

if (traceCommon) {
Expand Down Expand Up @@ -111,6 +115,26 @@ private void addProcessFunctionEditor(ProfilerPluginContext context) {
context.addClassFileTransformer(classTransformerBuilder.build());
}

// Processor - asynchronous

private void addInterceptorsForAsynchronousProcessors(ProfilerPluginContext context) {
addTBaseAsyncProcessorEditor(context);
}

private void addTBaseAsyncProcessorEditor(ProfilerPluginContext context) {
final ClassFileTransformerBuilder classTransformerBuilder = context.getClassFileTransformerBuilder("org.apache.thrift.TBaseAsyncProcessor");
classTransformerBuilder.injectMetadata(METADATA_SOCKET);
classTransformerBuilder.injectMetadata(METADATA_SERVER_MARKER);
classTransformerBuilder.injectMetadata(METADATA_ASYNC_MARKER);

// TBaseAsyncProcessor(AbstractNonblockingServer$AsyncFrameBuffer)
final MethodTransformerBuilder processMethodTransformerBuilder = classTransformerBuilder.editMethod("process", "org.apache.thrift.server.AbstractNonblockingServer$AsyncFrameBuffer");
processMethodTransformerBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
processMethodTransformerBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.thrift.interceptor.server.TBaseAsyncProcessorProcessInterceptor");

context.addClassFileTransformer(classTransformerBuilder.build());
}

// Common

private void addInterceptorsForRetrievingSocketAddresses(ProfilerPluginContext context) {
Expand Down Expand Up @@ -140,10 +164,23 @@ private void addInterceptorsForRetrievingSocketAddresses(ProfilerPluginContext c
"com.navercorp.pinpoint.plugin.thrift.interceptor.transport.wrapper.TSaslTransportConstructInterceptor",
new String[] {"org.apache.thrift.transport.TTransport"},
new String[] {"javax.security.sasl.SaslClient", "org.apache.thrift.transport.TTransport"});

// TMemoryInputTransport - simply inject socket metadata
addTTransportEditor(context, "org.apache.thrift.transport.TMemoryInputTransport");

// nonblocking
// AbstractNonblockingServer$FrameBuffer(TNonblockingTransport, SelectionKey, AbstractSelectThread)
addFrameBufferEditor(context);
}

// Common - transports

private void addTTransportEditor(ProfilerPluginContext context, String tTransportClassName) {
final ClassFileTransformerBuilder classTransformerBuilder = context.getClassFileTransformerBuilder(tTransportClassName);
classTransformerBuilder.injectMetadata(METADATA_SOCKET);
context.addClassFileTransformer(classTransformerBuilder.build());
}

private void addTTransportEditor(ProfilerPluginContext context, String tTransportClassName, String tTransportInterceptorClassName, String[] ... parameterTypeGroups ) {
final ClassFileTransformerBuilder classTransformerBuilder = context.getClassFileTransformerBuilder(tTransportClassName);
classTransformerBuilder.injectMetadata(METADATA_SOCKET);
Expand All @@ -157,6 +194,45 @@ private void addTTransportEditor(ProfilerPluginContext context, String tTranspor
context.addClassFileTransformer(classTransformerBuilder.build());
}

private void addFrameBufferEditor(ProfilerPluginContext context) {
final ClassFileTransformerBuilder classTransformerBuilder = context.getClassFileTransformerBuilder("org.apache.thrift.server.AbstractNonblockingServer$FrameBuffer");
classTransformerBuilder.injectMetadata(METADATA_SOCKET);
classTransformerBuilder.injectFieldAccessor(FIELD_FRAME_BUFFER_IN_TRANSPORT);

final String[] parameterTypeNames = new String[] {
"org.apache.thrift.server.AbstractNonblockingServer", // inner class - implicit reference to outer class instance
"org.apache.thrift.transport.TNonblockingTransport",
"java.nio.channels.SelectionKey",
"org.apache.thrift.server.AbstractNonblockingServer$AbstractSelectThread"
};

// [THRIFT-1972] - 0.9.1 added a field for the wrapper around trans_ field, while getting rid of getInputTransport() method
classTransformerBuilder.conditional(ClassConditions.hasField(FIELD_FRAME_BUFFER_IN_TRANSPORT_WRAPPER),
new ConditionalClassFileTransformerSetup() {
@Override
public void setup(ConditionalClassFileTransformerBuilder conditional) {
conditional.injectFieldAccessor(FIELD_FRAME_BUFFER_IN_TRANSPORT_WRAPPER);
final ConstructorTransformerBuilder constructorTransformerBuilder = conditional.editConstructor(parameterTypeNames);
constructorTransformerBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
constructorTransformerBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.thrift.interceptor.server.nonblocking.FrameBufferConstructInterceptor");
}
}
);
// 0.8.0, 0.9.0 doesn't have a separate trans_ field - hooking getInputTransport() method
classTransformerBuilder.conditional(ClassConditions.hasMethod("getInputTransport", "org.apache.thrift.transport.TTransport"),
new ConditionalClassFileTransformerSetup() {
@Override
public void setup(ConditionalClassFileTransformerBuilder conditional) {
final MethodTransformerBuilder getInputTransportMethodTransformerBuilder = conditional.editMethod("getInputTransport");
getInputTransportMethodTransformerBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
getInputTransportMethodTransformerBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.thrift.interceptor.server.nonblocking.FrameBufferGetInputTransportInterceptor");
}
}
);

context.addClassFileTransformer(classTransformerBuilder.build());
}

// Common - protocols

private void addTProtocolEditors(ProfilerPluginContext context) {
Expand Down Expand Up @@ -201,6 +277,13 @@ public boolean filter(MethodInfo method) {
final MethodTransformerBuilder readMessageEndMethodTransformerBuilder = classTransformerBuilder.editMethod("readMessageEnd");
readMessageEndMethodTransformerBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
readMessageEndMethodTransformerBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.thrift.interceptor.tprotocol.server.TProtocolReadMessageEndInterceptor");

// for async processors
classTransformerBuilder.injectMetadata(METADATA_ASYNC_MARKER);
// TProtocol.readMessageBegin()
final MethodTransformerBuilder readMessageBeginMethodTransformerBuilder = classTransformerBuilder.editMethod("readMessageBegin");
readMessageBeginMethodTransformerBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST);
readMessageBeginMethodTransformerBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.thrift.interceptor.tprotocol.server.TProtocolReadMessageBeginInterceptor");
}
context.addClassFileTransformer(classTransformerBuilder.build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.net.SocketAddress;

import org.apache.commons.lang3.StringUtils;
import org.apache.thrift.TBaseAsyncProcessor;
import org.apache.thrift.TBaseProcessor;
import org.apache.thrift.TServiceClient;

Expand All @@ -42,6 +43,18 @@ public static String getProcessorNameAsUri(TBaseProcessor<?> processor) {
return StringUtils.replace(PROCESSOR_PATTERN.matcher(actualProcessorName).replaceAll("."), ".", "/");
}

/**
* Returns the name of the specified {@link org.apache.thrift.TBaseAsyncProcessor TBaseAsyncProcessor}
* as uri to be used in Pinpoint.
*
* @param asyncProcessor the <tt>TBaseAsyncProcessor</tt> instance to retrieve the name from
* @return the name of the the given <tt>TBaseAsyncProcessor</tt> as uri
*/
public static String getAsyncProcessorNameAsUri(TBaseAsyncProcessor<?> asyncProcessor) {
String actualAsyncProcessorName = asyncProcessor.getClass().getName();
return StringUtils.replace(ASYNC_PROCESSOR_PATTERN.matcher(actualAsyncProcessorName).replaceAll("."), ".", "/");
}

/**
* Returns the name of the specified {@link org.apache.thrift.TServiceClient TServiceClient}
* to be used in Pinpoint.
Expand Down
Loading

0 comments on commit 357e185

Please sign in to comment.