From 31e8ada6219789867731bb666d289f3e870d7a67 Mon Sep 17 00:00:00 2001 From: Jaehong Kim Date: Tue, 16 Jun 2015 16:21:55 +0900 Subject: [PATCH] add arcus-plugin --- plugins/arcus/.gitignore | 5 + plugins/arcus/clover.license | 5 + plugins/arcus/pom.xml | 49 ++++ .../pinpoint/plugin/arcus/ArcusConstants.java | 26 ++ .../pinpoint/plugin/arcus/ArcusPlugin.java | 256 ++++++++++++++++++ .../plugin/arcus/ArcusPluginConfig.java | 48 ++++ .../plugin/arcus/ArcusTypeProvider.java | 34 +++ .../pinpoint/plugin/arcus/ParameterUtils.java | 23 ++ .../arcus/filter/ArcusMethodFilter.java | 82 ++++++ .../FrontCacheMemcachedMethodFilter.java | 65 +++++ .../arcus/filter/MemcachedMethodFilter.java | 66 +++++ .../arcus/interceptor/AddOpInterceptor.java | 45 +++ .../arcus/interceptor/ApiInterceptor.java | 135 +++++++++ .../CacheManagerConstructInterceptor.java | 41 +++ ...ontCacheGetFutureConstructInterceptor.java | 57 ++++ .../FrontCacheGetFutureGetInterceptor.java | 78 ++++++ .../interceptor/FutureGetInterceptor.java | 81 ++++++ .../FutureInternalMethodInterceptor.java | 36 +++ .../FutureSetOperationInterceptor.java | 43 +++ .../SetCacheManagerInterceptor.java | 41 +++ ...p.pinpoint.bootstrap.plugin.ProfilerPlugin | 1 + ...inpoint.common.trace.TraceMetadataProvider | 1 + .../plugin/arcus/ArcusPluginTest.java | 48 ++++ ...CacheGetFutureModifierIntegrationTest.java | 50 ++++ .../arcus/interceptor/ApiInterceptorTest.java | 28 ++ ...erationTransitionStateInterceptorTest.java | 43 +++ .../interceptor/FutureGetInterceptorTest.java | 138 ++++++++++ plugins/arcus/src/test/resources/log4j.xml | 44 +++ .../src/test/resources/pinpoint-test.config | 190 +++++++++++++ plugins/pom.xml | 6 + 30 files changed, 1765 insertions(+) create mode 100644 plugins/arcus/.gitignore create mode 100644 plugins/arcus/clover.license create mode 100644 plugins/arcus/pom.xml create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusConstants.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPlugin.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginConfig.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusTypeProvider.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ParameterUtils.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/ArcusMethodFilter.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/FrontCacheMemcachedMethodFilter.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/MemcachedMethodFilter.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/AddOpInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/CacheManagerConstructInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureConstructInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureGetInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureInternalMethodInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureSetOperationInterceptor.java create mode 100644 plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/SetCacheManagerInterceptor.java create mode 100644 plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin create mode 100644 plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider create mode 100644 plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginTest.java create mode 100644 plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/FrontCacheGetFutureModifierIntegrationTest.java create mode 100644 plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptorTest.java create mode 100644 plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/BaseOperationTransitionStateInterceptorTest.java create mode 100644 plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptorTest.java create mode 100644 plugins/arcus/src/test/resources/log4j.xml create mode 100644 plugins/arcus/src/test/resources/pinpoint-test.config diff --git a/plugins/arcus/.gitignore b/plugins/arcus/.gitignore new file mode 100644 index 000000000..8c2d47305 --- /dev/null +++ b/plugins/arcus/.gitignore @@ -0,0 +1,5 @@ +/target/ +/.settings/ +/.classpath +/.project +/*.iml diff --git a/plugins/arcus/clover.license b/plugins/arcus/clover.license new file mode 100644 index 000000000..2dda17dc1 --- /dev/null +++ b/plugins/arcus/clover.license @@ -0,0 +1,5 @@ +NmMRuoKXgVJaWcFxmQgPsNWFORqaKAmmTFKWebObfCEQOuf +mj2KSKWpbfygHlTk2r9juoUM2L0CwcuusX2To7Fr + 4.0.0 + + com.navercorp.pinpoint + pom + ../.. + 1.5.0-SNAPSHOT + + + pinpoint-arcus-plugin + pinpoint-arcus-plugin + jar + + + + com.navercorp.pinpoint + pinpoint-bootstrap + + + + com.navercorp.arcus + arcus-java-client + 1.8.1 + provided + + + + + org.slf4j + slf4j-api + + + + org.slf4j + jcl-over-slf4j + test + + + org.slf4j + slf4j-log4j12 + + + log4j + log4j + compile + + + diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusConstants.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusConstants.java new file mode 100644 index 000000000..5842e4e37 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusConstants.java @@ -0,0 +1,26 @@ +package com.navercorp.pinpoint.plugin.arcus; + +import static com.navercorp.pinpoint.common.trace.AnnotationKeyMatcher.*; +import static com.navercorp.pinpoint.common.trace.HistogramSchema.*; +import static com.navercorp.pinpoint.common.trace.ServiceTypeProperty.*; + +import com.navercorp.pinpoint.common.trace.ServiceType; + + + +public interface ArcusConstants { + public static final ServiceType ARCUS = ServiceType.of(8100, "ARCUS", FAST_SCHEMA, TERMINAL, RECORD_STATISTICS, INCLUDE_DESTINATION_ID); + public static final ServiceType ARCUS_FUTURE_GET = ServiceType.of(8101, "ARCUS_FUTURE_GET", "ARCUS", FAST_SCHEMA, TERMINAL, INCLUDE_DESTINATION_ID); + public static final ServiceType ARCUS_EHCACHE_FUTURE_GET = ServiceType.of(8102, "ARCUS_EHCACHE_FUTURE_GET", "ARCUS-EHCACHE", FAST_SCHEMA, TERMINAL, INCLUDE_DESTINATION_ID); + public static final ServiceType ARCUS_INTERNAL = ServiceType.of(8103, "ARCUS_INTERNAL", "ARCUS", FAST_SCHEMA); + + + public static final String ARCUS_SCOPE = "ArcusScope"; + public static final String ARCUS_FUTURE_SCOPE = "ArcusFutureScope"; + public static final String ATTRIBUTE_CONFIG = "arcusPluginConfig"; + public static final String METADATA_SERVICE_CODE = "serviceCode"; + public static final String MEATDATA_CACHE_NAME = "cacheName"; + public static final String METADATA_CACHE_KEY = "cacheKey"; + public static final String METADATA_OPERATION = "operation"; + public static final String METADATA_ASYNC_TRACE_ID = "asyncTraceId"; +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPlugin.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPlugin.java new file mode 100644 index 000000000..a5591c059 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPlugin.java @@ -0,0 +1,256 @@ +package com.navercorp.pinpoint.plugin.arcus; + +import static com.navercorp.pinpoint.bootstrap.plugin.transformer.ClassConditions.*; + +import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; +import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; +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.ProfilerPluginContext; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.BaseClassFileTransformerBuilder; +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.MethodTransformerBuilder; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerExceptionHandler; +import com.navercorp.pinpoint.bootstrap.plugin.transformer.MethodTransformerProperty; +import com.navercorp.pinpoint.plugin.arcus.filter.ArcusMethodFilter; +import com.navercorp.pinpoint.plugin.arcus.filter.FrontCacheMemcachedMethodFilter; +import com.navercorp.pinpoint.plugin.arcus.filter.MemcachedMethodFilter; + +/** + * + * @author jaehong.kim + * + */ +public class ArcusPlugin implements ProfilerPlugin, ArcusConstants { + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + + @Override + public void setup(ProfilerPluginContext context) { + ArcusPluginConfig config = new ArcusPluginConfig(context.getConfig()); + context.setAttribute(ArcusConstants.ATTRIBUTE_CONFIG, config); + + boolean arcus = config.isArcus(); + boolean memcached = config.isMemcached(); + + if (arcus) { + addArcusClientEditor(context, config); + addCollectionFutureEditor(context); + addFrontCacheGetFutureEditor(context); + addFrontCacheMemcachedClientEditor(context, config); + addCacheManagerEditor(context); + + // add none operation future. over 1.5.4 + addBTreeStoreGetFutureEditor(context); + addCollectionGetBulkFutureEditor(context); + addSMGetFutureFutureEditor(context); + } + + if (arcus || memcached) { + addMemcachedClientEditor(context, config); + + addBaseOperationImplEditor(context); + addGetFutureEditor(context); + addOperationFutureEditor(context); + // add none operation future. + addImmediateFutureEditor(context); + addBulkGetFutureEditor(context); + } + } + + private void addArcusClientEditor(ProfilerPluginContext context, final ArcusPluginConfig config) { + final ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.ArcusClient"); + builder.conditional(hasMethod("addOp", "net.spy.memcached.ops.Operation", "java.lang.String", "net.spy.memcached.ops.Operation"), new ConditionalClassFileTransformerSetup() { + @Override + public void setup(ConditionalClassFileTransformerBuilder conditional) { + boolean traceKey = config.isArcusKeyTrace(); + + conditional.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.SetCacheManagerInterceptor"); + + MethodTransformerBuilder mb = conditional.editMethods(new ArcusMethodFilter()); + mb.exceptionHandler(new MethodTransformerExceptionHandler() { + public void handle(String targetClassName, String targetMethodName, String[] targetMethodParameterTypes, Throwable exception) throws Throwable { + if (logger.isWarnEnabled()) { + logger.warn("Unsupported method " + targetClassName + "." + targetMethodName, exception); + } + } + }); + mb.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.ApiInterceptor", traceKey); + } + }); + + context.addClassFileTransformer(builder.build()); + } + + private void addCacheManagerEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.CacheManager"); + builder.injectMetadata(METADATA_SERVICE_CODE); + builder.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.CacheManagerConstructInterceptor"); + + context.addClassFileTransformer(builder.build()); + } + + private void addBaseOperationImplEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.protocol.BaseOperationImpl"); + builder.injectMetadata(METADATA_SERVICE_CODE); + + context.addClassFileTransformer(builder.build()); + } + + private void addFrontCacheGetFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.plugin.FrontCacheGetFuture"); + builder.injectMetadata(MEATDATA_CACHE_NAME); + builder.injectMetadata(METADATA_CACHE_KEY); + + builder.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.FrontCacheGetFutureConstructInterceptor"); + + MethodTransformerBuilder mb2 = builder.editMethod("get", "long", "java.util.concurrent.TimeUnit"); + mb2.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.FrontCacheGetFutureGetInterceptor"); + + MethodTransformerBuilder mb3 = builder.editMethod("get"); + mb3.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.FrontCacheGetFutureGetInterceptor"); + + context.addClassFileTransformer(builder.build()); + } + + private void addFrontCacheMemcachedClientEditor(ProfilerPluginContext context, final ArcusPluginConfig config) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.plugin.FrontCacheMemcachedClient"); + + // builder.conditional(hasDeclaredMethod("putFrontCache", "java.lang.String", "java.util.concurrent.Future", "long"), + // new ConditionalClassFileTransformerSetup() { + // + // @Override + // public void setup(ConditionalClassFileTransformerBuilder conditional) { + // boolean traceKey = config.isMemcachedKeyTrace(); + // MethodTransformerBuilder mb = conditional.editMethods(new FrontCacheMemcachedMethodFilter()); + // mb.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.ApiInterceptor", traceKey); + // } + // } + // ); + + boolean traceKey = config.isMemcachedKeyTrace(); + MethodTransformerBuilder mb = builder.editMethods(new FrontCacheMemcachedMethodFilter()); + mb.exceptionHandler(new MethodTransformerExceptionHandler() { + public void handle(String targetClassName, String targetMethodName, String[] targetMethodParameterTypes, Throwable exception) throws Throwable { + if (logger.isWarnEnabled()) { + logger.warn("Unsupported method " + targetClassName + "." + targetMethodName, exception); + } + } + }); + mb.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.ApiInterceptor", traceKey); + + context.addClassFileTransformer(builder.build()); + } + + private void addMemcachedClientEditor(ProfilerPluginContext context, final ArcusPluginConfig config) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.MemcachedClient"); + builder.conditional(hasDeclaredMethod("addOp", "java.lang.String", "net.spy.memcached.ops.Operation"), new ConditionalClassFileTransformerSetup() { + @Override + public void setup(ConditionalClassFileTransformerBuilder conditional) { + conditional.injectMetadata(METADATA_SERVICE_CODE); + conditional.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.AddOpInterceptor"); + } + }); + + boolean traceKey = config.isMemcachedKeyTrace(); + MethodTransformerBuilder mb2 = builder.editMethods(new MemcachedMethodFilter()); + mb2.exceptionHandler(new MethodTransformerExceptionHandler() { + public void handle(String targetClassName, String targetMethodName, String[] targetMethodParameterTypes, Throwable exception) throws Throwable { + if (logger.isWarnEnabled()) { + logger.warn("Unsupported method " + targetClassName + "." + targetMethodName, exception); + } + } + }); + mb2.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.ApiInterceptor", traceKey); + + context.addClassFileTransformer(builder.build()); + } + + private void injectFutureInterceptor(ProfilerPluginContext context, BaseClassFileTransformerBuilder builder) { + builder.injectMetadata(ArcusConstants.METADATA_OPERATION); + builder.injectMetadata(ArcusConstants.METADATA_ASYNC_TRACE_ID); + + // setOperation + final MethodTransformerBuilder setOperationMethodBuilder = builder.editMethod("setOperation", "net.spy.memcached.ops.Operation"); + setOperationMethodBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST); + setOperationMethodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.FutureSetOperationInterceptor"); + + // cancel, get, set + final MethodTransformerBuilder methodBuilder = builder.editMethods(new MethodFilter() { + @Override + public boolean filter(MethodInfo method) { + final String name = method.getName(); + return !(name.equals("cancel") || name.equals("get") || name.equals("set") || name.equals("signalComplete")); + } + }); + methodBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST); + methodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.FutureGetInterceptor"); + } + + private void addCollectionFutureEditor(ProfilerPluginContext context) { + final ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.CollectionFuture"); + injectFutureInterceptor(context, builder); + context.addClassFileTransformer(builder.build()); + } + + private void addGetFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.GetFuture"); + injectFutureInterceptor(context, builder); + + context.addClassFileTransformer(builder.build()); + } + + private void addOperationFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.OperationFuture"); + injectFutureInterceptor(context, builder); + + context.addClassFileTransformer(builder.build()); + } + + private void addImmediateFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.ImmediateFuture"); + injectFutureInternalInterceptor(context, builder); + context.addClassFileTransformer(builder.build()); + } + + private void addBulkGetFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.BulkGetFuture"); + injectFutureInternalInterceptor(context, builder); + context.addClassFileTransformer(builder.build()); + } + + private void addBTreeStoreGetFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.BTreeStoreAndGetFuture"); + injectFutureInternalInterceptor(context, builder); + context.addClassFileTransformer(builder.build()); + } + + private void addCollectionGetBulkFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.CollectionGetBulkFuture"); + injectFutureInternalInterceptor(context, builder); + context.addClassFileTransformer(builder.build()); + } + + private void addSMGetFutureFutureEditor(ProfilerPluginContext context) { + ClassFileTransformerBuilder builder = context.getClassFileTransformerBuilder("net.spy.memcached.internal.SMGetFuture"); + injectFutureInternalInterceptor(context, builder); + context.addClassFileTransformer(builder.build()); + } + + private void injectFutureInternalInterceptor(ProfilerPluginContext context, BaseClassFileTransformerBuilder builder) { + builder.injectMetadata(ArcusConstants.METADATA_ASYNC_TRACE_ID); + + // cancel, get + final MethodTransformerBuilder methodBuilder = builder.editMethods(new MethodFilter() { + @Override + public boolean filter(MethodInfo method) { + final String name = method.getName(); + return !(name.equals("cancel") || name.equals("get")); + } + }); + methodBuilder.property(MethodTransformerProperty.IGNORE_IF_NOT_EXIST); + methodBuilder.injectInterceptor("com.navercorp.pinpoint.plugin.arcus.interceptor.FutureInternalMethodInterceptor"); + } +} \ No newline at end of file diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginConfig.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginConfig.java new file mode 100644 index 000000000..8b95daf34 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginConfig.java @@ -0,0 +1,48 @@ +package com.navercorp.pinpoint.plugin.arcus; + +import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig; + +public class ArcusPluginConfig { + private final boolean arcus; + private final boolean arcusKeyTrace; + private final boolean memcached; + private final boolean memcachedKeyTrace; + + public ArcusPluginConfig(ProfilerConfig src) { + this.arcus = src.readBoolean("profiler.arcus", true); + this.arcusKeyTrace = src.readBoolean("profiler.arcus.keytrace", false); + this.memcached = src.readBoolean("profiler.memcached", true); + this.memcachedKeyTrace = src.readBoolean("profiler.memcached.keytrace", false); + } + + public boolean isArcus() { + return arcus; + } + + public boolean isArcusKeyTrace() { + return arcusKeyTrace; + } + + public boolean isMemcached() { + return memcached; + } + + public boolean isMemcachedKeyTrace() { + return memcachedKeyTrace; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("ArcusPluginConfig={arcus=").append(arcus); + sb.append(", arcusKeyTrace=").append(arcusKeyTrace); + sb.append(", memcached=").append(memcached); + sb.append(", memcachedKeyTrace=").append(memcachedKeyTrace); + sb.append("}"); + + return sb.toString(); + } + + +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusTypeProvider.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusTypeProvider.java new file mode 100644 index 000000000..5e6a97e85 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ArcusTypeProvider.java @@ -0,0 +1,34 @@ +/** + * 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.arcus; + +import com.navercorp.pinpoint.common.trace.TraceMetadataProvider; +import com.navercorp.pinpoint.common.trace.TraceMetadataSetupContext; + +import static com.navercorp.pinpoint.common.trace.AnnotationKeyMatcher.*; + +/** + * @author Jongho Moon + * + */ +public class ArcusTypeProvider implements TraceMetadataProvider, ArcusConstants { + + @Override + public void setup(TraceMetadataSetupContext context) { + context.addServiceType(ARCUS, ARGS_MATCHER); + context.addServiceType(ARCUS_FUTURE_GET); + context.addServiceType(ARCUS_EHCACHE_FUTURE_GET); + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ParameterUtils.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ParameterUtils.java new file mode 100644 index 000000000..49e5cb05e --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/ParameterUtils.java @@ -0,0 +1,23 @@ +package com.navercorp.pinpoint.plugin.arcus; + +import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; + +/** + * @author emeroad + */ +public class ParameterUtils { + + public static int findFirstString(MethodInfo method, int maxIndex) { + if (method == null) { + return -1; + } + final String[] methodParams = method.getParameterTypes(); + final int minIndex = Math.min(methodParams.length, maxIndex); + for(int i =0; i < minIndex; i++) { + if ("java.lang.String".equals(methodParams[i])) { + return i; + } + } + return -1; + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/ArcusMethodFilter.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/ArcusMethodFilter.java new file mode 100644 index 000000000..fb2da8903 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/ArcusMethodFilter.java @@ -0,0 +1,82 @@ +package com.navercorp.pinpoint.plugin.arcus.filter; + +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; +import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; + +/** + * @author emeroad + */ +public class ArcusMethodFilter implements MethodFilter { + private final static Object FIND = new Object(); + private final static Map WHITE_LIST_API; + + static { + WHITE_LIST_API = createRule(); + } + + private static Map createRule() { + String[] apiList = { + "asyncBopCreate", + "asyncBopDecr", + "asyncBopDelete", + "asyncBopFindPosition", + "asyncBopFindPositionWithGet", + "asyncBopGet", + "asyncBopGetBulk", + "asyncBopGetByPosition", + "asyncBopGetItemCount", + "asyncBopIncr", + "asyncBopInsert", + "asyncBopInsertAndGetTrimmed", + "asyncBopInsertBulk", + "asyncBopPipedInsertBulk", + "asyncBopPipedUpdateBulk", + "asyncBopSortMergeGet", + "asyncBopUpdate", + "asyncBopUpsert", + "asyncBopUpsertAndGetTrimmed", + "asyncGetAttr", + "asyncLopCreate", + "asyncLopDelete", + "asyncLopGet", + "asyncLopInsert", + "asyncLopInsertBulk", + "asyncLopPipedInsertBulk", + "asyncSetAttr", + "asyncSetBulk", + "asyncSetPipedExist", + "asyncSopCreate", + "asyncSopDelete", + "asyncSopExist", + "asyncSopGet", + "asyncSopInsert", + "asyncSopInsertBulk", + "asyncSopPipedExistBulk", + "asyncSopPipedInsertBulk" + }; + Map rule = new HashMap(); + for (String api : apiList) { + rule.put(api, FIND); + } + return rule; + } + + public ArcusMethodFilter() { + } + + @Override + public boolean filter(MethodInfo ctMethod) { + final int modifiers = ctMethod.getModifiers(); + if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + return true; + } + if (WHITE_LIST_API.get(ctMethod.getName()) == FIND) { + return false; + } + return true; + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/FrontCacheMemcachedMethodFilter.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/FrontCacheMemcachedMethodFilter.java new file mode 100644 index 000000000..9274102fb --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/FrontCacheMemcachedMethodFilter.java @@ -0,0 +1,65 @@ +package com.navercorp.pinpoint.plugin.arcus.filter; + +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; +import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; + +/** + * @author emeroad + * @author harebox + */ +public class FrontCacheMemcachedMethodFilter implements MethodFilter { + private final static Object FIND = new Object(); + private final static Map WHITE_LIST_API; + + static { + WHITE_LIST_API = createRule(); + } + + private static Map createRule() { + String[] apiList = { + "add", + "append", + "asyncCAS", + "asyncDecr", + "asyncGet", + "asyncGetBulk", + "asyncGets", + "asyncIncr", + "cas", + "decr", + "delete", + "get", + "getBulk", + "gets", + "incr", + "prepend", + "replace", + "set", + "putFrontCache" + }; + Map rule = new HashMap(); + for (String api : apiList) { + rule.put(api, FIND); + } + return rule; + } + + public FrontCacheMemcachedMethodFilter() { + } + + @Override + public boolean filter(MethodInfo ctMethod) { + final int modifiers = ctMethod.getModifiers(); + if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + return true; + } + if (WHITE_LIST_API.get(ctMethod.getName()) == FIND) { + return false; + } + return true; + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/MemcachedMethodFilter.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/MemcachedMethodFilter.java new file mode 100644 index 000000000..a5cfa72d9 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/filter/MemcachedMethodFilter.java @@ -0,0 +1,66 @@ +package com.navercorp.pinpoint.plugin.arcus.filter; + +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +import com.navercorp.pinpoint.bootstrap.instrument.MethodFilter; +import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; + +/** + * @author emeroad + */ +public class MemcachedMethodFilter implements MethodFilter { + private final static Object FIND = new Object(); + private final static Map WHITE_LIST_API; + + static { + WHITE_LIST_API = createRule(); + } + + private static Map createRule() { + String[] apiList = { + "add", + "append", + "asyncCAS", + "asyncDecr", + "asyncGet", + "asyncGetAndTouch", + "asyncGetBulk", + "asyncGets", + "asyncIncr", + "cas", + "decr", + "delete", + "get", + "getAndTouch", + "getBulk", + "gets", + "incr", + "prepend", + "replace", + "set", + "touch" + }; + Map rule = new HashMap(); + for (String api : apiList) { + rule.put(api, FIND); + } + return rule; + } + + public MemcachedMethodFilter() { + } + + @Override + public boolean filter(MethodInfo ctMethod) { + final int modifiers = ctMethod.getModifiers(); + if (!Modifier.isPublic(modifiers) || Modifier.isStatic(modifiers) || Modifier.isAbstract(modifiers) || Modifier.isNative(modifiers)) { + return true; + } + if (WHITE_LIST_API.get(ctMethod.getName()) == FIND) { + return false; + } + return true; + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/AddOpInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/AddOpInterceptor.java new file mode 100644 index 000000000..155dd16f3 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/AddOpInterceptor.java @@ -0,0 +1,45 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +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.bootstrap.plugin.annotation.TargetMethod; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + +/** + * + * @author netspider + * @author emeroad + */ +@TargetMethod(name="addOp", paramTypes={"java.lang.String", "net.spy.memcached.ops.Operation"}) +public class AddOpInterceptor implements SimpleAroundInterceptor { + + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final MetadataAccessor serviceCodeAccessor; + + public AddOpInterceptor(@Name(ArcusConstants.METADATA_SERVICE_CODE) MetadataAccessor serviceCodeAccessor) { + this.serviceCodeAccessor = serviceCodeAccessor; + } + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + + String serviceCode = serviceCodeAccessor.get(target); + serviceCodeAccessor.set(args[1], serviceCode); + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args, result, throwable); + } + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptor.java new file mode 100644 index 000000000..e8eba3ac1 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptor.java @@ -0,0 +1,135 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.concurrent.Future; + +import net.spy.memcached.MemcachedNode; +import net.spy.memcached.ops.Operation; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; +import com.navercorp.pinpoint.bootstrap.context.RecordableTrace; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.instrument.MethodInfo; +import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name; +import com.navercorp.pinpoint.common.trace.ServiceType; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; +import com.navercorp.pinpoint.plugin.arcus.ParameterUtils; + +/** + * @author emeroad + */ +@Group(ArcusConstants.ARCUS_SCOPE) +public class ApiInterceptor extends SpanEventSimpleAroundInterceptorForPlugin implements ArcusConstants { + private final boolean traceKey; + private final int keyIndex; + + private final MetadataAccessor serviceCodeAccessor; + private final MetadataAccessor operationAccessor; + private final MetadataAccessor asyncTraceIdAccessor; + + public ApiInterceptor(TraceContext context, MethodInfo targetMethod, + @Name(METADATA_ASYNC_TRACE_ID) MetadataAccessor asyncTraceIdAccessor, @Name(METADATA_SERVICE_CODE) MetadataAccessor serviceCodeAccessor, @Name(METADATA_OPERATION) MetadataAccessor operationAccessor, boolean traceKey) { + super(context, targetMethod.getDescriptor()); + + if (traceKey) { + int index = ParameterUtils.findFirstString(targetMethod, 3); + + if (index != -1) { + this.traceKey = true; + this.keyIndex = index; + } else { + this.traceKey = false; + this.keyIndex = -1; + } + } else { + this.traceKey = false; + this.keyIndex = -1; + } + + this.serviceCodeAccessor = serviceCodeAccessor; + this.operationAccessor = operationAccessor; + this.asyncTraceIdAccessor = asyncTraceIdAccessor; + } + + @Override + public void doInBeforeTrace(RecordableTrace trace, final Object target, Object[] args) { + trace.markBeforeTime(); + } + + @Override + public void doInAfterTrace(RecordableTrace trace, Object target, Object[] args, Object result, Throwable throwable) { + if (traceKey) { + final Object recordObject = args[keyIndex]; + trace.recordApi(getMethodDescriptor(), recordObject, keyIndex); + } else { + trace.recordApi(getMethodDescriptor()); + } + trace.recordException(throwable); + + // find the target node + if (result instanceof Future && operationAccessor.isApplicable(result)) { + Operation op = operationAccessor.get(result); + + if (op != null) { + MemcachedNode handlingNode = op.getHandlingNode(); + SocketAddress socketAddress = handlingNode.getSocketAddress(); + + if (socketAddress instanceof InetSocketAddress) { + InetSocketAddress address = (InetSocketAddress) socketAddress; + trace.recordEndPoint(address.getHostName() + ":" + address.getPort()); + } + } else { + logger.info("operation not found"); + } + } + + if(serviceCodeAccessor.isApplicable(target)) { + // determine the service type + String serviceCode = serviceCodeAccessor.get(target); + if (serviceCode != null) { + trace.recordDestinationId(serviceCode); + trace.recordServiceType(ARCUS); + } else { + trace.recordDestinationId("MEMCACHED"); + trace.recordServiceType(ServiceType.MEMCACHED); + } + } else { + trace.recordDestinationId("MEMCACHED"); + trace.recordServiceType(ServiceType.MEMCACHED); + } + + + try { + if(isAsynchronousInvocation(target, args, result, throwable)) { + // set asynchronous trace + final AsyncTraceId asyncTraceId = trace.getAsyncTraceId(); + trace.recordNextAsyncId(asyncTraceId.getAsyncId()); + asyncTraceIdAccessor.set(result, asyncTraceId); + if (isDebug) { + logger.debug("Set asyncTraceId metadata {}", asyncTraceId); + } + } + } catch(Throwable t) { + logger.warn("Failed to before process. {}", t.getMessage(), t); + } + + trace.markAfterTime(); + } + + private boolean isAsynchronousInvocation(final Object target, final Object[] args, Object result, Throwable throwable) { + if(throwable != null || result == null) { + return false; + } + + if (!asyncTraceIdAccessor.isApplicable(result)) { + logger.debug("Invalid result object. Need metadata accessor({}).", METADATA_ASYNC_TRACE_ID); + return false; + } + + return true; + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/CacheManagerConstructInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/CacheManagerConstructInterceptor.java new file mode 100644 index 000000000..3bc152199 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/CacheManagerConstructInterceptor.java @@ -0,0 +1,41 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +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.bootstrap.plugin.annotation.TargetConstructor; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + +/** + * + * @author netspider + * @author emeroad + */ +@TargetConstructor({"java.lang.String", "java.lang.String", "net.spy.memcached.ConnectionFactoryBuilder", "java.util.concurrent.CountDownLatch", "int", "int"}) +public class CacheManagerConstructInterceptor implements SimpleAroundInterceptor, ArcusConstants { + + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final MetadataAccessor serviceCodeAccessor; + + public CacheManagerConstructInterceptor(@Name(METADATA_SERVICE_CODE) MetadataAccessor serviceCodeAccessor) { + this.serviceCodeAccessor = serviceCodeAccessor; + } + + @Override + public void before(Object target, Object[] args) { + // do nothing + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args, result, throwable); + } + + serviceCodeAccessor.set(target, args[1]); + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureConstructInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureConstructInterceptor.java new file mode 100644 index 000000000..473e761ed --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureConstructInterceptor.java @@ -0,0 +1,57 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import net.sf.ehcache.Element; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +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.bootstrap.plugin.annotation.TargetConstructor; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + +/** + * @author harebox + */ +@TargetConstructor("net.sf.ehcache.Element") +public class FrontCacheGetFutureConstructInterceptor implements SimpleAroundInterceptor, ArcusConstants { + + // TODO This should be extracted from FrontCacheMemcachedClient. + private static final String DEFAULT_FRONTCACHE_NAME = "front"; + + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final MetadataAccessor cacheNameAccessor; + private final MetadataAccessor cacheKeyAccessor; + + public FrontCacheGetFutureConstructInterceptor(@Name(MEATDATA_CACHE_NAME) MetadataAccessor cacheNameAccessor, + @Name(ArcusConstants.METADATA_CACHE_KEY) MetadataAccessor cacheKeyAccessor) { + this.cacheNameAccessor = cacheNameAccessor; + this.cacheKeyAccessor = cacheKeyAccessor; + } + + @Override + public void before(Object target, Object[] args) { + // do nothing + + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args, result, throwable); + } + + try { + cacheNameAccessor.set(target, DEFAULT_FRONTCACHE_NAME); + + if (args[0] instanceof Element) { + Element element = (Element) args[0]; + cacheKeyAccessor.set(target, element.getObjectKey()); + } + } catch (Exception e) { + logger.error("failed to add metadata: {}", e); + } + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureGetInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureGetInterceptor.java new file mode 100644 index 000000000..7c9f84f2e --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FrontCacheGetFutureGetInterceptor.java @@ -0,0 +1,78 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +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.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + +/** + * @author harebox + */ +@Group(ArcusConstants.ARCUS_SCOPE) +public class FrontCacheGetFutureGetInterceptor implements SimpleAroundInterceptor, ArcusConstants { + + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final MethodDescriptor methodDescriptor; + private final TraceContext traceContext; + private final MetadataAccessor cacheNameAccessor; + + public FrontCacheGetFutureGetInterceptor(TraceContext traceContext, MethodDescriptor methodDescriptor, @Name(MEATDATA_CACHE_NAME) MetadataAccessor cacheNameAccessor) { + this.methodDescriptor = methodDescriptor; + this.traceContext = traceContext; + this.cacheNameAccessor = cacheNameAccessor; + } + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + + final Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } + + trace.traceBlockBegin(); + trace.markBeforeTime(); + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args, result, throwable); + } + + final Trace trace = traceContext.currentTraceObject(); + if (trace == null) { + return; + } + + try { + trace.recordApi(methodDescriptor); + +// String cacheKey = (String) getCacheKey.invoke(target); +// if (cacheKey != null) { +// // annotate it. +// } + + String cacheName = cacheNameAccessor.get(target); + if (cacheName != null) { + trace.recordDestinationId(cacheName); + } + + trace.recordServiceType(ARCUS_EHCACHE_FUTURE_GET); + trace.markAfterTime(); + } finally { + trace.traceBlockEnd(); + } + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptor.java new file mode 100644 index 000000000..965f6ad36 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptor.java @@ -0,0 +1,81 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +import net.spy.memcached.MemcachedNode; +import net.spy.memcached.ops.Operation; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; +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.SpanAsyncEventSimpleAroundInterceptor; +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.bootstrap.plugin.annotation.Name; +import com.navercorp.pinpoint.common.trace.ServiceType; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + +/** + * @author emeroad + * @author jaehong.kim + */ +@Group(ArcusConstants.ARCUS_FUTURE_SCOPE) +public class FutureGetInterceptor extends SpanAsyncEventSimpleAroundInterceptor implements ArcusConstants { + + private final MetadataAccessor operationAccessor; + private final MetadataAccessor serviceCodeAccessor; + + public FutureGetInterceptor(MethodDescriptor methodDescriptor, TraceContext traceContext, @Name(METADATA_ASYNC_TRACE_ID) MetadataAccessor asyncTraceIdAccessor, @Name(METADATA_SERVICE_CODE) MetadataAccessor serviceCodeAccessor, + @Name(METADATA_OPERATION) MetadataAccessor operationAccessor) { + super(traceContext, methodDescriptor, asyncTraceIdAccessor); + + this.serviceCodeAccessor = serviceCodeAccessor; + this.operationAccessor = operationAccessor; + } + + @Override + protected void doInBeforeTrace(Trace trace, AsyncTraceId asyncTraceId, Object target, Object[] args) { + trace.markBeforeTime(); + } + + @Override + protected void doInAfterTrace(Trace trace, Object target, Object[] args, Object result, Throwable throwable) { + // find the target node + final Operation op = operationAccessor.get(target); + if (op != null) { + MemcachedNode handlingNode = op.getHandlingNode(); + if (handlingNode != null) { + SocketAddress socketAddress = handlingNode.getSocketAddress(); + if (socketAddress instanceof InetSocketAddress) { + InetSocketAddress address = (InetSocketAddress) socketAddress; + trace.recordEndPoint(address.getHostName() + ":" + address.getPort()); + } + } else { + logger.info("no handling node"); + } + } else { + logger.info("operation not found"); + } + + // determine the service type + String serviceCode = serviceCodeAccessor.get(op); + if (serviceCode != null) { + trace.recordDestinationId(serviceCode); + trace.recordServiceType(ARCUS_FUTURE_GET); + } else { + trace.recordDestinationId("MEMCACHED"); + trace.recordServiceType(ServiceType.MEMCACHED_FUTURE_GET); + } + + if (op != null) { + trace.recordException(op.getException()); + } + trace.recordApi(methodDescriptor); + trace.markAfterTime(); + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureInternalMethodInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureInternalMethodInterceptor.java new file mode 100644 index 000000000..6df38e517 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureInternalMethodInterceptor.java @@ -0,0 +1,36 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +import com.navercorp.pinpoint.bootstrap.context.AsyncTraceId; +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.SpanAsyncEventSimpleAroundInterceptor; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Group; +import com.navercorp.pinpoint.bootstrap.plugin.annotation.Name; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + +/** + * @author emeroad + * @author jaehong.kim + */ +@Group(ArcusConstants.ARCUS_FUTURE_SCOPE) +public class FutureInternalMethodInterceptor extends SpanAsyncEventSimpleAroundInterceptor implements ArcusConstants { + + public FutureInternalMethodInterceptor(MethodDescriptor methodDescriptor, TraceContext traceContext, @Name(METADATA_ASYNC_TRACE_ID) MetadataAccessor asyncTraceIdAccessor) { + super(traceContext, methodDescriptor, asyncTraceIdAccessor); + } + + @Override + protected void doInBeforeTrace(Trace trace, AsyncTraceId asyncTraceId, Object target, Object[] args) { + trace.markBeforeTime(); + } + + @Override + protected void doInAfterTrace(Trace trace, Object target, Object[] args, Object result, Throwable throwable) { + trace.recordServiceType(ARCUS_INTERNAL); + trace.recordException(throwable); + trace.recordApi(methodDescriptor); + trace.markAfterTime(); + } +} \ No newline at end of file diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureSetOperationInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureSetOperationInterceptor.java new file mode 100644 index 000000000..1d1652731 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureSetOperationInterceptor.java @@ -0,0 +1,43 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +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.bootstrap.plugin.annotation.TargetMethod; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + + +/** + * @author harebox + * @author emeroad + */ +public class FutureSetOperationInterceptor implements SimpleAroundInterceptor, ArcusConstants { + + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + + private final MetadataAccessor operationAccessor; + + public FutureSetOperationInterceptor(@Name(METADATA_OPERATION) MetadataAccessor operationAccessor) { + this.operationAccessor = operationAccessor; + } + + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + + operationAccessor.set(target, args[0]); + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (isDebug) { + logger.afterInterceptor(target, args); + } + } +} diff --git a/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/SetCacheManagerInterceptor.java b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/SetCacheManagerInterceptor.java new file mode 100644 index 000000000..56dfc7ee4 --- /dev/null +++ b/plugins/arcus/src/main/java/com/navercorp/pinpoint/plugin/arcus/interceptor/SetCacheManagerInterceptor.java @@ -0,0 +1,41 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import com.navercorp.pinpoint.bootstrap.MetadataAccessor; +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.bootstrap.plugin.annotation.TargetMethod; +import com.navercorp.pinpoint.plugin.arcus.ArcusConstants; + +/** + * + * @author netspider + * @author emeroad + */ +@TargetMethod(name="setCacheManager", paramTypes="net.spy.memcached.CacheManager") +public class SetCacheManagerInterceptor implements SimpleAroundInterceptor, ArcusConstants { + + private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); + private final boolean isDebug = logger.isDebugEnabled(); + private final MetadataAccessor serviceCodeAccessor; + + public SetCacheManagerInterceptor(@Name(METADATA_SERVICE_CODE) MetadataAccessor serviceCodeAccessor) { + this.serviceCodeAccessor = serviceCodeAccessor; + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + // do nothing + } + + @Override + public void before(Object target, Object[] args) { + if (isDebug) { + logger.beforeInterceptor(target, args); + } + + String serviceCode = serviceCodeAccessor.get(args[0]); + serviceCodeAccessor.set(target, serviceCode); + } +} diff --git a/plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin b/plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin new file mode 100644 index 000000000..d7d060c02 --- /dev/null +++ b/plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin @@ -0,0 +1 @@ +com.navercorp.pinpoint.plugin.arcus.ArcusPlugin \ No newline at end of file diff --git a/plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider b/plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider new file mode 100644 index 000000000..4de5202c0 --- /dev/null +++ b/plugins/arcus/src/main/resources/META-INF/services/com.navercorp.pinpoint.common.trace.TraceMetadataProvider @@ -0,0 +1 @@ +com.navercorp.pinpoint.plugin.arcus.ArcusTypeProvider \ No newline at end of file diff --git a/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginTest.java b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginTest.java new file mode 100644 index 000000000..9327de951 --- /dev/null +++ b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/ArcusPluginTest.java @@ -0,0 +1,48 @@ +package com.navercorp.pinpoint.plugin.arcus; + +import org.junit.Ignore; +import org.junit.Test; + +//@RunWith(ForkRunner.class) +//@PinpointConfig("pinpoint-test.config") +//@PinpointAgent("build/pinpoint-agent") +//@OnChildClassLoader +public class ArcusPluginTest { + + // TODO how to test intercpetor? + + @Test + @Ignore // until arcus modifier/interceptors are removed from pinpoint-profiler + public void test() throws Exception { +// +// Class arcusClient = Class.forName("net.spy.memcached.ArcusClient"); +// +// Class cacheManager = Class.forName("net.spy.memcached.CacheManager"); +// assertTrue(ObjectAccessor.class.isAssignableFrom(cacheManager)); +// +// Class collectionFuture = Class.forName("net.spy.memcached.internal.CollectionFuture"); +// assertTrue(ObjectAccessor.class.isAssignableFrom(collectionFuture)); +// +// Class baseOperationImpl = Class.forName("net.spy.memcached.protocol.BaseOperationImpl"); +// assertTrue(ObjectAccessor.class.isAssignableFrom(baseOperationImpl)); +// +// +// Class getFuture = Class.forName("net.spy.memcached.internal.GetFuture"); +// assertTrue(ObjectAccessor.class.isAssignableFrom(getFuture)); +// +// Class immediateFuture = Class.forName("net.spy.memcached.internal.ImmediateFuture"); +//// assertTrue(OperationAccessor.class.isAssignableFrom(immediateFuture)); +// +// Class operationFuture = Class.forName("net.spy.memcached.internal.OperationFuture"); +// assertTrue(ObjectAccessor.class.isAssignableFrom(operationFuture)); +// +// Class frontCacheGetFuture = Class.forName("net.spy.memcached.plugin.FrontCacheGetFuture"); +// assertTrue(ObjectAccessor.class.isAssignableFrom(frontCacheGetFuture)); +// assertTrue(ObjectAccessor2.class.isAssignableFrom(frontCacheGetFuture)); +// +// Class frontCacheMemcachedClient = Class.forName("net.spy.memcached.plugin.FrontCacheMemcachedClient"); +// +// Class memcachedClient = Class.forName("net.spy.memcached.MemcachedClient"); +// assertTrue(ObjectAccessor.class.isAssignableFrom(memcachedClient)); + } +} \ No newline at end of file diff --git a/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/FrontCacheGetFutureModifierIntegrationTest.java b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/FrontCacheGetFutureModifierIntegrationTest.java new file mode 100644 index 000000000..15682dc96 --- /dev/null +++ b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/FrontCacheGetFutureModifierIntegrationTest.java @@ -0,0 +1,50 @@ +package com.navercorp.pinpoint.plugin.arcus; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +/** + * @author harebox + */ +public class FrontCacheGetFutureModifierIntegrationTest /*extends BasePinpointTest*/ { + + @Before + public void setUp() throws Exception { +// MockitoAnnotations.initMocks(this); + } + + @Test + @Ignore + // FIXME 테스트 깨짐 + public void frontCacheShouldBeTraced() throws Exception { +// // given: front-cache-enabled ArcusClient +// ConnectionFactoryBuilder cfb = new ConnectionFactoryBuilder(); +// cfb.setMaxFrontCacheElements(100); +// cfb.setFrontCacheExpireTime(100); +// ArcusClient client = ArcusClient.createArcusClient("ncloud.arcuscloud.nhncorp.com:17288", "ff31ddb85e9b431c8c0e5e50a4315c27", cfb); +// +// // when +// try { +// client.set("hello", 0, "world"); +// client.asyncGet("hello").get(); +// client.asyncGet("hello").get(); +// } catch (Exception e) { +// e.printStackTrace(); +// fail(); +// } finally { +// client.shutdown(); +// } +// +// // then +// final List spanEvents = getCurrentSpanEvents(); +// assertThat(spanEvents.size(), is(5)); +// +// final SpanEventBo getFutureSpan = spanEvents.get(2); +// final SpanEventBo frontCacheGetFutureSpan = spanEvents.get(4); +// +// assertNotNull(getFutureSpan.getEndPoint()); +// assertNull(frontCacheGetFutureSpan.getEndPoint()); +// assertThat(frontCacheGetFutureSpan.getDestinationId(), is("front")); + } +} diff --git a/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptorTest.java b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptorTest.java new file mode 100644 index 000000000..8096a4d80 --- /dev/null +++ b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/ApiInterceptorTest.java @@ -0,0 +1,28 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import org.junit.Test; + +public class ApiInterceptorTest { + + @Test + public void testAround() { +// String[] parameterTypes = new String[] { "java.lang.String", "int", "java.lang.Object" }; +// String[] parameterNames = new String[] { "key", "exptime", "value" }; +// Object[] args = new Object[] { "key", 10, "my_value" }; +// +// TraceContext traceContext = mock(TraceContext.class); +// MethodDescriptor methodDescriptor = new DefaultMethodDescriptor(Object.class.getName(), "set", parameterTypes, parameterNames); +// MethodInfo methodInfo = mock(MethodInfo.class); +// ObjectAccessor target = mock(ObjectAccessor.class); +// +// when(methodInfo.getDescriptor()).thenReturn(methodDescriptor); +// when(methodInfo.getParameterTypes()).thenReturn(parameterTypes); +// when(target._$PINPOINT$_getObject()).thenReturn("serviceCode"); +// +// ApiInterceptor interceptor = new ApiInterceptor(traceContext, methodInfo, true); +// +// +// interceptor.before(target, args); +// interceptor.after(target, args, null, null); + } +} \ No newline at end of file diff --git a/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/BaseOperationTransitionStateInterceptorTest.java b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/BaseOperationTransitionStateInterceptorTest.java new file mode 100644 index 000000000..9b80f8e98 --- /dev/null +++ b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/BaseOperationTransitionStateInterceptorTest.java @@ -0,0 +1,43 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + +import org.junit.Assert; +import net.spy.memcached.ops.OperationState; +import org.junit.Test; + +public class BaseOperationTransitionStateInterceptorTest { + + @Test + public void testComplete() throws Exception { + // 타입비교를 Arcus의 경우 TIMEDOUT state가 별도로 추가되어 정적 타입비교를 할수 있는 상황이 아님. + // toString()을 호출하여, 문자열 비교를 해야 함. + String complete = OperationState.COMPLETE.toString(); + Assert.assertEquals("COMPLETE", complete); + } + + @Test + public void existArcusTimeoutState() throws Exception { + // 클래스가 강제 로딩되서 다른 test에 영향을 줄수 있음. + if (!isArcusExist()) { + // arcus만의 state체크를 위한 것이므로 없으면 패스한다. + return; + } + // Arcus OperationState.timedout에 변경이 있는지 체크한다. + OperationState[] values = OperationState.values(); + for (OperationState value : values) { + if (value.toString().equals("TIMEDOUT")) { + return; + } + } + + Assert.fail("OperationState.TIMEDOUT state not found"); + } + + private boolean isArcusExist() { + try { + Class.forName("net.spy.memcached.ArcusClient"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } +} diff --git a/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptorTest.java b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptorTest.java new file mode 100644 index 000000000..4038151b8 --- /dev/null +++ b/plugins/arcus/src/test/java/com/navercorp/pinpoint/plugin/arcus/interceptor/FutureGetInterceptorTest.java @@ -0,0 +1,138 @@ +package com.navercorp.pinpoint.plugin.arcus.interceptor; + + +public class FutureGetInterceptorTest /*extends BaseInterceptorTest*/ { + +// private final Logger logger = LoggerFactory.getLogger(FutureGetInterceptorTest.class); +// +// FutureGetInterceptor interceptor = new FutureGetInterceptor(null, new MockTraceContextFactory().create()); +// +// @Before +// public void beforeEach() { +// setInterceptor(interceptor); +// super.beforeEach(); +// } +// +// @Test +// public void testSuccessful() throws IOException { +// Long timeout = 1000L; +// TimeUnit unit = TimeUnit.MILLISECONDS; +// +// MockOperationFuture future = mock(MockOperationFuture.class); +// MockOperation operation = mock(MockOperation.class); +// +// when(operation.getException()).thenReturn(null); +// when(operation.isCancelled()).thenReturn(false); +// when(future.__getOperation()).thenReturn(operation); +// +// MemcachedNode node = getMockMemcachedNode(); +// when(operation.getHandlingNode()).thenReturn(node); +// +// interceptor.before(future, new Object[] { timeout, unit }); +// interceptor.after(future, new Object[] { timeout, unit }, null, null); +// } +// +// private MemcachedNode getMockMemcachedNode() throws IOException { +// java.nio.channels.SocketChannel socketChannel = java.nio.channels.SocketChannel.open(); +// BlockingQueue readQueue = new LinkedBlockingQueue(); +// BlockingQueue writeQueue = new LinkedBlockingQueue (); +// BlockingQueue inputQueue = new LinkedBlockingQueue (); +// +// return new AsciiMemcachedNodeImpl(new InetSocketAddress(11211), socketChannel, 128, readQueue, writeQueue, inputQueue, 1000L); +// } +// +// @Test +// public void testTimeoutException() { +// Long timeout = 1000L; +// TimeUnit unit = TimeUnit.MILLISECONDS; +// +// MockOperationFuture future = mock(MockOperationFuture.class); +// MockOperation operation = mock(MockOperation.class); +// +// try { +// OperationException exception = new OperationException(OperationErrorType.GENERAL, "timed out"); +// when(operation.getException()).thenReturn(exception); +// when(operation.isCancelled()).thenReturn(true); +// when(future.__getOperation()).thenReturn(operation); +// +// MemcachedNode node = getMockMemcachedNode(); +// when(operation.getHandlingNode()).thenReturn(node); +// +// interceptor.before(future, new Object[] { timeout, unit }); +// interceptor.after(future, new Object[] { timeout, unit }, null, null); +// } catch (Exception e) { +// fail(e.getMessage()); +// } +// } +// +// class MockOperationFuture extends OperationFuture { +// public MockOperationFuture(CountDownLatch l, AtomicReference oref, +// long opTimeout) { +// super(l, oref, opTimeout); +// } +// +// public String __getServiceCode() { +// return "MEMCACHED"; +// } +// +// public Operation __getOperation() { +// return null; +// } +// } +// +// class MockOperation implements Operation { +// +// public String __getServiceCode() { +// return "MEMCACHED"; +// } +// +// public void cancel() { +// } +// +// public ByteBuffer getBuffer() { +// return null; +// } +// +// public OperationCallback getCallback() { +// return null; +// } +// +// public OperationException getException() { +// return null; +// } +// +// public MemcachedNode getHandlingNode() { +// return null; +// } +// +// public OperationState getState() { +// return null; +// } +// +// public void handleRead(ByteBuffer arg0) { +// +// } +// +// public boolean hasErrored() { +// return false; +// } +// +// public void initialize() { +// } +// +// public boolean isCancelled() { +// return false; +// } +// +// public void readFromBuffer(ByteBuffer arg0) throws IOException { +// } +// +// public void setHandlingNode(MemcachedNode arg0) { +// } +// +// public void writeComplete() { +// } +// +// } + +} diff --git a/plugins/arcus/src/test/resources/log4j.xml b/plugins/arcus/src/test/resources/log4j.xml new file mode 100644 index 000000000..29c5697d2 --- /dev/null +++ b/plugins/arcus/src/test/resources/log4j.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/arcus/src/test/resources/pinpoint-test.config b/plugins/arcus/src/test/resources/pinpoint-test.config new file mode 100644 index 000000000..9c2016e15 --- /dev/null +++ b/plugins/arcus/src/test/resources/pinpoint-test.config @@ -0,0 +1,190 @@ +# +# Pinpoint agent configuration +# (Phase : local) +# + +########################################################### +# Collector server # +########################################################### +# 로컬 +profiler.collector.ip=127.0.0.1 +# 개발 +#profiler.collector.ip=10.64.84.188 +# 운영 +#profiler.collector.ip=10.25.149.249 + +profiler.collector.udpspan.port=9996 +profiler.collector.udp.port=9995 +profiler.collector.tcp.port=9994 + + +########################################################### +# Profiler Global Configuration # +########################################################### +profiler.enable=true + +profiler.jvm.collect.interval=1000 + +profiler.sampling.enable=true + +# 아래 지정한 값중 한 개의 트랜잭션을 수집합니다. (예를들어 1로 지정하면 100%수집, 2로 지정하면 50%수집 셈) +profiler.sampling.rate=1 + +# span을 Io에 flush할 경우 buffering 여부 +profiler.io.buffering.enable=true + +# buffering 시 몇개 까지 저장할지 여부 +profiler.io.buffering.buffersize=20 + + + +profiler.spandatasender.write.queue.size=5120 +#profiler.spandatasender.socket.sendbuffersize=1048576 +#profiler.spandatasender.socket.timeout=3000 + +profiler.statdatasender.write.queue.size=5120 +#profiler.statdatasender.socket.sendbuffersize=1048576 +#profiler.statdatasender.socket.timeout=3000 + +profiler.heartbeat.interval=300000 + +# Tcp Data Command 허용 여부 +profiler.tcpdatasender.command.accept.enable=true + +########################################################### +# application type # +########################################################### +#profiler.applicationservertype=TOMCAT +#profiler.applicationservertype=BLOC + +########################################################### +# application type detect order # +########################################################### +profiler.type.detect.order= + +########################################################### +# user defined classes # +########################################################### +profiler.include=com.navercorp.pinpoint.testweb.controller.*,com.navercorp.pinpoint.testweb.MyClass + + +########################################################### +# JDBC # +########################################################### +profiler.jdbc=true +profiler.jdbc.sqlcachesize=1024 +profiler.jdbc.maxsqlbindvaluesize=1024 + +# +# MYSQL +# +profiler.jdbc.mysql=true +profiler.jdbc.mysql.setautocommit=true +profiler.jdbc.mysql.commit=true +profiler.jdbc.mysql.rollback=true + +# +# MSSQL +# +profiler.jdbc.mssql=false + +# +# Oracle +# +profiler.jdbc.oracle=true +profiler.jdbc.oracle.setautocommit=true +profiler.jdbc.oracle.commit=true +profiler.jdbc.oracle.rollback=true + +# +# CUBRID +# +profiler.jdbc.cubrid=true +profiler.jdbc.cubrid.setautocommit=true +profiler.jdbc.cubrid.commit=true +profiler.jdbc.cubrid.rollback=true + +# +# DBCP +# +profiler.jdbc.dbcp=true +profiler.jdbc.dbcp.connectionclose=true + + +########################################################### +# Apache HTTP Client 4.x # +########################################################### +profiler.apache.httpclient4=true +profiler.apache.httpclient4.cookie=true + +# cookie를 언제 덤프할지 결정. ALWAYS or EXCEPTION 2가지 +profiler.apache.httpclient4.cookie.dumptype=ALWAYS +profiler.apache.httpclient4.cookie.sampling.rate=1 + +# post, put의 entity를 덤프한다. 단 HttpEtity.isRepeatable()=true 인 Entity에 한정된다. +profiler.apache.httpclient4.entity=true + +# entity를 언제 덤프할지 결정. ALWAYS or EXCEPTION 2가지 +profiler.apache.httpclient4.entity.dumptype=ALWAYS +profiler.apache.httpclient4.entity.sampling.rate=1 + +profiler.apache.nio.httpclient4=true + + +########################################################### +# Ning Async HTTP Client # +########################################################### +profiler.ning.asynchttpclient=true +profiler.ning.asynchttpclient.cookie=true +profiler.ning.asynchttpclient.cookie.dumptype=ALWAYS +profiler.ning.asynchttpclient.cookie.dumpsize=1024 +profiler.ning.asynchttpclient.cookie.sampling.rate=1 +profiler.ning.asynchttpclient.entity=true +profiler.ning.asynchttpclient.entity.dumptype=ALWAYS +profiler.ning.asynchttpclient.entity.dumpsize=1024 +profiler.ning.asynchttpclient.entity.sampling.rate=1 +profiler.ning.asynchttpclient.param=true +profiler.ning.asynchttpclient.param.dumptype=ALWAYS +profiler.ning.asynchttpclient.param.dumpsize=1024 +profiler.ning.asynchttpclient.param.sampling.rate=1 + + +########################################################### +# LINE+ baseframework # +########################################################### +profiler.line.game.netty.param.dumpsize=512 +profiler.line.game.netty.entity.dumpsize=512 + + +########################################################### +# Arcus # +########################################################### +profiler.arcus=true +profiler.arcus.keytrace=true + + +########################################################### +# Memcached # +########################################################### +profiler.memcached=true +profiler.memcached.keytrace=true + + +########################################################### +# ibatis # +########################################################### +profiler.orm.ibatis=true + + +########################################################### +# mybatis # +########################################################### +profiler.orm.mybatis=true + +########################################################### +# spring-beans +########################################################### +profiler.spring.beans=true +profiler.spring.beans.name.pattern=ma.*, outer +profiler.spring.beans.class.pattern=.*Morae +profiler.spring.beans.annotation=org.springframework.stereotype.Component \ No newline at end of file diff --git a/plugins/pom.xml b/plugins/pom.xml index 8b47e35c8..1f50dee20 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -24,6 +24,7 @@ tomcat thrift user + arcus @@ -87,6 +88,11 @@ pinpoint-user-plugin ${project.version} + + com.navercorp.pinpoint + pinpoint-arcus-plugin + ${project.version} +