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 2022/07/28 02:00:43 UTC

[skywalking] branch master updated: Add `SUM_PER_MIN`(sumHistogramPercentile) downsampling in MAL. Add eBPF Network Profiling E2E (#9377)

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 b8cf95d165 Add `SUM_PER_MIN`(sumHistogramPercentile) downsampling in MAL. Add eBPF Network Profiling E2E  (#9377)
b8cf95d165 is described below

commit b8cf95d1654a2a902078bd0d89ad5f4f0ba731f6
Author: mrproliu <74...@qq.com>
AuthorDate: Thu Jul 28 10:00:36 2022 +0800

    Add `SUM_PER_MIN`(sumHistogramPercentile) downsampling in MAL. Add eBPF Network Profiling E2E  (#9377)
---
 .github/workflows/skywalking.yaml                  |   9 +
 docs/en/changes/changes.md                         |   2 +
 .../oap/meter/analyzer/dsl/DownsamplingType.java   |   2 +-
 .../oap/meter/analyzer/dsl/Expression.java         |   1 +
 .../oap/meter/analyzer/k8s/K8sInfoRegistry.java    |  24 +-
 .../analysis/meter/function/BucketedValues.java    |   7 +-
 .../sum/SumHistogramPercentileFunction.java        | 343 +++++++++++++++++++++
 .../function/sumpermin/SumPerMinFunction.java      | 196 ++++++++++++
 .../ebpf/EBPFProfilingMutationService.java         |   2 +-
 .../profiling/ebpf/EBPFProfilingQueryService.java  |   2 +-
 .../server/core/query/MetadataQueryService.java    |   5 +-
 .../oap/server/core/query/type/HeatMap.java        |   7 +-
 .../oap/server/core/query/type/Process.java        |   2 +
 .../core/storage/query/IMetadataQueryDAO.java      |  44 ++-
 .../sum/SumHistogramPercentileFunctionTest.java    | 254 +++++++++++++++
 .../function/sumpermin/SumPerMinFunctionTest.java  | 132 ++++++++
 .../handler/EBPFProfilingServiceHandler.java       |   8 +-
 .../meter-analyzer-config/network-profiling.yaml   |  56 ++--
 .../banyandb/measure/BanyanDBMetadataQueryDAO.java | 152 +++++----
 .../elasticsearch/query/MetadataQueryEsDAO.java    |  55 +++-
 .../plugin/jdbc/h2/dao/H2MetadataQueryDAO.java     | 138 ++++++---
 .../cases/kafka/log/expected/logs-filebeat.yml     |   1 +
 .../cases/kafka/log/expected/logs-fluentd.yml      |   1 +
 test/e2e-v2/cases/log/expected/logs.yml            |   1 +
 test/e2e-v2/cases/profiling/ebpf/network/e2e.yaml  | 184 +++++++++++
 .../ebpf/network/expected/dependency-processs.yml  |  61 ++++
 .../expected/metrics-has-value-label.yml}          |  21 +-
 .../expected/metrics-has-value.yml}                |  15 +-
 .../profiling/ebpf/network/expected/process.yml    |  86 ++++++
 .../expected/profiling-create.yml}                 |  18 +-
 .../expected/service-instance.yml}                 |  20 +-
 .../profiling/ebpf/network/expected/service.yml    |  71 +++++
 .../profiling-task-list.yml => network/kind.yaml}  |  38 ++-
 .../istio => profiling/ebpf/network}/rover.yaml    |  13 +-
 .../traffic-gen.yaml}                              |  40 ++-
 .../ebpf/offcpu/expected/profiling-task-list.yml   |   2 +
 .../ebpf/oncpu/expected/profiling-task-list.yml    |   2 +
 test/e2e-v2/cases/rover/process/istio/rover.yaml   |   1 +
 .../native-protocols/expected/logs-list.yml        |   1 +
 test/e2e-v2/script/env                             |   4 +-
 40 files changed, 1759 insertions(+), 262 deletions(-)

diff --git a/.github/workflows/skywalking.yaml b/.github/workflows/skywalking.yaml
index 82aaeabfc3..9adb41c716 100644
--- a/.github/workflows/skywalking.yaml
+++ b/.github/workflows/skywalking.yaml
@@ -441,6 +441,9 @@ jobs:
             env: OPENSEARCH_VERSION=1.2.0
           - name: eBPF Profiling Off CPU
             config: test/e2e-v2/cases/profiling/ebpf/offcpu/e2e.yaml
+          - name: eBPF Profiling Network
+            config: test/e2e-v2/cases/profiling/ebpf/network/e2e.yaml
+            env: ISTIO_VERSION=1.13.1
 
           - name: Kafka Basic
             config: test/e2e-v2/cases/kafka/simple-so11y/e2e.yaml
@@ -530,6 +533,12 @@ jobs:
         uses: apache/skywalking-infra-e2e@main
         with:
           e2e-file: $GITHUB_WORKSPACE/${{ matrix.test.config }}
+      - uses: actions/upload-artifact@v2
+        if: ${{ failure() }}
+        name: Upload Logs
+        with:
+          name: logs
+          path: "${{ env.SW_INFRA_E2E_LOG_DIR }}"
 
   e2e-test-istio:
     if: |
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index 0c4343f4fb..8a739bd5f1 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -26,6 +26,8 @@
 * Support `sumHistogram` in `MAL`.
 * [Breaking Change] Make the eBPF Profiling task support to the service instance level, index/table `ebpf_profiling_task` is required to be re-created when bump up from previous releases.
 * Fix race condition in Banyandb storage
+* Support `SUM_PER_MIN` downsampling in `MAL`.
+* Support `sumHistogramPercentile` in `MAL`.
 
 #### UI
 
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DownsamplingType.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DownsamplingType.java
index 587122f928..7372c548e7 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DownsamplingType.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/DownsamplingType.java
@@ -22,5 +22,5 @@ package org.apache.skywalking.oap.meter.analyzer.dsl;
  * DownsamplingType indicates the downsampling type of meter function
  */
 public enum DownsamplingType {
-    AVG, SUM, LATEST
+    AVG, SUM, LATEST, SUM_PER_MIN
 }
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/Expression.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/Expression.java
index d5e474af16..c10909fc63 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/Expression.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/dsl/Expression.java
@@ -113,6 +113,7 @@ public class Expression {
         public static final DownsamplingType AVG = DownsamplingType.AVG;
         public static final DownsamplingType SUM = DownsamplingType.SUM;
         public static final DownsamplingType LATEST = DownsamplingType.LATEST;
+        public static final DownsamplingType SUM_PER_MIN = DownsamplingType.SUM_PER_MIN;
 
         private final String literal;
 
diff --git a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/k8s/K8sInfoRegistry.java b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/k8s/K8sInfoRegistry.java
index d44bb84a39..e5efcfb0e6 100644
--- a/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/k8s/K8sInfoRegistry.java
+++ b/oap-server/analyzer/meter-analyzer/src/main/java/org/apache/skywalking/oap/meter/analyzer/k8s/K8sInfoRegistry.java
@@ -29,12 +29,12 @@ import io.kubernetes.client.openapi.models.V1LoadBalancerStatus;
 import io.kubernetes.client.openapi.models.V1PodList;
 import io.kubernetes.client.openapi.models.V1Service;
 import io.kubernetes.client.openapi.models.V1ServiceList;
+import io.kubernetes.client.openapi.models.V1ServiceSpec;
 import io.kubernetes.client.openapi.models.V1ServiceStatus;
 import io.kubernetes.client.util.Config;
 import io.kubernetes.client.openapi.ApiClient;
 import io.kubernetes.client.openapi.models.V1Pod;
 import java.util.Collection;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
@@ -180,6 +180,8 @@ public class K8sInfoRegistry {
             .map(V1LoadBalancerStatus::getIngress).filter(CollectionUtils::isNotEmpty)
             .ifPresent(l -> l.stream().filter(i -> StringUtil.isNotEmpty(i.getIp()))
                     .forEach(i -> ipServiceMap.remove(i.getIp())));
+        ofNullable(service.getSpec()).map(V1ServiceSpec::getClusterIPs).filter(CollectionUtils::isNotEmpty)
+            .ifPresent(l -> l.stream().filter(StringUtil::isNotEmpty).forEach(ipServiceMap::remove));
         recompose();
     }
 
@@ -234,17 +236,17 @@ public class K8sInfoRegistry {
             });
         });
         nameServiceMap.forEach((serviceName, service) -> {
-            if (isNull(service.getMetadata()) || isNull(service.getStatus()) || isNull(service.getStatus().getLoadBalancer())) {
-                return;
-            }
-            final List<V1LoadBalancerIngress> ingress = service.getStatus().getLoadBalancer().getIngress();
-            if (CollectionUtils.isEmpty(ingress)) {
-                return;
+            if (!isNull(service.getSpec()) && CollectionUtils.isNotEmpty(service.getSpec().getClusterIPs())) {
+                for (String clusterIP : service.getSpec().getClusterIPs()) {
+                    ipServiceMap.put(clusterIP, serviceName);
+                }
             }
-
-            for (V1LoadBalancerIngress loadBalancerIngress : ingress) {
-                if (StringUtil.isNotEmpty(loadBalancerIngress.getIp())) {
-                    ipServiceMap.put(loadBalancerIngress.getIp(), serviceName);
+            if (!isNull(service.getStatus()) && !isNull(service.getStatus().getLoadBalancer())
+                && CollectionUtils.isNotEmpty(service.getStatus().getLoadBalancer().getIngress())) {
+                for (V1LoadBalancerIngress loadBalancerIngress : service.getStatus().getLoadBalancer().getIngress()) {
+                    if (StringUtil.isNotEmpty(loadBalancerIngress.getIp())) {
+                        ipServiceMap.put(loadBalancerIngress.getIp(), serviceName);
+                    }
                 }
             }
         });
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java
index ab221f28da..432f7b8614 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java
@@ -23,6 +23,7 @@ import java.util.List;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 import org.apache.skywalking.oap.server.core.query.type.Bucket;
 import org.apache.skywalking.oap.server.core.query.type.HeatMap;
@@ -71,10 +72,14 @@ public class BucketedValues {
         final List<String> sortedKeys = dataset.sortedKeys(new HeatMap.KeyComparator(true));
         long[] existedBuckets = new long[sortedKeys.size()];
         for (int i = 0; i < sortedKeys.size(); i++) {
-            final String key = sortedKeys.get(i);
+            String key = sortedKeys.get(i);
             if (key.equals(Bucket.INFINITE_NEGATIVE)) {
                 existedBuckets[i] = Long.MIN_VALUE;
             } else {
+                // remove the group name
+                if (key.contains(":")) {
+                    key = StringUtils.substringAfterLast(key, ":");
+                }
                 existedBuckets[i] = Long.parseLong(key);
             }
         }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumHistogramPercentileFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumHistogramPercentileFunction.java
new file mode 100644
index 0000000000..497c85a40b
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumHistogramPercentileFunction.java
@@ -0,0 +1,343 @@
+/*
+ * 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.oap.server.core.analysis.meter.function.sum;
+
+import com.google.common.base.Strings;
+import io.vavr.Tuple;
+import io.vavr.Tuple2;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.UnexpectedException;
+import org.apache.skywalking.oap.server.core.analysis.meter.Meter;
+import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.MeterFunction;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.PercentileArgument;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
+import org.apache.skywalking.oap.server.core.analysis.metrics.IntList;
+import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
+import org.apache.skywalking.oap.server.core.analysis.metrics.MultiIntValuesHolder;
+import org.apache.skywalking.oap.server.core.query.type.Bucket;
+import org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData;
+import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
+import org.apache.skywalking.oap.server.core.storage.annotation.Column;
+import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
+import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
+import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collector;
+import java.util.stream.IntStream;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
+
+/**
+ * SumPercentile intends to calculate percentile based on the summary of raw values over the interval(minute, hour or day).
+ */
+@MeterFunction(functionName = "sumHistogramPercentile")
+@Slf4j
+public abstract class SumHistogramPercentileFunction extends Meter implements AcceptableValue<PercentileArgument>, MultiIntValuesHolder {
+    private static final String DEFAULT_GROUP = "pD";
+    public static final String DATASET = "dataset";
+    public static final String RANKS = "ranks";
+    public static final String VALUE = "value";
+    protected static final String SUMMATION = "summation";
+
+    @Setter
+    @Getter
+    @Column(columnName = ENTITY_ID)
+    @BanyanDB.ShardingKey(index = 0)
+    private String entityId;
+    @Getter
+    @Setter
+    @Column(columnName = VALUE, dataType = Column.ValueDataType.LABELED_VALUE, storageOnly = true)
+    private DataTable percentileValues = new DataTable(10);
+    @Getter
+    @Setter
+    @Column(columnName = SUMMATION, storageOnly = true)
+    protected DataTable summation = new DataTable(30);
+    /**
+     * Rank
+     */
+    @Getter
+    @Setter
+    @Column(columnName = RANKS, storageOnly = true)
+    private IntList ranks = new IntList(10);
+
+    private boolean isCalculated = false;
+
+    @Override
+    public void accept(final MeterEntity entity, final PercentileArgument value) {
+        if (summation.size() > 0) {
+            if (!value.getBucketedValues().isCompatible(summation)) {
+                throw new IllegalArgumentException(
+                    "Incompatible BucketedValues [" + value + "] for current PercentileFunction[" + summation + "]");
+            }
+        }
+
+        for (final int rank : value.getRanks()) {
+            if (rank <= 0) {
+                throw new IllegalArgumentException("Illegal rank value " + rank + ", must be positive");
+            }
+        }
+
+        if (ranks.size() > 0) {
+            if (ranks.size() != value.getRanks().length) {
+                throw new IllegalArgumentException(
+                    "Incompatible ranks size = [" + value.getRanks().length + "] for current PercentileFunction[" + ranks
+                        .size() + "]");
+            } else {
+                for (final int rank : value.getRanks()) {
+                    if (!ranks.include(rank)) {
+                        throw new IllegalArgumentException(
+                            "Rank " + rank + " doesn't exist in the previous ranks " + ranks);
+                    }
+                }
+            }
+        } else {
+            for (final int rank : value.getRanks()) {
+                ranks.add(rank);
+            }
+        }
+
+        this.entityId = entity.id();
+
+        String template = "%s";
+        if (!Strings.isNullOrEmpty(value.getBucketedValues().getGroup())) {
+            template  = value.getBucketedValues().getGroup() + ":%s";
+        }
+        final long[] values = value.getBucketedValues().getValues();
+        for (int i = 0; i < values.length; i++) {
+            long bucket = value.getBucketedValues().getBuckets()[i];
+            String bucketName = bucket == Long.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
+            String key = String.format(template, bucketName);
+            summation.valueAccumulation(key, values[i]);
+        }
+
+        this.isCalculated = false;
+    }
+
+    @Override
+    public boolean combine(final Metrics metrics) {
+        SumHistogramPercentileFunction percentile = (SumHistogramPercentileFunction) metrics;
+
+        if (this.ranks.size() > 0) {
+            IntList ranksOfThat = percentile.getRanks();
+            if (this.ranks.size() != ranksOfThat.size()) {
+                log.warn("Incompatible ranks size = [{}}] for current PercentileFunction[{}]",
+                         ranksOfThat.size(), this.ranks.size()
+                );
+                return true;
+            } else {
+                if (!this.ranks.equals(ranksOfThat)) {
+                    log.warn("Rank {} doesn't exist in the previous ranks {}", ranksOfThat, this.ranks);
+                    return true;
+                }
+            }
+        }
+
+        this.summation.append(percentile.summation);
+
+        this.isCalculated = false;
+        return true;
+    }
+
+    @Override
+    public void calculate() {
+        if (!isCalculated) {
+            summation.keys().stream()
+                   .map(key -> {
+                       if (key.contains(":")) {
+                           int index = key.lastIndexOf(":");
+                           return Tuple.of(key.substring(0, index), key);
+                       } else {
+                           return Tuple.of(DEFAULT_GROUP, key);
+                       }
+                   })
+                   .collect(groupingBy(Tuple2::_1, mapping(Tuple2::_2, Collector.of(
+                       DataTable::new,
+                       (dt, key) -> {
+                           String v;
+                           if (key.contains(":")) {
+                               int index = key.lastIndexOf(":");
+                               v = key.substring(index + 1);
+                           } else {
+                               v = key;
+                           }
+                           dt.put(v, summation.get(key));
+                       },
+                       DataTable::append
+                   ))))
+                   .forEach((group, subDataset) -> {
+                       long total;
+                       total = subDataset.sumOfValues();
+
+                    int[] roofs = new int[ranks.size()];
+                    for (int i = 0; i < ranks.size(); i++) {
+                        roofs[i] = Math.round(total * ranks.get(i) * 1.0f / 100);
+                    }
+
+                    int count = 0;
+                    final List<String> sortedKeys = subDataset.sortedKeys(Comparator.comparingLong(Long::parseLong));
+
+                    int loopIndex = 0;
+
+                    for (String key : sortedKeys) {
+                        final Long value = subDataset.get(key);
+
+                        count += value;
+                        for (int rankIdx = loopIndex; rankIdx < roofs.length; rankIdx++) {
+                            int roof = roofs[rankIdx];
+
+                            if (count >= roof) {
+                                if (group.equals(DEFAULT_GROUP)) {
+                                    percentileValues.put(String.valueOf(ranks.get(rankIdx)), Long.parseLong(key));
+                                } else {
+                                    percentileValues.put(String.format("%s:%s", group, ranks.get(rankIdx)), Long.parseLong(key));
+                                }
+                                loopIndex++;
+                            } else {
+                                break;
+                            }
+                        }
+                    }
+                });
+        }
+    }
+
+    @Override
+    public Metrics toHour() {
+        SumHistogramPercentileFunction metrics = (SumHistogramPercentileFunction) createNew();
+        metrics.setEntityId(getEntityId());
+        metrics.setTimeBucket(toTimeBucketInHour());
+        metrics.setSummation(getSummation());
+        metrics.setRanks(getRanks());
+        metrics.setPercentileValues(getPercentileValues());
+        return metrics;
+    }
+
+    @Override
+    public Metrics toDay() {
+        SumHistogramPercentileFunction metrics = (SumHistogramPercentileFunction) createNew();
+        metrics.setEntityId(getEntityId());
+        metrics.setTimeBucket(toTimeBucketInDay());
+        metrics.setSummation(getSummation());
+        metrics.setRanks(getRanks());
+        metrics.setPercentileValues(getPercentileValues());
+        return metrics;
+    }
+
+    @Override
+    public int[] getValues() {
+        return percentileValues.sortedValues(Comparator.comparingInt(Integer::parseInt))
+                               .stream()
+                               .flatMapToInt(l -> IntStream.of(l.intValue()))
+                               .toArray();
+    }
+
+    @Override
+    public int remoteHashCode() {
+        return entityId.hashCode();
+    }
+
+    @Override
+    public void deserialize(final RemoteData remoteData) {
+        this.setTimeBucket(remoteData.getDataLongs(0));
+
+        this.setEntityId(remoteData.getDataStrings(0));
+
+        this.setSummation(new DataTable(remoteData.getDataObjectStrings(0)));
+        this.setRanks(new IntList(remoteData.getDataObjectStrings(1)));
+        this.setPercentileValues(new DataTable(remoteData.getDataObjectStrings(2)));
+    }
+
+    @Override
+    public RemoteData.Builder serialize() {
+        RemoteData.Builder remoteBuilder = RemoteData.newBuilder();
+        remoteBuilder.addDataLongs(getTimeBucket());
+
+        remoteBuilder.addDataStrings(entityId);
+
+        remoteBuilder.addDataObjectStrings(summation.toStorageData());
+        remoteBuilder.addDataObjectStrings(ranks.toStorageData());
+        remoteBuilder.addDataObjectStrings(percentileValues.toStorageData());
+
+        return remoteBuilder;
+    }
+
+    @Override
+    protected String id0() {
+        return getTimeBucket() + Const.ID_CONNECTOR + entityId;
+    }
+
+    @Override
+    public Class<? extends AvgPercentileFunctionBuilder> builder() {
+        return AvgPercentileFunctionBuilder.class;
+    }
+
+    public static class AvgPercentileFunctionBuilder implements StorageBuilder<SumHistogramPercentileFunction> {
+        @Override
+        public SumHistogramPercentileFunction storage2Entity(final Convert2Entity converter) {
+            SumHistogramPercentileFunction metrics = new SumHistogramPercentileFunction() {
+                @Override
+                public AcceptableValue<PercentileArgument> createNew() {
+                    throw new UnexpectedException("createNew should not be called");
+                }
+            };
+            metrics.setSummation(new DataTable((String) converter.get(SUMMATION)));
+            metrics.setRanks(new IntList((String) converter.get(RANKS)));
+            metrics.setPercentileValues(new DataTable((String) converter.get(VALUE)));
+            metrics.setTimeBucket(((Number) converter.get(TIME_BUCKET)).longValue());
+            metrics.setEntityId((String) converter.get(ENTITY_ID));
+            return metrics;
+        }
+
+        @Override
+        public void entity2Storage(final SumHistogramPercentileFunction storageData, final Convert2Storage converter) {
+            converter.accept(SUMMATION, storageData.getSummation());
+            converter.accept(RANKS, storageData.getRanks());
+            converter.accept(VALUE, storageData.getPercentileValues());
+            converter.accept(TIME_BUCKET, storageData.getTimeBucket());
+            converter.accept(ENTITY_ID, storageData.getEntityId());
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof SumHistogramPercentileFunction)) {
+            return false;
+        }
+        SumHistogramPercentileFunction function = (SumHistogramPercentileFunction) o;
+        return Objects.equals(entityId, function.entityId) &&
+            getTimeBucket() == function.getTimeBucket();
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(entityId, getTimeBucket());
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinFunction.java
new file mode 100644
index 0000000000..7010827bbc
--- /dev/null
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinFunction.java
@@ -0,0 +1,196 @@
+/*
+ * 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.oap.server.core.analysis.meter.function.sumpermin;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.UnexpectedException;
+import org.apache.skywalking.oap.server.core.analysis.manual.instance.InstanceTraffic;
+import org.apache.skywalking.oap.server.core.analysis.meter.Meter;
+import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.MeterFunction;
+import org.apache.skywalking.oap.server.core.analysis.metrics.LongValueHolder;
+import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
+import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.Entrance;
+import org.apache.skywalking.oap.server.core.analysis.metrics.annotation.SourceFrom;
+import org.apache.skywalking.oap.server.core.query.sql.Function;
+import org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData;
+import org.apache.skywalking.oap.server.core.storage.annotation.BanyanDB;
+import org.apache.skywalking.oap.server.core.storage.annotation.Column;
+import org.apache.skywalking.oap.server.core.storage.type.Convert2Entity;
+import org.apache.skywalking.oap.server.core.storage.type.Convert2Storage;
+import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
+
+import java.util.Objects;
+
+@ToString
+@MeterFunction(functionName = "sum_per_min")
+public abstract class SumPerMinFunction extends Meter implements AcceptableValue<Long>, LongValueHolder {
+    protected static final String VALUE = "value";
+    protected static final String TOTAL = "total";
+
+    @Setter
+    @Getter
+    @Column(columnName = ENTITY_ID, length = 512)
+    @BanyanDB.ShardingKey(index = 0)
+    private String entityId;
+
+    @Setter
+    @Getter
+    @Column(columnName = InstanceTraffic.SERVICE_ID)
+    private String serviceId;
+
+    @Getter
+    @Setter
+    @Column(columnName = VALUE, dataType = Column.ValueDataType.COMMON_VALUE, function = Function.Avg)
+    private long value;
+
+    @Getter
+    @Setter
+    @Column(columnName = TOTAL, storageOnly = true)
+    private long total;
+
+    @Entrance
+    public final void combine(@SourceFrom long value) {
+        this.total += value;
+    }
+
+    @Override
+    public boolean combine(Metrics metrics) {
+        final SumPerMinFunction sumPerMinFunction = (SumPerMinFunction) metrics;
+        combine(sumPerMinFunction.getTotal());
+        return true;
+    }
+
+    @Override
+    public void calculate() {
+        setValue(this.total / getDurationInMinute());
+    }
+
+    @Override
+    public Metrics toHour() {
+        final SumPerMinFunction metrics = (SumPerMinFunction) createNew();
+        metrics.setEntityId(getEntityId());
+        metrics.setTimeBucket(toTimeBucketInHour());
+        metrics.setServiceId(getServiceId());
+        metrics.setTotal(getTotal());
+        return metrics;
+    }
+
+    @Override
+    public Metrics toDay() {
+        final SumPerMinFunction metrics = (SumPerMinFunction) createNew();
+        metrics.setEntityId(getEntityId());
+        metrics.setTimeBucket(toTimeBucketInDay());
+        metrics.setServiceId(getServiceId());
+        metrics.setTotal(getTotal());
+        return metrics;
+    }
+
+    @Override
+    public int remoteHashCode() {
+        return getEntityId().hashCode();
+    }
+
+    @Override
+    public void deserialize(RemoteData remoteData) {
+        setTotal(remoteData.getDataLongs(0));
+        setTimeBucket(remoteData.getDataLongs(1));
+
+        setEntityId(remoteData.getDataStrings(0));
+        setServiceId(remoteData.getDataStrings(1));
+    }
+
+    @Override
+    public RemoteData.Builder serialize() {
+        final RemoteData.Builder remoteBuilder = RemoteData.newBuilder();
+
+        remoteBuilder.addDataLongs(getTotal());
+        remoteBuilder.addDataLongs(getTimeBucket());
+
+        remoteBuilder.addDataStrings(getEntityId());
+        remoteBuilder.addDataStrings(getServiceId());
+        return remoteBuilder;
+    }
+
+    @Override
+    protected String id0() {
+        return getTimeBucket() + Const.ID_CONNECTOR + getEntityId();
+    }
+
+    @Override
+    public void accept(MeterEntity entity, Long value) {
+        setEntityId(entity.id());
+        setServiceId(entity.serviceId());
+        setTotal(getTotal() + value);
+    }
+
+    @Override
+    public Class<? extends StorageBuilder> builder() {
+        return SumPerMinStorageBuilder.class;
+    }
+
+    public static class SumPerMinStorageBuilder implements StorageBuilder<SumPerMinFunction> {
+        @Override
+        public SumPerMinFunction storage2Entity(final Convert2Entity converter) {
+            final SumPerMinFunction metrics = new SumPerMinFunction() {
+                @Override
+                public AcceptableValue<Long> createNew() {
+                    throw new UnexpectedException("createNew should not be called");
+                }
+            };
+            metrics.setValue(((Number) converter.get(VALUE)).longValue());
+            metrics.setTotal(((Number) converter.get(TOTAL)).longValue());
+            metrics.setTimeBucket(((Number) converter.get(TIME_BUCKET)).longValue());
+            metrics.setServiceId((String) converter.get(InstanceTraffic.SERVICE_ID));
+            metrics.setEntityId((String) converter.get(ENTITY_ID));
+            return metrics;
+        }
+
+        @Override
+        public void entity2Storage(final SumPerMinFunction storageData, final Convert2Storage converter) {
+            converter.accept(VALUE, storageData.getValue());
+            converter.accept(TOTAL, storageData.getTotal());
+            converter.accept(TIME_BUCKET, storageData.getTimeBucket());
+            converter.accept(InstanceTraffic.SERVICE_ID, storageData.getServiceId());
+            converter.accept(ENTITY_ID, storageData.getEntityId());
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof SumPerMinFunction)) {
+            return false;
+        }
+        final SumPerMinFunction function = (SumPerMinFunction) o;
+        return Objects.equals(getEntityId(), function.getEntityId())
+            && Objects.equals(getTimeBucket(), function.getTimeBucket());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getEntityId(), getTimeBucket());
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingMutationService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingMutationService.java
index ba6d7b2792..bb8df1a718 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingMutationService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingMutationService.java
@@ -266,7 +266,7 @@ public class EBPFProfilingMutationService implements Service {
         }
 
         // validate have processes under the instance
-        final long processesCount = getMetadataQueryDAO().getProcessesCount(null, request.getInstanceId(), null, null, 0, 0);
+        final long processesCount = getMetadataQueryDAO().getProcessCount(request.getInstanceId());
         if (processesCount <= 0) {
             return "The instance doesn't have processes.";
         }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingQueryService.java
index 260ccd3dd6..3c74857395 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profiling/ebpf/EBPFProfilingQueryService.java
@@ -155,7 +155,7 @@ public class EBPFProfilingQueryService implements Service {
         // query process count in last 10 minutes
         final long endTimestamp = System.currentTimeMillis();
         final long startTimestamp = endTimestamp - TimeUnit.MINUTES.toMillis(10);
-        final long processesCount = getMetadataQueryDAO().getProcessesCount(serviceId, null, null,
+        final long processesCount = getMetadataQueryDAO().getProcessCount(serviceId,
                 ProfilingSupportStatus.SUPPORT_EBPF_PROFILING, TimeBucket.getTimeBucket(startTimestamp, DownSampling.Minute),
                 TimeBucket.getTimeBucket(endTimestamp, DownSampling.Minute));
         if (processesCount <= 0) {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java
index 4ca6009fc6..dfd451b075 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/MetadataQueryService.java
@@ -104,8 +104,7 @@ public class MetadataQueryService implements org.apache.skywalking.oap.server.li
     }
 
     public List<Process> listProcesses(final Duration duration, final String instanceId) throws IOException {
-        return getMetadataQueryDAO().listProcesses(null, instanceId, null, null,
-                duration.getStartTimeBucket(), duration.getEndTimeBucket());
+        return getMetadataQueryDAO().listProcesses(instanceId, duration.getStartTimeBucket(), duration.getEndTimeBucket());
     }
 
     public Process getProcess(String processId) throws IOException {
@@ -121,7 +120,7 @@ public class MetadataQueryService implements org.apache.skywalking.oap.server.li
         }
         final long endTimestamp = System.currentTimeMillis();
         final long startTimestamp = endTimestamp - TimeUnit.MINUTES.toMillis(10);
-        final List<Process> processes = getMetadataQueryDAO().listProcesses(serviceId, null, null,
+        final List<Process> processes = getMetadataQueryDAO().listProcesses(serviceId,
                 ProfilingSupportStatus.SUPPORT_EBPF_PROFILING, TimeBucket.getTimeBucket(startTimestamp, DownSampling.Minute),
                 TimeBucket.getTimeBucket(endTimestamp, DownSampling.Minute));
         return CollectionUtils.isEmpty(processes) ?
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
index 24dd802cfb..7256ca57d6 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
@@ -25,6 +25,7 @@ import java.util.List;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
 
 /**
@@ -158,7 +159,11 @@ public class HeatMap {
 
         private String[] parseKey(String key) {
             if (key.contains(":")) {
-                return key.split(":");
+                // split the group and bucket
+                return new String[] {
+                    StringUtils.substringBeforeLast(key, ":"),
+                    StringUtils.substringAfterLast(key, ":"),
+                };
             }
             return new String[] {"default", key};
         }
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Process.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Process.java
index 8517e2d786..1cb6c7f883 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Process.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/Process.java
@@ -44,6 +44,8 @@ public class Process {
     private String agentId;
     @Setter
     private String detectType;
+    @Setter
+    private String profilingSupportStatus;
     private final List<Attribute> attributes;
     private final List<String> labels;
 
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java
index 1393d08b0a..632127f70e 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/storage/query/IMetadataQueryDAO.java
@@ -61,25 +61,41 @@ public interface IMetadataQueryDAO extends DAO {
     List<Endpoint> findEndpoint(final String keyword, final String serviceId, final int limit) throws IOException;
 
     /**
-     * @param serviceId the service of the processes.
-     * @param instanceId the service instance of the process.
-     * @param agentId the agent id which reports the process.
-     * @return list of processes matching the given conditions.
+     * @param serviceId the service id of the process.
+     * @param supportStatus the profiling status of the process.
+     * @param lastPingStartTimeBucket the start time bucket of last ping.
+     * @param lastPingEndTimeBucket the end time bucket of last ping.
      */
-    List<Process> listProcesses(final String serviceId, final String instanceId, final String agentId,
-                                final ProfilingSupportStatus profilingSupportStatus, final long lastPingStartTimeBucket,
+    List<Process> listProcesses(final String serviceId, final ProfilingSupportStatus supportStatus,
+                                final long lastPingStartTimeBucket, final long lastPingEndTimeBucket) throws IOException;
+
+    /**
+     * @param serviceInstanceId the instance id of the process.
+     * @param lastPingStartTimeBucket the start time bucket of last ping.
+     * @param lastPingEndTimeBucket the end time bucket of last ping.
+     */
+    List<Process> listProcesses(final String serviceInstanceId, final long lastPingStartTimeBucket,
                                 final long lastPingEndTimeBucket) throws IOException;
 
     /**
-     * get the count of processes
-     * @param serviceId the service of the processes.
-     * @param instanceId the service instance of the process.
-     * @param agentId the agent id which reports the process.
-     * @return the size of processes
+     * @param agentId the agent id of the process.
+     */
+    List<Process> listProcesses(final String agentId) throws IOException;
+
+    /**
+     * @param serviceId the service id of the process
+     * @param profilingSupportStatus the profiling status of the process.
+     * @param lastPingStartTimeBucket the start time bucket of last ping.
+     * @param lastPingEndTimeBucket the end time bucket of last ping.
+     */
+    long getProcessCount(final String serviceId,
+                         final ProfilingSupportStatus profilingSupportStatus, final long lastPingStartTimeBucket,
+                         final long lastPingEndTimeBucket) throws IOException;
+
+    /**
+     * @param instanceId the service instance id of the process
      */
-    long getProcessesCount(final String serviceId, final String instanceId, final String agentId,
-                           final ProfilingSupportStatus profilingSupportStatus, final long lastPingStartTimeBucket,
-                           final long lastPingEndTimeBucket) throws IOException;
+    long getProcessCount(final String instanceId) throws IOException;
 
     /**
      * @param processId the id of the process.
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumHistogramPercentileFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumHistogramPercentileFunctionTest.java
new file mode 100644
index 0000000000..75dbf407c2
--- /dev/null
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sum/SumHistogramPercentileFunctionTest.java
@@ -0,0 +1,254 @@
+/*
+ * 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.oap.server.core.analysis.meter.function.sum;
+
+import org.apache.skywalking.oap.server.core.analysis.Layer;
+import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.BucketedValues;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.PercentileArgument;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
+import org.apache.skywalking.oap.server.core.analysis.metrics.IntList;
+import org.apache.skywalking.oap.server.core.config.NamingControl;
+import org.apache.skywalking.oap.server.core.config.group.EndpointNameGrouping;
+import org.apache.skywalking.oap.server.core.storage.type.HashMapConverter;
+import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class SumHistogramPercentileFunctionTest {
+
+    private static final long[] BUCKETS = new long[] {
+        0,
+        50,
+        100,
+        250
+    };
+
+    private static final int[] RANKS = new int[] {
+        50,
+        90
+    };
+
+    @BeforeClass
+    public static void setup() {
+        MeterEntity.setNamingControl(
+            new NamingControl(512, 512, 512, new EndpointNameGrouping()));
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        MeterEntity.setNamingControl(null);
+    }
+
+    @Test
+    public void testFunction() {
+        PercentileFunctionInst inst = new PercentileFunctionInst();
+        inst.accept(
+            MeterEntity.newService("service-test", Layer.GENERAL),
+            new PercentileArgument(
+                new BucketedValues(
+                    BUCKETS,
+                    new long[] {
+                        10,
+                        20,
+                        30,
+                        40
+                    }
+                ),
+                RANKS
+            )
+        );
+
+        inst.accept(
+            MeterEntity.newService("service-test", Layer.GENERAL),
+            new PercentileArgument(
+                new BucketedValues(
+                    BUCKETS,
+                    new long[] {
+                        10,
+                        20,
+                        30,
+                        40
+                    }
+                ),
+                RANKS
+            )
+        );
+
+        inst.calculate();
+        final int[] values = inst.getValues();
+        /**
+         * Expected percentile dataset
+         * <pre>
+         *     0  , 20
+         *     50 , 40
+         *     100, 50 <- P50
+         *     250, 80 <- P90
+         * </pre>
+         */
+        Assert.assertArrayEquals(new int[] {
+            100,
+            250
+        }, values);
+    }
+
+    @Test
+    public void testSerialization() {
+        PercentileFunctionInst inst = new PercentileFunctionInst();
+        inst.accept(
+            MeterEntity.newService("service-test", Layer.GENERAL),
+            new PercentileArgument(
+                new BucketedValues(
+                    BUCKETS,
+                    new long[] {
+                        10,
+                        20,
+                        30,
+                        40
+                    }
+                ),
+                RANKS
+            )
+        );
+
+        PercentileFunctionInst inst2 = new PercentileFunctionInst();
+        inst2.deserialize(inst.serialize().build());
+
+        assertEquals(inst, inst2);
+        assertEquals(inst.getSummation(), inst2.getSummation());
+        assertEquals(inst.getRanks(), inst2.getRanks());
+        assertEquals(0, inst2.getPercentileValues().size());
+    }
+
+    @Test
+    public void testBuilder() throws IllegalAccessException, InstantiationException {
+        PercentileFunctionInst inst = new PercentileFunctionInst();
+        inst.accept(
+            MeterEntity.newService("service-test", Layer.GENERAL),
+            new PercentileArgument(
+                new BucketedValues(
+                    BUCKETS,
+                    new long[] {
+                        10,
+                        20,
+                        30,
+                        40
+                    }
+                ),
+                RANKS
+            )
+        );
+        inst.calculate();
+
+        final StorageBuilder storageBuilder = inst.builder().newInstance();
+
+        // Simulate the storage layer do, convert the datatable to string.
+        final HashMapConverter.ToStorage toStorage = new HashMapConverter.ToStorage();
+        storageBuilder.entity2Storage(inst, toStorage);
+        final Map<String, Object> map = toStorage.obtain();
+        map.put(
+            SumHistogramPercentileFunction.SUMMATION,
+            ((DataTable) map.get(SumHistogramPercentileFunction.SUMMATION)).toStorageData()
+        );
+        map.put(
+            SumHistogramPercentileFunction.VALUE,
+            ((DataTable) map.get(SumHistogramPercentileFunction.VALUE)).toStorageData()
+        );
+        map.put(
+            SumHistogramPercentileFunction.RANKS,
+            ((IntList) map.get(SumHistogramPercentileFunction.RANKS)).toStorageData()
+        );
+
+        final SumHistogramPercentileFunction inst2 = (SumHistogramPercentileFunction) storageBuilder.storage2Entity(
+            new HashMapConverter.ToEntity(map));
+        assertEquals(inst, inst2);
+        // HistogramFunction equal doesn't include dataset.
+        assertEquals(inst.getPercentileValues(), inst2.getPercentileValues());
+        assertEquals(inst.getRanks(), inst2.getRanks());
+    }
+
+    @Test
+    public void testFunctionWhenGroupContainsColon() {
+        BucketedValues valuesA = new BucketedValues(
+            BUCKETS,
+            new long[] {
+                10,
+                20,
+                30,
+                40
+            }
+        );
+        valuesA.setGroup("localhost:3306/swtest");
+
+        PercentileFunctionInst inst = new PercentileFunctionInst();
+        inst.accept(
+            MeterEntity.newService("service-test", Layer.GENERAL),
+            new PercentileArgument(
+                valuesA,
+                RANKS
+            )
+        );
+        BucketedValues valuesB = new BucketedValues(
+            BUCKETS,
+            new long[] {
+                10,
+                20,
+                30,
+                40
+            }
+        );
+        valuesB.setGroup("localhost:3306/swtest");
+
+        inst.accept(
+            MeterEntity.newService("service-test", Layer.GENERAL),
+            new PercentileArgument(
+                valuesB,
+                RANKS
+            )
+        );
+
+        inst.calculate();
+        final DataTable values = inst.getPercentileValues();
+        /**
+         * Expected percentile dataset
+         * <pre>
+         *     0  , 20
+         *     50 , 40
+         *     100, 60 <- P50
+         *     250, 80 <- P90
+         * </pre>
+         */
+        assertEquals(new Long(100), values.get("localhost:3306/swtest:50"));
+        assertEquals(new Long(250), values.get("localhost:3306/swtest:90"));
+    }
+
+    private static class PercentileFunctionInst extends SumHistogramPercentileFunction {
+        @Override
+        public AcceptableValue<PercentileArgument> createNew() {
+            return new SumHistogramPercentileFunctionTest.PercentileFunctionInst();
+        }
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinFunctionTest.java
new file mode 100644
index 0000000000..20721c4a87
--- /dev/null
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/sumpermin/SumPerMinFunctionTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.oap.server.core.analysis.meter.function.sumpermin;
+
+import org.apache.skywalking.oap.server.core.analysis.Layer;
+import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
+import org.apache.skywalking.oap.server.core.analysis.meter.MeterEntity;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
+import org.apache.skywalking.oap.server.core.analysis.meter.function.latest.LatestFunction;
+import org.apache.skywalking.oap.server.core.config.NamingControl;
+import org.apache.skywalking.oap.server.core.config.group.EndpointNameGrouping;
+import org.apache.skywalking.oap.server.core.storage.type.HashMapConverter;
+import org.apache.skywalking.oap.server.core.storage.type.StorageBuilder;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.util.Map;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+@RunWith(MockitoJUnitRunner.class)
+public class SumPerMinFunctionTest {
+
+    private SumPerMinFunctionInst function;
+
+    @BeforeClass
+    public static void setup() {
+        MeterEntity.setNamingControl(
+            new NamingControl(512, 512, 512, new EndpointNameGrouping()));
+    }
+
+    @Before
+    public void before() {
+        function = new SumPerMinFunctionInst();
+        function.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        MeterEntity.setNamingControl(null);
+    }
+
+    @Test
+    public void testAccept() {
+        long time1 = 1597113318673L;
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time1);
+        function.calculate();
+        assertThat(function.getValue(), is(time1));
+        long time2 = 1597113447737L;
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time2);
+        function.calculate();
+        assertThat(function.getValue(), is(time1 + time2));
+    }
+
+    @Test
+    public void testCalculate() {
+        long time1 = 1597113318673L;
+        long time2 = 1597113447737L;
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time1);
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time2);
+        function.calculate();
+        assertThat(function.getValue(), is(time1 + time2));
+    }
+
+    @Test
+    public void testHour() {
+        long time1 = 1597113318673L;
+        long time2 = 1597113447737L;
+        function.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time1);
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time2);
+        function.calculate();
+        final SumPerMinFunction hourFunction = (SumPerMinFunction) function.toHour();
+        hourFunction.calculate();
+        assertThat(hourFunction.getValue(), is((time1 + time2) / 60));
+    }
+
+    @Test
+    public void testSerialize() {
+        long time = 1597113447737L;
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time);
+        LatestFunction function2 = Mockito.spy(LatestFunction.class);
+        function2.deserialize(function.serialize().build());
+        assertThat(function2.getEntityId(), is(function.getEntityId()));
+        assertThat(function2.getTimeBucket(), is(function.getTimeBucket()));
+    }
+
+    @Test
+    public void testBuilder() throws IllegalAccessException, InstantiationException {
+        long time = 1597113447737L;
+        function.accept(MeterEntity.newService("sum_sync_time", Layer.GENERAL), time);
+        function.calculate();
+        StorageBuilder<SumPerMinFunction> storageBuilder = function.builder().newInstance();
+
+        final HashMapConverter.ToStorage toStorage = new HashMapConverter.ToStorage();
+        storageBuilder.entity2Storage(function, toStorage);
+        final Map<String, Object> map = toStorage.obtain();
+        map.put(SumPerMinFunction.VALUE, map.get(SumPerMinFunction.VALUE));
+
+        SumPerMinFunction function2 = storageBuilder.storage2Entity(new HashMapConverter.ToEntity(map));
+        assertThat(function2.getValue(), is(function.getValue()));
+    }
+
+    private static class SumPerMinFunctionInst extends SumPerMinFunction {
+        @Override
+        public AcceptableValue<Long> createNew() {
+            return new SumPerMinFunctionTest.SumPerMinFunctionInst();
+        }
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/EBPFProfilingServiceHandler.java b/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/EBPFProfilingServiceHandler.java
index 221d12b34a..e48a819492 100644
--- a/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/EBPFProfilingServiceHandler.java
+++ b/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/EBPFProfilingServiceHandler.java
@@ -84,8 +84,7 @@ public class EBPFProfilingServiceHandler extends EBPFProfilingServiceGrpc.EBPFPr
         final long latestUpdateTime = request.getLatestUpdateTime();
         try {
             // find exists process from agent
-            final List<Process> processes = metadataQueryDAO.listProcesses(null, null, agentId,
-                    ProfilingSupportStatus.SUPPORT_EBPF_PROFILING, 0, 0);
+            final List<Process> processes = metadataQueryDAO.listProcesses(agentId);
             if (CollectionUtils.isEmpty(processes)) {
                 responseObserver.onNext(Commands.newBuilder().build());
                 responseObserver.onCompleted();
@@ -120,8 +119,9 @@ public class EBPFProfilingServiceHandler extends EBPFProfilingServiceGrpc.EBPFPr
         }
         final ArrayList<EBPFProfilingTaskCommand> commands = new ArrayList<>(processes.size());
         for (Process process : processes) {
-            // The service id must match between process and task
-            if (!Objects.equals(process.getServiceId(), task.getServiceId())) {
+            // The service id must match between process and task and must could profiling
+            if (!Objects.equals(process.getServiceId(), task.getServiceId())
+                || !ProfilingSupportStatus.SUPPORT_EBPF_PROFILING.name().equals(process.getProfilingSupportStatus())) {
                 continue;
             }
 
diff --git a/oap-server/server-starter/src/main/resources/meter-analyzer-config/network-profiling.yaml b/oap-server/server-starter/src/main/resources/meter-analyzer-config/network-profiling.yaml
index 1841f8e308..326bcfb3ad 100644
--- a/oap-server/server-starter/src/main/resources/meter-analyzer-config/network-profiling.yaml
+++ b/oap-server/server-starter/src/main/resources/meter-analyzer-config/network-profiling.yaml
@@ -31,68 +31,68 @@ metricPrefix: process_relation
 metricsRules:
   # client side
   - name: client_write_cpm
-    exp:  rover_net_p_client_write_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_client_write_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: client_write_total_bytes
-    exp:  rover_net_p_client_write_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_client_write_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: client_write_avg_exe_time
     exp:  rover_net_p_client_write_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: client_read_cpm
-    exp:  rover_net_p_client_read_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_client_read_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: client_read_total_bytes
-    exp:  rover_net_p_client_read_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_client_read_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: client_read_avg_exe_time
     exp: rover_net_p_client_read_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: client_write_avg_rtt_time
     exp: rover_net_p_client_write_rtt_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: client_connect_cpm
-    exp: rover_net_p_client_connect_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp: rover_net_p_client_connect_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: client_connect_exe_time
     exp: rover_net_p_client_connect_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: client_close_cpm
-    exp: rover_net_p_client_close_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp: rover_net_p_client_close_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: client_close_avg_exe_time
     exp: rover_net_p_client_close_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: client_retransmit_cpm
-    exp: rover_net_p_client_retransmit_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp: rover_net_p_client_retransmit_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: client_drop_cpm
-    exp: rover_net_p_client_drop_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
-  - name: client_write_rtt_time_histogram
-    exp: rover_net_p_client_write_rtt_histogram.histogram().downsampling(SUM)
-  - name: client_write_exe_time_histogram
-    exp: rover_net_p_client_write_exe_time_histogram.histogram().downsampling(SUM)
-  - name: client_read_exe_time_histogram
-    exp: rover_net_p_client_read_exe_time_histogram.histogram().downsampling(SUM)
+    exp: rover_net_p_client_drop_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
+  - name: client_write_rtt_time_percentile
+    exp: rover_net_p_client_write_rtt_histogram.histogram().histogram_percentile([50,70,90,99]).downsampling(SUM)
+  - name: client_write_exe_time_percentile
+    exp: rover_net_p_client_write_exe_time_histogram.histogram().histogram_percentile([50,70,90,99]).downsampling(SUM)
+  - name: client_read_exe_time_percentile
+    exp: rover_net_p_client_read_exe_time_histogram.histogram().histogram_percentile([50,70,90,99]).downsampling(SUM)
 
   # server side
   - name: server_write_cpm
-    exp:  rover_net_p_server_write_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_server_write_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: server_write_total_bytes
-    exp:  rover_net_p_server_write_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_server_write_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: server_write_avg_exe_time
     exp:  rover_net_p_server_write_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: server_read_cpm
-    exp:  rover_net_p_server_read_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_server_read_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: server_read_total_bytes
-    exp:  rover_net_p_server_read_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp:  rover_net_p_server_read_bytes_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: server_read_avg_exe_time
     exp: rover_net_p_server_read_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: server_write_avg_rtt_time
     exp: rover_net_p_server_write_rtt_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: server_connect_cpm
-    exp: rover_net_p_server_connect_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp: rover_net_p_server_connect_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: server_connect_avg_exe_time
     exp: rover_net_p_server_connect_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: server_close_cpm
-    exp: rover_net_p_server_close_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp: rover_net_p_server_close_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: server_close_avg_exe_time
     exp: rover_net_p_server_close_exe_time_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id'])
   - name: server_retransmit_cpm
-    exp: rover_net_p_server_retransmit_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
+    exp: rover_net_p_server_retransmit_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
   - name: server_drop_cpm
-    exp: rover_net_p_server_drop_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM)
-  - name: server_write_rtt_time_histogram
-    exp: rover_net_p_server_write_rtt_histogram.histogram().downsampling(SUM)
-  - name: server_write_exe_time_histogram
-    exp: rover_net_p_server_write_exe_time_histogram.histogram().downsampling(SUM)
-  - name: server_read_exe_time_histogram
-    exp: rover_net_p_server_read_exe_time_histogram.histogram().downsampling(SUM)
\ No newline at end of file
+    exp: rover_net_p_server_drop_counts_counter.sum(['service', 'instance', 'side', 'client_process_id', 'server_process_id']).downsampling(SUM_PER_MIN)
+  - name: server_write_rtt_time_percentile
+    exp: rover_net_p_server_write_rtt_histogram.histogram().histogram_percentile([50,70,90,99]).downsampling(SUM)
+  - name: server_write_exe_time_percentile
+    exp: rover_net_p_server_write_exe_time_histogram.histogram().histogram_percentile([50,70,90,99]).downsampling(SUM)
+  - name: server_read_exe_time_percentile
+    exp: rover_net_p_server_read_exe_time_histogram.histogram().histogram_percentile([50,70,90,99]).downsampling(SUM)
\ No newline at end of file
diff --git a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java
index c5ef44ce9e..556fe7c5c2 100644
--- a/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-banyandb-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/banyandb/measure/BanyanDBMetadataQueryDAO.java
@@ -201,34 +201,20 @@ public class BanyanDBMetadataQueryDAO extends AbstractBanyanDBDAO implements IMe
     }
 
     @Override
-    public List<Process> listProcesses(String serviceId, String instanceId, String agentId, ProfilingSupportStatus profilingSupportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
+    public List<Process> listProcesses(String serviceId, ProfilingSupportStatus supportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
         MeasureQueryResponse resp = query(ProcessTraffic.INDEX_NAME,
-                PROCESS_TRAFFIC_TAGS,
-                Collections.emptySet(),
-                new QueryBuilder<MeasureQuery>() {
-                    @Override
-                    protected void apply(MeasureQuery query) {
-                        if (StringUtil.isNotEmpty(serviceId)) {
-                            query.and(eq(ProcessTraffic.SERVICE_ID, serviceId));
-                        }
-                        if (StringUtil.isNotEmpty(instanceId)) {
-                            query.and(eq(ProcessTraffic.INSTANCE_ID, instanceId));
-                        }
-                        if (StringUtil.isNotEmpty(agentId)) {
-                            query.and(eq(ProcessTraffic.AGENT_ID, agentId));
-                        }
-                        if (lastPingStartTimeBucket > 0) {
-                            query.and(gte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingStartTimeBucket));
-                        }
-                        if (lastPingEndTimeBucket > 0) {
-                            query.and(lte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingEndTimeBucket));
-                        }
-                        if (profilingSupportStatus != null) {
-                            query.and(eq(ProcessTraffic.PROFILING_SUPPORT_STATUS, profilingSupportStatus.value()));
-                        }
-                        query.and(ne(ProcessTraffic.DETECT_TYPE, ProcessDetectType.VIRTUAL.value()));
-                    }
-                });
+            PROCESS_TRAFFIC_TAGS,
+            Collections.emptySet(),
+            new QueryBuilder<MeasureQuery>() {
+                @Override
+                protected void apply(MeasureQuery query) {
+                    query.and(eq(ProcessTraffic.SERVICE_ID, serviceId));
+                    query.and(gte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingStartTimeBucket));
+                    query.and(lte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingEndTimeBucket));
+                    query.and(eq(ProcessTraffic.PROFILING_SUPPORT_STATUS, supportStatus.value()));
+                    query.and(ne(ProcessTraffic.DETECT_TYPE, ProcessDetectType.VIRTUAL.value()));
+                }
+            });
 
         final List<Process> processes = new ArrayList<>();
 
@@ -240,39 +226,90 @@ public class BanyanDBMetadataQueryDAO extends AbstractBanyanDBDAO implements IMe
     }
 
     @Override
-    public long getProcessesCount(String serviceId, String instanceId, String agentId, ProfilingSupportStatus profilingSupportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
+    public List<Process> listProcesses(String serviceInstanceId, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
         MeasureQueryResponse resp = query(ProcessTraffic.INDEX_NAME,
-                PROCESS_TRAFFIC_TAGS,
-                Collections.emptySet(),
-                new QueryBuilder<MeasureQuery>() {
-                    @Override
-                    protected void apply(MeasureQuery query) {
-                        if (StringUtil.isNotEmpty(serviceId)) {
-                            query.and(eq(ProcessTraffic.SERVICE_ID, serviceId));
-                        }
-                        if (StringUtil.isNotEmpty(instanceId)) {
-                            query.and(eq(ProcessTraffic.INSTANCE_ID, instanceId));
-                        }
-                        if (StringUtil.isNotEmpty(agentId)) {
-                            query.and(eq(ProcessTraffic.AGENT_ID, instanceId));
-                        }
-                        if (lastPingStartTimeBucket > 0) {
-                            query.and(gte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingStartTimeBucket));
-                        }
-                        if (lastPingEndTimeBucket > 0) {
-                            query.and(lte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingEndTimeBucket));
-                        }
-                        if (profilingSupportStatus != null) {
-                            query.and(eq(ProcessTraffic.PROFILING_SUPPORT_STATUS, profilingSupportStatus.value()));
-                        }
-                        query.and(ne(ProcessTraffic.DETECT_TYPE, ProcessDetectType.VIRTUAL.value()));
-                    }
-                });
+            PROCESS_TRAFFIC_TAGS,
+            Collections.emptySet(),
+            new QueryBuilder<MeasureQuery>() {
+                @Override
+                protected void apply(MeasureQuery query) {
+                    query.and(eq(ProcessTraffic.INSTANCE_ID, serviceInstanceId));
+                    query.and(gte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingStartTimeBucket));
+                    query.and(lte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingEndTimeBucket));
+                    query.and(ne(ProcessTraffic.DETECT_TYPE, ProcessDetectType.VIRTUAL.value()));
+                }
+            });
+
+        final List<Process> processes = new ArrayList<>();
+
+        for (final DataPoint dataPoint : resp.getDataPoints()) {
+            processes.add(buildProcess(dataPoint));
+        }
+
+        return processes;
+    }
+
+    @Override
+    public List<Process> listProcesses(String agentId) throws IOException {
+        MeasureQueryResponse resp = query(ProcessTraffic.INDEX_NAME,
+            PROCESS_TRAFFIC_TAGS,
+            Collections.emptySet(),
+            new QueryBuilder<MeasureQuery>() {
+                @Override
+                protected void apply(MeasureQuery query) {
+                    query.and(eq(ProcessTraffic.AGENT_ID, agentId));
+                    query.and(ne(ProcessTraffic.DETECT_TYPE, ProcessDetectType.VIRTUAL.value()));
+                }
+            });
+
+        final List<Process> processes = new ArrayList<>();
+
+        for (final DataPoint dataPoint : resp.getDataPoints()) {
+            processes.add(buildProcess(dataPoint));
+        }
+
+        return processes;
+    }
+
+    @Override
+    public long getProcessCount(String serviceId, ProfilingSupportStatus profilingSupportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
+        MeasureQueryResponse resp = query(ProcessTraffic.INDEX_NAME,
+            PROCESS_TRAFFIC_TAGS,
+            Collections.emptySet(),
+            new QueryBuilder<MeasureQuery>() {
+                @Override
+                protected void apply(MeasureQuery query) {
+                    query.and(eq(ProcessTraffic.SERVICE_ID, serviceId));
+                    query.and(gte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingStartTimeBucket));
+                    query.and(lte(ProcessTraffic.LAST_PING_TIME_BUCKET, lastPingEndTimeBucket));
+                    query.and(eq(ProcessTraffic.PROFILING_SUPPORT_STATUS, profilingSupportStatus.value()));
+                    query.and(ne(ProcessTraffic.DETECT_TYPE, ProcessDetectType.VIRTUAL.value()));
+                }
+            });
+
+        return resp.getDataPoints()
+            .stream()
+            .collect(Collectors.groupingBy((Function<DataPoint, String>) dataPoint -> dataPoint.getTagValue(ProcessTraffic.PROPERTIES)))
+            .size();
+    }
+
+    @Override
+    public long getProcessCount(String instanceId) throws IOException {
+        MeasureQueryResponse resp = query(ProcessTraffic.INDEX_NAME,
+            PROCESS_TRAFFIC_TAGS,
+            Collections.emptySet(),
+            new QueryBuilder<MeasureQuery>() {
+                @Override
+                protected void apply(MeasureQuery query) {
+                    query.and(eq(ProcessTraffic.INSTANCE_ID, instanceId));
+                    query.and(ne(ProcessTraffic.DETECT_TYPE, ProcessDetectType.VIRTUAL.value()));
+                }
+            });
 
         return resp.getDataPoints()
-                .stream()
-                .collect(Collectors.groupingBy((Function<DataPoint, String>) dataPoint -> dataPoint.getTagValue(ProcessTraffic.PROPERTIES)))
-                .size();
+            .stream()
+            .collect(Collectors.groupingBy((Function<DataPoint, String>) dataPoint -> dataPoint.getTagValue(ProcessTraffic.PROPERTIES)))
+            .size();
     }
 
     @Override
@@ -350,6 +387,7 @@ public class BanyanDBMetadataQueryDAO extends AbstractBanyanDBDAO implements IMe
         process.setInstanceName(IDManager.ServiceInstanceID.analysisId(instanceId).getName());
         process.setAgentId(dataPoint.getTagValue(ProcessTraffic.AGENT_ID));
         process.setDetectType(ProcessDetectType.valueOf(((Number) dataPoint.getTagValue(ProcessTraffic.DETECT_TYPE)).intValue()).name());
+        process.setProfilingSupportStatus(ProfilingSupportStatus.valueOf(((Number) dataPoint.getTagValue(ProcessTraffic.PROFILING_SUPPORT_STATUS)).intValue()).name());
 
         String propString = dataPoint.getTagValue(ProcessTraffic.PROPERTIES);
         if (!Strings.isNullOrEmpty(propString)) {
diff --git a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java
index 402c5f2d12..5db92975fa 100644
--- a/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java
+++ b/oap-server/server-storage-plugin/storage-elasticsearch-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/elasticsearch/query/MetadataQueryEsDAO.java
@@ -214,30 +214,66 @@ public class MetadataQueryEsDAO extends EsDAO implements IMetadataQueryDAO {
     }
 
     @Override
-    public List<Process> listProcesses(String serviceId, String instanceId, String agentId, final ProfilingSupportStatus profilingSupportStatus,
-                                       final long lastPingStartTimeBucket, final long lastPingEndTimeBucket) throws IOException {
+    public List<Process> listProcesses(String serviceId, ProfilingSupportStatus supportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
         final String index =
             IndexController.LogicIndicesRegister.getPhysicalTableName(ProcessTraffic.INDEX_NAME);
 
         final BoolQueryBuilder query = Query.bool();
         final SearchBuilder search = Search.builder().query(query).size(queryMaxSize);
-        appendProcessWhereQuery(query, serviceId, instanceId, agentId, profilingSupportStatus,
-                lastPingStartTimeBucket, lastPingEndTimeBucket);
+        appendProcessWhereQuery(query, serviceId, null, null, supportStatus, lastPingStartTimeBucket, lastPingEndTimeBucket);
         final SearchResponse results = getClient().search(index, search.build());
 
         return buildProcesses(results);
     }
 
     @Override
-    public long getProcessesCount(String serviceId, String instanceId, String agentId, final ProfilingSupportStatus profilingSupportStatus,
-                                  final long lastPingStartTimeBucket, final long lastPingEndTimeBucket) throws IOException {
+    public List<Process> listProcesses(String serviceInstanceId, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
         final String index =
-                IndexController.LogicIndicesRegister.getPhysicalTableName(ProcessTraffic.INDEX_NAME);
+            IndexController.LogicIndicesRegister.getPhysicalTableName(ProcessTraffic.INDEX_NAME);
+
+        final BoolQueryBuilder query = Query.bool();
+        final SearchBuilder search = Search.builder().query(query).size(queryMaxSize);
+        appendProcessWhereQuery(query, null, serviceInstanceId, null, null, lastPingStartTimeBucket, lastPingEndTimeBucket);
+        final SearchResponse results = getClient().search(index, search.build());
+
+        return buildProcesses(results);
+    }
+
+    @Override
+    public List<Process> listProcesses(String agentId) throws IOException {
+        final String index =
+            IndexController.LogicIndicesRegister.getPhysicalTableName(ProcessTraffic.INDEX_NAME);
+
+        final BoolQueryBuilder query = Query.bool();
+        final SearchBuilder search = Search.builder().query(query).size(queryMaxSize);
+        appendProcessWhereQuery(query, null, null, agentId, null, 0, 0);
+        final SearchResponse results = getClient().search(index, search.build());
+
+        return buildProcesses(results);
+    }
+
+    @Override
+    public long getProcessCount(String serviceId, ProfilingSupportStatus profilingSupportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
+        final String index =
+            IndexController.LogicIndicesRegister.getPhysicalTableName(ProcessTraffic.INDEX_NAME);
+
+        final BoolQueryBuilder query = Query.bool();
+        final SearchBuilder search = Search.builder().query(query).size(0);
+        appendProcessWhereQuery(query, serviceId, null, null, profilingSupportStatus,
+            lastPingStartTimeBucket, lastPingEndTimeBucket);
+        final SearchResponse results = getClient().search(index, search.build());
+
+        return results.getHits().getTotal();
+    }
+
+    @Override
+    public long getProcessCount(String instanceId) throws IOException {
+        final String index =
+            IndexController.LogicIndicesRegister.getPhysicalTableName(ProcessTraffic.INDEX_NAME);
 
         final BoolQueryBuilder query = Query.bool();
         final SearchBuilder search = Search.builder().query(query).size(0);
-        appendProcessWhereQuery(query, serviceId, instanceId, agentId, profilingSupportStatus,
-                lastPingStartTimeBucket, lastPingEndTimeBucket);
+        appendProcessWhereQuery(query, null, instanceId, null, null, 0, 0);
         final SearchResponse results = getClient().search(index, search.build());
 
         return results.getHits().getTotal();
@@ -353,6 +389,7 @@ public class MetadataQueryEsDAO extends EsDAO implements IMetadataQueryDAO {
             process.setInstanceName(IDManager.ServiceInstanceID.analysisId(instanceId).getName());
             process.setAgentId(processTraffic.getAgentId());
             process.setDetectType(ProcessDetectType.valueOf(processTraffic.getDetectType()).name());
+            process.setProfilingSupportStatus(ProfilingSupportStatus.valueOf(processTraffic.getProfilingSupportStatus()).name());
 
             JsonObject properties = processTraffic.getProperties();
             if (properties != null) {
diff --git a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetadataQueryDAO.java b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetadataQueryDAO.java
index 671e391ebc..619959aced 100644
--- a/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetadataQueryDAO.java
+++ b/oap-server/server-storage-plugin/storage-jdbc-hikaricp-plugin/src/main/java/org/apache/skywalking/oap/server/storage/plugin/jdbc/h2/dao/H2MetadataQueryDAO.java
@@ -185,6 +185,101 @@ public class H2MetadataQueryDAO implements IMetadataQueryDAO {
         return endpoints;
     }
 
+    @Override
+    public List<Process> listProcesses(String serviceId, ProfilingSupportStatus supportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
+        StringBuilder sql = new StringBuilder();
+        List<Object> condition = new ArrayList<>();
+        sql.append("select * from ").append(ProcessTraffic.INDEX_NAME);
+        appendProcessWhereQuery(sql, condition, serviceId, null, null, supportStatus, lastPingStartTimeBucket, lastPingEndTimeBucket);
+        sql.append(" limit ").append(metadataQueryMaxSize);
+
+        try (Connection connection = h2Client.getConnection()) {
+            try (ResultSet resultSet = h2Client.executeQuery(
+                connection, sql.toString(), condition.toArray(new Object[0]))) {
+                return buildProcesses(resultSet);
+            }
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+
+    @Override
+    public List<Process> listProcesses(String serviceInstanceId, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
+        StringBuilder sql = new StringBuilder();
+        List<Object> condition = new ArrayList<>();
+        sql.append("select * from ").append(ProcessTraffic.INDEX_NAME);
+        appendProcessWhereQuery(sql, condition, null, serviceInstanceId, null, null, lastPingStartTimeBucket, lastPingEndTimeBucket);
+        sql.append(" limit ").append(metadataQueryMaxSize);
+
+        try (Connection connection = h2Client.getConnection()) {
+            try (ResultSet resultSet = h2Client.executeQuery(
+                connection, sql.toString(), condition.toArray(new Object[0]))) {
+                return buildProcesses(resultSet);
+            }
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+
+    @Override
+    public List<Process> listProcesses(String agentId) throws IOException {
+        StringBuilder sql = new StringBuilder();
+        List<Object> condition = new ArrayList<>(2);
+        sql.append("select * from ").append(ProcessTraffic.INDEX_NAME);
+        appendProcessWhereQuery(sql, condition, null, null, agentId, null, 0, 0);
+        sql.append(" limit ").append(metadataQueryMaxSize);
+
+        try (Connection connection = h2Client.getConnection()) {
+            try (ResultSet resultSet = h2Client.executeQuery(
+                connection, sql.toString(), condition.toArray(new Object[0]))) {
+                return buildProcesses(resultSet);
+            }
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+
+    @Override
+    public long getProcessCount(String serviceId, ProfilingSupportStatus profilingSupportStatus, long lastPingStartTimeBucket, long lastPingEndTimeBucket) throws IOException {
+        StringBuilder sql = new StringBuilder();
+        List<Object> condition = new ArrayList<>(5);
+        sql.append("select count(1) total from ").append(ProcessTraffic.INDEX_NAME);
+        appendProcessWhereQuery(sql, condition, serviceId, null, null, profilingSupportStatus,
+            lastPingStartTimeBucket, lastPingEndTimeBucket);
+
+        try (Connection connection = h2Client.getConnection()) {
+            try (ResultSet resultSet = h2Client.executeQuery(
+                connection, sql.toString(), condition.toArray(new Object[0]))) {
+                if (!resultSet.next()) {
+                    return 0;
+                }
+                return resultSet.getLong("total");
+            }
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+
+    @Override
+    public long getProcessCount(String instanceId) throws IOException {
+        StringBuilder sql = new StringBuilder();
+        List<Object> condition = new ArrayList<>(3);
+        sql.append("select count(1) total from ").append(ProcessTraffic.INDEX_NAME);
+        appendProcessWhereQuery(sql, condition, null, instanceId, null, null, 0, 0);
+
+        try (Connection connection = h2Client.getConnection()) {
+            try (ResultSet resultSet = h2Client.executeQuery(
+                connection, sql.toString(), condition.toArray(new Object[0]))) {
+                if (!resultSet.next()) {
+                    return 0;
+                }
+                return resultSet.getLong("total");
+            }
+        } catch (SQLException e) {
+            throw new IOException(e);
+        }
+    }
+
     private List<Service> buildServices(ResultSet resultSet) throws SQLException {
         List<Service> services = new ArrayList<>();
         while (resultSet.next()) {
@@ -231,48 +326,6 @@ public class H2MetadataQueryDAO implements IMetadataQueryDAO {
         return serviceInstances;
     }
 
-    @Override
-    public List<Process> listProcesses(String serviceId, String instanceId, String agentId, final ProfilingSupportStatus profilingSupportStatus,
-                                       final long lastPingStartTimeBucket, final long lastPingEndTimeBucket) throws IOException {
-        StringBuilder sql = new StringBuilder();
-        List<Object> condition = new ArrayList<>(3);
-        sql.append("select * from ").append(ProcessTraffic.INDEX_NAME);
-        appendProcessWhereQuery(sql, condition, serviceId, instanceId, agentId, profilingSupportStatus,
-                lastPingStartTimeBucket, lastPingEndTimeBucket);
-        sql.append(" limit ").append(metadataQueryMaxSize);
-
-        try (Connection connection = h2Client.getConnection()) {
-            try (ResultSet resultSet = h2Client.executeQuery(
-                    connection, sql.toString(), condition.toArray(new Object[0]))) {
-                return buildProcesses(resultSet);
-            }
-        } catch (SQLException e) {
-            throw new IOException(e);
-        }
-    }
-
-    @Override
-    public long getProcessesCount(String serviceId, String instanceId, String agentId, final ProfilingSupportStatus profilingSupportStatus,
-                                  final long lastPingStartTimeBucket, final long lastPingEndTimeBucket) throws IOException {
-        StringBuilder sql = new StringBuilder();
-        List<Object> condition = new ArrayList<>(3);
-        sql.append("select count(1) total from ").append(ProcessTraffic.INDEX_NAME);
-        appendProcessWhereQuery(sql, condition, serviceId, instanceId, agentId, profilingSupportStatus,
-                lastPingStartTimeBucket, lastPingEndTimeBucket);
-
-        try (Connection connection = h2Client.getConnection()) {
-            try (ResultSet resultSet = h2Client.executeQuery(
-                    connection, sql.toString(), condition.toArray(new Object[0]))) {
-                if (!resultSet.next()) {
-                    return 0;
-                }
-                return resultSet.getLong("total");
-            }
-        } catch (SQLException e) {
-            throw new IOException(e);
-        }
-    }
-
     private void appendProcessWhereQuery(StringBuilder sql, List<Object> condition, String serviceId, String instanceId,
                                          String agentId, final ProfilingSupportStatus profilingSupportStatus,
                                          final long lastPingStartTimeBucket, final long lastPingEndTimeBucket) {
@@ -361,6 +414,7 @@ public class H2MetadataQueryDAO implements IMetadataQueryDAO {
             process.setInstanceName(instanceIDDefinition.getName());
             process.setAgentId(resultSet.getString(ProcessTraffic.AGENT_ID));
             process.setDetectType(ProcessDetectType.valueOf(resultSet.getInt(ProcessTraffic.DETECT_TYPE)).name());
+            process.setProfilingSupportStatus(ProfilingSupportStatus.valueOf(resultSet.getInt(ProcessTraffic.PROFILING_SUPPORT_STATUS)).name());
             String propertiesString = resultSet.getString(ProcessTraffic.PROPERTIES);
             if (!Strings.isNullOrEmpty(propertiesString)) {
                 JsonObject properties = GSON.fromJson(propertiesString, JsonObject.class);
diff --git a/test/e2e-v2/cases/kafka/log/expected/logs-filebeat.yml b/test/e2e-v2/cases/kafka/log/expected/logs-filebeat.yml
index 1ca69d9dab..277029d597 100644
--- a/test/e2e-v2/cases/kafka/log/expected/logs-filebeat.yml
+++ b/test/e2e-v2/cases/kafka/log/expected/logs-filebeat.yml
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+errorreason: null
 logs:
 {{- contains .logs }}
 - servicename: e2e-service-provider
diff --git a/test/e2e-v2/cases/kafka/log/expected/logs-fluentd.yml b/test/e2e-v2/cases/kafka/log/expected/logs-fluentd.yml
index 51d896c408..de22a8a03b 100644
--- a/test/e2e-v2/cases/kafka/log/expected/logs-fluentd.yml
+++ b/test/e2e-v2/cases/kafka/log/expected/logs-fluentd.yml
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+errorreason: null
 logs:
 {{- contains .logs }}
 - servicename: e2e-service-provider
diff --git a/test/e2e-v2/cases/log/expected/logs.yml b/test/e2e-v2/cases/log/expected/logs.yml
index 30f1a86014..43897b6a68 100644
--- a/test/e2e-v2/cases/log/expected/logs.yml
+++ b/test/e2e-v2/cases/log/expected/logs.yml
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+errorreason: null
 logs:
 {{- contains .logs }}
 - servicename: e2e-service-provider
diff --git a/test/e2e-v2/cases/profiling/ebpf/network/e2e.yaml b/test/e2e-v2/cases/profiling/ebpf/network/e2e.yaml
new file mode 100644
index 0000000000..2eed39d541
--- /dev/null
+++ b/test/e2e-v2/cases/profiling/ebpf/network/e2e.yaml
@@ -0,0 +1,184 @@
+# 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.
+
+# This file is used to show how to write configuration files and can be used to test.
+
+setup:
+  env: kind
+  file: kind.yaml
+  init-system-environment: ../../../../script/env
+  kind:
+    import-images:
+      - skywalking/ui:latest
+      - skywalking/oap:latest
+    expose-ports:
+      - namespace: istio-system
+        resource: service/skywalking-ui
+        port: 80
+  steps:
+    - name: set PATH
+      command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
+    - name: install yq
+      command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
+    - name: install swctl
+      command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
+    - name: install kubectl
+      command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh kubectl
+    - name: install istio
+      command: |
+        bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh istioctl
+        istioctl install -y --set profile=demo
+        kubectl label namespace default istio-injection=enabled
+    - name: Install helm
+      command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh helm
+    - name: Install kubectl
+      command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh kubectl
+    - name: Install SkyWalking
+      command: |
+        rm -rf skywalking-kubernetes && git clone https://github.com/apache/skywalking-kubernetes.git
+        cd skywalking-kubernetes
+        cd chart
+        helm dep up skywalking
+        helm -n istio-system install skywalking skywalking \
+                       --set fullnameOverride=skywalking \
+                       --set elasticsearch.replicas=1 \
+                       --set elasticsearch.minimumMasterNodes=1 \
+                       --set elasticsearch.imageTag=7.5.1 \
+                       --set oap.env.SW_METER_ANALYZER_ACTIVE_FILES='network-profiling' \
+                       --set oap.envoy.als.enabled=true \
+                       --set oap.replicas=1 \
+                       --set ui.image.repository=skywalking/ui \
+                       --set ui.image.tag=latest \
+                       --set oap.image.tag=latest \
+                       --set oap.image.repository=skywalking/oap \
+                       --set oap.storageType=elasticsearch
+      wait:
+        - namespace: istio-system
+          resource: deployments/skywalking-oap
+          for: condition=available
+    - name: Deploy demo services
+      command: |
+        kubectl apply -f https://raw.githubusercontent.com/istio/istio/$ISTIO_VERSION/samples/bookinfo/platform/kube/bookinfo.yaml
+        kubectl apply -f https://raw.githubusercontent.com/istio/istio/$ISTIO_VERSION/samples/bookinfo/networking/bookinfo-gateway.yaml
+        kubectl apply -f https://raw.githubusercontent.com/istio/istio/$ISTIO_VERSION/samples/bookinfo/networking/destination-rule-all.yaml
+        kubectl apply -f https://raw.githubusercontent.com/istio/istio/$ISTIO_VERSION/samples/bookinfo/networking/virtual-service-all-v1.yaml
+      wait:
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+    - name: Install SkyWalking Rover
+      command: |
+        envsubst < test/e2e-v2/cases/profiling/ebpf/network/rover.yaml | kubectl apply -f -
+      wait:
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+    - name: Generate traffic
+      path: traffic-gen.yaml
+      wait:
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+  timeout: 25m
+
+verify:
+  retry:
+    count: 20
+    interval: 10s
+  cases:
+    # service list
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql service ls
+      expected: expected/service.yml
+    # service instance list
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=default::productpage
+      expected: expected/service-instance.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql process list --service-name=default::productpage --instance-name=productpage
+      expected: expected/process.yml
+
+    # create network profiling task
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql profiling ebpf create network --service-name=default::productpage --instance-name=productpage
+      expected: expected/profiling-create.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql dep process --service-name default::productpage --instance-name=productpage
+      expected: expected/dependency-processs.yml
+
+    # single value of process relation, client/server side read/write
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name process_relation_client_write_cpm|yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name process_relation_client_write_total_bytes|yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name process_relation_client_write_avg_exe_time|yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name process_relation_client_read_cpm|yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name process_relation_server_write_cpm|yq e 'to_entries' -
+      expected: expected/metrics-has-value.yml
+
+    # histogram value of process relation, client side write_rtt/write_exe/read time
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics multiple-linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name=process_relation_client_write_rtt_time_percentile|yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+      expected: expected/metrics-has-value-label.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics multiple-linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name=process_relation_client_write_exe_time_percentile|yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+      expected: expected/metrics-has-value-label.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics multiple-linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name=process_relation_client_read_exe_time_percentile|yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+      expected: expected/metrics-has-value-label.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics multiple-linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name=process_relation_server_write_rtt_time_percentile|yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+      expected: expected/metrics-has-value-label.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics multiple-linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name=process_relation_server_write_exe_time_percentile|yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+      expected: expected/metrics-has-value-label.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics multiple-linear \
+        --service-name default::productpage --instance-name productpage --process-name envoy \
+        --dest-service-name default::productpage --dest-instance-name productpage --dest-process-name /usr/local/bin/python \
+        --name=process_relation_server_write_exe_time_percentile|yq e 'to_entries | with(.[] ; .value=(.value | to_entries))' -
+      expected: expected/metrics-has-value-label.yml
diff --git a/test/e2e-v2/cases/profiling/ebpf/network/expected/dependency-processs.yml b/test/e2e-v2/cases/profiling/ebpf/network/expected/dependency-processs.yml
new file mode 100644
index 0000000000..6f27cef41c
--- /dev/null
+++ b/test/e2e-v2/cases/profiling/ebpf/network/expected/dependency-processs.yml
@@ -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.
+
+{{- define "genProcessId" }}
+{{- with $processName := . }}
+{{- with $serviceId := "default::productpage" | b64enc | printf "%s.1" }}
+{{- with $instanceId := "productpage" | b64enc | printf "%s_%s" $serviceId }}
+{{- printf "%s" (sha256enc (printf "%s_%s" $processName $instanceId)) }}
+{{- end }}
+{{- end }}
+{{- end }}
+{{- end}}
+
+nodes:
+{{- contains .nodes }}
+- id: {{template "genProcessId" "/usr/local/bin/python"}}
+  name: /usr/local/bin/python
+  serviceid: {{ b64enc "default::productpage" }}.1
+  servicename: default::productpage
+  serviceinstanceid: {{ b64enc "default::productpage" }}.1_{{ b64enc "productpage" }}
+  serviceinstancename: productpage
+  isreal: true
+- id: {{template "genProcessId" "envoy"}}
+  name: envoy
+  serviceid: {{ b64enc "default::productpage" }}.1
+  servicename: default::productpage
+  serviceinstanceid: {{ b64enc "default::productpage" }}.1_{{ b64enc "productpage" }}
+  serviceinstancename: productpage
+  isreal: true
+{{- end }}
+calls:
+{{- contains .calls }}
+- source: {{template "genProcessId" "/usr/local/bin/python"}}
+  sourcecomponents: []
+  target: {{template "genProcessId" "envoy"}}
+  targetcomponents: []
+  id: {{template "genProcessId" "/usr/local/bin/python"}}-{{template "genProcessId" "envoy"}}
+  detectpoints:
+    - CLIENT
+    - SERVER
+- source: {{template "genProcessId" "envoy"}}
+  sourcecomponents: []
+  target: {{template "genProcessId" "/usr/local/bin/python"}}
+  targetcomponents: []
+  id: {{template "genProcessId" "envoy"}}-{{template "genProcessId" "/usr/local/bin/python"}}
+  detectpoints:
+    - CLIENT
+    - SERVER
+{{- end }}
\ No newline at end of file
diff --git a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/network/expected/metrics-has-value-label.yml
similarity index 69%
copy from test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
copy to test/e2e-v2/cases/profiling/ebpf/network/expected/metrics-has-value-label.yml
index f561c46ca7..a4becdf89c 100644
--- a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/network/expected/metrics-has-value-label.yml
@@ -14,17 +14,10 @@
 # limitations under the License.
 
 {{- contains . }}
-- taskid: {{ notEmpty .taskid }}
-  serviceid: {{ b64enc "sqrt" }}.1
-  servicename: sqrt
-  processlabels:
-    {{- contains .processlabels }}
-    - e2e-label1
-    - e2e-label2
-    {{- end }}
-  taskstarttime: {{ gt .taskstarttime 0 }}
-  triggertype: FIXED_TIME
-  fixedtriggerduration: 60
-  targettype: ON_CPU
-  createtime: {{ gt .createtime 0 }}
-{{- end }}
\ No newline at end of file
+- key: {{ notEmpty .key }}
+  value:
+  {{- contains .value }}
+  - key: {{ notEmpty .key }}
+    value: {{ ge .value 1 }}
+  {{- end }}
+{{- end }}
diff --git a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/network/expected/metrics-has-value.yml
similarity index 69%
copy from test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
copy to test/e2e-v2/cases/profiling/ebpf/network/expected/metrics-has-value.yml
index f561c46ca7..d9c49854c9 100644
--- a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/network/expected/metrics-has-value.yml
@@ -14,17 +14,6 @@
 # limitations under the License.
 
 {{- contains . }}
-- taskid: {{ notEmpty .taskid }}
-  serviceid: {{ b64enc "sqrt" }}.1
-  servicename: sqrt
-  processlabels:
-    {{- contains .processlabels }}
-    - e2e-label1
-    - e2e-label2
-    {{- end }}
-  taskstarttime: {{ gt .taskstarttime 0 }}
-  triggertype: FIXED_TIME
-  fixedtriggerduration: 60
-  targettype: ON_CPU
-  createtime: {{ gt .createtime 0 }}
+- key: {{ notEmpty .key }}
+  value: {{ ge .value 1 }}
 {{- end }}
\ No newline at end of file
diff --git a/test/e2e-v2/cases/profiling/ebpf/network/expected/process.yml b/test/e2e-v2/cases/profiling/ebpf/network/expected/process.yml
new file mode 100644
index 0000000000..498938be5f
--- /dev/null
+++ b/test/e2e-v2/cases/profiling/ebpf/network/expected/process.yml
@@ -0,0 +1,86 @@
+# 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.
+
+{{- contains . }}
+- id: {{ notEmpty .id }}
+  name: /usr/local/bin/python
+  serviceid: {{ b64enc "default::productpage" }}.1
+  servicename: default::productpage
+  instanceid: {{ b64enc "default::productpage" }}.1_{{ b64enc "productpage" }}
+  instancename: productpage
+  agentid: {{ notEmpty .agentid }}
+  detecttype: KUBERNETES
+  attributes:
+    {{- contains .attributes }}
+    - name: host_ip
+      value: {{ notEmpty .value }}
+    - name: container_ip
+      value: {{ notEmpty .value }}
+    - name: pid
+      value: {{ notEmpty .value }}
+    - name: command_line
+      value: {{ notEmpty .value }}
+    - name: support_ebpf_profiling
+      value: "false"
+    {{- end }}
+  labels:
+    - mesh-application
+- id: {{ notEmpty .id }}
+  name: envoy
+  serviceid: {{ b64enc "default::productpage" }}.1
+  servicename: default::productpage
+  instanceid: {{ b64enc "default::productpage" }}.1_{{ b64enc "productpage" }}
+  instancename: productpage
+  agentid: {{ notEmpty .agentid }}
+  detecttype: KUBERNETES
+  attributes:
+    {{- contains .attributes }}
+    - name: host_ip
+      value: {{ notEmpty .value }}
+    - name: container_ip
+      value: {{ notEmpty .value }}
+    - name: pid
+      value: {{ notEmpty .value }}
+    - name: command_line
+      value: {{ notEmpty .value }}
+    - name: support_ebpf_profiling
+      value: true
+    {{- end }}
+  labels:
+    - mesh-envoy
+- id: {{ notEmpty .id }}
+  name: pilot-agent
+  serviceid: {{ b64enc "default::productpage" }}.1
+  servicename: default::productpage
+  instanceid: {{ b64enc "default::productpage" }}.1_{{ b64enc "productpage" }}
+  instancename: productpage
+  agentid: {{ notEmpty .agentid }}
+  detecttype: KUBERNETES
+  attributes:
+    {{- contains .attributes }}
+    - name: host_ip
+      value: {{ notEmpty .value }}
+    - name: container_ip
+      value: {{ notEmpty .value }}
+    - name: pid
+      value: {{ notEmpty .value }}
+    - name: command_line
+      value: {{ notEmpty .value }}
+    - name: support_ebpf_profiling
+      value: "false"
+    {{- end }}
+  labels:
+    - mesh-envoy
+{{- end }}
diff --git a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/network/expected/profiling-create.yml
similarity index 67%
copy from test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
copy to test/e2e-v2/cases/profiling/ebpf/network/expected/profiling-create.yml
index f561c46ca7..176b195aee 100644
--- a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/network/expected/profiling-create.yml
@@ -13,18 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-{{- contains . }}
-- taskid: {{ notEmpty .taskid }}
-  serviceid: {{ b64enc "sqrt" }}.1
-  servicename: sqrt
-  processlabels:
-    {{- contains .processlabels }}
-    - e2e-label1
-    - e2e-label2
-    {{- end }}
-  taskstarttime: {{ gt .taskstarttime 0 }}
-  triggertype: FIXED_TIME
-  fixedtriggerduration: 60
-  targettype: ON_CPU
-  createtime: {{ gt .createtime 0 }}
-{{- end }}
\ No newline at end of file
+status: true
+errorreason: null
+id: {{ notEmpty .id }}
\ No newline at end of file
diff --git a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/network/expected/service-instance.yml
similarity index 69%
copy from test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
copy to test/e2e-v2/cases/profiling/ebpf/network/expected/service-instance.yml
index f561c46ca7..45640d753d 100644
--- a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/network/expected/service-instance.yml
@@ -14,17 +14,9 @@
 # limitations under the License.
 
 {{- contains . }}
-- taskid: {{ notEmpty .taskid }}
-  serviceid: {{ b64enc "sqrt" }}.1
-  servicename: sqrt
-  processlabels:
-    {{- contains .processlabels }}
-    - e2e-label1
-    - e2e-label2
-    {{- end }}
-  taskstarttime: {{ gt .taskstarttime 0 }}
-  triggertype: FIXED_TIME
-  fixedtriggerduration: 60
-  targettype: ON_CPU
-  createtime: {{ gt .createtime 0 }}
-{{- end }}
\ No newline at end of file
+- id: {{ b64enc "default::productpage" }}.1_{{ b64enc "productpage" }}
+  name: productpage
+  attributes: []
+  language: UNKNOWN
+  instanceuuid: {{ b64enc "default::productpage" }}.1_{{ b64enc "productpage" }}
+{{- end }}
diff --git a/test/e2e-v2/cases/profiling/ebpf/network/expected/service.yml b/test/e2e-v2/cases/profiling/ebpf/network/expected/service.yml
new file mode 100644
index 0000000000..40bbced17c
--- /dev/null
+++ b/test/e2e-v2/cases/profiling/ebpf/network/expected/service.yml
@@ -0,0 +1,71 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{{- contains . }}
+- id: {{ b64enc "default::details" }}.1
+  name: default::details
+  group: default
+  shortname: details
+  layers:
+    {{- contains .layers }}
+    - MESH_DP
+    - MESH
+    {{- end }}
+  normal: true
+- id: {{ b64enc "istio-system::istio-ingressgateway" }}.1
+  name: istio-system::istio-ingressgateway
+  group: istio-system
+  shortname: istio-ingressgateway
+  layers:
+    - MESH_DP
+  normal: true
+- id: {{ b64enc "default::productpage" }}.1
+  name: default::productpage
+  group: default
+  shortname: productpage
+  layers:
+    {{- contains .layers }}
+    - MESH_DP
+    - MESH
+    {{- end }}
+  normal: true
+- id: {{ b64enc "default::ratings" }}.1
+  name: default::ratings
+  group: default
+  shortname: ratings
+  layers:
+    {{- contains .layers }}
+    - MESH_DP
+    - MESH
+    {{- end }}
+  normal: true
+- id: {{ b64enc "default::reviews" }}.1
+  name: default::reviews
+  group: default
+  shortname: reviews
+  layers:
+    {{- contains .layers }}
+    - MESH_DP
+    - MESH
+    {{- end }}
+  normal: true
+- id: {{ b64enc "istio-system::istio-egressgateway" }}.1
+  name: istio-system::istio-egressgateway
+  group: istio-system
+  shortname: istio-egressgateway
+  layers:
+    - MESH_DP
+  normal: true
+{{- end }}
\ No newline at end of file
diff --git a/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/network/kind.yaml
similarity index 58%
copy from test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml
copy to test/e2e-v2/cases/profiling/ebpf/network/kind.yaml
index a4d2edbc2e..f9ba27eaec 100644
--- a/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/network/kind.yaml
@@ -13,18 +13,26 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-  {{- contains . }}
-- taskid: {{ notEmpty .taskid }}
-  serviceid: {{ b64enc "file" }}.1
-  servicename: file
-  processlabels:
-    {{- contains .processlabels }}
-    - e2e-label1
-    - e2e-label2
-    {{- end }}
-  taskstarttime: {{ gt .taskstarttime 0 }}
-  triggertype: FIXED_TIME
-  fixedtriggerduration: 60
-  targettype: OFF_CPU
-  createtime: {{ gt .createtime 0 }}
-  {{- end }}
\ No newline at end of file
+# this config file contains all config fields with comments
+# NOTE: this is not a particularly useful config file
+kind: Cluster
+apiVersion: kind.x-k8s.io/v1alpha4
+nodes:
+  # the control plane node config
+  - role: control-plane
+    extraMounts:
+      - hostPath: /
+        containerPath: /host
+  # the three workers
+  - role: worker
+    extraMounts:
+      - hostPath: /
+        containerPath: /host
+  - role: worker
+    extraMounts:
+      - hostPath: /
+        containerPath: /host
+  - role: worker
+    extraMounts:
+      - hostPath: /
+        containerPath: /host
diff --git a/test/e2e-v2/cases/rover/process/istio/rover.yaml b/test/e2e-v2/cases/profiling/ebpf/network/rover.yaml
similarity index 78%
copy from test/e2e-v2/cases/rover/process/istio/rover.yaml
copy to test/e2e-v2/cases/profiling/ebpf/network/rover.yaml
index b064754824..5f726f5887 100644
--- a/test/e2e-v2/cases/rover/process/istio/rover.yaml
+++ b/test/e2e-v2/cases/profiling/ebpf/network/rover.yaml
@@ -60,6 +60,7 @@ spec:
         - name: skywalking-rover
           # SkyWalking Rover image path
           image: ghcr.io/apache/skywalking-rover/skywalking-rover:$SW_ROVER_COMMIT
+          imagePullPolicy: Always
           securityContext:
             capabilities:
               add:
@@ -82,11 +83,21 @@ spec:
               value: skywalking-oap.istio-system:11800
             - name: ROVER_PROCESS_DISCOVERY_KUBERNETES_ANALYZER_K8S_SERVICE_ACTIVE
               value: "false"
+            - name: ROVER_HOST_MAPPING
+              value: /host
+            - name: ROVER_LOGGER_LEVEL
+              value: DEBUG
+            - name: ROVER_PROCESS_DISCOVERY_KUBERNETES_ANALYZER_ISTIO_APPLICATION_PROCESS_NAME
+              value: "{{.Process.ExeNameInCommandLine}}"
+            - name: ROVER_PROCESS_DISCOVERY_KUBERNETES_ANALYZER_ISTIO_ENVOY_INSTANCE_NAME
+              value: "{{.Pod.LabelValue \"service.istio.io/canonical-name,app.kubernetes.io/name,app\" }}"
+            - name: ROVER_PROCESS_DISCOVERY_KUBERNETES_ANALYZER_ISTIO_APPLICATION_INSTANCE_NAME
+              value: "{{.Pod.LabelValue \"service.istio.io/canonical-name,app.kubernetes.io/name,app\" }}"
       hostPID: true
       hostNetwork: true
       dnsPolicy: ClusterFirstWithHostNet
       volumes:
         - name: host
           hostPath:
-            path: /
+            path: /host
             type: Directory
\ No newline at end of file
diff --git a/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/network/traffic-gen.yaml
similarity index 57%
copy from test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml
copy to test/e2e-v2/cases/profiling/ebpf/network/traffic-gen.yaml
index a4d2edbc2e..73853c7418 100644
--- a/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/network/traffic-gen.yaml
@@ -13,18 +13,28 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-  {{- contains . }}
-- taskid: {{ notEmpty .taskid }}
-  serviceid: {{ b64enc "file" }}.1
-  servicename: file
-  processlabels:
-    {{- contains .processlabels }}
-    - e2e-label1
-    - e2e-label2
-    {{- end }}
-  taskstarttime: {{ gt .taskstarttime 0 }}
-  triggertype: FIXED_TIME
-  fixedtriggerduration: 60
-  targettype: OFF_CPU
-  createtime: {{ gt .createtime 0 }}
-  {{- end }}
\ No newline at end of file
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: trafficgenerator
+  labels:
+    app: trafficgenerator
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: trafficgenerator
+  template:
+    metadata:
+      annotations:
+        sidecar.istio.io/inject: "false"
+      labels:
+        app: trafficgenerator
+    spec:
+      containers:
+        - name: trafficgenerator
+          image: williamyeh/wrk
+          command: ["wrk", "-t1", "-c1", "-d2000m", "http://istio-ingressgateway.istio-system:80/productpage"]
+          resources:
+            requests:
+              cpu: 0.1
\ No newline at end of file
diff --git a/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml
index a4d2edbc2e..50eeab15dd 100644
--- a/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/offcpu/expected/profiling-task-list.yml
@@ -17,6 +17,8 @@
 - taskid: {{ notEmpty .taskid }}
   serviceid: {{ b64enc "file" }}.1
   servicename: file
+  serviceinstanceid: null
+  serviceinstancename: null
   processlabels:
     {{- contains .processlabels }}
     - e2e-label1
diff --git a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml b/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
index f561c46ca7..faa04bc518 100644
--- a/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
+++ b/test/e2e-v2/cases/profiling/ebpf/oncpu/expected/profiling-task-list.yml
@@ -17,6 +17,8 @@
 - taskid: {{ notEmpty .taskid }}
   serviceid: {{ b64enc "sqrt" }}.1
   servicename: sqrt
+  serviceinstanceid: null
+  serviceinstancename: null
   processlabels:
     {{- contains .processlabels }}
     - e2e-label1
diff --git a/test/e2e-v2/cases/rover/process/istio/rover.yaml b/test/e2e-v2/cases/rover/process/istio/rover.yaml
index b064754824..0d2d9cdbf2 100644
--- a/test/e2e-v2/cases/rover/process/istio/rover.yaml
+++ b/test/e2e-v2/cases/rover/process/istio/rover.yaml
@@ -60,6 +60,7 @@ spec:
         - name: skywalking-rover
           # SkyWalking Rover image path
           image: ghcr.io/apache/skywalking-rover/skywalking-rover:$SW_ROVER_COMMIT
+          imagePullPolicy: Always
           securityContext:
             capabilities:
               add:
diff --git a/test/e2e-v2/cases/satellite/native-protocols/expected/logs-list.yml b/test/e2e-v2/cases/satellite/native-protocols/expected/logs-list.yml
index 967db0440a..4f95dd50f3 100644
--- a/test/e2e-v2/cases/satellite/native-protocols/expected/logs-list.yml
+++ b/test/e2e-v2/cases/satellite/native-protocols/expected/logs-list.yml
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+errorreason: null
 logs:
 {{- contains .logs }}
   - servicename: e2e-service-provider
diff --git a/test/e2e-v2/script/env b/test/e2e-v2/script/env
index 7f89dd5ea0..1d192eb4ba 100644
--- a/test/e2e-v2/script/env
+++ b/test/e2e-v2/script/env
@@ -22,7 +22,7 @@ SW_AGENT_PYTHON_COMMIT=c76a6ec51a478ac91abb20ec8f22a99b8d4d6a58
 SW_AGENT_CLIENT_JS_COMMIT=af0565a67d382b683c1dbd94c379b7080db61449
 SW_AGENT_CLIENT_JS_TEST_COMMIT=4f1eb1dcdbde3ec4a38534bf01dded4ab5d2f016
 SW_KUBERNETES_COMMIT_SHA=0f3ec68e5a7e1608cec8688716b848ed15e971e5
-SW_ROVER_COMMIT=3fd84981b9d0229da09090e517592e61a89ae3fe
+SW_ROVER_COMMIT=96bfd2a51e582f34ccbbedfd4bceb7407559de2a
 SW_BANYANDB_COMMIT=5a326d7e36a008c5ea10e3ae506309cb29733c53
 
-SW_CTL_COMMIT=bdcba1c93b1ad702a88f30b798df5e99d963689d
+SW_CTL_COMMIT=a73f65367b335e08412c0471e85ad8f15e92d411