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 2025/05/22 05:51:35 UTC

(skywalking) branch master updated: Add Ambient Mesh E2E (#13255)

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 5622cb9f71 Add Ambient Mesh E2E (#13255)
5622cb9f71 is described below

commit 5622cb9f71a30fbe25af2b3c8782a8615df6e029
Author: mrproliu <74...@qq.com>
AuthorDate: Thu May 22 13:51:28 2025 +0800

    Add Ambient Mesh E2E (#13255)
---
 .github/workflows/skywalking.yaml                  |  66 +++++-
 apm-protocol/apm-network/src/main/proto            |   2 +-
 docs/en/changes/changes.md                         |   1 +
 .../skywalking-ebpf-receiver-plugin/pom.xml        |   7 +-
 .../provider/handler/AccessLogServiceHandler.java  | 179 ++++++++++++++++-
 .../src/main/resources/component-libraries.yml     |   1 +
 test/e2e-v2/cases/cilium/traffic-gen.yaml          |   2 +-
 test/e2e-v2/cases/istio/ambient-als/e2e.yaml       | 222 +++++++++++++++++++++
 .../expected/dependency-global-mesh.yml            | 104 ++++++++++
 .../dependency-services-instance-productpage.yml}  |  30 ++-
 .../expected/metrics-has-value.yml}                |  24 ++-
 .../expected/service-endpoint-productpage.yml}     |   9 +-
 .../expected/service-endpoint-reviews.yml}         |   9 +-
 .../expected/service-instance.yml}                 |  12 +-
 .../cases/istio/ambient-als/expected/service.yml   |  64 ++++++
 .../{cilium => istio/ambient-als}/traffic-gen.yaml |   4 +-
 test/e2e-v2/cases/istio/kind.k25.yaml              |   3 +
 test/e2e-v2/cases/istio/kind.k28.yaml              |   3 +
 test/e2e-v2/cases/istio/values.yaml                |  19 ++
 test/e2e-v2/cases/php/e2e.yaml                     |   4 +-
 .../profiling/ebpf/access_log/traffic-gen.yaml     |   2 +-
 .../profiling/ebpf/continuous/postgres/e2e.yaml    |  85 ++++++++
 test/e2e-v2/cases/storage/banyandb/stages/e2e.yaml |   2 +-
 test/e2e-v2/script/env                             |   2 +-
 24 files changed, 811 insertions(+), 45 deletions(-)

diff --git a/.github/workflows/skywalking.yaml b/.github/workflows/skywalking.yaml
index 599d547c4a..1bde7c328a 100644
--- a/.github/workflows/skywalking.yaml
+++ b/.github/workflows/skywalking.yaml
@@ -826,7 +826,7 @@ jobs:
           KUBERNETES_VERSION: ${{ matrix.versions.kubernetes }}
           ALS_ANALYZER: ${{ matrix.analyzer }}
         with:
-          e2e-file: $GITHUB_WORKSPACE/test/e2e-v2/cases/istio/als/e2e.yaml
+          e2e-file: test/e2e-v2/cases/istio/als/e2e.yaml
       - if: ${{ failure() }}
         run: |
           df -h
@@ -839,6 +839,67 @@ jobs:
           name: test-logs-${{ matrix.test.name }}
           path: "${{ env.SW_INFRA_E2E_LOG_DIR }}"
 
+  e2e-test-istio-ambient:
+    if: |
+      ( always() && ! cancelled() ) &&
+      ((github.event_name == 'schedule' && github.repository == 'apache/skywalking') || needs.changes.outputs.oap == 'true')
+    name: E2E test
+    needs: [docker]
+    runs-on: ubuntu-24.04
+    timeout-minutes: 60
+    strategy:
+      fail-fast: false
+      matrix:
+        analyzer: [k8s-mesh, mx-mesh]
+        versions:
+          - istio: 1.23.0
+            kubernetes: 28
+          - istio: 1.24.0
+            kubernetes: 28
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          submodules: true
+          persist-credentials: false
+      - run: grep -v '^#' test/e2e-v2/script/env >> "$GITHUB_ENV"
+      - uses: apache/skywalking-cli/actions/setup@master
+        with:
+          version: ${{ env.SW_CTL_COMMIT }}
+      - uses: actions/download-artifact@v4
+        name: Download docker images
+        with:
+          name: docker-images-11
+          path: docker-images
+      - name: Load docker images
+        run: |
+          find docker-images -name "*.tar" -exec docker load -i {} \;
+          find docker-images -name "*.tar" -exec rm {} \;
+      - name: Login to ghcr
+        uses: docker/login-action@v3
+        with:
+          registry: ghcr.io
+          username: ${{ github.repository_owner }}
+          password: ${{ secrets.GITHUB_TOKEN }}
+      - name: ${{ matrix.test.name }}
+        uses: apache/skywalking-infra-e2e@cf589b4a0b9f8e6f436f78e9cfd94a1ee5494180
+        env:
+          ISTIO_VERSION: ${{ matrix.versions.istio }}
+          KUBERNETES_VERSION: ${{ matrix.versions.kubernetes }}
+          ALS_ANALYZER: ${{ matrix.analyzer }}
+        with:
+          e2e-file: test/e2e-v2/cases/istio/ambient-als/e2e.yaml
+      - if: ${{ failure() }}
+        run: |
+          df -h
+          du -sh .
+          docker images
+      - uses: actions/upload-artifact@v4
+        if: ${{ failure() }}
+        name: Upload Logs
+        with:
+          name: test-istio-ambient-logs-${{ matrix.versions.istio }}-${{ matrix.versions.kubernetes }}-${{ matrix.analyzer }}
+          path: "${{ env.SW_INFRA_E2E_LOG_DIR }}"
+
   e2e-test-java-versions:
     if: |
       ( always() && ! cancelled() ) &&
@@ -1004,6 +1065,7 @@ jobs:
       - slow-integration-test
       - e2e-test
       - e2e-test-istio
+      - e2e-test-istio-ambient
       - e2e-test-java-versions
     runs-on: ubuntu-latest
     timeout-minutes: 10
@@ -1023,6 +1085,7 @@ jobs:
           timeConsumingITResults=${{ needs.slow-integration-test.result }};
           e2eResults=${{ needs.e2e-test.result }};
           e2eIstioResults=${{ needs.e2e-test-istio.result }};
+          e2eIstioAmbientResults=${{ needs.e2e-test-istio-ambient.result }};
           e2eJavaVersionResults=${{ needs.e2e-test-java-versions.result }};
 
           [[ ${depLicenseResults} == 'success' ]] || [[ ${execute} != 'true' && ${depLicenseResults} == 'skipped' ]] || exit -2;
@@ -1030,6 +1093,7 @@ jobs:
           [[ ${integrationResults} == 'success' ]] || [[ ${execute} != 'true' && ${integrationResults} == 'skipped' ]] || exit -4;
           [[ ${e2eResults} == 'success' ]] || [[ ${execute} != 'true' && ${e2eResults} == 'skipped' ]] || exit -5;
           [[ ${e2eIstioResults} == 'success' ]] || [[ ${execute} != 'true' && ${e2eIstioResults} == 'skipped' ]] || exit -6;
+          [[ ${e2eIstioAmbientResults} == 'success' ]] || [[ ${execute} != 'true' && ${e2eIstioAmbientResults} == 'skipped' ]] || exit -6;
           [[ ${e2eJavaVersionResults} == 'success' ]] || [[ ${execute} != 'true' && ${e2eJavaVersionResults} == 'skipped' ]] || exit -7;
           [[ ${timeConsumingITResults} == 'success' ]] || [[ ${execute} != 'true' && ${timeConsumingITResults} == 'skipped' ]] || exit -8;
 
diff --git a/apm-protocol/apm-network/src/main/proto b/apm-protocol/apm-network/src/main/proto
index 07e6018301..157baf3e7a 160000
--- a/apm-protocol/apm-network/src/main/proto
+++ b/apm-protocol/apm-network/src/main/proto
@@ -1 +1 @@
-Subproject commit 07e6018301187a6a9429e5c204c62df1e4db7a6b
+Subproject commit 157baf3e7a9710d3041e9caec39eecab7e0c5a82
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index b167a8d4e6..920a7a99e1 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -19,6 +19,7 @@
 * Support analysis waypoint metrics in Envoy ALS receiver.
 * Add Ztunnel component in the topology.
 * [Break Change] Change `compomentId` to `componentIds` in the K8SServiceRelation Scope. 
+* Adapt the mesh metrics if detect the ambient mesh in the eBPF access log receiver.
 
 #### UI
 
diff --git a/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/pom.xml b/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/pom.xml
index 2863e5907d..4329ffaebf 100644
--- a/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/pom.xml
+++ b/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/pom.xml
@@ -33,10 +33,15 @@
             <artifactId>skywalking-sharing-server-plugin</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>skywalking-mesh-receiver-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.apache.skywalking</groupId>
             <artifactId>agent-analyzer</artifactId>
             <version>${project.version}</version>
         </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/AccessLogServiceHandler.java b/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/AccessLogServiceHandler.java
index 9c469b176c..118eadaed3 100644
--- a/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/AccessLogServiceHandler.java
+++ b/oap-server/server-receiver-plugin/skywalking-ebpf-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/ebpf/provider/handler/AccessLogServiceHandler.java
@@ -23,6 +23,7 @@ import io.vavr.Tuple2;
 import lombok.Getter;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.skywalking.aop.server.receiver.mesh.TelemetryDataDispatcher;
 import org.apache.skywalking.apm.network.common.v3.DetectPoint;
 import org.apache.skywalking.apm.network.ebpf.accesslog.v3.AccessLogConnection;
 import org.apache.skywalking.apm.network.ebpf.accesslog.v3.AccessLogConnectionTLSMode;
@@ -46,7 +47,15 @@ import org.apache.skywalking.apm.network.ebpf.accesslog.v3.EBPFTimestamp;
 import org.apache.skywalking.apm.network.ebpf.accesslog.v3.IPAddress;
 import org.apache.skywalking.apm.network.ebpf.accesslog.v3.KubernetesProcessAddress;
 import org.apache.skywalking.apm.network.ebpf.accesslog.v3.ZTunnelAttachmentEnvironment;
+import org.apache.skywalking.apm.network.ebpf.accesslog.v3.ZTunnelAttachmentEnvironmentDetectBy;
 import org.apache.skywalking.apm.network.ebpf.accesslog.v3.ZTunnelAttachmentSecurityPolicy;
+import org.apache.skywalking.apm.network.servicemesh.v3.HTTPServiceMeshMetric;
+import org.apache.skywalking.apm.network.servicemesh.v3.HTTPServiceMeshMetrics;
+import org.apache.skywalking.apm.network.servicemesh.v3.Protocol;
+import org.apache.skywalking.apm.network.servicemesh.v3.ServiceMeshMetrics;
+import org.apache.skywalking.apm.network.servicemesh.v3.TCPServiceMeshMetric;
+import org.apache.skywalking.apm.network.servicemesh.v3.TCPServiceMeshMetrics;
+import org.apache.skywalking.library.elasticsearch.response.NodeInfo;
 import org.apache.skywalking.library.kubernetes.ObjectID;
 import org.apache.skywalking.oap.meter.analyzer.k8s.K8sInfoRegistry;
 import org.apache.skywalking.oap.server.core.Const;
@@ -60,6 +69,7 @@ import org.apache.skywalking.oap.server.core.source.K8SService;
 import org.apache.skywalking.oap.server.core.source.K8SServiceInstance;
 import org.apache.skywalking.oap.server.core.source.K8SServiceInstanceRelation;
 import org.apache.skywalking.oap.server.core.source.K8SServiceRelation;
+import org.apache.skywalking.oap.server.core.source.Service;
 import org.apache.skywalking.oap.server.core.source.SourceReceiver;
 import org.apache.skywalking.oap.server.library.module.ModuleManager;
 import org.apache.skywalking.oap.server.library.util.StringUtil;
@@ -74,6 +84,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
@@ -100,6 +111,7 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
         this.sourceReceiver = moduleManager.find(CoreModule.NAME).provider().getService(SourceReceiver.class);
         this.namingControl = moduleManager.find(CoreModule.NAME).provider().getService(NamingControl.class);
 
+        TelemetryDataDispatcher.init(moduleManager);
         MetricsCreator metricsCreator = moduleManager.find(TelemetryModule.NAME)
             .provider()
             .getService(MetricsCreator.class);
@@ -150,6 +162,8 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
                         return;
                     }
 
+                    prepareForDispatch(node, connection, logMessage);
+
                     for (AccessLogKernelLog accessLogKernelLog : logMessage.getKernelLogsList()) {
                         inCounter.inc();
                         dispatchKernelLog(node, connection, accessLogKernelLog);
@@ -178,6 +192,119 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
         };
     }
 
+    protected void prepareForDispatch(NodeInfo node, ConnectionInfo connection, EBPFAccessLogMessage logMessage) {
+        // if the connection is communicated with ztunnel, then needs to generate mesh metrics
+        if (connection.getOriginalConnection().hasAttachment() && connection.getOriginalConnection().getAttachment().hasZTunnel()) {
+            prepareDispatchForZtunnelMesh(node, connection, logMessage);
+        }
+    }
+
+    protected void prepareDispatchForZtunnelMesh(NodeInfo node, ConnectionInfo connection, EBPFAccessLogMessage logMessage) {
+        final K8SServiceRelation serviceRelation = connection.toServiceRelation();
+        buildBaseServiceFromRelation(serviceRelation, Layer.MESH)
+            .forEach(sourceReceiver::receive);
+        // adapt to the mesh metrics
+        String tlsMode = Const.TLS_MODE.NON_TLS;
+        if (AccessLogConnectionTLSMode.TLS.equals(connection.getTlsMode())) {
+            tlsMode = Const.TLS_MODE.TLS;
+        }
+        if (ZTunnelAttachmentSecurityPolicy.MTLS.equals(connection.getOriginalConnection().getAttachment().getZTunnel().getSecurityPolicy())) {
+            tlsMode = Const.TLS_MODE.M_TLS;
+        }
+
+        if (logMessage.hasProtocolLog()) {
+            final AccessLogProtocolLogs protocolLog = logMessage.getProtocolLog();
+            final ServiceMeshMetrics.Builder serviceMeshMetrics = ServiceMeshMetrics.newBuilder();
+            switch (protocolLog.getProtocolCase()) {
+                case HTTP:
+                    serviceMeshMetrics.setHttpMetrics(HTTPServiceMeshMetrics.newBuilder()
+                        .addMetrics(generateHTTPServiceMeshMetrics(node, connection, protocolLog.getHttp(), tlsMode)));
+                    break;
+            }
+            TelemetryDataDispatcher.process(serviceMeshMetrics.build());
+        }
+
+        final ServiceMeshMetrics.Builder serviceMeshMetrics = ServiceMeshMetrics.newBuilder();
+        final TCPServiceMeshMetrics.Builder builder = TCPServiceMeshMetrics.newBuilder();
+        for (AccessLogKernelLog accessLogKernelLog : logMessage.getKernelLogsList()) {
+            Optional.ofNullable(generateTCPServiceMeshMetrics(node, connection, accessLogKernelLog, tlsMode))
+                    .ifPresent(builder::addMetrics);
+        }
+        serviceMeshMetrics.setTcpMetrics(builder.build());
+        TelemetryDataDispatcher.process(serviceMeshMetrics.build());
+    }
+
+    protected HTTPServiceMeshMetric generateHTTPServiceMeshMetrics(NodeInfo node, ConnectionInfo connection,
+                                                                   AccessLogHTTPProtocol http, String tlsMode) {
+        KubernetesProcessAddress source, dest;
+        if (DetectPoint.client.equals(connection.getRole())) {
+            source = connection.getLocal();
+            dest = connection.getRemote();
+        } else {
+            source = connection.getRemote();
+            dest = connection.getLocal();
+        }
+        final long startTime = node.parseTimestamp(http.getStartTime());
+        final long endTime = node.parseTimestamp(http.getEndTime());
+        return HTTPServiceMeshMetric.newBuilder()
+            .setStartTime(startTime)
+            .setEndTime(endTime)
+            .setSourceServiceName(buildServiceNameByAddress(node, source))
+            .setSourceServiceInstance(buildServiceInstanceName(source))
+            .setDestServiceName(buildServiceNameByAddress(node, dest))
+            .setDestServiceInstance(buildServiceInstanceName(dest))
+            .setEndpoint(buildHTTPProtocolEndpointName(connection, http))
+            .setLatency((int) (endTime - startTime))
+            .setResponseCode(http.getResponse().getStatusCode())
+            .setStatus(http.getResponse().getStatusCode() < 500)
+            .setProtocol(Protocol.HTTP)
+            .setDetectPoint(connection.getRole())
+            .setTlsMode(tlsMode).build();
+    }
+
+    protected TCPServiceMeshMetric generateTCPServiceMeshMetrics(NodeInfo node, ConnectionInfo connection,
+                                                                 AccessLogKernelLog kernelLog, String tlsMode) {
+        long receivedBytes = 0, sentBytes = 0;
+        long startTime = 0, endTime = 0;
+        switch (kernelLog.getOperationCase()) {
+            case CONNECT:
+            case ACCEPT:
+            case CLOSE:
+                return null;
+            case WRITE:
+                final AccessLogKernelWriteOperation write = kernelLog.getWrite();
+                sentBytes = write.getL4Metrics().getTotalPackageSize();
+                startTime = node.parseTimestamp(write.getStartTime());
+                endTime = node.parseTimestamp(write.getEndTime());
+                break;
+            case READ:
+                final AccessLogKernelReadOperation read = kernelLog.getRead();
+                receivedBytes = read.getL2Metrics().getTotalPackageSize();
+                startTime = node.parseTimestamp(read.getStartTime());
+                endTime = node.parseTimestamp(read.getEndTime());
+                break;
+        }
+        KubernetesProcessAddress source, dest;
+        if (DetectPoint.client.equals(connection.getRole())) {
+            source = connection.getLocal();
+            dest = connection.getRemote();
+        } else {
+            source = connection.getRemote();
+            dest = connection.getLocal();
+        }
+        return TCPServiceMeshMetric.newBuilder()
+            .setStartTime(startTime)
+            .setEndTime(endTime)
+            .setSourceServiceName(buildServiceNameByAddress(node, source))
+            .setSourceServiceInstance(buildServiceInstanceName(source))
+            .setDestServiceName(buildServiceNameByAddress(node, dest))
+            .setDestServiceInstance(buildServiceInstanceName(dest))
+            .setDetectPoint(connection.getRole())
+            .setTlsMode(tlsMode)
+            .setReceivedBytes(receivedBytes)
+            .setSentBytes(sentBytes).build();
+    }
+
     protected List<K8SMetrics> buildKernelLogMetrics(NodeInfo node, ConnectionInfo connection, AccessLogKernelLog kernelLog) {
         return Arrays.asList(connection.toService(), connection.toServiceInstance(),
             connection.toServiceRelation(), connection.toServiceInstanceRelation());
@@ -395,6 +522,11 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
             return TimeBucket.getMinuteTimeBucket(seconds * 1000);
         }
 
+        public long parseTimestamp(EBPFTimestamp timestamp) {
+            return TimeUnit.SECONDS.toMillis(bootTime.getSeconds() +
+                TimeUnit.NANOSECONDS.toSeconds(timestamp.getOffset().getOffset()));
+        }
+
         public boolean shouldExcludeNamespace(String namespace) {
             return excludeNamespaces.contains(namespace);
         }
@@ -422,17 +554,19 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
     }
 
     protected String buildProtocolEndpointName(ConnectionInfo connectionInfo, AccessLogProtocolLogs protocol) {
-        final String serviceName = connectionInfo.buildLocalServiceName();
         switch (protocol.getProtocolCase()) {
             case HTTP:
-                final AccessLogHTTPProtocol http = protocol.getHttp();
-                return namingControl.formatEndpointName(serviceName,
-                    StringUtils.upperCase(http.getRequest().getMethod().name()) + ":" + http.getRequest().getPath());
+                return buildHTTPProtocolEndpointName(connectionInfo, protocol.getHttp());
             default:
                 return null;
         }
     }
 
+    protected String buildHTTPProtocolEndpointName(ConnectionInfo connectionInfo, AccessLogHTTPProtocol http) {
+        return namingControl.formatEndpointName(connectionInfo.buildLocalServiceName(),
+            StringUtils.upperCase(http.getRequest().getMethod().name()) + ":" + http.getRequest().getPath());
+    }
+
     protected void recordIgnoreSameService(String sourceService) {
         final DropDataReason dropDataReason = dropReasons.computeIfAbsent(sourceService,
             key -> DropDataReason.buildWhenSameService(sourceService));
@@ -491,11 +625,13 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
 
     protected KubernetesProcessAddress buildKubernetesAddressByIP(NodeInfo nodeInfo, AccessLogConnection connection, boolean isLocal, IPAddress ipAddress) {
         String host = ipAddress.getHost();
-        // if the resolving address is not local, and have attached ztunnel info, then using the ztunnel mapped host
-        if (!isLocal && connection.hasAttachment() && connection.getAttachment().hasZTunnel()) {
+        // if the resolving address is not local, have attached ztunnel info,
+        // and must is detected by outbound, then using the ztunnel mapped host
+        if (!isLocal && connection.hasAttachment() && connection.getAttachment().hasZTunnel() &&
+            ZTunnelAttachmentEnvironmentDetectBy.ZTUNNEL_OUTBOUND_FUNC.equals(connection.getAttachment().getZTunnel().getBy())) {
             final ZTunnelAttachmentEnvironment ztunnel = connection.getAttachment().getZTunnel();
             host = ztunnel.getRealDestinationIp();
-            log.debug("detected the ztunnel connection, so update the remote IP address as: {}, detect by: {}", host,
+            log.debug("detected the ztunnel outbound connection, so update the remote IP address as: {}, detect by: {}", host,
                 ztunnel.getBy());
         }
         final ObjectID service = K8sInfoRegistry.getInstance().findServiceByIP(host);
@@ -535,9 +671,11 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
 
     protected List<Integer> buildConnectionComponentId(ConnectionInfo connectionInfo) {
         final AccessLogConnection originalConnection = connectionInfo.getOriginalConnection();
-        if (originalConnection.hasAttachment() && originalConnection.getAttachment().hasZTunnel() &&
-            ZTunnelAttachmentSecurityPolicy.MTLS.equals(originalConnection.getAttachment().getZTunnel().getSecurityPolicy())) {
-            return Arrays.asList(142, 162); // mTLS, ztunnel
+        if (originalConnection.hasAttachment() && originalConnection.getAttachment().hasZTunnel()) {
+            if (ZTunnelAttachmentSecurityPolicy.MTLS.equals(originalConnection.getAttachment().getZTunnel().getSecurityPolicy())) {
+                return Arrays.asList(142, 162); // mTLS, ztunnel
+            }
+            return Arrays.asList(162); // ztunnel
         }
         return Arrays.asList(buildProtocolComponentID(connectionInfo));
     }
@@ -725,6 +863,10 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
             }
         }
 
+        public AccessLogConnection getOriginal() {
+            return originalConnection;
+        }
+
         public String toString() {
             return String.format("local: %s, remote: %s, role: %s, tlsMode: %s, protocolType: %s, valid: %b",
                 buildConnectionAddressString(originalConnection.getLocal()),
@@ -766,4 +908,21 @@ public class AccessLogServiceHandler extends EBPFAccessLogServiceGrpc.EBPFAccess
     protected long convertNsToMs(long latency) {
         return TimeUnit.NANOSECONDS.toMillis(latency);
     }
+
+    protected List<Service> buildBaseServiceFromRelation(K8SServiceRelation relation, Layer layer) {
+        if (relation == null) {
+            return Collections.emptyList();
+        }
+        Service localService = new Service();
+        localService.setLayer(layer);
+        localService.setName(relation.getSourceServiceName());
+        localService.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+        Service remoteService = new Service();
+        remoteService.setLayer(layer);
+        remoteService.setName(relation.getDestServiceName());
+        remoteService.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+        log.debug("generate the {} layer service local service: {}, remote service: {}",
+            layer, relation.getSourceServiceName(), relation.getDestServiceName());
+        return Arrays.asList(localService, remoteService);
+    }
 }
diff --git a/oap-server/server-starter/src/main/resources/component-libraries.yml b/oap-server/server-starter/src/main/resources/component-libraries.yml
index d6174eaeb8..25c1aba053 100644
--- a/oap-server/server-starter/src/main/resources/component-libraries.yml
+++ b/oap-server/server-starter/src/main/resources/component-libraries.yml
@@ -538,6 +538,7 @@ ThreadPerTask-executor:
 ztunnel:
   id: 162
   languages: ebpf, mesh
+  priority: 10
 
 # .NET/.NET Core components
 # [3000, 4000) for C#/.NET only
diff --git a/test/e2e-v2/cases/cilium/traffic-gen.yaml b/test/e2e-v2/cases/cilium/traffic-gen.yaml
index 590ff4d98f..6f946ae52e 100644
--- a/test/e2e-v2/cases/cilium/traffic-gen.yaml
+++ b/test/e2e-v2/cases/cilium/traffic-gen.yaml
@@ -39,7 +39,7 @@ spec:
             - |
               while true; do
                 curl -s -o /dev/null -w "%{http_code}\n" http://productpage:9080/productpage
-                sleep 1
+                sleep 5
               done
           resources:
             requests:
diff --git a/test/e2e-v2/cases/istio/ambient-als/e2e.yaml b/test/e2e-v2/cases/istio/ambient-als/e2e.yaml
new file mode 100644
index 0000000000..8017f29b44
--- /dev/null
+++ b/test/e2e-v2/cases/istio/ambient-als/e2e.yaml
@@ -0,0 +1,222 @@
+# 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.k${KUBERNETES_VERSION}.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=ambient --skip-confirmation --set meshConfig.accessLogFile=/dev/stdout \
+          --set meshConfig.defaultConfig.envoyAccessLogService.address=skywalking-oap.istio-system:11800 \
+          --set meshConfig.enableEnvoyAccessLogService=true
+        kubectl get crd gateways.gateway.networking.k8s.io &> /dev/null || \
+          kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0-rc.1/standard-install.yaml
+        kubectl label namespace default istio.io/dataplane-mode=ambient
+    - name: install waypoint
+      command: istioctl waypoint apply --name simple-http-waypoint && sleep 10
+      wait:
+        - namespace: default
+          resource: deployments/simple-http-waypoint
+          for: condition=available
+    - name: Install helm
+      command: bash test/e2e-v2/script/prepare/setup-e2e-shell/install.sh helm
+    - name: Install SkyWalking
+      command: |
+        helm -n istio-system install skywalking \
+          oci://ghcr.io/apache/skywalking-helm/skywalking-helm \
+          --version "0.0.0-${SW_KUBERNETES_COMMIT_SHA}" \
+          --set fullnameOverride=skywalking \
+          --set elasticsearch.replicas=1 \
+          --set elasticsearch.minimumMasterNodes=1 \
+          --set oap.env.SW_ENVOY_METRIC_ALS_HTTP_ANALYSIS=$ALS_ANALYZER \
+          --set oap.env.SW_ENVOY_METRIC_ALS_TCP_ANALYSIS=$ALS_ANALYZER \
+          --set oap.env.K8S_SERVICE_NAME_RULE='e2e::${service.metadata.name}' \
+          --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 \
+          -f test/e2e-v2/cases/istio/values.yaml
+      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
+        # Enable TCP services
+        kubectl apply -f https://raw.githubusercontent.com/istio/istio/$ISTIO_VERSION/samples/bookinfo/platform/kube/bookinfo-ratings-v2.yaml
+        kubectl apply -f https://raw.githubusercontent.com/istio/istio/$ISTIO_VERSION/samples/bookinfo/platform/kube/bookinfo-db.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-ratings-db.yaml
+      wait:
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+    - name: Add reviews service as waypoint transform
+      command: kubectl label service -n default details istio.io/use-waypoint=simple-http-waypoint --overwrite
+    - name: Install SkyWalking Rover
+      command: |
+        envsubst < test/e2e-v2/cases/profiling/ebpf/access_log/rover.yaml | kubectl apply -f -
+      wait:
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+    - name: Status of istio mesh
+      command: istioctl zc all && sleep 15 # sleep for waiting the rover ready to monitoring all services
+    - name: Generate traffic
+      path: traffic-gen.yaml
+      wait:
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+  timeout: 25m
+
+verify:
+  retry:
+    count: 20
+    interval: 15s
+  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=productpage.default
+      expected: expected/service-instance.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=reviews.default
+      expected: expected/service-instance.yml
+    # service endpoint
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql endpoint list --service-name=productpage.default
+      expected: expected/service-endpoint-productpage.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql endpoint list --service-name=reviews.default
+      expected: expected/service-endpoint-reviews.yml
+
+    # mesh service metrics: productpage.default
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_sla --service-name=productpage.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_cpm --service-name=productpage.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_resp_time --service-name=productpage.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_apdex --service-name=productpage.default
+      expected: expected/metrics-has-value.yml
+    # service metrics: reviews.default
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_sla --service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_cpm --service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_resp_time --service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_apdex --service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    # service instance metrics: productpage.default
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_resp_time --service-name=productpage.default --instance-name=$( \
+          swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=productpage.default | yq e '.[0].name' -
+        )
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_cpm --service-name=productpage.default --instance-name=$( \
+          swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=productpage.default | yq e '.[0].name' -
+        )
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_sla --service-name=productpage.default --instance-name=$( \
+          swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=productpage.default | yq e '.[0].name' -
+        )
+      expected: expected/metrics-has-value.yml
+    # service instance metrics: reviews.default
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_resp_time --service-name=reviews.default --instance-name=$( \
+          swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=reviews.default | yq e '.[0].name' -
+        )
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_cpm --service-name=reviews.default --instance-name=$( \
+          swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=reviews.default | yq e '.[0].name' -
+        )
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_sla --service-name=reviews.default --instance-name=$( \
+          swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=reviews.default | yq e '.[0].name' -
+        )
+      expected: expected/metrics-has-value.yml
+
+    # service endpoint metrics: productpage.default GET:/productpage
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=endpoint_cpm --endpoint-name=GET:/productpage --service-name=productpage.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=endpoint_resp_time --endpoint-name=GET:/productpage --service-name=productpage.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=endpoint_sla --endpoint-name=GET:/productpage --service-name=productpage.default
+      expected: expected/metrics-has-value.yml
+    # service endpoint metrics: reviews.default GET:/reviews/0
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=endpoint_cpm --endpoint-name=GET:/reviews/0 --service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=endpoint_resp_time --endpoint-name=GET:/reviews/0 --service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=endpoint_sla --endpoint-name=GET:/reviews/0 --service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+
+    # dependency service
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql dependency global --layer=MESH
+      expected: expected/dependency-global-mesh.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql dependency instance --service-name=productpage.default --dest-service-name=reviews.default
+      expected: expected/dependency-services-instance-productpage.yml
+
+    # service relation metrics
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_relation_client_cpm  --service-name=productpage.default --dest-service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    - query: swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_relation_server_cpm  --service-name=productpage.default --dest-service-name=reviews.default
+      expected: expected/metrics-has-value.yml
+    # service instance relation metrics, productpage.default -> reviews.default
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_relation_client_cpm \
+          --service-name=productpage.default --instance-name=$( \
+            swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=productpage.default | yq e '.[0].name' - ) \
+          --dest-service-name=reviews.default --dest-instance-name=$( \
+            swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=reviews.default | yq e '.[0].name' - )
+      expected: expected/metrics-has-value.yml
+    - query: |
+        swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql metrics exec --expression=service_instance_relation_server_cpm \
+          --service-name=productpage.default --instance-name=$( \
+            swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=productpage.default | yq e '.[0].name' - ) \
+          --dest-service-name=reviews.default --dest-instance-name=$( \
+            swctl --display yaml --base-url=http://${service_skywalking_ui_host}:${service_skywalking_ui_80}/graphql instance list --service-name=reviews.default | yq e '.[0].name' - )
+
+      expected: expected/metrics-has-value.yml
diff --git a/test/e2e-v2/cases/istio/ambient-als/expected/dependency-global-mesh.yml b/test/e2e-v2/cases/istio/ambient-als/expected/dependency-global-mesh.yml
new file mode 100644
index 0000000000..438172c4b3
--- /dev/null
+++ b/test/e2e-v2/cases/istio/ambient-als/expected/dependency-global-mesh.yml
@@ -0,0 +1,104 @@
+# 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.
+
+debuggingtrace: null
+nodes:
+{{- contains .nodes }}
+- id: {{ b64enc "reviews.default"}}.1
+  name: reviews.default
+  type: http
+  isreal: true
+  layers:
+  {{- contains .layers }}
+    - MESH
+    - K8S_SERVICE
+  {{- end }}
+- id: {{ b64enc "simple-http-waypoint.default"}}.1
+  name: simple-http-waypoint.default
+  type: tls
+  isreal: true
+  layers:
+  {{- contains .layers }}
+  - MESH
+  - K8S_SERVICE
+  {{- end }}
+- id: {{ b64enc "productpage.default"}}.1
+  name: productpage.default
+  type: http
+  isreal: true
+  layers:
+  {{- contains .layers }}
+    - MESH
+    - K8S_SERVICE
+  {{- end }}
+- id: {{ b64enc "details.default" }}.1
+  name: details.default
+  type: http
+  isreal: true
+  layers:
+  {{- contains .layers }}
+    - MESH
+    - K8S_SERVICE
+  {{- end }}
+{{- end }}
+calls:
+{{- contains .calls }}
+- source: {{ b64enc "productpage.default"}}.1
+  sourcecomponents:
+    {{- contains .sourcecomponents }}
+    - tcp
+    - http
+    {{- end }}
+  target: {{ b64enc "simple-http-waypoint.default"}}.1
+  targetcomponents:
+  {{- contains .targetcomponents }}
+  - ztunnel
+  {{- end }}
+  id: {{ b64enc "productpage.default"}}.1-{{ b64enc "simple-http-waypoint.default"}}.1
+  detectpoints:
+    - CLIENT
+    - SERVER
+- source: {{ b64enc "simple-http-waypoint.default"}}.1
+  sourcecomponents:
+  {{- contains .sourcecomponents }}
+  - tls
+  {{- end }}
+  target: {{ b64enc "details.default"}}.1
+  targetcomponents:
+  {{- contains .targetcomponents }}
+  - ztunnel
+  {{- end }}
+  id: {{ b64enc "simple-http-waypoint.default" }}.1-{{ b64enc "details.default"}}.1
+  detectpoints:
+    - CLIENT
+    - SERVER
+- source: {{ b64enc "productpage.default" }}.1
+  sourcecomponents:
+    {{- contains .sourcecomponents }}
+    - ztunnel
+    - tcp
+    - http
+    {{- end }}
+  target: {{ b64enc "reviews.default"}}.1
+  targetcomponents:
+  {{- contains .targetcomponents }}
+    - ztunnel
+    - http
+  {{- end }}
+  id: {{ b64enc "productpage.default" }}.1-{{ b64enc "reviews.default"}}.1
+  detectpoints:
+    - CLIENT
+    - SERVER
+{{- end }}
diff --git a/test/e2e-v2/cases/istio/kind.k25.yaml b/test/e2e-v2/cases/istio/ambient-als/expected/dependency-services-instance-productpage.yml
similarity index 55%
copy from test/e2e-v2/cases/istio/kind.k25.yaml
copy to test/e2e-v2/cases/istio/ambient-als/expected/dependency-services-instance-productpage.yml
index fe248b66f6..180cfc64e1 100644
--- a/test/e2e-v2/cases/istio/kind.k25.yaml
+++ b/test/e2e-v2/cases/istio/ambient-als/expected/dependency-services-instance-productpage.yml
@@ -13,8 +13,30 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-kind: Cluster
-apiVersion: kind.x-k8s.io/v1alpha4
+debuggingtrace: null
 nodes:
-  - role: control-plane
-    image: kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8
+{{- contains .nodes }}
+- id: {{ notEmpty .id }}
+  name: {{ notEmpty .name }}
+  serviceid: {{ b64enc "reviews.default" }}.1
+  servicename: reviews.default
+  type: ""
+  isreal: true
+- id: {{ notEmpty .id }}
+  name: {{ notEmpty .name }}
+  serviceid: {{ b64enc "productpage.default" }}.1
+  servicename: productpage.default
+  type: ""
+  isreal: true
+{{- end }}
+calls:
+{{- contains .calls }}
+- source: {{ notEmpty .source }}
+  sourcecomponents: []
+  target: {{ notEmpty .target }}
+  targetcomponents: []
+  id: {{ notEmpty .source }}-{{ notEmpty .target }}
+  detectpoints:
+    - CLIENT
+    - SERVER
+{{- end }}
diff --git a/test/e2e-v2/cases/istio/kind.k25.yaml b/test/e2e-v2/cases/istio/ambient-als/expected/metrics-has-value.yml
similarity index 66%
copy from test/e2e-v2/cases/istio/kind.k25.yaml
copy to test/e2e-v2/cases/istio/ambient-als/expected/metrics-has-value.yml
index fe248b66f6..d5e6476d7a 100644
--- a/test/e2e-v2/cases/istio/kind.k25.yaml
+++ b/test/e2e-v2/cases/istio/ambient-als/expected/metrics-has-value.yml
@@ -13,8 +13,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-kind: Cluster
-apiVersion: kind.x-k8s.io/v1alpha4
-nodes:
-  - role: control-plane
-    image: kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8
+debuggingtrace: null
+type: TIME_SERIES_VALUES
+results:
+  {{- contains .results }}
+  - metric:
+      labels: []
+    values:
+      {{- contains .values }}
+      - id: "{{ notEmpty .id }}"
+        value: {{ .value }}
+        owner: null
+        traceid: null
+      - id: "{{ notEmpty .id }}"
+        value: null
+        owner: null
+        traceid: null
+      {{- end}}
+  {{- end}}
+error: null
diff --git a/test/e2e-v2/cases/istio/kind.k25.yaml b/test/e2e-v2/cases/istio/ambient-als/expected/service-endpoint-productpage.yml
similarity index 80%
copy from test/e2e-v2/cases/istio/kind.k25.yaml
copy to test/e2e-v2/cases/istio/ambient-als/expected/service-endpoint-productpage.yml
index fe248b66f6..f5788fe089 100644
--- a/test/e2e-v2/cases/istio/kind.k25.yaml
+++ b/test/e2e-v2/cases/istio/ambient-als/expected/service-endpoint-productpage.yml
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-kind: Cluster
-apiVersion: kind.x-k8s.io/v1alpha4
-nodes:
-  - role: control-plane
-    image: kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8
+{{- contains . }}
+- id: {{ b64enc "productpage.default" }}.1_{{ b64enc "GET:/productpage" }}
+  name: GET:/productpage
+{{- end }}
diff --git a/test/e2e-v2/cases/istio/kind.k25.yaml b/test/e2e-v2/cases/istio/ambient-als/expected/service-endpoint-reviews.yml
similarity index 80%
copy from test/e2e-v2/cases/istio/kind.k25.yaml
copy to test/e2e-v2/cases/istio/ambient-als/expected/service-endpoint-reviews.yml
index fe248b66f6..1fffece05b 100644
--- a/test/e2e-v2/cases/istio/kind.k25.yaml
+++ b/test/e2e-v2/cases/istio/ambient-als/expected/service-endpoint-reviews.yml
@@ -13,8 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-kind: Cluster
-apiVersion: kind.x-k8s.io/v1alpha4
-nodes:
-  - role: control-plane
-    image: kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8
+{{- contains . }}
+- id: {{ b64enc "reviews.default" }}.1_{{ b64enc "GET:/reviews/0" }}
+  name: GET:/reviews/0
+{{- end }}
diff --git a/test/e2e-v2/cases/istio/kind.k25.yaml b/test/e2e-v2/cases/istio/ambient-als/expected/service-instance.yml
similarity index 80%
copy from test/e2e-v2/cases/istio/kind.k25.yaml
copy to test/e2e-v2/cases/istio/ambient-als/expected/service-instance.yml
index fe248b66f6..658cdbd553 100644
--- a/test/e2e-v2/cases/istio/kind.k25.yaml
+++ b/test/e2e-v2/cases/istio/ambient-als/expected/service-instance.yml
@@ -13,8 +13,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-kind: Cluster
-apiVersion: kind.x-k8s.io/v1alpha4
-nodes:
-  - role: control-plane
-    image: kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8
+{{- contains . }}
+- id: {{ notEmpty .id }}
+  name: {{ notEmpty .name }}
+  attributes: []
+  language: UNKNOWN
+  instanceuuid: {{ notEmpty .instanceuuid }}
+{{- end }}
diff --git a/test/e2e-v2/cases/istio/ambient-als/expected/service.yml b/test/e2e-v2/cases/istio/ambient-als/expected/service.yml
new file mode 100644
index 0000000000..f98b6e7778
--- /dev/null
+++ b/test/e2e-v2/cases/istio/ambient-als/expected/service.yml
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{{- contains . }}
+- id: {{ b64enc "details.default" }}.1
+  name: details.default
+  group: ""
+  shortname: details.default
+  layers:
+    - MESH
+    - K8S_SERVICE
+  normal: true
+- id: {{ b64enc "e2e::simple-http-waypoint" }}.1
+  name: e2e::simple-http-waypoint
+  group: "e2e"
+  shortname: simple-http-waypoint
+  layers:
+    - MESH
+  normal: true
+- id: {{ b64enc "reviews.default" }}.1
+  name: reviews.default
+  group: ""
+  shortname: reviews.default
+  layers:
+    - MESH
+    - K8S_SERVICE
+  normal: true
+- id: {{ b64enc "ratings.default" }}.1
+  name: ratings.default
+  group: ""
+  shortname: ratings.default
+  layers:
+    - MESH
+    - K8S_SERVICE
+  normal: true
+- id: {{ b64enc "productpage.default" }}.1
+  name: productpage.default
+  group: ""
+  shortname: productpage.default
+  layers:
+    - MESH
+    - K8S_SERVICE
+  normal: true
+- id: {{ b64enc "mongodb.default" }}.1
+  name: mongodb.default
+  group: ""
+  shortname: mongodb.default
+  layers:
+    - MESH
+    - K8S_SERVICE
+  normal: true
+{{- end }}
diff --git a/test/e2e-v2/cases/cilium/traffic-gen.yaml b/test/e2e-v2/cases/istio/ambient-als/traffic-gen.yaml
similarity index 95%
copy from test/e2e-v2/cases/cilium/traffic-gen.yaml
copy to test/e2e-v2/cases/istio/ambient-als/traffic-gen.yaml
index 590ff4d98f..65e2ac62d2 100644
--- a/test/e2e-v2/cases/cilium/traffic-gen.yaml
+++ b/test/e2e-v2/cases/istio/ambient-als/traffic-gen.yaml
@@ -38,8 +38,8 @@ spec:
           args:
             - |
               while true; do
-                curl -s -o /dev/null -w "%{http_code}\n" http://productpage:9080/productpage
-                sleep 1
+                curl -s -o /dev/null -w "%{http_code}\n" http://productpage.default:9080/productpage
+                sleep 5
               done
           resources:
             requests:
diff --git a/test/e2e-v2/cases/istio/kind.k25.yaml b/test/e2e-v2/cases/istio/kind.k25.yaml
index fe248b66f6..c3271a47ed 100644
--- a/test/e2e-v2/cases/istio/kind.k25.yaml
+++ b/test/e2e-v2/cases/istio/kind.k25.yaml
@@ -18,3 +18,6 @@ apiVersion: kind.x-k8s.io/v1alpha4
 nodes:
   - role: control-plane
     image: kindest/node:v1.25.11@sha256:227fa11ce74ea76a0474eeefb84cb75d8dad1b08638371ecf0e86259b35be0c8
+    extraMounts:
+      -   hostPath: /
+          containerPath: /host
diff --git a/test/e2e-v2/cases/istio/kind.k28.yaml b/test/e2e-v2/cases/istio/kind.k28.yaml
index 6bb82dfce8..f2f618b841 100644
--- a/test/e2e-v2/cases/istio/kind.k28.yaml
+++ b/test/e2e-v2/cases/istio/kind.k28.yaml
@@ -18,3 +18,6 @@ apiVersion: kind.x-k8s.io/v1alpha4
 nodes:
   - role: control-plane
     image: kindest/node:v1.28.15@sha256:a7c05c7ae043a0b8c818f5a06188bc2c4098f6cb59ca7d1856df00375d839251
+    extraMounts:
+      -   hostPath: /
+          containerPath: /host
diff --git a/test/e2e-v2/cases/istio/values.yaml b/test/e2e-v2/cases/istio/values.yaml
index 27426bbd75..115282057d 100644
--- a/test/e2e-v2/cases/istio/values.yaml
+++ b/test/e2e-v2/cases/istio/values.yaml
@@ -18,6 +18,25 @@ oap:
     metadata-service-mapping.yaml: |
       serviceName: e2e::${LABELS."service.istio.io/canonical-name",SERVICE}
       serviceInstanceName: ${NAME}
+    log4j2.xml: |
+      <Configuration status="INFO">
+        <Appenders>
+          <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout>
+              <LevelPatternSelector defaultPattern="%d %c %L [%t] %-5p %x - %m%n">
+                <PatternMatch key="ERROR" pattern="%d %c %L [%t] %-5p %x - [%swversion] %m%n" />
+              </LevelPatternSelector>
+            </PatternLayout>
+          </Console>
+        </Appenders>
+        <Loggers>
+          <logger name="org.apache.skywalking.oap.server.receiver.ebpf.provider.handler" level="DEBUG"/>
+          <Root level="INFO">
+            <AppenderRef ref="Console"/>
+          </Root>
+        </Loggers>
+      </Configuration>
+
 
 elasticsearch:
   esConfig:
diff --git a/test/e2e-v2/cases/php/e2e.yaml b/test/e2e-v2/cases/php/e2e.yaml
index bed6bfeddf..dd8ced3960 100644
--- a/test/e2e-v2/cases/php/e2e.yaml
+++ b/test/e2e-v2/cases/php/e2e.yaml
@@ -38,8 +38,8 @@ trigger:
 verify:
   # verify with retry strategy
   retry:
-    count: 20
-    interval: 10s
+    count: 30
+    interval: 15s
   cases:
     # layer list
     - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql layer ls
diff --git a/test/e2e-v2/cases/profiling/ebpf/access_log/traffic-gen.yaml b/test/e2e-v2/cases/profiling/ebpf/access_log/traffic-gen.yaml
index a1d08fef93..addefc63d7 100644
--- a/test/e2e-v2/cases/profiling/ebpf/access_log/traffic-gen.yaml
+++ b/test/e2e-v2/cases/profiling/ebpf/access_log/traffic-gen.yaml
@@ -39,7 +39,7 @@ spec:
             - |
               while true; do
                 curl -s -o /dev/null -w "%{http_code}\n" http://productpage:9080/productpage
-                sleep 1
+                sleep 5
               done
           resources:
             requests:
diff --git a/test/e2e-v2/cases/profiling/ebpf/continuous/postgres/e2e.yaml b/test/e2e-v2/cases/profiling/ebpf/continuous/postgres/e2e.yaml
new file mode 100644
index 0000000000..6be954ee94
--- /dev/null
+++ b/test/e2e-v2/cases/profiling/ebpf/continuous/postgres/e2e.yaml
@@ -0,0 +1,85 @@
+# 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
+      - test/continuous:test
+    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 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: |
+        kubectl create namespace istio-system
+        helm -n istio-system install skywalking \
+          oci://ghcr.io/apache/skywalking-helm/skywalking-helm \
+          --version "0.0.0-${SW_KUBERNETES_COMMIT_SHA}" \
+          --set fullnameOverride=skywalking \
+          --set elasticsearch.enabled=false \
+          --set banyandb.enabled=true \
+          --set banyandb.image.tag=${SW_BANYANDB_COMMIT} \
+          --set banyandb.image.repository=ghcr.io/apache/skywalking-banyandb \
+          --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=banyandb \
+          -f test/e2e-v2/cases/profiling/ebpf/kubernetes-values.yaml
+      wait:
+        - namespace: istio-system
+          resource: deployments/skywalking-oap
+          for: condition=available
+    - name: Deploy services
+      command: |
+        export IMAGE_NAME=test/continuous:test
+        export HAS_SERVICE_EXP=".Pod.HasContainer \\\"test-continuous\\\""
+        export SERVICE_NAME_EXP="sqrt"
+        envsubst < test/e2e-v2/cases/profiling/ebpf/continuous/service.yaml | kubectl apply -f -
+        envsubst < test/e2e-v2/cases/profiling/ebpf/rover.yaml | kubectl apply -f -
+      wait:
+        - namespace: default
+          resource: pod
+          for: condition=Ready
+  timeout: 25m
+
+verify:
+  retry:
+    count: 20
+    interval: 10s
+  cases:
+    - includes:
+        - ../profiling-cases.yaml
\ No newline at end of file
diff --git a/test/e2e-v2/cases/storage/banyandb/stages/e2e.yaml b/test/e2e-v2/cases/storage/banyandb/stages/e2e.yaml
index 70d9466e44..d02da95cc7 100644
--- a/test/e2e-v2/cases/storage/banyandb/stages/e2e.yaml
+++ b/test/e2e-v2/cases/storage/banyandb/stages/e2e.yaml
@@ -66,6 +66,6 @@ verify:
     - query: |
         swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql trace ls --trace-id=$( \
           swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql trace ls --tags http.method=get --start="-96h" --end="-48h" --cold=true \
-            | yq e '.traces | select(.[].endpointnames[0]=="/dubbox-case/case/dubbox-rest/404-test") | .[0].traceids[0]' -
+            | yq e '.traces | select(.[].endpointnames[0]=="/dubbox-case/case/dubbox-rest/404-test") | .[2].traceids[0]' -
         ) --start="-96h" --end="-48h" --cold=true
       expected: ../../expected/cold/trace-detail.yml
diff --git a/test/e2e-v2/script/env b/test/e2e-v2/script/env
index ef63dca6e4..09ad865c6c 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=6fe5e6f0d3b7686c6be0457733e825ee68cb9b35
-SW_ROVER_COMMIT=738b1a42fe4941e0b4e6f5816403437cf572708f
+SW_ROVER_COMMIT=79292fe07f17f98f486e0c4471213e1961fb2d1d
 SW_BANYANDB_COMMIT=c4b4384f3083f44ca6067257f5fa59030427ad6b
 SW_AGENT_PHP_COMMIT=3192c553002707d344bd6774cfab5bc61f67a1d3
 SW_PREDICTOR_COMMIT=54a0197654a3781a6f73ce35146c712af297c994