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 4067fba  Add some new thread metric and class metric to JVMMetric 
(#7230) (#7243)
4067fba is described below

commit 4067fba2abde828c5dcdcf7797df802354f692d3
Author: Switch <[email protected]>
AuthorDate: Wed Jul 7 16:30:55 2021 +0800

    Add some new thread metric and class metric to JVMMetric (#7230) (#7243)
---
 .github/workflows/e2e.compat.yaml                  |   2 +-
 CHANGES.md                                         |   1 +
 apm-protocol/apm-network/src/main/proto            |   2 +-
 .../skywalking/apm/agent/core/jvm/JVMService.java  |   6 +-
 .../ClassProvider.java}                            |  29 ++--
 .../apm/agent/core/jvm/thread/ThreadProvider.java  |  38 ++++-
 .../core/jvm/clazz/ClassProviderBenchmark.java     |  63 ++++++++
 .../core/jvm/thread/ThreadProviderBenchmark.java   |  64 ++++++++
 docs/en/concepts-and-designs/scope-definitions.md  |  20 ++-
 .../analyzer/provider/jvm/JVMSourceDispatcher.java |  26 +++
 .../apache/skywalking/oal/rt/grammar/OALLexer.g4   |   1 +
 .../apache/skywalking/oal/rt/grammar/OALParser.g4  |   2 +-
 .../src/main/resources/oal/java-agent.oal          |   9 +-
 .../resources/ui-initialized-templates/apm.yml     |  22 +++
 .../oap/server/core/source/DefaultScopeDefine.java |   2 +
 ...JVMThread.java => ServiceInstanceJVMClass.java} |  14 +-
 .../core/source/ServiceInstanceJVMThread.java      |  12 ++
 .../skywalking/e2e/metrics/MetricsQuery.java       |  15 ++
 test/e2e/e2e-protocol/src/main/proto               |   2 +-
 .../apache/skywalking/e2e/compat/CompatE2E.java    | 141 +++++++++++++++++
 .../org/apache/skywalking/e2e/kafka/KafkaE2E.java  | 165 +------------------
 .../apache/skywalking/e2e/simple/SimpleE2E.java    | 170 +-------------------
 .../simple/{SimpleE2E.java => SimpleE2EBase.java}  | 176 +++------------------
 23 files changed, 461 insertions(+), 521 deletions(-)

diff --git a/.github/workflows/e2e.compat.yaml 
b/.github/workflows/e2e.compat.yaml
index ff87efe..e67bdbf 100644
--- a/.github/workflows/e2e.compat.yaml
+++ b/.github/workflows/e2e.compat.yaml
@@ -58,4 +58,4 @@ jobs:
         if: env.SKIP_CI != 'true'
         uses: ./.github/actions/e2e-test
         with:
-          test_class: org.apache.skywalking.e2e.simple.SimpleE2E
+          test_class: org.apache.skywalking.e2e.compat.CompatE2E
diff --git a/CHANGES.md b/CHANGES.md
index f8d8c70..3aeba63 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -74,6 +74,7 @@ Release Notes.
 * Replace zuul proxy with spring cloud gateway 2.x. in webapp module.
 * Upgrade etcd cluster coordinator and dynamic configuration to v3.x.
 * Configuration: Allow to configure server maximum request header size.
+* Add thread state metric and class loaded info metric to JVMMetric.
 
 #### UI
 
diff --git a/apm-protocol/apm-network/src/main/proto 
b/apm-protocol/apm-network/src/main/proto
index 7da226c..e626ee0 160000
--- a/apm-protocol/apm-network/src/main/proto
+++ b/apm-protocol/apm-network/src/main/proto
@@ -1 +1 @@
-Subproject commit 7da226cfced7fa4eb91c6528e8c30827288531a0
+Subproject commit e626ee04850703c220f64b642d2893fa65572943
diff --git 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/JVMService.java
 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/JVMService.java
index 736fccf..4c9b25d 100644
--- 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/JVMService.java
+++ 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/JVMService.java
@@ -25,6 +25,7 @@ import org.apache.skywalking.apm.agent.core.boot.BootService;
 import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor;
 import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory;
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.jvm.clazz.ClassProvider;
 import org.apache.skywalking.apm.agent.core.jvm.cpu.CPUProvider;
 import org.apache.skywalking.apm.agent.core.jvm.gc.GCProvider;
 import org.apache.skywalking.apm.agent.core.jvm.memory.MemoryProvider;
@@ -37,8 +38,8 @@ import 
org.apache.skywalking.apm.network.language.agent.v3.JVMMetric;
 import org.apache.skywalking.apm.util.RunnableWithExceptionProtection;
 
 /**
- * The <code>JVMService</code> represents a timer, which collectors JVM cpu, 
memory, memorypool and gc info, and send
- * the collected info to Collector through the channel provided by {@link 
GRPCChannelManager}
+ * The <code>JVMService</code> represents a timer, which collectors JVM cpu, 
memory, memorypool, gc, thread and class info,
+ * and send the collected info to Collector through the channel provided by 
{@link GRPCChannelManager}
  */
 @DefaultImplementor
 public class JVMService implements BootService, Runnable {
@@ -100,6 +101,7 @@ public class JVMService implements BootService, Runnable {
             
jvmBuilder.addAllMemoryPool(MemoryPoolProvider.INSTANCE.getMemoryPoolMetricsList());
             jvmBuilder.addAllGc(GCProvider.INSTANCE.getGCList());
             jvmBuilder.setThread(ThreadProvider.INSTANCE.getThreadMetrics());
+            jvmBuilder.setClazz(ClassProvider.INSTANCE.getClassMetrics());
 
             sender.offer(jvmBuilder.build());
         } catch (Exception e) {
diff --git 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProvider.java
 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/clazz/ClassProvider.java
similarity index 50%
copy from 
apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProvider.java
copy to 
apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/clazz/ClassProvider.java
index 25243f2..769cadc 100644
--- 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProvider.java
+++ 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/clazz/ClassProvider.java
@@ -16,27 +16,28 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.jvm.thread;
+package org.apache.skywalking.apm.agent.core.jvm.clazz;
 
+import java.lang.management.ClassLoadingMXBean;
 import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadMXBean;
-import org.apache.skywalking.apm.network.language.agent.v3.Thread;
+import org.apache.skywalking.apm.network.language.agent.v3.Class;
 
-public enum ThreadProvider {
+public enum ClassProvider {
     INSTANCE;
-    private final ThreadMXBean threadMXBean;
+    private final ClassLoadingMXBean classLoadingMXBean;
 
-    ThreadProvider() {
-        this.threadMXBean = ManagementFactory.getThreadMXBean();
+    ClassProvider() {
+        this.classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
     }
 
-    public Thread getThreadMetrics() {
-        int threadCount = threadMXBean.getThreadCount();
-        int daemonThreadCount = threadMXBean.getDaemonThreadCount();
-        int peakThreadCount = threadMXBean.getPeakThreadCount();
-        return Thread.newBuilder().setLiveCount(threadCount)
-                .setDaemonCount(daemonThreadCount)
-                .setPeakCount(peakThreadCount).build();
+    public Class getClassMetrics() {
+        int loadedClassCount = classLoadingMXBean.getLoadedClassCount();
+        long totalUnloadedClassCount = 
classLoadingMXBean.getUnloadedClassCount();
+        long totalLoadedClassCount = 
classLoadingMXBean.getTotalLoadedClassCount();
+        return Class.newBuilder().setLoadedClassCount(loadedClassCount)
+                .setTotalUnloadedClassCount(totalUnloadedClassCount)
+                .setTotalLoadedClassCount(totalLoadedClassCount)
+                .build();
     }
 
 }
diff --git 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProvider.java
 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProvider.java
index 25243f2..3e89ce7 100644
--- 
a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProvider.java
+++ 
b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProvider.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.apm.agent.core.jvm.thread;
 
 import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
 import java.lang.management.ThreadMXBean;
 import org.apache.skywalking.apm.network.language.agent.v3.Thread;
 
@@ -31,12 +32,47 @@ public enum ThreadProvider {
     }
 
     public Thread getThreadMetrics() {
+        int runnableStateThreadCount = 0;
+        int blockedStateThreadCount = 0;
+        int waitingStateThreadCount = 0;
+        int timedWaitingStateThreadCount = 0;
+
+        ThreadInfo[] threadInfos = 
threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), 0);
+        if (threadInfos != null) {
+            for (ThreadInfo threadInfo : threadInfos) {
+                if (threadInfo == null) {
+                    continue;
+                }
+                switch (threadInfo.getThreadState()) {
+                    case RUNNABLE:
+                        runnableStateThreadCount++;
+                        break;
+                    case BLOCKED:
+                        blockedStateThreadCount++;
+                        break;
+                    case WAITING:
+                        waitingStateThreadCount++;
+                        break;
+                    case TIMED_WAITING:
+                        timedWaitingStateThreadCount++;
+                        break;
+                    default:
+                        break;
+                    }
+            }
+        }
+
         int threadCount = threadMXBean.getThreadCount();
         int daemonThreadCount = threadMXBean.getDaemonThreadCount();
         int peakThreadCount = threadMXBean.getPeakThreadCount();
         return Thread.newBuilder().setLiveCount(threadCount)
                 .setDaemonCount(daemonThreadCount)
-                .setPeakCount(peakThreadCount).build();
+                .setPeakCount(peakThreadCount)
+                .setRunnableStateThreadCount(runnableStateThreadCount)
+                .setBlockedStateThreadCount(blockedStateThreadCount)
+                .setWaitingStateThreadCount(waitingStateThreadCount)
+                .setTimedWaitingStateThreadCount(timedWaitingStateThreadCount)
+                .build();
     }
 
 }
diff --git 
a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/jvm/clazz/ClassProviderBenchmark.java
 
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/jvm/clazz/ClassProviderBenchmark.java
new file mode 100644
index 0000000..547e9ca
--- /dev/null
+++ 
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/jvm/clazz/ClassProviderBenchmark.java
@@ -0,0 +1,63 @@
+/*
+ * 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.agent.core.jvm.clazz;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+
+public class ClassProviderBenchmark {
+
+    @Benchmark
+    @Fork(value = 5, warmups = 3)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @BenchmarkMode(Mode.Throughput)
+    public void getThreadMetrics(Blackhole bh) {
+        bh.consume(ClassProvider.INSTANCE.getClassMetrics());
+    }
+
+    public static void main(String[] args) throws Exception {
+        Options opt = new 
OptionsBuilder().include(ClassProviderBenchmark.class.getSimpleName())
+                .build();
+        new Runner(opt).run();
+    }
+
+    /**
+     # JMH version: 1.21
+     # VM version: JDK 1.8.0_231, Java HotSpot(TM) 64-Bit Server VM, 25.231-b11
+     # VM invoker: 
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/bin/java
+     # VM options: -javaagent:/Users/switch/Library/Application 
Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/211.7442.40/IntelliJ 
IDEA.app/Contents/lib/idea_rt.jar=52931:/Users/switch/Library/Application 
Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/211.7442.40/IntelliJ 
IDEA.app/Contents/bin -Dfile.encoding=UTF-8
+     # Warmup: 5 iterations, 10 s each
+     # Measurement: 5 iterations, 10 s each
+     # Timeout: 10 min per iteration
+     # Threads: 1 thread, will synchronize iterations
+     # Benchmark mode: Throughput, ops/time
+     *
+     * Benchmark                                 Mode  Cnt        Score      
Error  Units
+     * ClassProviderBenchmark.getThreadMetrics  thrpt   25  6542809.978 ± 
8794.520  ops/s
+     */
+}
\ No newline at end of file
diff --git 
a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProviderBenchmark.java
 
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProviderBenchmark.java
new file mode 100644
index 0000000..e60c8f9
--- /dev/null
+++ 
b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/jvm/thread/ThreadProviderBenchmark.java
@@ -0,0 +1,64 @@
+/*
+ * 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.agent.core.jvm.thread;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.concurrent.TimeUnit;
+
+public class ThreadProviderBenchmark {
+
+    @Benchmark
+    @Fork(value = 5, warmups = 3)
+    @OutputTimeUnit(TimeUnit.SECONDS)
+    @BenchmarkMode(Mode.Throughput)
+    public void getThreadMetrics(Blackhole bh) {
+        bh.consume(ThreadProvider.INSTANCE.getThreadMetrics());
+    }
+
+    public static void main(String[] args) throws Exception {
+        Options opt = new 
OptionsBuilder().include(ThreadProviderBenchmark.class.getSimpleName())
+                .build();
+        new Runner(opt).run();
+    }
+
+    /**
+     * # JMH version: 1.21
+     * # VM version: JDK 1.8.0_231, Java HotSpot(TM) 64-Bit Server VM, 
25.231-b11
+     * # VM invoker: 
/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home/jre/bin/java
+     * # VM options: -javaagent:/Users/switch/Library/Application 
Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/211.7442.40/IntelliJ 
IDEA.app/Contents/lib/idea_rt.jar=52623:/Users/switch/Library/Application 
Support/JetBrains/Toolbox/apps/IDEA-U/ch-0/211.7442.40/IntelliJ 
IDEA.app/Contents/bin -Dfile.encoding=UTF-8
+     * # Warmup: 5 iterations, 10 s each
+     * # Measurement: 5 iterations, 10 s each
+     * # Timeout: 10 min per iteration
+     * # Threads: 1 thread, will synchronize iterations
+     * # Benchmark mode: Throughput, ops/time
+     * # Benchmark: 
org.apache.skywalking.apm.agent.core.jvm.thread.ThreadProviderBenchmark.getThreadMetrics
+     *
+     * Benchmark                                  Mode  Cnt       Score      
Error  Units
+     * ThreadProviderBenchmark.getThreadMetrics  thrpt   25  247393.607 ± 
2493.640  ops/s
+     */
+}
\ No newline at end of file
diff --git a/docs/en/concepts-and-designs/scope-definitions.md 
b/docs/en/concepts-and-designs/scope-definitions.md
index 51b330a..812f777 100644
--- a/docs/en/concepts-and-designs/scope-definitions.md
+++ b/docs/en/concepts-and-designs/scope-definitions.md
@@ -104,9 +104,23 @@ This calculates the metrics data if the service instance 
is a JVM and collects t
 |---|---|---|---|
 | name |  The name of the service instance, such as `ip:port@Service Name`.  
**Note**: Currently, the native agent uses `uuid@ipv4` as the instance name, 
which does not assist in setting up a filter in aggregation. | | string|
 | serviceName | The name of the service. | | string |
-| liveCount | The current number of live threads. | | int |
-| daemonCount | The current number of daemon threads. | | int |
-| peakCount | The current number of peak threads. | | int |
+| liveCount | The current number of live threads. | | long |
+| daemonCount | The current number of daemon threads. | | long |
+| peakCount | The current number of peak threads. | | long |
+| runnableStateThreadCount | The current number of threads in runnable state. 
| | long |
+| blockedStateThreadCount | The current number of threads in blocked state. | 
| long |
+| waitingStateThreadCount | The current number of threads in waiting state. | 
| long |
+| timedWaitingStateThreadCount | The current number of threads in time-waiting 
state. | | long |
+
+6. SCOPE `ServiceInstanceJVMClass`
+
+| Name | Remarks | Group Key | Type | 
+|---|---|---|---|
+| name |  The name of the service instance, such as `ip:port@Service Name`.  
**Note**: Currently, the native agent uses `uuid@ipv4` as the instance name, 
which does not assist in setting up a filter in aggregation. | | string|
+| serviceName | The name of the service. | | string |
+| loadedClassCount | The number of classes that are currently loaded in the 
JVM. | | long |
+| totalUnloadedClassCount | The total number of classes unloaded since the JVM 
has started execution. | | long |
+| totalLoadedClassCount | The total number of classes that have been loaded 
since the JVM has started execution. | | long |
 
 ### SCOPE `Endpoint`
 
diff --git 
a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/jvm/JVMSourceDispatcher.java
 
b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/jvm/JVMSourceDispatcher.java
index ad2d360..bed6241 100644
--- 
a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/jvm/JVMSourceDispatcher.java
+++ 
b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/jvm/JVMSourceDispatcher.java
@@ -21,6 +21,7 @@ package 
org.apache.skywalking.oap.server.analyzer.provider.jvm;
 import java.util.List;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.apm.network.common.v3.CPU;
+import org.apache.skywalking.apm.network.language.agent.v3.Class;
 import org.apache.skywalking.apm.network.language.agent.v3.GC;
 import org.apache.skywalking.apm.network.language.agent.v3.JVMMetric;
 import org.apache.skywalking.apm.network.language.agent.v3.Memory;
@@ -33,6 +34,7 @@ import 
org.apache.skywalking.oap.server.core.analysis.TimeBucket;
 import org.apache.skywalking.oap.server.core.source.GCPhrase;
 import org.apache.skywalking.oap.server.core.source.MemoryPoolType;
 import org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMCPU;
+import org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMClass;
 import org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMGC;
 import org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMMemory;
 import 
org.apache.skywalking.oap.server.core.source.ServiceInstanceJVMMemoryPool;
@@ -64,6 +66,8 @@ public class JVMSourceDispatcher {
             service, serviceId, serviceInstance, serviceInstanceId, 
minuteTimeBucket, metrics.getGcList());
         this.sendToThreadMetricProcess(
             service, serviceId, serviceInstance, serviceInstanceId, 
minuteTimeBucket, metrics.getThread());
+        this.sendToClassMetricProcess(
+                service, serviceId, serviceInstance, serviceInstanceId, 
minuteTimeBucket, metrics.getClazz());
     }
 
     private void sendToCpuMetricProcess(String service,
@@ -193,7 +197,29 @@ public class JVMSourceDispatcher {
         serviceInstanceJVMThread.setLiveCount(thread.getLiveCount());
         serviceInstanceJVMThread.setDaemonCount(thread.getDaemonCount());
         serviceInstanceJVMThread.setPeakCount(thread.getPeakCount());
+        
serviceInstanceJVMThread.setRunnableStateThreadCount(thread.getRunnableStateThreadCount());
+        
serviceInstanceJVMThread.setBlockedStateThreadCount(thread.getBlockedStateThreadCount());
+        
serviceInstanceJVMThread.setWaitingStateThreadCount(thread.getWaitingStateThreadCount());
+        
serviceInstanceJVMThread.setTimedWaitingStateThreadCount(thread.getTimedWaitingStateThreadCount());
         serviceInstanceJVMThread.setTimeBucket(timeBucket);
         sourceReceiver.receive(serviceInstanceJVMThread);
     }
+
+    private void sendToClassMetricProcess(String service,
+                                          String serviceId,
+                                          String serviceInstance,
+                                          String serviceInstanceId,
+                                          long timeBucket,
+                                          Class clazz) {
+        ServiceInstanceJVMClass serviceInstanceJVMClass = new 
ServiceInstanceJVMClass();
+        serviceInstanceJVMClass.setId(serviceInstanceId);
+        serviceInstanceJVMClass.setName(serviceInstance);
+        serviceInstanceJVMClass.setServiceId(serviceId);
+        serviceInstanceJVMClass.setServiceName(service);
+        
serviceInstanceJVMClass.setLoadedClassCount(clazz.getLoadedClassCount());
+        
serviceInstanceJVMClass.setTotalUnloadedClassCount(clazz.getTotalUnloadedClassCount());
+        
serviceInstanceJVMClass.setTotalLoadedClassCount(clazz.getTotalLoadedClassCount());
+        serviceInstanceJVMClass.setTimeBucket(timeBucket);
+        sourceReceiver.receive(serviceInstanceJVMClass);
+    }
 }
diff --git 
a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4
 
b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4
index ea3976f..25654da 100644
--- 
a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4
+++ 
b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALLexer.g4
@@ -39,6 +39,7 @@ SRC_SERVICE_INSTANCE_JVM_MEMORY: 'ServiceInstanceJVMMemory';
 SRC_SERVICE_INSTANCE_JVM_MEMORY_POOL: 'ServiceInstanceJVMMemoryPool';
 SRC_SERVICE_INSTANCE_JVM_GC: 'ServiceInstanceJVMGC';
 SRC_SERVICE_INSTANCE_JVM_THREAD: 'ServiceInstanceJVMThread';
+SRC_SERVICE_INSTANCE_JVM_CLASS:'ServiceInstanceJVMClass';
 SRC_DATABASE_ACCESS: 'DatabaseAccess';
 SRC_SERVICE_INSTANCE_CLR_CPU: 'ServiceInstanceCLRCPU';
 SRC_SERVICE_INSTANCE_CLR_GC: 'ServiceInstanceCLRGC';
diff --git 
a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4
 
b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4
index 337d0ab..050defc 100644
--- 
a/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4
+++ 
b/oap-server/oal-grammar/src/main/antlr4/org/apache/skywalking/oal/rt/grammar/OALParser.g4
@@ -53,7 +53,7 @@ source
     : SRC_ALL | SRC_SERVICE | SRC_DATABASE_ACCESS | SRC_SERVICE_INSTANCE | 
SRC_ENDPOINT |
       SRC_SERVICE_RELATION | SRC_SERVICE_INSTANCE_RELATION | 
SRC_ENDPOINT_RELATION |
       SRC_SERVICE_INSTANCE_CLR_CPU | SRC_SERVICE_INSTANCE_CLR_GC | 
SRC_SERVICE_INSTANCE_CLR_THREAD |
-      SRC_SERVICE_INSTANCE_JVM_CPU | SRC_SERVICE_INSTANCE_JVM_MEMORY | 
SRC_SERVICE_INSTANCE_JVM_MEMORY_POOL | SRC_SERVICE_INSTANCE_JVM_GC | 
SRC_SERVICE_INSTANCE_JVM_THREAD |// JVM source of service instance
+      SRC_SERVICE_INSTANCE_JVM_CPU | SRC_SERVICE_INSTANCE_JVM_MEMORY | 
SRC_SERVICE_INSTANCE_JVM_MEMORY_POOL | SRC_SERVICE_INSTANCE_JVM_GC | 
SRC_SERVICE_INSTANCE_JVM_THREAD | SRC_SERVICE_INSTANCE_JVM_CLASS |// JVM source 
of service instance
       SRC_ENVOY_INSTANCE_METRIC |
       SRC_BROWSER_APP_PERF | SRC_BROWSER_APP_PAGE_PERF | 
SRC_BROWSER_APP_SINGLE_VERSION_PERF |
       SRC_BROWSER_APP_TRAFFIC | SRC_BROWSER_APP_PAGE_TRAFFIC | 
SRC_BROWSER_APP_SINGLE_VERSION_TRAFFIC |
diff --git a/oap-server/server-bootstrap/src/main/resources/oal/java-agent.oal 
b/oap-server/server-bootstrap/src/main/resources/oal/java-agent.oal
index ca34460..b7a3702 100644
--- a/oap-server/server-bootstrap/src/main/resources/oal/java-agent.oal
+++ b/oap-server/server-bootstrap/src/main/resources/oal/java-agent.oal
@@ -28,4 +28,11 @@ instance_jvm_young_gc_count = 
from(ServiceInstanceJVMGC.count).filter(phrase ==
 instance_jvm_old_gc_count = from(ServiceInstanceJVMGC.count).filter(phrase == 
GCPhrase.OLD).sum();
 instance_jvm_thread_live_count = 
from(ServiceInstanceJVMThread.liveCount).longAvg();
 instance_jvm_thread_daemon_count = 
from(ServiceInstanceJVMThread.daemonCount).longAvg();
-instance_jvm_thread_peak_count = 
from(ServiceInstanceJVMThread.peakCount).longAvg();
\ No newline at end of file
+instance_jvm_thread_peak_count = 
from(ServiceInstanceJVMThread.peakCount).longAvg();
+instance_jvm_thread_runnable_state_thread_count = 
from(ServiceInstanceJVMThread.runnableStateThreadCount).longAvg();
+instance_jvm_thread_blocked_state_thread_count = 
from(ServiceInstanceJVMThread.blockedStateThreadCount).longAvg();
+instance_jvm_thread_waiting_state_thread_count = 
from(ServiceInstanceJVMThread.waitingStateThreadCount).longAvg();
+instance_jvm_thread_timed_waiting_state_thread_count = 
from(ServiceInstanceJVMThread.timedWaitingStateThreadCount).longAvg();
+instance_jvm_class_loaded_class_count = 
from(ServiceInstanceJVMClass.loadedClassCount).longAvg();
+instance_jvm_class_total_unloaded_class_count = 
from(ServiceInstanceJVMClass.totalUnloadedClassCount).longAvg();
+instance_jvm_class_total_loaded_class_count = 
from(ServiceInstanceJVMClass.totalLoadedClassCount).longAvg();
\ No newline at end of file
diff --git 
a/oap-server/server-bootstrap/src/main/resources/ui-initialized-templates/apm.yml
 
b/oap-server/server-bootstrap/src/main/resources/ui-initialized-templates/apm.yml
index 901bd88..5854c07 100644
--- 
a/oap-server/server-bootstrap/src/main/resources/ui-initialized-templates/apm.yml
+++ 
b/oap-server/server-bootstrap/src/main/resources/ui-initialized-templates/apm.yml
@@ -402,6 +402,28 @@ templates:
                 },
                 {
                   "width": 3,
+                  "title": "JVM Thread State Count (Java Service)",
+                  "height": "250",
+                  "entityType": "ServiceInstance",
+                  "independentSelector": false,
+                  "metricType": "REGULAR_VALUE",
+                  "metricName": 
"instance_jvm_thread_runnable_state_thread_count, 
instance_jvm_thread_blocked_state_thread_count, 
instance_jvm_thread_waiting_state_thread_count, 
instance_jvm_thread_timed_waiting_state_thread_count",
+                  "queryMetricType": "readMetricsValues",
+                  "chartType": "ChartBar"
+                },
+                {
+                  "width": 3,
+                  "title": "JVM Class Count (Java Service)",
+                  "height": "250",
+                  "entityType": "ServiceInstance",
+                  "independentSelector": false,
+                  "metricType": "REGULAR_VALUE",
+                  "metricName": "instance_jvm_class_loaded_class_count, 
instance_jvm_class_total_unloaded_class_count, 
instance_jvm_class_total_loaded_class_count",
+                  "queryMetricType": "readMetricsValues",
+                  "chartType": "ChartArea"
+                },
+                {
+                  "width": 3,
                   "title": "CLR CPU  (.NET Service)",
                   "height": "250",
                   "entityType": "ServiceInstance",
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java
index f87d82b..43f2fa5 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/DefaultScopeDefine.java
@@ -83,6 +83,8 @@ public class DefaultScopeDefine {
 
     public static final int EVENT = 43;
 
+    public static final int SERVICE_INSTANCE_JVM_CLASS = 44;
+
     /**
      * Catalog of scope, the metrics processor could use this to group all 
generated metrics by oal rt.
      */
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMThread.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMClass.java
similarity index 83%
copy from 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMThread.java
copy to 
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMClass.java
index 42ee6a2..4516198 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMThread.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMClass.java
@@ -22,14 +22,14 @@ import lombok.Getter;
 import lombok.Setter;
 
 import static 
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SERVICE_INSTANCE_CATALOG_NAME;
-import static 
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SERVICE_INSTANCE_JVM_THREAD;
+import static 
org.apache.skywalking.oap.server.core.source.DefaultScopeDefine.SERVICE_INSTANCE_JVM_CLASS;
 
-@ScopeDeclaration(id = SERVICE_INSTANCE_JVM_THREAD, name = 
"ServiceInstanceJVMThread", catalog = SERVICE_INSTANCE_CATALOG_NAME)
+@ScopeDeclaration(id = SERVICE_INSTANCE_JVM_CLASS, name = 
"ServiceInstanceJVMClass", catalog = SERVICE_INSTANCE_CATALOG_NAME)
 @ScopeDefaultColumn.VirtualColumnDefinition(fieldName = "entityId", columnName 
= "entity_id", isID = true, type = String.class)
-public class ServiceInstanceJVMThread extends Source {
+public class ServiceInstanceJVMClass extends Source {
     @Override
     public int scope() {
-        return SERVICE_INSTANCE_JVM_THREAD;
+        return SERVICE_INSTANCE_JVM_CLASS;
     }
 
     @Override
@@ -54,11 +54,11 @@ public class ServiceInstanceJVMThread extends Source {
     private String serviceId;
     @Getter
     @Setter
-    private long liveCount;
+    private long loadedClassCount;
     @Getter
     @Setter
-    private long daemonCount;
+    private long totalUnloadedClassCount;
     @Getter
     @Setter
-    private long peakCount;
+    private long totalLoadedClassCount;
 }
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMThread.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMThread.java
index 42ee6a2..741d2ac 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMThread.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/source/ServiceInstanceJVMThread.java
@@ -61,4 +61,16 @@ public class ServiceInstanceJVMThread extends Source {
     @Getter
     @Setter
     private long peakCount;
+    @Getter
+    @Setter
+    private long runnableStateThreadCount;
+    @Getter
+    @Setter
+    private long blockedStateThreadCount;
+    @Getter
+    @Setter
+    private long waitingStateThreadCount;
+    @Getter
+    @Setter
+    private long timedWaitingStateThreadCount;
 }
diff --git 
a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/metrics/MetricsQuery.java
 
b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/metrics/MetricsQuery.java
index 7117760..110a8ce 100644
--- 
a/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/metrics/MetricsQuery.java
+++ 
b/test/e2e/e2e-data/src/main/java/org/apache/skywalking/e2e/metrics/MetricsQuery.java
@@ -75,7 +75,22 @@ public class MetricsQuery extends 
AbstractQuery<MetricsQuery> {
     public static String INSTANCE_JVM_THREAD_LIVE_COUNT = 
"instance_jvm_thread_live_count";
     public static String INSTANCE_JVM_THREAD_DAEMON_COUNT = 
"instance_jvm_thread_daemon_count";
     public static String INSTANCE_JVM_THREAD_PEAK_COUNT = 
"instance_jvm_thread_peak_count";
+    public static String INSTANCE_JVM_THREAD_RUNNABLE_STATE_THREAD_COUNT = 
"instance_jvm_thread_runnable_state_thread_count";
+    public static String INSTANCE_JVM_CLASS_LOADED_CLASS_COUNT = 
"instance_jvm_class_loaded_class_count";
+    public static String INSTANCE_JVM_CLASS_TOTAL_LOADED_CLASS_COUNT = 
"instance_jvm_class_total_loaded_class_count";
     public static String [] ALL_INSTANCE_JVM_METRICS = {
+        INSTANCE_JVM_CLASS_TOTAL_LOADED_CLASS_COUNT,
+        INSTANCE_JVM_CLASS_LOADED_CLASS_COUNT,
+        INSTANCE_JVM_THREAD_RUNNABLE_STATE_THREAD_COUNT,
+        INSTANCE_JVM_THREAD_LIVE_COUNT,
+        INSTANCE_JVM_THREAD_DAEMON_COUNT,
+        INSTANCE_JVM_THREAD_PEAK_COUNT,
+        INSTANCE_JVM_MEMORY_NOHEAP,
+        INSTANCE_JVM_MEMORY_HEAP_MAX,
+        INSTANCE_JVM_MEMORY_HEAP,
+    };
+
+    public static String [] ALL_INSTANCE_JVM_METRICS_COMPAT = {
         INSTANCE_JVM_THREAD_LIVE_COUNT,
         INSTANCE_JVM_THREAD_DAEMON_COUNT,
         INSTANCE_JVM_THREAD_PEAK_COUNT,
diff --git a/test/e2e/e2e-protocol/src/main/proto 
b/test/e2e/e2e-protocol/src/main/proto
index 9a689b0..e626ee0 160000
--- a/test/e2e/e2e-protocol/src/main/proto
+++ b/test/e2e/e2e-protocol/src/main/proto
@@ -1 +1 @@
-Subproject commit 9a689b0188cbdc7bd8d6ddd99b4ad5283e82fe88
+Subproject commit e626ee04850703c220f64b642d2893fa65572943
diff --git 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/compat/CompatE2E.java
 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/compat/CompatE2E.java
new file mode 100644
index 0000000..7881254
--- /dev/null
+++ 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/compat/CompatE2E.java
@@ -0,0 +1,141 @@
+/*
+ * 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.e2e.compat;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.e2e.annotation.ContainerHostAndPort;
+import org.apache.skywalking.e2e.annotation.DockerCompose;
+import org.apache.skywalking.e2e.base.SkyWalkingE2E;
+import org.apache.skywalking.e2e.common.HostAndPort;
+import org.apache.skywalking.e2e.retryable.RetryableTest;
+import org.apache.skywalking.e2e.service.Service;
+import org.apache.skywalking.e2e.service.ServicesMatcher;
+import org.apache.skywalking.e2e.service.ServicesQuery;
+import org.apache.skywalking.e2e.service.endpoint.Endpoints;
+import org.apache.skywalking.e2e.service.instance.Instances;
+import org.apache.skywalking.e2e.simple.SimpleE2EBase;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopology;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyMatcher;
+import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyQuery;
+import org.apache.skywalking.e2e.topo.TopoMatcher;
+import org.apache.skywalking.e2e.topo.TopoQuery;
+import org.apache.skywalking.e2e.topo.Topology;
+import org.apache.skywalking.e2e.trace.Trace;
+import org.apache.skywalking.e2e.trace.TracesMatcher;
+import org.apache.skywalking.e2e.trace.TracesQuery;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.testcontainers.containers.DockerComposeContainer;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_JVM_METRICS_COMPAT;
+import static org.apache.skywalking.e2e.utils.Times.now;
+import static org.apache.skywalking.e2e.utils.Yamls.load;
+
+@Slf4j
+@SkyWalkingE2E
+public class CompatE2E extends SimpleE2EBase {
+    @SuppressWarnings("unused")
+    @DockerCompose("docker/simple/${SW_SIMPLE_CASE}/docker-compose.yml")
+    protected DockerComposeContainer<?> justForSideEffects;
+
+    @SuppressWarnings("unused")
+    @ContainerHostAndPort(name = "ui", port = 8080)
+    protected HostAndPort swWebappHostPort;
+
+    @SuppressWarnings("unused")
+    @ContainerHostAndPort(name = "provider", port = 9090)
+    protected HostAndPort serviceHostPort;
+
+    @BeforeAll
+    void setUp() throws Exception {
+        queryClient(swWebappHostPort);
+
+        trafficController(serviceHostPort, "/users");
+    }
+
+    @AfterAll
+    public void tearDown() {
+        trafficController.stop();
+    }
+
+    @RetryableTest
+    void services() throws Exception {
+        List<Service> services = graphql.services(new 
ServicesQuery().start(startTime).end(now()));
+
+        services = services.stream().filter(s -> 
!s.getLabel().equals("oap::oap-server")).collect(Collectors.toList());
+        LOGGER.info("services: {}", services);
+
+        
load("expected/simple/services.yml").as(ServicesMatcher.class).verify(services);
+
+        for (final Service service : services) {
+            LOGGER.info("verifying service instances: {}", service);
+
+            verifyServiceMetrics(service);
+
+            final Instances instances = verifyServiceInstances(service);
+
+            verifyInstancesMetrics(instances);
+
+            verifyInstancesJVMMetrics(instances, 
ALL_INSTANCE_JVM_METRICS_COMPAT);
+
+            final Endpoints endpoints = verifyServiceEndpoints(service);
+
+            verifyEndpointsMetrics(endpoints);
+        }
+    }
+
+    @RetryableTest
+    void traces() throws Exception {
+        final List<Trace> traces = graphql.traces(new 
TracesQuery().start(startTime).end(now()).orderByDuration());
+
+        LOGGER.info("traces: {}", traces);
+
+        
load("expected/simple/traces.yml").as(TracesMatcher.class).verifyLoosely(traces);
+    }
+
+    @RetryableTest
+    void topology() throws Exception {
+        final Topology topology = graphql.topo(new 
TopoQuery().stepByMinute().start(startTime.minusDays(1)).end(now()));
+
+        LOGGER.info("topology: {}", topology);
+
+        
load("expected/simple/topo.yml").as(TopoMatcher.class).verify(topology);
+
+        verifyServiceRelationMetrics(topology.getCalls());
+    }
+
+    @RetryableTest
+    void serviceInstances() throws Exception {
+        final ServiceInstanceTopology topology = graphql.serviceInstanceTopo(
+            new ServiceInstanceTopologyQuery().stepByMinute()
+                                              .start(startTime.minusDays(1))
+                                              .end(now())
+                                              .clientServiceId("VXNlcg==.0")
+                                              
.serverServiceId("WW91cl9BcHBsaWNhdGlvbk5hbWU=.1"));
+
+        LOGGER.info("instance topology: {}", topology);
+
+        
load("expected/simple/serviceInstanceTopo.yml").as(ServiceInstanceTopologyMatcher.class).verify(topology);
+
+        verifyServiceInstanceRelationMetrics(topology.getCalls());
+    }
+}
diff --git 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/kafka/KafkaE2E.java 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/kafka/KafkaE2E.java
index 89716aa..25c3e03 100644
--- 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/kafka/KafkaE2E.java
+++ 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/kafka/KafkaE2E.java
@@ -24,11 +24,9 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.e2e.annotation.ContainerHostAndPort;
 import org.apache.skywalking.e2e.annotation.DockerCompose;
 import org.apache.skywalking.e2e.base.SkyWalkingE2E;
-import org.apache.skywalking.e2e.base.SkyWalkingTestAdapter;
 import org.apache.skywalking.e2e.common.HostAndPort;
 import org.apache.skywalking.e2e.metrics.AtLeastOneOfMetricsMatcher;
 import org.apache.skywalking.e2e.metrics.Metrics;
-import org.apache.skywalking.e2e.metrics.MetricsQuery;
 import org.apache.skywalking.e2e.metrics.MetricsValueMatcher;
 import org.apache.skywalking.e2e.metrics.ReadLabeledMetricsQuery;
 import org.apache.skywalking.e2e.metrics.ReadMetrics;
@@ -37,15 +35,12 @@ import org.apache.skywalking.e2e.retryable.RetryableTest;
 import org.apache.skywalking.e2e.service.Service;
 import org.apache.skywalking.e2e.service.ServicesMatcher;
 import org.apache.skywalking.e2e.service.ServicesQuery;
-import org.apache.skywalking.e2e.service.endpoint.Endpoint;
-import org.apache.skywalking.e2e.service.endpoint.EndpointQuery;
 import org.apache.skywalking.e2e.service.endpoint.Endpoints;
-import org.apache.skywalking.e2e.service.endpoint.EndpointsMatcher;
 import org.apache.skywalking.e2e.service.instance.Instance;
 import org.apache.skywalking.e2e.service.instance.Instances;
 import org.apache.skywalking.e2e.service.instance.InstancesMatcher;
 import org.apache.skywalking.e2e.service.instance.InstancesQuery;
-import org.apache.skywalking.e2e.topo.Call;
+import org.apache.skywalking.e2e.simple.SimpleE2EBase;
 import org.apache.skywalking.e2e.topo.ServiceInstanceTopology;
 import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyMatcher;
 import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyQuery;
@@ -59,18 +54,6 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.testcontainers.containers.DockerComposeContainer;
 
-import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyMetrics;
-import static 
org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyPercentileMetrics;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_MULTIPLE_LINEAR_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_JVM_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_MULTIPLE_LINEAR_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_CLIENT_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_SERVER_METRICS;
 import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SO11Y_LABELED_METRICS;
 import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SO11Y_LINER_METRICS;
 import static org.apache.skywalking.e2e.utils.Times.now;
@@ -78,7 +61,7 @@ import static org.apache.skywalking.e2e.utils.Yamls.load;
 
 @Slf4j
 @SkyWalkingE2E
-public class KafkaE2E extends SkyWalkingTestAdapter {
+public class KafkaE2E extends SimpleE2EBase {
 
     @SuppressWarnings("unused")
     @DockerCompose({
@@ -221,148 +204,4 @@ public class KafkaE2E extends SkyWalkingTestAdapter {
             }
         }
     }
-
-    private Instances verifyServiceInstances(final Service service) throws 
Exception {
-        final Instances instances = graphql.instances(
-            new 
InstancesQuery().serviceId(service.getKey()).start(startTime).end(now())
-        );
-
-        LOGGER.info("instances: {}", instances);
-
-        
load("expected/simple/instances.yml").as(InstancesMatcher.class).verify(instances);
-
-        return instances;
-    }
-
-    private Endpoints verifyServiceEndpoints(final Service service) throws 
Exception {
-        final Endpoints endpoints = graphql.endpoints(new 
EndpointQuery().serviceId(service.getKey()));
-
-        LOGGER.info("endpoints: {}", endpoints);
-
-        
load("expected/simple/endpoints.yml").as(EndpointsMatcher.class).verify(endpoints);
-
-        return endpoints;
-    }
-
-    private void verifyInstancesMetrics(final Instances instances) throws 
Exception {
-        for (Instance instance : instances.getInstances()) {
-            for (String metricsName : ALL_INSTANCE_METRICS) {
-                LOGGER.info("verifying service instance response time: {}", 
instance);
-                final Metrics instanceMetrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricsName).id(instance.getKey())
-                );
-
-                LOGGER.info("instance metrics: {}", instanceMetrics);
-
-                final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new 
AtLeastOneOfMetricsMatcher();
-                final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-                greaterThanZero.setValue("gt 0");
-                instanceRespTimeMatcher.setValue(greaterThanZero);
-                instanceRespTimeMatcher.verify(instanceMetrics);
-                LOGGER.info("{}: {}", metricsName, instanceMetrics);
-            }
-        }
-    }
-
-    private void verifyInstancesJVMMetrics(final Instances instances) throws 
Exception {
-        for (Instance instance : instances.getInstances()) {
-            for (String metricsName : ALL_INSTANCE_JVM_METRICS) {
-                LOGGER.info("verifying service instance response time: {}", 
instance);
-                final Metrics instanceJVMMetrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricsName).id(instance.getKey())
-                );
-
-                LOGGER.info("instance jvm metrics: {}", instanceJVMMetrics);
-
-                final AtLeastOneOfMetricsMatcher instanceThreadMatcher = new 
AtLeastOneOfMetricsMatcher();
-                final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-                greaterThanZero.setValue("gt 0");
-                instanceThreadMatcher.setValue(greaterThanZero);
-                instanceThreadMatcher.verify(instanceJVMMetrics);
-                LOGGER.info("{}: {}", metricsName, instanceJVMMetrics);
-            }
-        }
-    }
-
-    private void verifyEndpointsMetrics(final Endpoints endpoints) throws 
Exception {
-        for (Endpoint endpoint : endpoints.getEndpoints()) {
-            if (!endpoint.getLabel().equals("/users")) {
-                continue;
-            }
-            for (final String metricName : ALL_ENDPOINT_METRICS) {
-                LOGGER.info("verifying endpoint {}: {}", endpoint, metricName);
-
-                final Metrics metrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricName).id(endpoint.getKey())
-                );
-
-                LOGGER.info("metrics: {}", metrics);
-
-                final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new 
AtLeastOneOfMetricsMatcher();
-                final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-                greaterThanZero.setValue("gt 0");
-                instanceRespTimeMatcher.setValue(greaterThanZero);
-                instanceRespTimeMatcher.verify(metrics);
-
-                LOGGER.info("{}: {}", metricName, metrics);
-            }
-            for (String metricName : ALL_ENDPOINT_MULTIPLE_LINEAR_METRICS) {
-                verifyPercentileMetrics(graphql, metricName, 
endpoint.getKey(), startTime);
-            }
-        }
-    }
-
-    private void verifyServiceMetrics(final Service service) throws Exception {
-        for (String metricName : ALL_SERVICE_METRICS) {
-            LOGGER.info("verifying service {}, metrics: {}", service, 
metricName);
-            final Metrics serviceMetrics = graphql.metrics(
-                new 
MetricsQuery().stepByMinute().metricsName(metricName).id(service.getKey())
-            );
-            LOGGER.info("serviceMetrics: {}", serviceMetrics);
-            final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new 
AtLeastOneOfMetricsMatcher();
-            final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-            greaterThanZero.setValue("gt 0");
-            instanceRespTimeMatcher.setValue(greaterThanZero);
-            instanceRespTimeMatcher.verify(serviceMetrics);
-            LOGGER.info("{}: {}", metricName, serviceMetrics);
-        }
-
-        for (String metricName : ALL_SERVICE_MULTIPLE_LINEAR_METRICS) {
-            verifyPercentileMetrics(graphql, metricName, service.getKey(), 
startTime);
-        }
-    }
-
-    private void verifyServiceInstanceRelationMetrics(final List<Call> calls) 
throws Exception {
-        verifyRelationMetrics(
-            calls, ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS,
-            ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS
-        );
-    }
-
-    private void verifyServiceRelationMetrics(final List<Call> calls) throws 
Exception {
-        verifyRelationMetrics(calls, ALL_SERVICE_RELATION_CLIENT_METRICS, 
ALL_SERVICE_RELATION_SERVER_METRICS);
-    }
-
-    private void verifyRelationMetrics(final List<Call> calls,
-                                       final String[] relationClientMetrics,
-                                       final String[] relationServerMetrics) 
throws Exception {
-        for (Call call : calls) {
-            for (String detectPoint : call.getDetectPoints()) {
-                switch (detectPoint) {
-                    case "CLIENT": {
-                        for (String metricName : relationClientMetrics) {
-                            verifyMetrics(graphql, metricName, call.getId(), 
startTime);
-                        }
-                        break;
-                    }
-                    case "SERVER": {
-                        for (String metricName : relationServerMetrics) {
-                            verifyMetrics(graphql, metricName, call.getId(), 
startTime);
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-    }
 }
diff --git 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2E.java
 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2E.java
index 0a80655..f39dee3 100644
--- 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2E.java
+++ 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2E.java
@@ -24,25 +24,13 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.skywalking.e2e.annotation.ContainerHostAndPort;
 import org.apache.skywalking.e2e.annotation.DockerCompose;
 import org.apache.skywalking.e2e.base.SkyWalkingE2E;
-import org.apache.skywalking.e2e.base.SkyWalkingTestAdapter;
 import org.apache.skywalking.e2e.common.HostAndPort;
-import org.apache.skywalking.e2e.metrics.AtLeastOneOfMetricsMatcher;
-import org.apache.skywalking.e2e.metrics.Metrics;
-import org.apache.skywalking.e2e.metrics.MetricsQuery;
-import org.apache.skywalking.e2e.metrics.MetricsValueMatcher;
 import org.apache.skywalking.e2e.retryable.RetryableTest;
 import org.apache.skywalking.e2e.service.Service;
 import org.apache.skywalking.e2e.service.ServicesMatcher;
 import org.apache.skywalking.e2e.service.ServicesQuery;
-import org.apache.skywalking.e2e.service.endpoint.Endpoint;
-import org.apache.skywalking.e2e.service.endpoint.EndpointQuery;
 import org.apache.skywalking.e2e.service.endpoint.Endpoints;
-import org.apache.skywalking.e2e.service.endpoint.EndpointsMatcher;
-import org.apache.skywalking.e2e.service.instance.Instance;
 import org.apache.skywalking.e2e.service.instance.Instances;
-import org.apache.skywalking.e2e.service.instance.InstancesMatcher;
-import org.apache.skywalking.e2e.service.instance.InstancesQuery;
-import org.apache.skywalking.e2e.topo.Call;
 import org.apache.skywalking.e2e.topo.ServiceInstanceTopology;
 import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyMatcher;
 import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyQuery;
@@ -56,18 +44,6 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.testcontainers.containers.DockerComposeContainer;
 
-import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyMetrics;
-import static 
org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyPercentileMetrics;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_ENDPOINT_MULTIPLE_LINEAR_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_JVM_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_INSTANCE_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_MULTIPLE_LINEAR_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_CLIENT_METRICS;
-import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATION_SERVER_METRICS;
 import static org.apache.skywalking.e2e.utils.Times.now;
 import static org.apache.skywalking.e2e.utils.Yamls.load;
 
@@ -107,7 +83,7 @@ import static org.apache.skywalking.e2e.utils.Yamls.load;
  */
 @Slf4j
 @SkyWalkingE2E
-public class SimpleE2E extends SkyWalkingTestAdapter {
+public class SimpleE2E extends SimpleE2EBase {
     @SuppressWarnings("unused")
     @DockerCompose("docker/simple/${SW_SIMPLE_CASE}/docker-compose.yml")
     protected DockerComposeContainer<?> justForSideEffects;
@@ -193,148 +169,4 @@ public class SimpleE2E extends SkyWalkingTestAdapter {
 
         verifyServiceInstanceRelationMetrics(topology.getCalls());
     }
-
-    private Instances verifyServiceInstances(final Service service) throws 
Exception {
-        final Instances instances = graphql.instances(
-            new 
InstancesQuery().serviceId(service.getKey()).start(startTime).end(now())
-        );
-
-        LOGGER.info("instances: {}", instances);
-
-        
load("expected/simple/instances.yml").as(InstancesMatcher.class).verify(instances);
-
-        return instances;
-    }
-
-    private Endpoints verifyServiceEndpoints(final Service service) throws 
Exception {
-        final Endpoints endpoints = graphql.endpoints(new 
EndpointQuery().serviceId(service.getKey()));
-
-        LOGGER.info("endpoints: {}", endpoints);
-
-        
load("expected/simple/endpoints.yml").as(EndpointsMatcher.class).verify(endpoints);
-
-        return endpoints;
-    }
-
-    private void verifyInstancesMetrics(final Instances instances) throws 
Exception {
-        for (Instance instance : instances.getInstances()) {
-            for (String metricsName : ALL_INSTANCE_METRICS) {
-                LOGGER.info("verifying service instance response time: {}", 
instance);
-                final Metrics instanceMetrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricsName).id(instance.getKey())
-                );
-
-                LOGGER.info("instance metrics: {}", instanceMetrics);
-
-                final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new 
AtLeastOneOfMetricsMatcher();
-                final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-                greaterThanZero.setValue("gt 0");
-                instanceRespTimeMatcher.setValue(greaterThanZero);
-                instanceRespTimeMatcher.verify(instanceMetrics);
-                LOGGER.info("{}: {}", metricsName, instanceMetrics);
-            }
-        }
-    }
-
-    private void verifyInstancesJVMMetrics(final Instances instances) throws 
Exception {
-        for (Instance instance : instances.getInstances()) {
-            for (String metricsName : ALL_INSTANCE_JVM_METRICS) {
-                LOGGER.info("verifying service instance response time: {}", 
instance);
-                final Metrics instanceJVMMetrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricsName).id(instance.getKey())
-                );
-
-                LOGGER.info("instance jvm metrics: {}", instanceJVMMetrics);
-
-                final AtLeastOneOfMetricsMatcher instanceMatcher = new 
AtLeastOneOfMetricsMatcher();
-                final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-                greaterThanZero.setValue("gt 0");
-                instanceMatcher.setValue(greaterThanZero);
-                instanceMatcher.verify(instanceJVMMetrics);
-                LOGGER.info("{}: {}", metricsName, instanceJVMMetrics);
-            }
-        }
-    }
-
-    private void verifyEndpointsMetrics(final Endpoints endpoints) throws 
Exception {
-        for (Endpoint endpoint : endpoints.getEndpoints()) {
-            if (!endpoint.getLabel().equals("/users")) {
-                continue;
-            }
-            for (final String metricName : ALL_ENDPOINT_METRICS) {
-                LOGGER.info("verifying endpoint {}: {}", endpoint, metricName);
-
-                final Metrics metrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricName).id(endpoint.getKey())
-                );
-
-                LOGGER.info("metrics: {}", metrics);
-
-                final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new 
AtLeastOneOfMetricsMatcher();
-                final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-                greaterThanZero.setValue("gt 0");
-                instanceRespTimeMatcher.setValue(greaterThanZero);
-                instanceRespTimeMatcher.verify(metrics);
-
-                LOGGER.info("{}: {}", metricName, metrics);
-            }
-            for (String metricName : ALL_ENDPOINT_MULTIPLE_LINEAR_METRICS) {
-                verifyPercentileMetrics(graphql, metricName, 
endpoint.getKey(), startTime);
-            }
-        }
-    }
-
-    private void verifyServiceMetrics(final Service service) throws Exception {
-        for (String metricName : ALL_SERVICE_METRICS) {
-            LOGGER.info("verifying service {}, metrics: {}", service, 
metricName);
-            final Metrics serviceMetrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricName).id(service.getKey())
-            );
-            LOGGER.info("serviceMetrics: {}", serviceMetrics);
-            final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new 
AtLeastOneOfMetricsMatcher();
-            final MetricsValueMatcher greaterThanZero = new 
MetricsValueMatcher();
-            greaterThanZero.setValue("gt 0");
-            instanceRespTimeMatcher.setValue(greaterThanZero);
-            instanceRespTimeMatcher.verify(serviceMetrics);
-            LOGGER.info("{}: {}", metricName, serviceMetrics);
-        }
-
-        for (String metricName : ALL_SERVICE_MULTIPLE_LINEAR_METRICS) {
-            verifyPercentileMetrics(graphql, metricName, service.getKey(), 
startTime);
-        }
-    }
-
-    private void verifyServiceInstanceRelationMetrics(final List<Call> calls) 
throws Exception {
-        verifyRelationMetrics(
-            calls, ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS,
-            ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS
-        );
-    }
-
-    private void verifyServiceRelationMetrics(final List<Call> calls) throws 
Exception {
-        verifyRelationMetrics(calls, ALL_SERVICE_RELATION_CLIENT_METRICS, 
ALL_SERVICE_RELATION_SERVER_METRICS);
-    }
-
-    private void verifyRelationMetrics(final List<Call> calls,
-                                       final String[] relationClientMetrics,
-                                       final String[] relationServerMetrics) 
throws Exception {
-        for (Call call : calls) {
-            for (String detectPoint : call.getDetectPoints()) {
-                switch (detectPoint) {
-                    case "CLIENT": {
-                        for (String metricName : relationClientMetrics) {
-                            verifyMetrics(graphql, metricName, call.getId(), 
startTime);
-                        }
-                        break;
-                    }
-                    case "SERVER": {
-                        for (String metricName : relationServerMetrics) {
-                            verifyMetrics(graphql, metricName, call.getId(), 
startTime);
-                        }
-                        break;
-                    }
-                }
-            }
-        }
-    }
 }
diff --git 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2E.java
 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2EBase.java
similarity index 59%
copy from 
test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2E.java
copy to 
test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2EBase.java
index 0a80655..abd2ea3 100644
--- 
a/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2E.java
+++ 
b/test/e2e/e2e-test/src/test/java/org/apache/skywalking/e2e/simple/SimpleE2EBase.java
@@ -6,34 +6,25 @@
  * (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
+ *      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.e2e.simple;
 
 import java.util.List;
-import java.util.stream.Collectors;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.skywalking.e2e.annotation.ContainerHostAndPort;
-import org.apache.skywalking.e2e.annotation.DockerCompose;
-import org.apache.skywalking.e2e.base.SkyWalkingE2E;
 import org.apache.skywalking.e2e.base.SkyWalkingTestAdapter;
-import org.apache.skywalking.e2e.common.HostAndPort;
 import org.apache.skywalking.e2e.metrics.AtLeastOneOfMetricsMatcher;
 import org.apache.skywalking.e2e.metrics.Metrics;
 import org.apache.skywalking.e2e.metrics.MetricsQuery;
 import org.apache.skywalking.e2e.metrics.MetricsValueMatcher;
-import org.apache.skywalking.e2e.retryable.RetryableTest;
 import org.apache.skywalking.e2e.service.Service;
-import org.apache.skywalking.e2e.service.ServicesMatcher;
-import org.apache.skywalking.e2e.service.ServicesQuery;
 import org.apache.skywalking.e2e.service.endpoint.Endpoint;
 import org.apache.skywalking.e2e.service.endpoint.EndpointQuery;
 import org.apache.skywalking.e2e.service.endpoint.Endpoints;
@@ -43,18 +34,6 @@ import org.apache.skywalking.e2e.service.instance.Instances;
 import org.apache.skywalking.e2e.service.instance.InstancesMatcher;
 import org.apache.skywalking.e2e.service.instance.InstancesQuery;
 import org.apache.skywalking.e2e.topo.Call;
-import org.apache.skywalking.e2e.topo.ServiceInstanceTopology;
-import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyMatcher;
-import org.apache.skywalking.e2e.topo.ServiceInstanceTopologyQuery;
-import org.apache.skywalking.e2e.topo.TopoMatcher;
-import org.apache.skywalking.e2e.topo.TopoQuery;
-import org.apache.skywalking.e2e.topo.Topology;
-import org.apache.skywalking.e2e.trace.Trace;
-import org.apache.skywalking.e2e.trace.TracesMatcher;
-import org.apache.skywalking.e2e.trace.TracesQuery;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.testcontainers.containers.DockerComposeContainer;
 
 import static org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyMetrics;
 import static 
org.apache.skywalking.e2e.metrics.MetricsMatcher.verifyPercentileMetrics;
@@ -71,130 +50,9 @@ import static 
org.apache.skywalking.e2e.metrics.MetricsQuery.ALL_SERVICE_RELATIO
 import static org.apache.skywalking.e2e.utils.Times.now;
 import static org.apache.skywalking.e2e.utils.Yamls.load;
 
-/**
- * A test case for simple functionality verification
- *
- * The components are typically:
- *
- * - an single agent, (provider), generating traffic data
- *
- * - an OAP node, (oap)
- *
- * - a webapp, (ui) for querying
- *
- * The verifications are:
- *
- * - services
- *
- * - services metrics
- *
- * - services relations
- *
- * - endpoints
- *
- * - endpoints metrics
- *
- * - instances
- *
- * - instance metrics
- *
- * - topology
- *
- * - traces
- *
- * if your case needs the same aforementioned verifications, consider simply 
provide a docker-compose.yml with the
- * specific orchestration and reuse these codes.
- */
 @Slf4j
-@SkyWalkingE2E
-public class SimpleE2E extends SkyWalkingTestAdapter {
-    @SuppressWarnings("unused")
-    @DockerCompose("docker/simple/${SW_SIMPLE_CASE}/docker-compose.yml")
-    protected DockerComposeContainer<?> justForSideEffects;
-
-    @SuppressWarnings("unused")
-    @ContainerHostAndPort(name = "ui", port = 8080)
-    protected HostAndPort swWebappHostPort;
-
-    @SuppressWarnings("unused")
-    @ContainerHostAndPort(name = "provider", port = 9090)
-    protected HostAndPort serviceHostPort;
-
-    @BeforeAll
-    void setUp() throws Exception {
-        queryClient(swWebappHostPort);
-
-        trafficController(serviceHostPort, "/users");
-    }
-
-    @AfterAll
-    public void tearDown() {
-        trafficController.stop();
-    }
-
-    @RetryableTest
-    void services() throws Exception {
-        List<Service> services = graphql.services(new 
ServicesQuery().start(startTime).end(now()));
-
-        services = services.stream().filter(s -> 
!s.getLabel().equals("oap::oap-server")).collect(Collectors.toList());
-        LOGGER.info("services: {}", services);
-
-        
load("expected/simple/services.yml").as(ServicesMatcher.class).verify(services);
-
-        for (final Service service : services) {
-            LOGGER.info("verifying service instances: {}", service);
-
-            verifyServiceMetrics(service);
-
-            final Instances instances = verifyServiceInstances(service);
-
-            verifyInstancesMetrics(instances);
-
-            verifyInstancesJVMMetrics(instances);
-
-            final Endpoints endpoints = verifyServiceEndpoints(service);
-
-            verifyEndpointsMetrics(endpoints);
-        }
-    }
-
-    @RetryableTest
-    void traces() throws Exception {
-        final List<Trace> traces = graphql.traces(new 
TracesQuery().start(startTime).end(now()).orderByDuration());
-
-        LOGGER.info("traces: {}", traces);
-
-        
load("expected/simple/traces.yml").as(TracesMatcher.class).verifyLoosely(traces);
-    }
-
-    @RetryableTest
-    void topology() throws Exception {
-        final Topology topology = graphql.topo(new 
TopoQuery().stepByMinute().start(startTime.minusDays(1)).end(now()));
-
-        LOGGER.info("topology: {}", topology);
-
-        
load("expected/simple/topo.yml").as(TopoMatcher.class).verify(topology);
-
-        verifyServiceRelationMetrics(topology.getCalls());
-    }
-
-    @RetryableTest
-    void serviceInstances() throws Exception {
-        final ServiceInstanceTopology topology = graphql.serviceInstanceTopo(
-            new ServiceInstanceTopologyQuery().stepByMinute()
-                                              .start(startTime.minusDays(1))
-                                              .end(now())
-                                              .clientServiceId("VXNlcg==.0")
-                                              
.serverServiceId("WW91cl9BcHBsaWNhdGlvbk5hbWU=.1"));
-
-        LOGGER.info("instance topology: {}", topology);
-
-        
load("expected/simple/serviceInstanceTopo.yml").as(ServiceInstanceTopologyMatcher.class).verify(topology);
-
-        verifyServiceInstanceRelationMetrics(topology.getCalls());
-    }
-
-    private Instances verifyServiceInstances(final Service service) throws 
Exception {
+public class SimpleE2EBase extends SkyWalkingTestAdapter {
+    protected Instances verifyServiceInstances(final Service service) throws 
Exception {
         final Instances instances = graphql.instances(
             new 
InstancesQuery().serviceId(service.getKey()).start(startTime).end(now())
         );
@@ -206,7 +64,7 @@ public class SimpleE2E extends SkyWalkingTestAdapter {
         return instances;
     }
 
-    private Endpoints verifyServiceEndpoints(final Service service) throws 
Exception {
+    protected Endpoints verifyServiceEndpoints(final Service service) throws 
Exception {
         final Endpoints endpoints = graphql.endpoints(new 
EndpointQuery().serviceId(service.getKey()));
 
         LOGGER.info("endpoints: {}", endpoints);
@@ -216,7 +74,7 @@ public class SimpleE2E extends SkyWalkingTestAdapter {
         return endpoints;
     }
 
-    private void verifyInstancesMetrics(final Instances instances) throws 
Exception {
+    protected void verifyInstancesMetrics(final Instances instances) throws 
Exception {
         for (Instance instance : instances.getInstances()) {
             for (String metricsName : ALL_INSTANCE_METRICS) {
                 LOGGER.info("verifying service instance response time: {}", 
instance);
@@ -236,9 +94,13 @@ public class SimpleE2E extends SkyWalkingTestAdapter {
         }
     }
 
-    private void verifyInstancesJVMMetrics(final Instances instances) throws 
Exception {
+    protected void verifyInstancesJVMMetrics(final Instances instances) throws 
Exception {
+        verifyInstancesJVMMetrics(instances, ALL_INSTANCE_JVM_METRICS);
+    }
+
+    protected void verifyInstancesJVMMetrics(final Instances instances, final 
String[] metrics) throws Exception {
         for (Instance instance : instances.getInstances()) {
-            for (String metricsName : ALL_INSTANCE_JVM_METRICS) {
+            for (String metricsName : metrics) {
                 LOGGER.info("verifying service instance response time: {}", 
instance);
                 final Metrics instanceJVMMetrics = graphql.metrics(
                     new 
MetricsQuery().stepByMinute().metricsName(metricsName).id(instance.getKey())
@@ -256,7 +118,7 @@ public class SimpleE2E extends SkyWalkingTestAdapter {
         }
     }
 
-    private void verifyEndpointsMetrics(final Endpoints endpoints) throws 
Exception {
+    protected void verifyEndpointsMetrics(final Endpoints endpoints) throws 
Exception {
         for (Endpoint endpoint : endpoints.getEndpoints()) {
             if (!endpoint.getLabel().equals("/users")) {
                 continue;
@@ -284,11 +146,11 @@ public class SimpleE2E extends SkyWalkingTestAdapter {
         }
     }
 
-    private void verifyServiceMetrics(final Service service) throws Exception {
+    protected void verifyServiceMetrics(final Service service) throws 
Exception {
         for (String metricName : ALL_SERVICE_METRICS) {
             LOGGER.info("verifying service {}, metrics: {}", service, 
metricName);
             final Metrics serviceMetrics = graphql.metrics(
-                    new 
MetricsQuery().stepByMinute().metricsName(metricName).id(service.getKey())
+                new 
MetricsQuery().stepByMinute().metricsName(metricName).id(service.getKey())
             );
             LOGGER.info("serviceMetrics: {}", serviceMetrics);
             final AtLeastOneOfMetricsMatcher instanceRespTimeMatcher = new 
AtLeastOneOfMetricsMatcher();
@@ -304,20 +166,20 @@ public class SimpleE2E extends SkyWalkingTestAdapter {
         }
     }
 
-    private void verifyServiceInstanceRelationMetrics(final List<Call> calls) 
throws Exception {
+    protected void verifyServiceInstanceRelationMetrics(final List<Call> 
calls) throws Exception {
         verifyRelationMetrics(
             calls, ALL_SERVICE_INSTANCE_RELATION_CLIENT_METRICS,
             ALL_SERVICE_INSTANCE_RELATION_SERVER_METRICS
         );
     }
 
-    private void verifyServiceRelationMetrics(final List<Call> calls) throws 
Exception {
+    protected void verifyServiceRelationMetrics(final List<Call> calls) throws 
Exception {
         verifyRelationMetrics(calls, ALL_SERVICE_RELATION_CLIENT_METRICS, 
ALL_SERVICE_RELATION_SERVER_METRICS);
     }
 
-    private void verifyRelationMetrics(final List<Call> calls,
-                                       final String[] relationClientMetrics,
-                                       final String[] relationServerMetrics) 
throws Exception {
+    protected void verifyRelationMetrics(final List<Call> calls,
+                                         final String[] relationClientMetrics,
+                                         final String[] relationServerMetrics) 
throws Exception {
         for (Call call : calls) {
             for (String detectPoint : call.getDetectPoints()) {
                 switch (detectPoint) {

Reply via email to