diff --git a/.github/workflows/plugins-test.3.yaml b/.github/workflows/plugins-test.3.yaml index cfdac7493..5d651642e 100644 --- a/.github/workflows/plugins-test.3.yaml +++ b/.github/workflows/plugins-test.3.yaml @@ -52,6 +52,7 @@ jobs: strategy: matrix: case: + - aerospike-scenario - mysql-scenario - undertow-scenario - webflux-scenario diff --git a/CHANGES.md b/CHANGES.md index 10c97b880..88e517366 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -138,6 +138,7 @@ Callable { * Fix the thread safety bug of finishing operation for the span named "SpringCloudGateway/sendRequest" * Fix NPE in guava-eventbus-plugin. * Add WebSphere Liberty 23.x plugin +* Add Plugin to support aerospike Java client #### Documentation diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index bfe00cc5a..facacc64e 100755 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -238,4 +238,7 @@ public class ComponentsDefine { public static final OfficialComponent GRIZZLY = new OfficialComponent(147, "Grizzly"); public static final OfficialComponent WEBSPHERE = new OfficialComponent(148, "WebSphere"); + + public static final OfficialComponent AEROSPIKE = new OfficialComponent(149, "Aerospike"); + } diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml new file mode 100644 index 000000000..70dde9365 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/pom.xml @@ -0,0 +1,48 @@ + + + + + + apm-sdk-plugin + org.apache.skywalking + 9.0.0-SNAPSHOT + + 4.0.0 + + apm-aerospike-plugin + jar + + aerospike-plugin + + + + com.aerospike + aerospike-client + 6.0.0 + provided + + + + 8 + 8 + + + diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/AerospikeClientConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/AerospikeClientConstructorInterceptor.java new file mode 100644 index 000000000..696a7a591 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/AerospikeClientConstructorInterceptor.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.aerospike; + +import com.aerospike.client.Host; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.util.StringUtil; + +import java.util.ArrayList; + +public class AerospikeClientConstructorInterceptor implements InstanceConstructorInterceptor { + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + String peer = ""; + if (allArguments.length >= 1 && allArguments[0] instanceof String) { + peer = allArguments[0] + ":" + allArguments[1]; + } else if (allArguments.length >= 2 && allArguments[1] instanceof String) { + peer = allArguments[1] + ":" + allArguments[2]; + } else if (allArguments.length >= 2 && allArguments[1] instanceof Host) { + Host host = (Host) allArguments[1]; + peer = host.name + ":" + host.port; + } else if (allArguments.length >= 2 && allArguments[1] instanceof Host[]) { + Host[] hosts = (Host[]) allArguments[1]; + ArrayList names = new ArrayList(hosts.length); + for (Host host: hosts) { + names.add(host.name + ":" + host.port); + } + peer = StringUtil.join(';', names.toArray(new String[0])); + } + objInst.setSkyWalkingDynamicField(peer); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/AerospikeClientMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/AerospikeClientMethodInterceptor.java new file mode 100644 index 000000000..4e42ec57c --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/AerospikeClientMethodInterceptor.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.aerospike; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +public class AerospikeClientMethodInterceptor implements InstanceMethodsAroundInterceptor { + private static final Set OPERATION_MAPPING_READ = new HashSet<>(Arrays.asList( + "get", + "prepend", + "exists", + "getHeader", + "scanAll", + "scanNode", + "scanPartitions", + "getLargeList", + "getLargeMap", + "getLargeSet", + "getLargeStack", + "query", + "queryNode", + "queryPartitions", + "queryAggregate", + "queryAggregateNode", + "info" + )); + + private static final Set OPERATION_MAPPING_WRITE = new HashSet<>(Arrays.asList( + "append", + "put", + "add", + "delete", + "touch", + "operate", + "register", + "registerUdfString", + "removeUdf", + "execute" + )); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + String peer = String.valueOf(objInst.getSkyWalkingDynamicField()); + String methodName = method.getName(); + AbstractSpan span = ContextManager.createExitSpan("Aerospike/" + methodName, peer); + span.setComponent(ComponentsDefine.AEROSPIKE); + Tags.CACHE_TYPE.set(span, "Aerospike"); + SpanLayer.asCache(span); + parseOperation(methodName).ifPresent(op -> Tags.CACHE_OP.set(span, op)); + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan span = ContextManager.activeSpan(); + span.log(t); + } + + private Optional parseOperation(String cmd) { + if (OPERATION_MAPPING_READ.contains(cmd)) { + return Optional.of("read"); + } + if (OPERATION_MAPPING_WRITE.contains(cmd)) { + return Optional.of("write"); + } + return Optional.empty(); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/define/AerospikeClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/define/AerospikeClientInstrumentation.java new file mode 100644 index 000000000..5af25f161 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/java/org/apache/skywalking/apm/plugin/aerospike/define/AerospikeClientInstrumentation.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.plugin.aerospike.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class AerospikeClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "com.aerospike.client.AerospikeClient"; + private static final String HOST_ARG_TYPE_NAME = "com.aerospike.client.policy.ClientPolicy"; + private static final String AEROSPIKE_CLIENT_CONSTRUCTOR_INTERCEPTOR = "org.apache.skywalking.apm.plugin.aerospike.AerospikeClientConstructorInterceptor"; + private static final String AEROSPIKE_CLIENT_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.aerospike.AerospikeClientMethodInterceptor"; + private static final String[] ENHANCE_METHODS = new String[] { + "append", + "put", + "prepend", + "add", + "delete", + "touch", + "exists", + "get", + "getHeader", + "operate", + "scanAll", + "scanNode", + "scanPartitions", + "getLargeList", + "getLargeMap", + "getLargeSet", + "getLargeStack", + "register", + "registerUdfString", + "removeUdf", + "execute", + "query", + "queryNode", + "queryPartitions", + "queryAggregate", + "queryAggregateNode", + "info" + }; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, HOST_ARG_TYPE_NAME); + } + + @Override + public String getConstructorInterceptor() { + return AEROSPIKE_CLIENT_CONSTRUCTOR_INTERCEPTOR; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + final InstanceMethodsInterceptPoint[] points = new InstanceMethodsInterceptPoint[ENHANCE_METHODS.length]; + for (int i = 0; i < ENHANCE_METHODS.length; i++) { + final String method = ENHANCE_METHODS[i]; + final InstanceMethodsInterceptPoint point = new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(method); + } + + @Override + public String getMethodsInterceptor() { + return AEROSPIKE_CLIENT_METHOD_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + }; + points[i] = point; + } + return points; + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..5f883dc8d --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/aerospike-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +aerospike=org.apache.skywalking.apm.plugin.aerospike.define.AerospikeClientInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index dbb572136..d44f682ec 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -133,6 +133,7 @@ grizzly-2.3.x-4.x-work-threadpool-plugin rocketMQ-5.x-plugin websphere-liberty-23.x-plugin + aerospike-plugin pom diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md index 80d613f6d..749539889 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -1,4 +1,5 @@ # Skywalking Agent List +- aerospike - activemq-5.x - armeria-063-084 - armeria-085 diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 43832d4d4..3ed5dbf76 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -79,6 +79,7 @@ metrics based on the tracing data. * [NATS](https://github.com/nats-io/nats.java) 2.14.x -> 2.15.x * Aliyun ONS 1.x (Optional¹) * NoSQL + * [aerospike](https://github.com/aerospike/aerospike-client-java) 3.x -> 6.x * Redis * [Jedis](https://github.com/xetorthio/jedis) 2.x-4.x * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.2+ diff --git a/test/plugin/scenarios/aerospike-scenario/bin/startup.sh b/test/plugin/scenarios/aerospike-scenario/bin/startup.sh new file mode 100644 index 000000000..faec41d9c --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/bin/startup.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +home="$(cd "$(dirname $0)"; pwd)" + +java -jar ${agent_opts} -Daerospike.host=${AEROSPIKE_HOST} -Daerospike.port=${AEROSPIKE_PORT} ${home}/../libs/aerospike-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/aerospike-scenario/config/expectedData.yaml b/test/plugin/scenarios/aerospike-scenario/config/expectedData.yaml new file mode 100644 index 000000000..940d456aa --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/config/expectedData.yaml @@ -0,0 +1,121 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +segmentItems: + - serviceName: aerospike-scenario + segmentSize: ge 1 + segments: + - segmentId: not null + spans: + - operationName: Aerospike/put + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 149 + isError: false + spanType: Exit + peer: aerospike-server:3000 + skipAnalysis: false + tags: + - { key: cache.type, value: Aerospike} + - { key: cache.op, value: write } + - operationName: Aerospike/exists + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 149 + isError: false + spanType: Exit + peer: aerospike-server:3000 + skipAnalysis: false + tags: + - { key: cache.type, value: Aerospike } + - { key: cache.op, value: read } + - operationName: Aerospike/get + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 149 + isError: false + spanType: Exit + peer: aerospike-server:3000 + skipAnalysis: false + tags: + - { key: cache.type, value: Aerospike } + - { key: cache.op, value: read } + - operationName: Aerospike/append + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 149 + isError: false + spanType: Exit + peer: aerospike-server:3000 + skipAnalysis: false + tags: + - { key: cache.type, value: Aerospike } + - { key: cache.op, value: write } + - operationName: Aerospike/operate + parentSpanId: 0 + spanId: 5 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 149 + isError: false + spanType: Exit + peer: aerospike-server:3000 + skipAnalysis: false + tags: + - { key: cache.type, value: Aerospike } + - { key: cache.op, value: write } + - operationName: Aerospike/delete + parentSpanId: 0 + spanId: 6 + spanLayer: Cache + startTime: gt 0 + endTime: gt 0 + componentId: 149 + isError: false + spanType: Exit + peer: aerospike-server:3000 + skipAnalysis: false + tags: + - { key: cache.type, value: Aerospike } + - { key: cache.op, value: write } + - operationName: GET:/aerospike-scenario/case/aerospike-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: gt 0 + endTime: gt 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - { key: url, value: 'http://localhost:8080/aerospike-scenario/case/aerospike-scenario' } + - { key: http.method, value: GET } + - { key: http.status_code, value: '200' } diff --git a/test/plugin/scenarios/aerospike-scenario/configuration.yml b/test/plugin/scenarios/aerospike-scenario/configuration.yml new file mode 100644 index 000000000..844bbe0b2 --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/configuration.yml @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +type: jvm +entryService: http://localhost:8080/aerospike-scenario/case/aerospike-scenario +healthCheck: http://localhost:8080/aerospike-scenario/case/healthCheck +startScript: ./bin/startup.sh +environment: + - AEROSPIKE_HOST=aerospike-server + - AEROSPIKE_PORT=3000 +dependencies: + aerospike-server: + image: aerospike:ce-6.0.0.0 + hostname: aerospike-server diff --git a/test/plugin/scenarios/aerospike-scenario/pom.xml b/test/plugin/scenarios/aerospike-scenario/pom.xml new file mode 100644 index 000000000..1258d64e6 --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/pom.xml @@ -0,0 +1,126 @@ + + + + + org.apache.skywalking.apm.testcase + aerospike-scenario + 1.0.0 + jar + + 4.0.0 + + + UTF-8 + 1.8 + 3.8.1 + YOUR VERSION + 2.1.6.RELEASE + 1.18.20 + + + skywalking-aerospike-scenario + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + + + + + com.aerospike + aerospike-client + 6.0.0 + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + + aerospike-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + diff --git a/test/plugin/scenarios/aerospike-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/aerospike-scenario/src/main/assembly/assembly.xml new file mode 100644 index 000000000..408ee8fff --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/aerospike-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/Application.java b/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/Application.java new file mode 100644 index 000000000..45e83ed6d --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/Application.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.testcase.aerospike; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + try { + SpringApplication.run(Application.class, args); + } catch (Exception e) { + // Never do this + } + } +} diff --git a/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/controller/AerospikeCommandExecutor.java b/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/controller/AerospikeCommandExecutor.java new file mode 100644 index 000000000..daf3f637b --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/controller/AerospikeCommandExecutor.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.testcase.aerospike.controller; + +import com.aerospike.client.AerospikeClient; +import com.aerospike.client.Bin; +import com.aerospike.client.Key; +import com.aerospike.client.Operation; +import com.aerospike.client.policy.WritePolicy; + +public class AerospikeCommandExecutor implements AutoCloseable { + private final AerospikeClient client; + private final WritePolicy defaultWritePolicy = new WritePolicy(); + private final WritePolicy defaultReadPolicy = new WritePolicy(); + private static final String VALUENAME = "DATA"; + private static final String NAMESPACE = "test"; + private static final String SETNAME = "skywalking"; + + public AerospikeCommandExecutor(String host, Integer port) { + client = new AerospikeClient(host, port); + } + + public void set(String key, String value) { + final Key k = new Key(NAMESPACE, SETNAME, key); + final Bin bin = new Bin(VALUENAME, value); + + client.put(defaultWritePolicy, k, bin); + } + + public void exists(String key) { + final Key k = new Key(NAMESPACE, SETNAME, key); + + client.exists(null, k); + } + + public void get(String key) { + final Key k = new Key(NAMESPACE, SETNAME, key); + + client.get(defaultReadPolicy, k); + } + + public void append(String key, String value) { + final Key k = new Key(NAMESPACE, SETNAME, key); + final Bin bin = new Bin(VALUENAME, value); + + client.append(defaultWritePolicy, k, bin); + } + + public void operate(String key, long by) { + final Key k = new Key(NAMESPACE, SETNAME, key); + + client.operate(defaultWritePolicy, k, Operation.add(new Bin(VALUENAME, by)), Operation.get(VALUENAME)); + } + + public void delete(String key) { + final Key k = new Key(NAMESPACE, SETNAME, key); + + client.delete(null, k); + } + + public void close() throws Exception { + client.close(); + } +} \ No newline at end of file diff --git a/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/controller/CaseController.java b/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/controller/CaseController.java new file mode 100644 index 000000000..0513b2faa --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/src/main/java/org/apache/skywalking/apm/testcase/aerospike/controller/CaseController.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.skywalking.apm.testcase.aerospike.controller; + +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/case") +@Log4j2 +public class CaseController { + + private static final String SUCCESS = "Success"; + + @Value("${aerospike.host:127.0.0.1}") + private String aerospikeHost; + + @Value("${aerospike.port:3000}") + private Integer aerospikePort; + + @RequestMapping("/aerospike-scenario") + @ResponseBody + public String testcase() throws Exception { + try (AerospikeCommandExecutor command = new AerospikeCommandExecutor(aerospikeHost, aerospikePort)) { + command.set("a", "a"); + command.exists("a"); + command.get("a"); + command.append("a", "a"); + command.operate("b", 1); + command.delete("a"); + } + + return SUCCESS; + } + + @RequestMapping("/healthCheck") + @ResponseBody + public String healthCheck() { + // your codes + return SUCCESS; + } + +} diff --git a/test/plugin/scenarios/aerospike-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/aerospike-scenario/src/main/resources/application.yaml new file mode 100644 index 000000000..0e5175d49 --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/src/main/resources/application.yaml @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +# +server: + port: 8080 + servlet: + context-path: /aerospike-scenario +logging: + config: classpath:log4j2.xml \ No newline at end of file diff --git a/test/plugin/scenarios/aerospike-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/aerospike-scenario/src/main/resources/log4j2.xml new file mode 100644 index 000000000..9849ed5a8 --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/aerospike-scenario/support-version.list b/test/plugin/scenarios/aerospike-scenario/support-version.list new file mode 100644 index 000000000..2c7a7c9a4 --- /dev/null +++ b/test/plugin/scenarios/aerospike-scenario/support-version.list @@ -0,0 +1,21 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +# lists your version here (Contains only the last version number of each minor version.) +6.0.0 +5.0.0 +4.0.0 +3.0.0 \ No newline at end of file