Skip to content

Commit d42e245

Browse files
authored
Add plugin to support Aerospike Java client (#565)
1 parent e464f18 commit d42e245

22 files changed

Lines changed: 924 additions & 0 deletions

File tree

.github/workflows/plugins-test.3.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ jobs:
5252
strategy:
5353
matrix:
5454
case:
55+
- aerospike-scenario
5556
- mysql-scenario
5657
- undertow-scenario
5758
- webflux-scenario

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ Callable {
138138
* Fix the thread safety bug of finishing operation for the span named "SpringCloudGateway/sendRequest"
139139
* Fix NPE in guava-eventbus-plugin.
140140
* Add WebSphere Liberty 23.x plugin
141+
* Add Plugin to support aerospike Java client
141142

142143
#### Documentation
143144

apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,4 +238,7 @@ public class ComponentsDefine {
238238
public static final OfficialComponent GRIZZLY = new OfficialComponent(147, "Grizzly");
239239

240240
public static final OfficialComponent WEBSPHERE = new OfficialComponent(148, "WebSphere");
241+
242+
public static final OfficialComponent AEROSPIKE = new OfficialComponent(149, "Aerospike");
243+
241244
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Licensed to the Apache Software Foundation (ASF) under one or more
4+
~ contributor license agreements. See the NOTICE file distributed with
5+
~ this work for additional information regarding copyright ownership.
6+
~ The ASF licenses this file to You under the Apache License, Version 2.0
7+
~ (the "License"); you may not use this file except in compliance with
8+
~ the License. You may obtain a copy of the License at
9+
~
10+
~ http://www.apache.org/licenses/LICENSE-2.0
11+
~
12+
~ Unless required by applicable law or agreed to in writing, software
13+
~ distributed under the License is distributed on an "AS IS" BASIS,
14+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
~ See the License for the specific language governing permissions and
16+
~ limitations under the License.
17+
~
18+
-->
19+
20+
<project xmlns="http://maven.apache.org/POM/4.0.0"
21+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
23+
<parent>
24+
<artifactId>apm-sdk-plugin</artifactId>
25+
<groupId>org.apache.skywalking</groupId>
26+
<version>9.0.0-SNAPSHOT</version>
27+
</parent>
28+
<modelVersion>4.0.0</modelVersion>
29+
30+
<artifactId>apm-aerospike-plugin</artifactId>
31+
<packaging>jar</packaging>
32+
33+
<name>aerospike-plugin</name>
34+
35+
<dependencies>
36+
<dependency>
37+
<groupId>com.aerospike</groupId>
38+
<artifactId>aerospike-client</artifactId>
39+
<version>6.0.0</version>
40+
<scope>provided</scope>
41+
</dependency>
42+
</dependencies>
43+
<properties>
44+
<maven.compiler.source>8</maven.compiler.source>
45+
<maven.compiler.target>8</maven.compiler.target>
46+
</properties>
47+
48+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.skywalking.apm.plugin.aerospike;
19+
20+
import com.aerospike.client.Host;
21+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
22+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
23+
import org.apache.skywalking.apm.util.StringUtil;
24+
25+
import java.util.ArrayList;
26+
27+
public class AerospikeClientConstructorInterceptor implements InstanceConstructorInterceptor {
28+
@Override
29+
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
30+
String peer = "";
31+
if (allArguments.length >= 1 && allArguments[0] instanceof String) {
32+
peer = allArguments[0] + ":" + allArguments[1];
33+
} else if (allArguments.length >= 2 && allArguments[1] instanceof String) {
34+
peer = allArguments[1] + ":" + allArguments[2];
35+
} else if (allArguments.length >= 2 && allArguments[1] instanceof Host) {
36+
Host host = (Host) allArguments[1];
37+
peer = host.name + ":" + host.port;
38+
} else if (allArguments.length >= 2 && allArguments[1] instanceof Host[]) {
39+
Host[] hosts = (Host[]) allArguments[1];
40+
ArrayList<String> names = new ArrayList<String>(hosts.length);
41+
for (Host host: hosts) {
42+
names.add(host.name + ":" + host.port);
43+
}
44+
peer = StringUtil.join(';', names.toArray(new String[0]));
45+
}
46+
objInst.setSkyWalkingDynamicField(peer);
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.skywalking.apm.plugin.aerospike;
19+
20+
import org.apache.skywalking.apm.agent.core.context.ContextManager;
21+
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
22+
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
23+
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
25+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
26+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
27+
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
28+
29+
import java.lang.reflect.Method;
30+
import java.util.Arrays;
31+
import java.util.HashSet;
32+
import java.util.Optional;
33+
import java.util.Set;
34+
35+
public class AerospikeClientMethodInterceptor implements InstanceMethodsAroundInterceptor {
36+
private static final Set<String> OPERATION_MAPPING_READ = new HashSet<>(Arrays.asList(
37+
"get",
38+
"prepend",
39+
"exists",
40+
"getHeader",
41+
"scanAll",
42+
"scanNode",
43+
"scanPartitions",
44+
"getLargeList",
45+
"getLargeMap",
46+
"getLargeSet",
47+
"getLargeStack",
48+
"query",
49+
"queryNode",
50+
"queryPartitions",
51+
"queryAggregate",
52+
"queryAggregateNode",
53+
"info"
54+
));
55+
56+
private static final Set<String> OPERATION_MAPPING_WRITE = new HashSet<>(Arrays.asList(
57+
"append",
58+
"put",
59+
"add",
60+
"delete",
61+
"touch",
62+
"operate",
63+
"register",
64+
"registerUdfString",
65+
"removeUdf",
66+
"execute"
67+
));
68+
69+
@Override
70+
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
71+
MethodInterceptResult result) throws Throwable {
72+
String peer = String.valueOf(objInst.getSkyWalkingDynamicField());
73+
String methodName = method.getName();
74+
AbstractSpan span = ContextManager.createExitSpan("Aerospike/" + methodName, peer);
75+
span.setComponent(ComponentsDefine.AEROSPIKE);
76+
Tags.CACHE_TYPE.set(span, "Aerospike");
77+
SpanLayer.asCache(span);
78+
parseOperation(methodName).ifPresent(op -> Tags.CACHE_OP.set(span, op));
79+
}
80+
81+
@Override
82+
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
83+
Object ret) throws Throwable {
84+
ContextManager.stopSpan();
85+
return ret;
86+
}
87+
88+
@Override
89+
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
90+
Class<?>[] argumentsTypes, Throwable t) {
91+
AbstractSpan span = ContextManager.activeSpan();
92+
span.log(t);
93+
}
94+
95+
private Optional<String> parseOperation(String cmd) {
96+
if (OPERATION_MAPPING_READ.contains(cmd)) {
97+
return Optional.of("read");
98+
}
99+
if (OPERATION_MAPPING_WRITE.contains(cmd)) {
100+
return Optional.of("write");
101+
}
102+
return Optional.empty();
103+
}
104+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.skywalking.apm.plugin.aerospike.define;
19+
20+
import net.bytebuddy.description.method.MethodDescription;
21+
import net.bytebuddy.matcher.ElementMatcher;
22+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
23+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
24+
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
25+
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
26+
27+
import static net.bytebuddy.matcher.ElementMatchers.named;
28+
import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
29+
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
30+
31+
public class AerospikeClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
32+
private static final String ENHANCE_CLASS = "com.aerospike.client.AerospikeClient";
33+
private static final String HOST_ARG_TYPE_NAME = "com.aerospike.client.policy.ClientPolicy";
34+
private static final String AEROSPIKE_CLIENT_CONSTRUCTOR_INTERCEPTOR = "org.apache.skywalking.apm.plugin.aerospike.AerospikeClientConstructorInterceptor";
35+
private static final String AEROSPIKE_CLIENT_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.aerospike.AerospikeClientMethodInterceptor";
36+
private static final String[] ENHANCE_METHODS = new String[] {
37+
"append",
38+
"put",
39+
"prepend",
40+
"add",
41+
"delete",
42+
"touch",
43+
"exists",
44+
"get",
45+
"getHeader",
46+
"operate",
47+
"scanAll",
48+
"scanNode",
49+
"scanPartitions",
50+
"getLargeList",
51+
"getLargeMap",
52+
"getLargeSet",
53+
"getLargeStack",
54+
"register",
55+
"registerUdfString",
56+
"removeUdf",
57+
"execute",
58+
"query",
59+
"queryNode",
60+
"queryPartitions",
61+
"queryAggregate",
62+
"queryAggregateNode",
63+
"info"
64+
};
65+
66+
@Override
67+
public ClassMatch enhanceClass() {
68+
return byName(ENHANCE_CLASS);
69+
}
70+
71+
@Override
72+
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
73+
return new ConstructorInterceptPoint[] {
74+
new ConstructorInterceptPoint() {
75+
@Override
76+
public ElementMatcher<MethodDescription> getConstructorMatcher() {
77+
return takesArgumentWithType(0, HOST_ARG_TYPE_NAME);
78+
}
79+
80+
@Override
81+
public String getConstructorInterceptor() {
82+
return AEROSPIKE_CLIENT_CONSTRUCTOR_INTERCEPTOR;
83+
}
84+
}
85+
};
86+
}
87+
88+
@Override
89+
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
90+
final InstanceMethodsInterceptPoint[] points = new InstanceMethodsInterceptPoint[ENHANCE_METHODS.length];
91+
for (int i = 0; i < ENHANCE_METHODS.length; i++) {
92+
final String method = ENHANCE_METHODS[i];
93+
final InstanceMethodsInterceptPoint point = new InstanceMethodsInterceptPoint() {
94+
@Override
95+
public ElementMatcher<MethodDescription> getMethodsMatcher() {
96+
return named(method);
97+
}
98+
99+
@Override
100+
public String getMethodsInterceptor() {
101+
return AEROSPIKE_CLIENT_METHOD_INTERCEPTOR;
102+
}
103+
104+
@Override
105+
public boolean isOverrideArgs() {
106+
return false;
107+
}
108+
};
109+
points[i] = point;
110+
}
111+
return points;
112+
}
113+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
aerospike=org.apache.skywalking.apm.plugin.aerospike.define.AerospikeClientInstrumentation

apm-sniffer/apm-sdk-plugin/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
<module>grizzly-2.3.x-4.x-work-threadpool-plugin</module>
134134
<module>rocketMQ-5.x-plugin</module>
135135
<module>websphere-liberty-23.x-plugin</module>
136+
<module>aerospike-plugin</module>
136137
</modules>
137138
<packaging>pom</packaging>
138139

docs/en/setup/service-agent/java-agent/Plugin-list.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Skywalking Agent List
2+
- aerospike
23
- activemq-5.x
34
- armeria-063-084
45
- armeria-085

0 commit comments

Comments
 (0)