Skip to content

Commit

Permalink
[#11592] Update arcus-plugin to support arcus java client 1.13.4
Browse files Browse the repository at this point in the history
  • Loading branch information
jaehong-kim committed Oct 18, 2024
1 parent 34cad8b commit 3d7e792
Show file tree
Hide file tree
Showing 11 changed files with 321 additions and 63 deletions.
51 changes: 51 additions & 0 deletions agent-module/agent-testweb/arcus-plugin-testweb/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-agent-testweb</artifactId>
<version>3.0.1-SNAPSHOT</version>
</parent>

<artifactId>pinpoint-arcus-plugin-testweb</artifactId>

<packaging>jar</packaging>

<properties>
<pinpoint.agent.jvmargument>
${pinpoint.agent.default.jvmargument}
</pinpoint.agent.jvmargument>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>com.navercorp.arcus</groupId>
<artifactId>arcus-java-client</artifactId>
<version>1.12.1</version>
</dependency>
<dependency>
<groupId>com.navercorp.pinpoint</groupId>
<artifactId>pinpoint-agent-testweb-commons</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2024 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.pinpoint.test.plugin;

import net.spy.memcached.ArcusClient;
import net.spy.memcached.ConnectionFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ArcusClientConfiguration {

@Bean
public ArcusClient arcusClient() {
System.setProperty("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.Log4JLogger");
System.setProperty("net.sf.ehcache.skipUpdateCheck", "true");

ConnectionFactoryBuilder builder = new ConnectionFactoryBuilder();
builder.setFrontCacheExpireTime(10000);
builder.setMaxFrontCacheElements(100);
return ArcusClient.createArcusClient("", "", builder);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2023 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.pinpoint.test.plugin;

import com.pinpoint.test.common.view.ApiLinkPage;
import com.pinpoint.test.common.view.HrefTag;
import net.spy.memcached.ArcusClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.result.method.RequestMappingInfo;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@RestController
public class ArcusPluginController {
private static final String KEY = "test:hello";
private final static String ARCUS = "ARCUS";
private final static String ARCUS_FUTURE_GET = "ARCUS_FUTURE_GET";
private final static String ARCUS_EHCACHE_FUTURE_GET = "ARCUS_EHCACHE_FUTURE_GET";

private final RequestMappingHandlerMapping handlerMapping;

@Autowired
private ArcusClient arcusClient;

@Autowired
public ArcusPluginController(RequestMappingHandlerMapping handlerMapping) {
this.handlerMapping = handlerMapping;
}

@GetMapping("/")
String welcome() {
Map<RequestMappingInfo, HandlerMethod> handlerMethods = this.handlerMapping.getHandlerMethods();
List<HrefTag> list = new ArrayList<>();
for (RequestMappingInfo info : handlerMethods.keySet()) {
for (String path : info.getDirectPaths()) {
list.add(HrefTag.of(path));
}
}
list.sort(Comparator.comparing(HrefTag::getPath));
return new ApiLinkPage("redis-lettuce-plugin-testweb")
.addHrefTag(list)
.build();
}

@GetMapping("/arcus/set")
public String set() throws Exception {
Future<Boolean> future = arcusClient.set(KEY, 600, "Hello, Arcus!");

future.get(700L, TimeUnit.MILLISECONDS);
return "OK";
}

@GetMapping("/arcus/asyncGet")
public String asyncGet() throws Exception {
Future<Object> future = arcusClient.asyncGet(KEY);

return (String) future.get(3000L, TimeUnit.MILLISECONDS);
}

@GetMapping("/arcus/get")
public String get() {
return (String) arcusClient.get(KEY);
}

@GetMapping("/arcus/frontcache")
public String frontCache() {
String value = (String) arcusClient.get(KEY);
return arcusClient.getLocalCacheManager().getElement(KEY).toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2020 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.pinpoint.test.plugin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ArcusPluginTestStarter {

public static void main(String[] args) {
SpringApplication.run(ArcusPluginTestStarter.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Defined in commandlineArgument of agent-test pom.xml

server:
port: 18080

springdoc:
swagger-ui:
path: /

1 change: 1 addition & 0 deletions agent-module/agent-testweb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
<module>closed-module-testweb</module>
<module>closed-module-testlib</module>
<module>mariadb-jdbc-plugin-testweb</module>
<module>arcus-plugin-testweb</module>
</modules>

<dependencyManagement>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@
import com.navercorp.pinpoint.plugin.arcus.filter.FrontCacheMemcachedMethodFilter;
import com.navercorp.pinpoint.plugin.arcus.interceptor.AddOpInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.ApiInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.CacheManagerConstructInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.FrontCacheGetFutureConstructInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.FrontCacheGetFutureGetInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.FutureGetInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.FutureInternalMethodInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.FutureSetOperationInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.LocalCacheManagerConstructorInterceptor;
import com.navercorp.pinpoint.plugin.arcus.interceptor.SetCacheManagerInterceptor;

import java.security.ProtectionDomain;
Expand Down Expand Up @@ -104,12 +104,9 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, Strin
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);

if (target.hasMethod("addOp", "java.lang.String", "net.spy.memcached.ops.Operation")) {
InstrumentUtils.findMethodOrIgnore(target, "setCacheManager", "net.spy.memcached.CacheManager").addInterceptor(SetCacheManagerInterceptor.class);
final ArcusPluginConfig config = new ArcusPluginConfig(instrumentor.getProfilerConfig());
boolean traceKey = config.isArcusKeyTrace();

final InstrumentMethod setCacheManagerMethod = InstrumentUtils.findMethod(target, "setCacheManager", "net.spy.memcached.CacheManager");
setCacheManagerMethod.addInterceptor(SetCacheManagerInterceptor.class);

for (InstrumentMethod m : target.getDeclaredMethods(new ArcusMethodFilter())) {
try {
m.addScopedInterceptor(ApiInterceptor.class, va(traceKey), ArcusConstants.ARCUS_SCOPE);
Expand All @@ -121,9 +118,8 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, Strin
}

return target.toBytecode();
} else {
return null;
}
return null;
}
}

Expand All @@ -136,16 +132,7 @@ public static class CacheManagerTransform implements TransformCallback {
@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);
target.addField(ServiceCodeAccessor.class);

InstrumentMethod constructorMethod = target.getConstructor("java.lang.String", "java.lang.String", "net.spy.memcached.ConnectionFactoryBuilder", "java.util.concurrent.CountDownLatch", "int", "int");
if (constructorMethod == null) {
// over 1.13.3
constructorMethod = target.getConstructor("java.lang.String", "java.lang.String", "net.spy.memcached.ConnectionFactoryBuilder", "int", "int");
}
if (constructorMethod != null) {
constructorMethod.addInterceptor(CacheManagerConstructInterceptor.class);
}
target.addGetter(ServiceCodeGetter.class, "serviceCode");

return target.toBytecode();
}
Expand All @@ -161,31 +148,49 @@ public static class BaseOperationImplTransform implements TransformCallback {
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);
target.addField(ServiceCodeAccessor.class);

return target.toBytecode();
}
}

private void addFrontCacheGetFutureEditor() {
transformTemplate.transform("net.spy.memcached.plugin.LocalCacheManager", LocalCacheManagerTransform.class);
transformTemplate.transform("net.spy.memcached.plugin.FrontCacheGetFuture", FrontCacheGetFutureTransform.class);
}

public static class FrontCacheGetFutureTransform implements TransformCallback {
public static class LocalCacheManagerTransform implements TransformCallback {

@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);
target.addField(CacheNameAccessor.class);

InstrumentUtils.findConstructorOrIgnore(target, "java.lang.String").addInterceptor(LocalCacheManagerConstructorInterceptor.class);
InstrumentUtils.findConstructorOrIgnore(target, "java.lang.String", "int", "int", "boolean", "boolean").addInterceptor(LocalCacheManagerConstructorInterceptor.class);

return target.toBytecode();
}
}

public static class FrontCacheGetFutureTransform implements TransformCallback {

@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);
target.addField(CacheNameAccessor.class);
target.addField(CacheKeyAccessor.class);

final InstrumentMethod constructorMethod = InstrumentUtils.findConstructor(target, "net.sf.ehcache.Element");
constructorMethod.addInterceptor(FrontCacheGetFutureConstructInterceptor.class);

final InstrumentMethod get0 = InstrumentUtils.findMethod(target, "get", "long", "java.util.concurrent.TimeUnit");
get0.addScopedInterceptor(FrontCacheGetFutureGetInterceptor.class, ArcusConstants.ARCUS_SCOPE);
InstrumentMethod constructorMethod = target.getConstructor("net.sf.ehcache.Element");
if (constructorMethod == null) {
// // 1.13.4
constructorMethod = target.getConstructor("net.spy.memcached.plugin.LocalCacheManager", "java.lang.String", "net.spy.memcached.internal.GetFuture");
}
if (constructorMethod != null) {
constructorMethod.addInterceptor(FrontCacheGetFutureConstructInterceptor.class);
}

final InstrumentMethod get1 = InstrumentUtils.findMethod(target, "get");
get1.addScopedInterceptor(FrontCacheGetFutureGetInterceptor.class, ArcusConstants.ARCUS_SCOPE);
InstrumentUtils.findMethodOrIgnore(target, "get", "long", "java.util.concurrent.TimeUnit").addScopedInterceptor(FrontCacheGetFutureGetInterceptor.class, ArcusConstants.ARCUS_SCOPE);
InstrumentUtils.findMethodOrIgnore(target, "get").addScopedInterceptor(FrontCacheGetFutureGetInterceptor.class, ArcusConstants.ARCUS_SCOPE);

return target.toBytecode();
}
Expand All @@ -202,9 +207,9 @@ public static class FrontCacheMemcachedClientTransform implements TransformCallb
@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);

final ArcusPluginConfig config = new ArcusPluginConfig(instrumentor.getProfilerConfig());
boolean traceKey = config.isMemcachedKeyTrace();

for (InstrumentMethod m : target.getDeclaredMethods(new FrontCacheMemcachedMethodFilter())) {
try {
m.addScopedInterceptor(ApiInterceptor.class, va(traceKey), ArcusConstants.ARCUS_SCOPE);
Expand Down Expand Up @@ -233,12 +238,11 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, Strin

if (target.hasDeclaredMethod("addOp", "java.lang.String", "net.spy.memcached.ops.Operation")) {
target.addField(ServiceCodeAccessor.class);
final InstrumentMethod addOpMethod = InstrumentUtils.findMethod(target, "addOp", "java.lang.String", "net.spy.memcached.ops.Operation");
addOpMethod.addInterceptor(AddOpInterceptor.class);
InstrumentUtils.findMethodOrIgnore(target, "addOp", "java.lang.String", "net.spy.memcached.ops.Operation").addInterceptor(AddOpInterceptor.class);
}

final ArcusPluginConfig config = new ArcusPluginConfig(instrumentor.getProfilerConfig());
boolean traceKey = config.isMemcachedKeyTrace();

for (InstrumentMethod m : target.getDeclaredMethods(new FrontCacheMemcachedMethodFilter())) {
try {
m.addScopedInterceptor(ApiInterceptor.class, va(traceKey), ArcusConstants.ARCUS_SCOPE);
Expand All @@ -258,7 +262,6 @@ public static class FutureTransform implements TransformCallback {
@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);

target.addField(OperationAccessor.class);
target.addField(AsyncContextAccessor.class);

Expand Down Expand Up @@ -299,7 +302,6 @@ public static class InternalFutureTransform implements TransformCallback {
@Override
public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException {
InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer);

target.addField(AsyncContextAccessor.class);

// cancel, get, set
Expand Down
Loading

0 comments on commit 3d7e792

Please sign in to comment.