You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2019/10/10 14:39:43 UTC

[skywalking] branch master updated: Provide plugin for Ehcache 2.x (#3575)

This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 5880417  Provide plugin for Ehcache 2.x (#3575)
5880417 is described below

commit 58804174e19be6f10d30588a33c381d07deb923f
Author: mrproliu <74...@qq.com>
AuthorDate: Thu Oct 10 22:39:37 2019 +0800

    Provide plugin for Ehcache 2.x (#3575)
    
    * support ehcache 2.x
---
 Jenkinsfile-Agent-Test                             |   6 +
 .../network/trace/component/ComponentsDefine.java  |   2 +
 .../apm-sdk-plugin/ehcache-2.x-plugin/pom.xml      |  50 ++++++
 .../ehcache/v2/EhcacheConstructorInterceptor.java  |  38 +++++
 .../apm/plugin/ehcache/v2/EhcacheEnhanceInfo.java  |  42 +++++
 .../plugin/ehcache/v2/EhcacheLockInterceptor.java  |  65 ++++++++
 .../ehcache/v2/EhcacheOperateAllInterceptor.java   |  55 ++++++
 .../v2/EhcacheOperateElementInterceptor.java       |  62 +++++++
 .../v2/EhcacheOperateObjectInterceptor.java        |  61 +++++++
 .../v2/define/EhcachePluginInstrumentation.java    | 185 +++++++++++++++++++++
 .../src/main/resources/skywalking-plugin.def       |  17 ++
 .../plugin/ehcache/v2/EhcacheInterceptorTest.java  | 173 +++++++++++++++++++
 apm-sniffer/apm-sdk-plugin/pom.xml                 |   1 +
 .../service-agent/java-agent/Supported-list.md     |   2 +
 .../src/test/resources/component-libraries.yml     |   3 +
 .../src/main/resources/component-libraries.yml     |   3 +
 .../ehcache-2.x-scenario/config/expectedData.yaml  | 136 +++++++++++++++
 .../ehcache-2.x-scenario/configuration.yml         |  20 +++
 test/plugin/scenarios/ehcache-2.x-scenario/pom.xml |  77 +++++++++
 .../apm/testcase/ehcache/v2/CaseServlet.java       |  73 ++++++++
 .../testcase/ehcache/v2/HealthCheckServlet.java    |  40 +++++
 .../src/main/resources/cache.xml                   |  36 ++++
 .../src/main/resources/log4j2.xml                  |  30 ++++
 .../src/main/webapp/WEB-INF/web.xml                |  45 +++++
 .../ehcache-2.x-scenario/support-version.list      |  35 ++++
 25 files changed, 1257 insertions(+)

diff --git a/Jenkinsfile-Agent-Test b/Jenkinsfile-Agent-Test
index b4412b1..8cc864c 100755
--- a/Jenkinsfile-Agent-Test
+++ b/Jenkinsfile-Agent-Test
@@ -60,6 +60,12 @@ pipeline {
                 sh 'bash test/plugin/run.sh --build_id=${BUILD_ID} httpclient-4.3.x-scenario'
             }
         }
+
+        stage('ehcache 2.8.x-2.10.x') {
+            steps {
+                sh 'bash test/plugin/run.sh --build_id=${BUILD_ID} ehcache-2.x-scenario'
+            }
+        }
     }
 
     post {
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 7bb53c8..45c494a 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
@@ -139,4 +139,6 @@ public class ComponentsDefine {
     public static final OfficialComponent PULSAR_PRODUCER = new OfficialComponent(73, "pulsar-producer");
 
     public static final OfficialComponent PULSAR_CONSUMER = new OfficialComponent(74, "pulsar-consumer");
+
+    public static final OfficialComponent EHCACHE = new OfficialComponent(75, "Ehcache");
 }
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/pom.xml
new file mode 100644
index 0000000..4c0d0ea
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/pom.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+
+<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">
+    <parent>
+        <artifactId>apm-sdk-plugin</artifactId>
+        <groupId>org.apache.skywalking</groupId>
+        <version>6.5.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>apm-ehcache-2.x-plugin</artifactId>
+    <name>ehcache-2.x-plugin</name>
+    <packaging>jar</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <ehcache-client.version>2.10.2.2.21</ehcache-client.version>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>net.sf.ehcache</groupId>
+            <artifactId>ehcache</artifactId>
+            <version>${ehcache-client.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+
+
+
+</project>
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheConstructorInterceptor.java
new file mode 100644
index 0000000..718d901
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheConstructorInterceptor.java
@@ -0,0 +1,38 @@
+/*
+ * 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.ehcache.v2;
+
+import net.sf.ehcache.config.CacheConfiguration;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+/**
+ * @author MrPro
+ */
+public class EhcacheConstructorInterceptor implements InstanceConstructorInterceptor {
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+        CacheConfiguration cacheConfiguration = (CacheConfiguration) allArguments[0];
+
+        // get cache name
+        if (cacheConfiguration != null) {
+            objInst.setSkyWalkingDynamicField(new EhcacheEnhanceInfo(cacheConfiguration.getName()));
+        }
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheEnhanceInfo.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheEnhanceInfo.java
new file mode 100644
index 0000000..b61caef
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheEnhanceInfo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.ehcache.v2;
+
+/**
+ * @author MrPro
+ */
+public class EhcacheEnhanceInfo {
+
+    private String cacheName;
+
+    public EhcacheEnhanceInfo() {
+    }
+
+    public EhcacheEnhanceInfo(String cacheName) {
+        this.cacheName = cacheName;
+    }
+
+    public String getCacheName() {
+        return cacheName;
+    }
+
+    public void setCacheName(String cacheName) {
+        this.cacheName = cacheName;
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheLockInterceptor.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheLockInterceptor.java
new file mode 100644
index 0000000..73be481
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheLockInterceptor.java
@@ -0,0 +1,65 @@
+/*
+ * 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.ehcache.v2;
+
+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 static org.apache.skywalking.apm.plugin.ehcache.v2.define.EhcachePluginInstrumentation.LOCK_ENHANCE_METHOD_SUFFIX;
+
+/**
+ * @author MrPro
+ */
+public class EhcacheLockInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+        EhcacheEnhanceInfo enhanceInfo = (EhcacheEnhanceInfo) objInst.getSkyWalkingDynamicField();
+
+        String operateName = method.getName().substring(0, method.getName().length() - LOCK_ENHANCE_METHOD_SUFFIX.length());
+
+        AbstractSpan span = ContextManager.createLocalSpan("Ehcache/" + operateName + "/" + enhanceInfo.getCacheName());
+        span.setComponent(ComponentsDefine.EHCACHE);
+        SpanLayer.asCache(span);
+
+        Object element = allArguments[0];
+        if (element != null) {
+            Tags.DB_STATEMENT.set(span, element.toString());
+        }
+    }
+
+    @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().errorOccurred().log(t);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateAllInterceptor.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateAllInterceptor.java
new file mode 100644
index 0000000..eb478e4
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateAllInterceptor.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.ehcache.v2;
+
+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;
+
+/**
+ * @author MrPro
+ */
+public class EhcacheOperateAllInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+        EhcacheEnhanceInfo enhanceInfo = (EhcacheEnhanceInfo) objInst.getSkyWalkingDynamicField();
+
+        AbstractSpan span = ContextManager.createLocalSpan("Ehcache/" + method.getName() + "/" + enhanceInfo.getCacheName());
+        span.setComponent(ComponentsDefine.EHCACHE);
+        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().errorOccurred().log(t);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateElementInterceptor.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateElementInterceptor.java
new file mode 100644
index 0000000..e2ef5e4
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateElementInterceptor.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.plugin.ehcache.v2;
+
+import net.sf.ehcache.Element;
+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;
+
+/**
+ * @author MrPro
+ */
+public class EhcacheOperateElementInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+        EhcacheEnhanceInfo enhanceInfo = (EhcacheEnhanceInfo) objInst.getSkyWalkingDynamicField();
+
+        AbstractSpan span = ContextManager.createLocalSpan("Ehcache/" + method.getName() + "/" + enhanceInfo.getCacheName());
+        span.setComponent(ComponentsDefine.EHCACHE);
+        SpanLayer.asCache(span);
+
+        Element element = (Element) allArguments[0];
+        if (element != null && element.getObjectKey() != null) {
+            Tags.DB_STATEMENT.set(span, element.getObjectKey().toString());
+        }
+    }
+
+    @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().errorOccurred().log(t);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateObjectInterceptor.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateObjectInterceptor.java
new file mode 100644
index 0000000..bfbdffa
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheOperateObjectInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ehcache.v2;
+
+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;
+
+/**
+ * @author MrPro
+ */
+public class EhcacheOperateObjectInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+        EhcacheEnhanceInfo enhanceInfo = (EhcacheEnhanceInfo) objInst.getSkyWalkingDynamicField();
+
+        AbstractSpan span = ContextManager.createLocalSpan("Ehcache/" + method.getName() + "/" + enhanceInfo.getCacheName());
+        span.setComponent(ComponentsDefine.EHCACHE);
+        SpanLayer.asCache(span);
+
+        Object element = allArguments[0];
+        if (element != null) {
+            Tags.DB_STATEMENT.set(span, element.toString());
+        }
+    }
+
+    @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().errorOccurred().log(t);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/define/EhcachePluginInstrumentation.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/define/EhcachePluginInstrumentation.java
new file mode 100644
index 0000000..fb3baaf
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/ehcache/v2/define/EhcachePluginInstrumentation.java
@@ -0,0 +1,185 @@
+/*
+ * 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.ehcache.v2.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.*;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ *
+ * {@link EhcachePluginInstrumentation} enhance @{@link net.sf.ehcache.Cache}
+ *
+ * @author MrPro
+ */
+public class EhcachePluginInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    public static final String INTERCEPT_CLASS = "net.sf.ehcache.Cache";
+    public static final String CONSTRUCTOR_CLASS_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.ehcache.v2.EhcacheConstructorInterceptor";
+
+    // get and put value
+    public static final String PUT_CACHE_ENHANCE_METHOD = "put";
+    public static final String GET_CACHE_ENHANCE_METHOD = "get";
+    public static final String GET_QUIET_CACHE_ENHANCE_METHOD = "getQuiet";
+    public static final String REMOVE_CACHE_ENHANCE_METHOD = "remove";
+    public static final String REMOVE_AND_RETURN_ELEMENT_CACHE_ENHANCE_METHOD = "removeAndReturnElement";
+    public static final String REPLACE_CACHE_ENHANCE_METHOD = "replace";
+    public static final String REMOVE_QUIET_CACHE_ENHANCE_METHOD = "removeQuiet";
+    public static final String REMOVE_WITH_WRITE_CACHE_INHANCE_METHOD = "removeWithWriter";
+    public static final String REMOVE_ELEMENT_CACHE_ENHANCE_METHOD = "removeElement";
+    public static final String REMOVE_ALL_CACHE_INHANCE_METHOD = "removeAll";
+    public static final String PUT_ALL_CACHE_ENHANCE_METHOD = "putAll";
+    public static final String PUT_WITH_WRITE_CACHE_ENHANCE_METHOD = "putWithWriter";
+    public static final String PUT_QUITE_CACHE_ENHANCE_METHOD = "putQuiet";
+    public static final String GET_WITH_LOADER_CACHE_ENHANCE_METHOD = "getWithLoader";
+    public static final String PUT_IF_ABSENT_CACHE_ENHANCE_METHOD = "putIfAbsent";
+    public static final String GET_ALL_CACHE_ENHANCE_METHOD = "getAll";
+    public static final String LOAD_ALL_CACHE_ENHANCE_METHOD = "loadAll";
+    public static final String GET_ALL_WITH_LOADER_CACHE_ENHANCE_METHOD = "getAllWithLoader";
+    public static final String OPERATE_ELEMENT_CACHE_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.ehcache.v2.EhcacheOperateElementInterceptor";
+    public static final String OPERATE_OBJECT_CACHE_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.ehcache.v2.EhcacheOperateObjectInterceptor";
+    public static final String OPERATE_ALL_CACHE_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.ehcache.v2.EhcacheOperateAllInterceptor";
+
+
+    // lock and release
+    public static final String LOCK_ENHANCE_METHOD_SUFFIX = "LockOnKey";
+    public static final String WRITE_LOCK_TRY_ENHANCE_METHOD = "tryWrite" + LOCK_ENHANCE_METHOD_SUFFIX;
+    public static final String WRITE_LOCK_RELEASE_ENHANCE_METHOD = "releaseWrite" + LOCK_ENHANCE_METHOD_SUFFIX;
+    public static final String READ_LOCK_TRY_ENHANCE_METHOD = "tryRead" + LOCK_ENHANCE_METHOD_SUFFIX;
+    public static final String READ_LOCK_RELEASE_ENHANCE_METHOD = "releaseRead" + LOCK_ENHANCE_METHOD_SUFFIX;
+    public static final String READ_WRITE_LOCK_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.ehcache.v2.EhcacheLockInterceptor";
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[] {
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getConstructorMatcher() {
+                    return takesArgument(0, named("net.sf.ehcache.config.CacheConfiguration"));
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return CONSTRUCTOR_CLASS_INTERCEPT_CLASS;
+                }
+            }
+        };
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[] {
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named(GET_WITH_LOADER_CACHE_ENHANCE_METHOD)
+                        .or(named(GET_CACHE_ENHANCE_METHOD).and(takesArgument(0, Object.class)))
+                        .or(named(GET_QUIET_CACHE_ENHANCE_METHOD).and(takesArgument(0, Object.class)))
+                        .or(named(REMOVE_CACHE_ENHANCE_METHOD).and(takesArguments(2)).and(takesArgument(0, Object.class)))
+                        .or(named(REMOVE_AND_RETURN_ELEMENT_CACHE_ENHANCE_METHOD))
+                        .or(named(REMOVE_QUIET_CACHE_ENHANCE_METHOD))
+                        .or(named(REMOVE_WITH_WRITE_CACHE_INHANCE_METHOD));
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return OPERATE_OBJECT_CACHE_INTERCEPTOR_CLASS;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+
+            },
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named(PUT_WITH_WRITE_CACHE_ENHANCE_METHOD)
+                        .or(named(PUT_QUITE_CACHE_ENHANCE_METHOD))
+                        .or(named(REMOVE_ELEMENT_CACHE_ENHANCE_METHOD))
+                        .or(named(REPLACE_CACHE_ENHANCE_METHOD))
+                        .or(named(PUT_IF_ABSENT_CACHE_ENHANCE_METHOD).and(takesArguments(2)))
+                        .or(named(PUT_CACHE_ENHANCE_METHOD).and(takesArguments(2)));
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return OPERATE_ELEMENT_CACHE_INTERCEPTOR_CLASS;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            },
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named(REMOVE_ALL_CACHE_INHANCE_METHOD).and(takesArguments(1).and(takesArgument(0, Boolean.TYPE)))
+                        .or(named(REMOVE_ALL_CACHE_INHANCE_METHOD).and(takesArguments(2)))
+                        .or(named(PUT_ALL_CACHE_ENHANCE_METHOD).and(takesArguments(2)))
+                        .or(named(GET_ALL_WITH_LOADER_CACHE_ENHANCE_METHOD))
+                        .or(named(GET_ALL_CACHE_ENHANCE_METHOD))
+                        .or(named(LOAD_ALL_CACHE_ENHANCE_METHOD));
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return OPERATE_ALL_CACHE_INTERCEPTOR_CLASS;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            },
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named(READ_LOCK_RELEASE_ENHANCE_METHOD)
+                        .or(named(READ_LOCK_TRY_ENHANCE_METHOD)
+                        .or(named(WRITE_LOCK_RELEASE_ENHANCE_METHOD))
+                        .or(named(WRITE_LOCK_TRY_ENHANCE_METHOD)));
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return READ_WRITE_LOCK_INTERCEPTOR_CLASS;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
+    }
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byName(INTERCEPT_CLASS);
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000..cfbaa19
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-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.
+
+ehcache-2.x=org.apache.skywalking.apm.plugin.ehcache.v2.define.EhcachePluginInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheInterceptorTest.java
new file mode 100644
index 0000000..566261a
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/ehcache-2.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/ehcache/v2/EhcacheInterceptorTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.ehcache.v2;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.Element;
+import net.sf.ehcache.config.CacheConfiguration;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+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.apache.skywalking.apm.plugin.ehcache.v2.define.EhcachePluginInstrumentation.*;
+import static org.hamcrest.CoreMatchers.is;
+
+/**
+ * @author MrPro
+ */
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class EhcacheInterceptorTest {
+
+    private static final String CACHE_NAME = "test";
+
+    @SegmentStoragePoint
+    private SegmentStorage segmentStorage;
+
+    @Rule
+    public AgentServiceRule serviceRule = new AgentServiceRule();
+
+    private EhcacheOperateObjectInterceptor operateObjectInterceptor;
+    private EhcacheOperateElementInterceptor operateElementInterceptor;
+    private EhcacheOperateAllInterceptor operateAllInterceptor;
+    private EhcacheLockInterceptor lockInterceptor;
+    private EhcacheConstructorInterceptor constructorInterceptor;
+    private Object[] operateObjectArguments;
+    private Object[] operateElementArguments;
+    private Object[] tryLockArguments;
+    private Object[] releaseLockArguments;
+
+    private Exception exception;
+
+    private Method putCacheMethod;
+    private Method getCacheMethod;
+    private Method getAllMethod;
+
+    private Method tryReadLockMethod;
+    private Method tryWriteLockMethod;
+    private Method releaseReadLockMethod;
+    private Method releaseWriteLockMethod;
+
+    private EnhancedInstance enhancedInstance = new EnhancedInstance() {
+        @Override
+        public Object getSkyWalkingDynamicField() {
+            return new EhcacheEnhanceInfo(CACHE_NAME);
+        }
+
+        @Override
+        public void setSkyWalkingDynamicField(Object value) {
+        }
+    };
+
+    @Before
+    public void setUp() throws NoSuchMethodException {
+        operateObjectInterceptor = new EhcacheOperateObjectInterceptor();
+        operateElementInterceptor = new EhcacheOperateElementInterceptor();
+        operateAllInterceptor = new EhcacheOperateAllInterceptor();
+        constructorInterceptor = new EhcacheConstructorInterceptor();
+        lockInterceptor = new EhcacheLockInterceptor();
+
+        exception = new Exception();
+
+        operateObjectArguments = new Object[] {"dataKey"};
+        operateElementArguments = new Element[] {new Element("dataKey", 1)};
+        tryLockArguments = new Object[] {"dataKey", 3000};
+        releaseLockArguments = new Object[] {"dataKey"};
+
+        putCacheMethod = Whitebox.getMethods(Cache.class, PUT_CACHE_ENHANCE_METHOD)[0];
+        getCacheMethod = Whitebox.getMethods(Cache.class, GET_CACHE_ENHANCE_METHOD)[0];
+        getAllMethod = Whitebox.getMethods(Cache.class, GET_ALL_CACHE_ENHANCE_METHOD)[0];
+
+        tryReadLockMethod = Whitebox.getMethods(Cache.class, READ_LOCK_TRY_ENHANCE_METHOD)[0];
+        tryWriteLockMethod = Whitebox.getMethods(Cache.class, WRITE_LOCK_TRY_ENHANCE_METHOD)[0];
+        releaseReadLockMethod = Whitebox.getMethods(Cache.class, READ_LOCK_RELEASE_ENHANCE_METHOD)[0];
+        releaseWriteLockMethod = Whitebox.getMethods(Cache.class, WRITE_LOCK_RELEASE_ENHANCE_METHOD)[0];
+    }
+
+    @Test
+    public void assertConstruct() throws Throwable {
+        constructorInterceptor.onConstruct(enhancedInstance, new Object[] {new CacheConfiguration(CACHE_NAME, 20)});
+    }
+
+    @Test
+    public void assertPutSuccess() throws Throwable {
+        // put arguments
+        operateElementInterceptor.beforeMethod(enhancedInstance, putCacheMethod, operateElementArguments, null, null);
+        operateElementInterceptor.handleMethodException(enhancedInstance, putCacheMethod, null, null, exception);
+        operateElementInterceptor.afterMethod(enhancedInstance, putCacheMethod, operateElementArguments, null, null);
+
+        List<TraceSegment> traceSegments = segmentStorage.getTraceSegments();
+        Assert.assertThat(traceSegments.size(), is(1));
+    }
+
+    @Test
+    public void assertGetSuccess() throws Throwable {
+        operateObjectInterceptor.beforeMethod(enhancedInstance, getCacheMethod, operateObjectArguments, null, null);
+        operateObjectInterceptor.handleMethodException(enhancedInstance, getCacheMethod, null, null, exception);
+        operateObjectInterceptor.afterMethod(enhancedInstance, getCacheMethod, operateObjectArguments, null, null);
+
+        List<TraceSegment> traceSegments = segmentStorage.getTraceSegments();
+        Assert.assertThat(traceSegments.size(), is(1));
+    }
+
+    @Test
+    public void assertGetAllSuccess() throws Throwable {
+        operateAllInterceptor.beforeMethod(enhancedInstance, getAllMethod, null, null, null);
+        operateAllInterceptor.handleMethodException(enhancedInstance, getAllMethod, null, null, exception);
+        operateAllInterceptor.afterMethod(enhancedInstance, getAllMethod, null, null, null);
+
+        List<TraceSegment> traceSegments = segmentStorage.getTraceSegments();
+        Assert.assertThat(traceSegments.size(), is(1));
+    }
+
+
+    @Test
+    public void assertLockSuccess() throws Throwable {
+        lockInterceptor.beforeMethod(enhancedInstance, tryReadLockMethod, tryLockArguments, null, null);
+        lockInterceptor.handleMethodException(enhancedInstance, tryReadLockMethod, null, null, exception);
+        lockInterceptor.afterMethod(enhancedInstance, tryReadLockMethod, tryLockArguments, null, null);
+
+        lockInterceptor.beforeMethod(enhancedInstance, tryWriteLockMethod, tryLockArguments, null, null);
+        lockInterceptor.afterMethod(enhancedInstance, tryWriteLockMethod, tryLockArguments, null, null);
+
+        lockInterceptor.beforeMethod(enhancedInstance, releaseReadLockMethod, releaseLockArguments, null, null);
+        lockInterceptor.afterMethod(enhancedInstance, releaseReadLockMethod, releaseLockArguments, null, null);
+
+        lockInterceptor.beforeMethod(enhancedInstance, releaseWriteLockMethod, releaseLockArguments, null, null);
+        lockInterceptor.afterMethod(enhancedInstance, releaseWriteLockMethod, releaseLockArguments, null, null);
+
+        List<TraceSegment> traceSegments = segmentStorage.getTraceSegments();
+        Assert.assertThat(traceSegments.size(), is(4));
+    }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index d38c4bc..e7c75ea 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -76,6 +76,7 @@
         <module>solrj-7.x-plugin</module>
         <module>cassandra-java-driver-3.x-plugin</module>
         <module>light4j-plugins</module>
+        <module>ehcache-2.x-plugin</module>
         <module>pulsar-plugin</module>
     </modules>
     <packaging>pom</packaging>
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 07db4d8..9faff55 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -80,6 +80,8 @@
   * Vert.x Web 3.x
 * Thread Schedule Framework
   * [Spring @Async](https://github.com/spring-projects/spring-framework) 4.x and 5.x
+* Cache
+  * [Ehcache](https://www.ehcache.org/) 2.x
 
 
 ¹Due to license incompatibilities/restrictions these plugins are hosted and released in 3rd part repository, 
diff --git a/oap-server/server-core/src/test/resources/component-libraries.yml b/oap-server/server-core/src/test/resources/component-libraries.yml
index bdcf6c2..5a57c5f 100755
--- a/oap-server/server-core/src/test/resources/component-libraries.yml
+++ b/oap-server/server-core/src/test/resources/component-libraries.yml
@@ -224,6 +224,9 @@ Cassandra:
 Light4J:
   id: 71
   languages: Java
+Ehcache:
+  id: 75
+  languages: Java
 
 # .NET/.NET Core components
 # [3000, 4000) for C#/.NET only
diff --git a/oap-server/server-starter/src/main/resources/component-libraries.yml b/oap-server/server-starter/src/main/resources/component-libraries.yml
index 778ebd1..45d0ea8 100755
--- a/oap-server/server-starter/src/main/resources/component-libraries.yml
+++ b/oap-server/server-starter/src/main/resources/component-libraries.yml
@@ -251,6 +251,9 @@ pulsar-producer:
 pulsar-consumer:
   id: 74
   languages: Java
+Ehcache:
+  id: 75
+  languages: Java
 
 # .NET/.NET Core components
 # [3000, 4000) for C#/.NET only
diff --git a/test/plugin/scenarios/ehcache-2.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/ehcache-2.x-scenario/config/expectedData.yaml
new file mode 100644
index 0000000..0562b9a
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/config/expectedData.yaml
@@ -0,0 +1,136 @@
+# 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.
+registryItems:
+  applications:
+    - {ehcache-2.x-scenario: 2}
+  instances:
+    - {ehcache-2.x-scenario: 1}
+  operationNames:
+    - ehcache-2.x-scenario: [/ehcache-2.x-scenario/case/ehcache, /ehcache-2.x-scenario/healthCheck]
+  heartbeat: []
+segmentItems:
+  - applicationCode: ehcache-2.x-scenario
+    segmentSize: 2
+    segments:
+      - segmentId: not null
+        spans:
+          - operationName: /ehcache-2.x-scenario/healthCheck
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 1
+            componentName: ''
+            isError: false
+            spanType: Entry
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: url, value: 'http://localhost:8080/ehcache-2.x-scenario/healthCheck'}
+              - {key: http.method, value: HEAD}
+      - segmentId: not null
+        spans:
+          - operationName: Ehcache/put/testCache
+            operationId: 0
+            parentSpanId: 0
+            spanId: 1
+            spanLayer: Cache
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 75
+            componentName: ''
+            isError: false
+            spanType: Local
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: db.statement, value: dataKey}
+          - operationName: Ehcache/get/testCache
+            operationId: 0
+            parentSpanId: 0
+            spanId: 2
+            spanLayer: Cache
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 75
+            componentName: ''
+            isError: false
+            spanType: Local
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: db.statement, value: dataKey}
+          - operationName: Ehcache/putAll/testCache
+            operationId: 0
+            parentSpanId: 0
+            panId: 3
+            spanLayer: Cache
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 75
+            componentName: ''
+            isError: false
+            spanType: Local
+            peer: ''
+            peerId: 0
+          - operationName: Ehcache/tryRead/testCache
+            operationId: 0
+            parentSpanId: 0
+            spanId: 4
+            spanLayer: Cache
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 75
+            componentName: ''
+            isError: false
+            spanType: Local
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: db.statement, value: dataKey}
+          - operationName: Ehcache/releaseRead/testCache
+            operationId: 0
+            parentSpanId: 0
+            spanId: 5
+            spanLayer: Cache
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 75
+            componentName: ''
+            isError: false
+            spanType: Local
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: db.statement, value: dataKey}
+          - operationName: /ehcache-2.x-scenario/case/ehcache
+            operationId: 0
+            parentSpanId: -1
+            spanId: 0
+            spanLayer: Http
+            startTime: nq 0
+            endTime: nq 0
+            componentId: 1
+            componentName: ''
+            isError: false
+            spanType: Entry
+            peer: ''
+            peerId: 0
+            tags:
+              - {key: url, value: 'http://localhost:8080/ehcache-2.x-scenario/case/ehcache'}
+              - {key: http.method, value: GET}
\ No newline at end of file
diff --git a/test/plugin/scenarios/ehcache-2.x-scenario/configuration.yml b/test/plugin/scenarios/ehcache-2.x-scenario/configuration.yml
new file mode 100644
index 0000000..708a55d
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/configuration.yml
@@ -0,0 +1,20 @@
+# 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/ehcache-2.x-scenario/case/ehcache
+healthCheck: http://localhost:8080/ehcache-2.x-scenario/healthCheck
+framework: ehcache-2.x
diff --git a/test/plugin/scenarios/ehcache-2.x-scenario/pom.xml b/test/plugin/scenarios/ehcache-2.x-scenario/pom.xml
new file mode 100644
index 0000000..3eadc99
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<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>
+
+    <groupId>org.apache.skywalking</groupId>
+    <artifactId>ehcache-2.x-scenario</artifactId>
+    <version>5.0.0</version>
+    <packaging>war</packaging>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <compiler.version>1.8</compiler.version>
+
+
+        <test.framework>ehcache</test.framework>
+        <test.framework.version>2.10.4</test.framework.version>
+    </properties>
+
+    <name>skywalking-ehcache-2.x-scenario</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>javax.servlet-api</artifactId>
+            <version>3.1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <version>2.8.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <version>2.8.1</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.ehcache</groupId>
+            <artifactId>ehcache</artifactId>
+            <version>${test.framework.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>ehcache-2.x-scenario</finalName>
+        <plugins>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>${compiler.version}</source>
+                    <target>${compiler.version}</target>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/test/plugin/scenarios/ehcache-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/ehcache/v2/CaseServlet.java b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/ehcache/v2/CaseServlet.java
new file mode 100644
index 0000000..3dfc508
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/ehcache/v2/CaseServlet.java
@@ -0,0 +1,73 @@
+/*
+ * 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.ehcache.v2;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
+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.Arrays;
+
+public class CaseServlet extends HttpServlet {
+
+    CacheManager cacheManager = CacheManager.create(CaseServlet.class.getResource("/cache.xml"));
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        Cache cache = cacheManager.getCache("testCache");
+
+        String objectKey = "dataKey";
+
+        Element el = new Element(objectKey, "2");
+
+        // EhcacheOperateElementInterceptor
+        cache.put(el);
+
+        // EhcacheOperateObjectInterceptor
+        cache.get(objectKey);
+
+        // EhcacheOperateAllInterceptor
+        cache.putAll(Arrays.asList(new Element[] {el}));
+
+        // EhcacheLockInterceptor
+        try {
+            boolean success = cache.tryReadLockOnKey(objectKey, 300);
+        } catch (InterruptedException e) {
+        } finally {
+            cache.releaseReadLockOnKey(objectKey);
+        }
+
+        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/ehcache-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/ehcache/v2/HealthCheckServlet.java b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/ehcache/v2/HealthCheckServlet.java
new file mode 100644
index 0000000..51bb510
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/ehcache/v2/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.ehcache.v2;
+
+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/ehcache-2.x-scenario/src/main/resources/cache.xml b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/resources/cache.xml
new file mode 100644
index 0000000..8725b6f
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/resources/cache.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
+       
+   <diskStore path="java.io.tmpdir/ehcache"/>
+
+   <defaultCache
+        maxEntriesLocalHeap="10000"
+        eternal="false"
+        timeToIdleSeconds="120"
+        timeToLiveSeconds="120"
+        maxEntriesLocalDisk="10000000"
+        diskExpiryThreadIntervalSeconds="120"
+        memoryStoreEvictionPolicy="LRU">
+
+       <persistence strategy="localTempSwap"/>
+   </defaultCache>
+    ​
+    <cache name="testCache" maxElementsInMemory="1000" overflowToDisk="false" memoryStoreEvictionPolicy="LRU"/>
+</ehcache>
diff --git a/test/plugin/scenarios/ehcache-2.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/resources/log4j2.xml
new file mode 100644
index 0000000..4c6c06d
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  ~
+  -->
+<Configuration status="info">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d [%traceId] %-5p %c{1}:%L - %m%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="OFF">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/test/plugin/scenarios/ehcache-2.x-scenario/src/main/webapp/WEB-INF/web.xml b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..1dde5b3
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,45 @@
+<!--
+  ~ 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.
+  ~
+  -->
+<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
+		 http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+         version="3.1">
+    <display-name>skywalking-ehcache-2.x-scenario</display-name>
+
+    <servlet>
+        <servlet-name>caseServlet</servlet-name>
+        <servlet-class>org.apache.skywalking.apm.testcase.ehcache.v2.CaseServlet</servlet-class>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>caseServlet</servlet-name>
+        <url-pattern>/case/ehcache</url-pattern>
+    </servlet-mapping>
+
+    <servlet>
+        <servlet-name>healthCheck</servlet-name>
+        <servlet-class>org.apache.skywalking.apm.testcase.ehcache.v2.HealthCheckServlet</servlet-class>
+    </servlet>
+    <servlet-mapping>
+        <servlet-name>healthCheck</servlet-name>
+        <url-pattern>/healthCheck</url-pattern>
+    </servlet-mapping>
+
+
+
+</web-app>
diff --git a/test/plugin/scenarios/ehcache-2.x-scenario/support-version.list b/test/plugin/scenarios/ehcache-2.x-scenario/support-version.list
new file mode 100644
index 0000000..a28040a
--- /dev/null
+++ b/test/plugin/scenarios/ehcache-2.x-scenario/support-version.list
@@ -0,0 +1,35 @@
+# 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.
+
+2.10.6
+2.10.5
+2.10.4
+2.10.3
+2.10.2.2.21
+2.10.2
+2.10.1
+2.10.0
+2.9.1
+2.9.0
+2.8.9
+2.8.8
+2.8.6
+2.8.5
+2.8.4
+2.8.3
+2.8.2
+2.8.1
+2.8.0