diff --git a/.github/workflows/plugins-test.0.yaml b/.github/workflows/plugins-test.0.yaml index 9c8ac3f94..5356fc617 100644 --- a/.github/workflows/plugins-test.0.yaml +++ b/.github/workflows/plugins-test.0.yaml @@ -71,6 +71,7 @@ jobs: - gateway-2.0.x-scenario - grpc-scenario - gson-scenario + - guava-cache-scenario - elasticjob-3.x-scenario - springmvc-reactive-scenario - springmvc-reactive-devtools-scenario diff --git a/CHANGES.md b/CHANGES.md index 3aeba6339..21d6cb0de 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,6 +29,7 @@ Release Notes. * Fix async finish repeatedly in `spring-webflux-5.x-webclient` plugin. * Add agent plugin to support Sentinel. * Move `ehcache-2.x` plugin as an optional plugin. +* Support `guava-cache` plugin #### OAP-Backend 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 2fc8cb538..8fb8ddb38 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 @@ -204,4 +204,7 @@ public class ComponentsDefine { public static final OfficialComponent NEO4J = new OfficialComponent(112, "Neo4j"); public static final OfficialComponent SENTINEL = new OfficialComponent(113, "Sentinel"); + + public static final OfficialComponent GUAVA_CACHE = new OfficialComponent(114, "GuavaCache"); + } diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml new file mode 100644 index 000000000..15528eec1 --- /dev/null +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/pom.xml @@ -0,0 +1,50 @@ + + + + + + org.apache.skywalking + optional-plugins + 8.7.0-SNAPSHOT + + + apm-guava-cache-plugin + guava-cache-plugin + jar + + 4.0.0 + + + 23.0 + + + + + + com.google.guava + guava + ${guava-client.version} + provided + + + + + \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheAllInterceptor.java b/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheAllInterceptor.java new file mode 100644 index 000000000..fb945a199 --- /dev/null +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheAllInterceptor.java @@ -0,0 +1,50 @@ +/* + * 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.guava.cache; + +import org.apache.skywalking.apm.agent.core.context.ContextManager; +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; + +public class GuavaCacheAllInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + AbstractSpan span = ContextManager.createLocalSpan("GuavaCache/" + method.getName()); + span.setComponent(ComponentsDefine.GUAVA_CACHE); + SpanLayer.asCache(span); + } + + @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) { + ContextManager.activeSpan().log(t); + } +} diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheInterceptor.java b/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheInterceptor.java new file mode 100644 index 000000000..05d3bbabb --- /dev/null +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheInterceptor.java @@ -0,0 +1,55 @@ +/* + * 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.guava.cache; + +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; + +public class GuavaCacheInterceptor implements InstanceMethodsAroundInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + AbstractSpan span = ContextManager.createLocalSpan("GuavaCache/" + method.getName()); + span.setComponent(ComponentsDefine.GUAVA_CACHE); + Object key = allArguments[0]; + if (key != null) { + Tags.DB_STATEMENT.set(span, key.toString()); + } + SpanLayer.asCache(span); + } + + @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) { + ContextManager.activeSpan().log(t); + } +} diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/define/GuavaCachePluginInstrumentation.java b/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/define/GuavaCachePluginInstrumentation.java new file mode 100644 index 000000000..4ac151565 --- /dev/null +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/java/org/apache/skywalking/apm/plugin/guava/cache/define/GuavaCachePluginInstrumentation.java @@ -0,0 +1,99 @@ +/* + * 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.guava.cache.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.match.MultiClassNameMatch.byMultiClassMatch; + +public class GuavaCachePluginInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + public static final String INTERCEPT_LOCALMANUAL_CLASS = "com.google.common.cache.LocalCache$LocalManualCache"; + public static final String INTERCEPT_LOCALLOADING_CLASS = "com.google.common.cache.LocalCache$LocalLoadingCache"; + public static final String INTERCEPT_FORWARDING_CLASS = "com.google.common.cache.ForwardingCache"; + public static final String GET_ALL_PRESENT_ENHANCE_METHOD = "getAllPresent"; + public static final String INVALIDATE_ALL_ENHANCE_METHOD = "invalidateAll"; + public static final String GET_ENHANCE_METHOD = "get"; + public static final String INVALIDATE_ENHANCE_METHOD = "invalidate"; + public static final String PUT_ALL_ENHANCE_METHOD = "putAll"; + public static final String PUT_ENHANCE_METHOD = "put"; + public static final String GET_IF_PRESENT_ENHANCE_METHOD = "getIfPresent"; + public static final String GUAVA_CACHE_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.guava.cache.GuavaCacheInterceptor"; + public static final String GUAVA_CACHE_ALL_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.guava.cache.GuavaCacheAllInterceptor"; + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(GET_ENHANCE_METHOD) + .or(named(INVALIDATE_ENHANCE_METHOD)) + .or(named(PUT_ENHANCE_METHOD)) + .or(named(GET_IF_PRESENT_ENHANCE_METHOD)); + } + + @Override + public String getMethodsInterceptor() { + return GUAVA_CACHE_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + + }, + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(GET_ALL_PRESENT_ENHANCE_METHOD) + .or(named(INVALIDATE_ALL_ENHANCE_METHOD)) + .or(named(PUT_ALL_ENHANCE_METHOD)); + } + + @Override + public String getMethodsInterceptor() { + return GUAVA_CACHE_ALL_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return true; + } + + } + }; + } + + @Override + protected ClassMatch enhanceClass() { + return byMultiClassMatch(INTERCEPT_LOCALMANUAL_CLASS, INTERCEPT_LOCALLOADING_CLASS, INTERCEPT_FORWARDING_CLASS); + } +} diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/guava-cache-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..7c9d7dae2 --- /dev/null +++ b/apm-sniffer/optional-plugins/guava-cache-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. + +guava-cache=org.apache.skywalking.apm.plugin.guava.cache.define.GuavaCachePluginInstrumentation \ No newline at end of file diff --git a/apm-sniffer/optional-plugins/guava-cache-plugin/src/test/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheInterceptorTest.java b/apm-sniffer/optional-plugins/guava-cache-plugin/src/test/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheInterceptorTest.java new file mode 100644 index 000000000..2930ef7b1 --- /dev/null +++ b/apm-sniffer/optional-plugins/guava-cache-plugin/src/test/java/org/apache/skywalking/apm/plugin/guava/cache/GuavaCacheInterceptorTest.java @@ -0,0 +1,146 @@ +/* + * 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.guava.cache; + +import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.powermock.reflect.Whitebox; + +import java.lang.reflect.Method; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class GuavaCacheInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + private GuavaCacheInterceptor guavaCacheInterceptor; + + private GuavaCacheAllInterceptor guavaCacheAllInterceptor; + + private Object[] operateObjectArguments; + + private Exception exception; + + private Method getAllPresentMethod; + private Method invalidateAllMethod; + private Method getMethod; + + private Method invalidateMethod; + private Method putAllMethod; + private Method putMethod; + private Method getIfPresentMethod; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + @Before + public void setUp() throws Exception { + guavaCacheInterceptor = new GuavaCacheInterceptor(); + guavaCacheAllInterceptor = new GuavaCacheAllInterceptor(); + exception = new Exception(); + operateObjectArguments = new Object[]{"dataKey"}; + Class cache = Class.forName("com.google.common.cache.LocalCache$LocalManualCache"); + getAllPresentMethod = Whitebox.getMethods(cache, "getAllPresent")[0]; + invalidateAllMethod = Whitebox.getMethods(cache, "invalidateAll")[0]; + getMethod = Whitebox.getMethods(cache, "get")[0]; + invalidateMethod = Whitebox.getMethods(cache, "invalidate")[0]; + putAllMethod = Whitebox.getMethods(cache, "putAll")[0]; + putMethod = Whitebox.getMethods(cache, "put")[0]; + getIfPresentMethod = Whitebox.getMethods(cache, "getIfPresent")[0]; + + } + + @Test + public void assertGetAllPresentSuccess() throws Throwable { + guavaCacheAllInterceptor.beforeMethod(null, getAllPresentMethod, null, null, null); + guavaCacheAllInterceptor.handleMethodException(null, getAllPresentMethod, null, null, exception); + guavaCacheAllInterceptor.afterMethod(null, getAllPresentMethod, null, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void assertInvalidAllSuccess() throws Throwable { + guavaCacheAllInterceptor.beforeMethod(null, invalidateAllMethod, null, null, null); + guavaCacheAllInterceptor.handleMethodException(null, invalidateAllMethod, null, null, exception); + guavaCacheAllInterceptor.afterMethod(null, invalidateAllMethod, null, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void assertGetSuccess() throws Throwable { + guavaCacheInterceptor.beforeMethod(null, getMethod, operateObjectArguments, null, null); + guavaCacheInterceptor.handleMethodException(null, getMethod, operateObjectArguments, null, exception); + guavaCacheInterceptor.afterMethod(null, getMethod, operateObjectArguments, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void assertInvalidateSuccess() throws Throwable { + guavaCacheInterceptor.beforeMethod(null, invalidateMethod, operateObjectArguments, null, null); + guavaCacheInterceptor.handleMethodException(null, invalidateMethod, operateObjectArguments, null, exception); + guavaCacheInterceptor.afterMethod(null, invalidateMethod, operateObjectArguments, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void assertPutAllMethodSuccess() throws Throwable { + guavaCacheAllInterceptor.beforeMethod(null, putAllMethod, null, null, null); + guavaCacheAllInterceptor.handleMethodException(null, putAllMethod, null, null, exception); + guavaCacheAllInterceptor.afterMethod(null, putAllMethod, null, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void assertPutMethodSuccess() throws Throwable { + guavaCacheInterceptor.beforeMethod(null, putMethod, operateObjectArguments, null, null); + guavaCacheInterceptor.handleMethodException(null, putMethod, operateObjectArguments, null, exception); + guavaCacheInterceptor.afterMethod(null, putMethod, operateObjectArguments, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } + + @Test + public void assertGetIfPresentMethodSuccess() throws Throwable { + guavaCacheInterceptor.beforeMethod(null, getIfPresentMethod, operateObjectArguments, null, null); + guavaCacheInterceptor.handleMethodException(null, getIfPresentMethod, operateObjectArguments, null, exception); + guavaCacheInterceptor.afterMethod(null, getIfPresentMethod, operateObjectArguments, null, null); + List traceSegments = segmentStorage.getTraceSegments(); + Assert.assertThat(traceSegments.size(), is(1)); + } +} diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml index 8f49f27f3..897a05092 100644 --- a/apm-sniffer/optional-plugins/pom.xml +++ b/apm-sniffer/optional-plugins/pom.xml @@ -52,6 +52,7 @@ mybatis-3.x-plugin sentinel-1.x-plugin ehcache-2.x-plugin + guava-cache-plugin 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 1d46c7431..58d5ee5ca 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -23,6 +23,7 @@ - graphql - grpc-1.x - gson-2.8.x +- guava-cache - h2-1.x - hbase-1.x/2.x - httpasyncclient-4.x diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index c25337adf..d41c926c1 100755 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -195,6 +195,7 @@ Now, we have the following known optional plugins. * Plugin of mybatis-3.x in optional plugin folder. The reason of being optional plugin is, many local span are generated, which also spend more CPU, memory and network. * Plugin of sentinel-1.x in the optional plugin folder. The reason for being an optional plugin is, the sentinel plugin generates a large number of local spans, which have a potential performance impact. * Plugin of ehcache-2.x in the optional plugin folder. The reason for being an optional plugin is, this plugin enhanced cache framework, generates large number of local spans, which have a potential performance impact. +* Plugin of guava-cache in the optional plugin folder. The reason for being an optional plugin is, this plugin enhanced cache framework, generates large number of local spans, which have a potential performance impact. ## Bootstrap class plugins All bootstrap plugins are optional, due to unexpected risk. Bootstrap plugins are provided in `bootstrap-plugins` folder. 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 a5fd41e4d..a08d39cab 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -116,6 +116,7 @@ metrics based on the tracing data. * JRE Callable and Runnable (Optional²) * Cache * [Ehcache](https://www.ehcache.org/) 2.x + * [GuavaCache](https://github.com/google/guava) 18.x -> 23.x (Optional²) * Kotlin * [Coroutine](https://kotlinlang.org/docs/reference/coroutines-overview.html) 1.0.1 -> 1.3.x (Optional²) * GraphQL diff --git a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml index 5e6e1588c..0d3d112f7 100755 --- a/oap-server/server-bootstrap/src/main/resources/component-libraries.yml +++ b/oap-server/server-bootstrap/src/main/resources/component-libraries.yml @@ -371,6 +371,9 @@ Neo4j: Sentinel: id: 113 languages: Java +GuavaCache: + id: 114 + languages: Java # .NET/.NET Core components # [3000, 4000) for C#/.NET only diff --git a/test/plugin/scenarios/guava-cache-scenario/config/expectedData.yaml b/test/plugin/scenarios/guava-cache-scenario/config/expectedData.yaml new file mode 100644 index 000000000..c33f4d9c6 --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/config/expectedData.yaml @@ -0,0 +1,101 @@ +# 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: guava-cache-scenario + segmentSize: ge 1 + segments: + - segmentId: not null + spans: + - operationName: GuavaCache/put + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 114 + isError: false + spanType: Local + peer: '' + tags: + - {key: db.statement, value: testKey1} + skipAnalysis: 'false' + - operationName: GuavaCache/invalidate + operationId: 0 + parentSpanId: 0 + spanId: 2 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 114 + isError: false + spanType: Local + peer: '' + tags: + - {key: db.statement, value: testKey1} + skipAnalysis: 'false' + - operationName: GuavaCache/get + operationId: 0 + parentSpanId: 0 + spanId: 3 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 114 + isError: false + spanType: Local + peer: '' + tags: + - {key: db.statement, value: testKey1} + skipAnalysis: 'false' + - operationName: GuavaCache/getIfPresent + operationId: 0 + parentSpanId: 0 + spanId: 4 + spanLayer: Cache + startTime: nq 0 + endTime: nq 0 + componentId: 114 + isError: false + spanType: Local + peer: '' + tags: + - {key: db.statement, value: testKey1} + skipAnalysis: 'false' + - {operationName: GuavaCache/putAll, operationId: 0, parentSpanId: 0, spanId: 5, spanLayer: Cache, + startTime: nq 0, endTime: nq 0, componentId: 114, isError: false, + spanType: Local, peer: '', skipAnalysis: false} + - {operationName: GuavaCache/getAllPresent, operationId: 0, parentSpanId: 0, spanId: 6, + spanLayer: Cache, startTime: nq 0, endTime: nq 0, componentId: 114, + isError: false, spanType: Local, peer: '', skipAnalysis: false} + - {operationName: GuavaCache/invalidateAll, operationId: 0, parentSpanId: 0, spanId: 7, + spanLayer: Cache, startTime: nq 0, endTime: nq 0, componentId: 114, + isError: false, spanType: Local, peer: '', skipAnalysis: false} + - operationName: /guava-cache-scenario/case/guava + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + tags: + - {key: url, value: 'http://localhost:8080/guava-cache-scenario/case/guava'} + - {key: http.method, value: GET} + skipAnalysis: 'false' diff --git a/test/plugin/scenarios/guava-cache-scenario/configuration.yml b/test/plugin/scenarios/guava-cache-scenario/configuration.yml new file mode 100644 index 000000000..f6615dbb5 --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/configuration.yml @@ -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. + +type: tomcat +entryService: http://localhost:8080/guava-cache-scenario/case/guava +healthCheck: http://localhost:8080/guava-cache-scenario/healthCheck +runningMode: with_optional +withPlugins: apm-guava-cache-plugin-*.jar diff --git a/test/plugin/scenarios/guava-cache-scenario/pom.xml b/test/plugin/scenarios/guava-cache-scenario/pom.xml new file mode 100644 index 000000000..b875f7343 --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/pom.xml @@ -0,0 +1,77 @@ + + + + 4.0.0 + + org.apache.skywalking + guava-cache-scenario + 5.0.0 + war + + + UTF-8 + 1.8 + + + guava + 23.0 + + + skywalking-guava-cache-scenario + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + org.apache.logging.log4j + log4j-api + 2.8.1 + + + org.apache.logging.log4j + log4j-core + 2.8.1 + + + com.google.guava + guava + ${test.framework.version} + + + + + guava-cache-scenario + + + maven-compiler-plugin + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/guava-cache-scenario/src/main/java/org/apache/skywalking/apm/testcase/guava/cache/CaseServlet.java b/test/plugin/scenarios/guava-cache-scenario/src/main/java/org/apache/skywalking/apm/testcase/guava/cache/CaseServlet.java new file mode 100644 index 000000000..e417210ee --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/src/main/java/org/apache/skywalking/apm/testcase/guava/cache/CaseServlet.java @@ -0,0 +1,71 @@ +/* + * 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.guava.cache; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +public class CaseServlet extends HttpServlet { + + Cache cache = CacheBuilder.newBuilder().softValues().build(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String key1 = "testKey1"; + String value1 = "testValue1"; + cache.put(key1, value1); + cache.invalidate(key1); + try { + cache.get(key1, () -> value1); + } catch (ExecutionException e) { + e.printStackTrace(); + } + cache.getIfPresent(key1); + Map kvs = Maps.newHashMap(); + String key2 = "testKey2"; + String value2 = "testValue2"; + kvs.put(key2, value2); + cache.putAll(kvs); + List testKeys = Lists.newArrayList(key1, key2); + cache.getAllPresent(testKeys); + cache.invalidateAll(); + PrintWriter printWriter = resp.getWriter(); + printWriter.write("success"); + printWriter.flush(); + printWriter.close(); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + doGet(req, resp); + } + +} diff --git a/test/plugin/scenarios/guava-cache-scenario/src/main/java/org/apache/skywalking/apm/testcase/guava/cache/HealthCheckServlet.java b/test/plugin/scenarios/guava-cache-scenario/src/main/java/org/apache/skywalking/apm/testcase/guava/cache/HealthCheckServlet.java new file mode 100644 index 000000000..5ebfa8bd8 --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/src/main/java/org/apache/skywalking/apm/testcase/guava/cache/HealthCheckServlet.java @@ -0,0 +1,40 @@ +/* + * 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.guava.cache; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class HealthCheckServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + PrintWriter writer = resp.getWriter(); + writer.write("Success"); + writer.flush(); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + doGet(req, resp); + } +} diff --git a/test/plugin/scenarios/guava-cache-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/guava-cache-scenario/src/main/resources/log4j2.xml new file mode 100644 index 000000000..4c6c06d40 --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/guava-cache-scenario/src/main/webapp/WEB-INF/web.xml b/test/plugin/scenarios/guava-cache-scenario/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..539fef6a1 --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,44 @@ + + + skywalking-guava-cache-scenario + + + caseServlet + org.apache.skywalking.apm.testcase.guava.cache.CaseServlet + + + caseServlet + /case/guava + + + + healthCheck + org.apache.skywalking.apm.testcase.guava.cache.HealthCheckServlet + + + healthCheck + /healthCheck + + + + diff --git a/test/plugin/scenarios/guava-cache-scenario/support-version.list b/test/plugin/scenarios/guava-cache-scenario/support-version.list new file mode 100644 index 000000000..41e6e7502 --- /dev/null +++ b/test/plugin/scenarios/guava-cache-scenario/support-version.list @@ -0,0 +1,22 @@ +# 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. + +18.0 +19.0 +20.0 +21.0 +22.0 +23.0 \ No newline at end of file