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

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-graalvm-distro.git


The following commit(s) were added to refs/heads/main by this push:
     new 86791a4  Add TraceQL/PromQL/LogQL e2e tests, fix source tarball build 
and release tooling (#12)
86791a4 is described below

commit 86791a437e293e64d42c6cb90615d4244b863f2e
Author: 吴晟 Wu Sheng <[email protected]>
AuthorDate: Mon Mar 16 17:01:50 2026 +0800

    Add TraceQL/PromQL/LogQL e2e tests, fix source tarball build and release 
tooling (#12)
    
    - **TraceQL module**: Add Tempo-compatible trace query API with Zipkin and 
SkyWalking datasource support.
    - **PromQL/LogQL/TraceQL e2e tests**: Three new e2e test cases for 
Prometheus, Loki, and Tempo compatible query APIs.
    - **Build-time entity auto-discovery**: Scan 
`org.apache.skywalking.oap.query.*.entity` packages at build time for Jackson 
reflection config instead of hardcoding class names.
    - **Source tarball build fix**: Gracefully handle absent `.git` in version 
generation using Ant `if:set` — Apache source release builds no longer require 
git.
    - **New version format**: `{distro}[-{commit}]-distro-{sw}[-{sw_commit}]` 
(e.g., `0.2.0-abc1234-distro-10.4.0-def5678`).
    - **Release tooling fixes**: SHA-512 checksum files now contain only hash + 
filename (no local paths), darwin SHA-512 re-uploaded after GPG signing, vote 
email links to `compiling.md`.
    - **Compiling docs**: Add "Building from Apache Source Tarball" section.
---
 .github/workflows/ci.yml                           |   6 +
 .../server/buildtools/common/AcceptedModules.java  |   1 +
 build-tools/precompiler/pom.xml                    |   4 +
 .../server/buildtools/precompiler/Precompiler.java |  75 +++++++++-
 .../resources/META-INF/module-config-classes.txt   |   3 +-
 changes/changes.md                                 |  11 ++
 docs/distro-policy.md                              |   4 +-
 oap-graalvm-server/pom.xml                         |   4 +
 .../server/graalvm/GraalVMOAPServerStartUp.java    |   5 +
 .../server/library/util/YamlConfigLoaderUtils.java |  45 ++++++
 .../src/main/resources/application.yml             |  12 ++
 pom.xml                                            |   5 +
 test/e2e/cases/logql/docker-compose.yml            | 162 +++++++++++++++++++++
 test/e2e/cases/logql/e2e.yaml                      |  51 +++++++
 test/e2e/cases/promql/docker-compose.yml           | 130 +++++++++++++++++
 test/e2e/cases/promql/e2e.yaml                     |  51 +++++++
 test/e2e/cases/promql/promql-cases.yaml            | 155 ++++++++++++++++++++
 test/e2e/cases/traceql/docker-compose.yml          |  74 ++++++++++
 test/e2e/cases/traceql/e2e.yaml                    |  48 ++++++
 19 files changed, 836 insertions(+), 10 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a86a61a..1879cc3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -321,6 +321,12 @@ jobs:
             case: vm-zabbix
           - name: Zipkin
             case: zipkin
+          - name: PromQL
+            case: promql
+          - name: LogQL
+            case: logql
+          - name: TraceQL
+            case: traceql
           - name: Baseline
             case: baseline
     steps:
diff --git 
a/build-tools/build-common/src/main/java/org/apache/skywalking/oap/server/buildtools/common/AcceptedModules.java
 
b/build-tools/build-common/src/main/java/org/apache/skywalking/oap/server/buildtools/common/AcceptedModules.java
index 6a5b4bb..2568533 100644
--- 
a/build-tools/build-common/src/main/java/org/apache/skywalking/oap/server/buildtools/common/AcceptedModules.java
+++ 
b/build-tools/build-common/src/main/java/org/apache/skywalking/oap/server/buildtools/common/AcceptedModules.java
@@ -86,6 +86,7 @@ public final class AcceptedModules {
         new ModuleProviderPair("query-zipkin", "default"),
         new ModuleProviderPair("promql", "default"),
         new ModuleProviderPair("logql", "default"),
+        new ModuleProviderPair("traceQL", "default"),
         new ModuleProviderPair("status-query", "default"),
         // Alarm
         new ModuleProviderPair("alarm", "default"),
diff --git a/build-tools/precompiler/pom.xml b/build-tools/precompiler/pom.xml
index 816c205..c520b68 100644
--- a/build-tools/precompiler/pom.xml
+++ b/build-tools/precompiler/pom.xml
@@ -111,6 +111,10 @@
             <groupId>org.apache.skywalking</groupId>
             <artifactId>logql-plugin</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>traceql-plugin</artifactId>
+        </dependency>
 
         <!-- Health checker (HealthCheckerHttpService) -->
         <dependency>
diff --git 
a/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
 
b/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
index 25e4878..eef110d 100644
--- 
a/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
+++ 
b/build-tools/precompiler/src/main/java/org/apache/skywalking/oap/server/buildtools/precompiler/Precompiler.java
@@ -236,6 +236,12 @@ public class Precompiler {
         writeManifest(annotationScanDir.resolve("GraphQLTypes.txt"),
             scanGraphQLTypes(allClasses));
 
+        // ---- Query plugin entity class scanning ----
+        // Auto-discover all classes under 
org.apache.skywalking.oap.query.*.entity packages
+        // (including inner classes and codec serializers) for Jackson 
reflection config.
+        writeManifest(annotationScanDir.resolve("QueryEntityClasses.txt"),
+            scanQueryEntityClasses(allClasses));
+
         // ---- MAL pre-compilation (v2 ANTLR4 + Javassist) ----
         compileMAL(outputDir, allClasses);
 
@@ -837,17 +843,25 @@ public class Precompiler {
                 if (aClass.isInterface() || 
Modifier.isAbstract(aClass.getModifiers())) {
                     continue;
                 }
-                // Check if any method has Armeria routing annotations
-                for (Method method : aClass.getDeclaredMethods()) {
+                // Check if any method (including inherited) has Armeria 
routing annotations
+                boolean matched = false;
+                for (Method method : aClass.getMethods()) {
                     if ((postAnno != null && 
method.isAnnotationPresent(postAnno))
                         || (getAnno != null && 
method.isAnnotationPresent(getAnno))
                         || (pathAnno != null && 
method.isAnnotationPresent(pathAnno))) {
-                        result.add(aClass.getName());
-                        // Also collect @ExceptionHandler referenced classes
-                        collectExceptionHandlerClasses(aClass, result);
-                        break;
+                        matched = true;
+                        // Include declaring class of inherited annotated 
methods (e.g. abstract base handlers)
+                        // so Armeria can reflect on their @Get/@Path 
annotations at runtime
+                        Class<?> declaring = method.getDeclaringClass();
+                        if (declaring != aClass && declaring != Object.class) {
+                            result.add(declaring.getName());
+                        }
                     }
                 }
+                if (matched) {
+                    result.add(aClass.getName());
+                    collectExceptionHandlerClasses(aClass, result);
+                }
             } catch (NoClassDefFoundError | Exception ignored) {
             }
         }
@@ -902,6 +916,51 @@ public class Precompiler {
         }
     }
 
+    /**
+     * Auto-discover all classes under {@code 
org.apache.skywalking.oap.query.*.entity} packages.
+     * These are Jackson-serialized POJOs (Lombok {@code @Data}) returned by 
Armeria HTTP handlers
+     * in query plugins (PromQL, LogQL, TraceQL, etc.). Inner static classes 
and codec serializers
+     * are included. Enums are excluded (Jackson handles them without 
reflection metadata).
+     *
+     * <p>This replaces hardcoded class lists — new query plugins are picked 
up automatically.
+     */
+    private static List<String> scanQueryEntityClasses(
+        ImmutableSet<ClassPath.ClassInfo> allClasses) {
+
+        // Match: 
org.apache.skywalking.oap.query.<plugin>.entity[.<sub>].<ClassName>
+        Set<String> result = new HashSet<>();
+        for (ClassPath.ClassInfo classInfo : allClasses) {
+            String name = classInfo.getName();
+            if (!name.startsWith("org.apache.skywalking.oap.query.")) {
+                continue;
+            }
+            // Check that the package contains ".entity."
+            String afterQuery = 
name.substring("org.apache.skywalking.oap.query.".length());
+            if (afterQuery.indexOf(".entity.") < 0) {
+                continue;
+            }
+            try {
+                Class<?> aClass = classInfo.load();
+                if (aClass.isInterface()) {
+                    continue;
+                }
+                result.add(aClass.getName());
+                // Also include inner static classes (e.g. 
SearchResponse$Trace, StreamLog$Result)
+                for (Class<?> inner : aClass.getDeclaredClasses()) {
+                    if (!inner.isInterface()) {
+                        result.add(inner.getName());
+                    }
+                }
+            } catch (NoClassDefFoundError | Exception ignored) {
+            }
+        }
+
+        List<String> sorted = new ArrayList<>(result);
+        Collections.sort(sorted);
+        log.info("Scanned query entity classes: {} classes", sorted.size());
+        return sorted;
+    }
+
     @SuppressWarnings("unchecked")
     private static Class<? extends Annotation> loadAnnotation(String fqcn) {
         try {
@@ -1328,8 +1387,10 @@ public class Precompiler {
         }
 
         // Armeria HTTP handlers — full access (Armeria reflects on 
@Post/@Get/@Path method annotations)
+        // Query entity classes — full access (Jackson serializes @Data POJOs 
in HTTP responses)
         String[] httpHandlerManifests = {
-            "ArmeriaHandlers.txt", "GraphQLResolvers.txt", "GraphQLTypes.txt"
+            "ArmeriaHandlers.txt", "GraphQLResolvers.txt", "GraphQLTypes.txt",
+            "QueryEntityClasses.txt"
         };
         for (String manifest : httpHandlerManifests) {
             Path file = annotationScanDir.resolve(manifest);
diff --git 
a/build-tools/precompiler/src/main/resources/META-INF/module-config-classes.txt 
b/build-tools/precompiler/src/main/resources/META-INF/module-config-classes.txt
index 83c14b4..12fb33e 100644
--- 
a/build-tools/precompiler/src/main/resources/META-INF/module-config-classes.txt
+++ 
b/build-tools/precompiler/src/main/resources/META-INF/module-config-classes.txt
@@ -1,8 +1,9 @@
-org.apache.skywalking.oap.log.analyzer.provider.LogAnalyzerModuleConfig
+org.apache.skywalking.oap.log.analyzer.v2.provider.LogAnalyzerModuleConfig
 org.apache.skywalking.oap.query.debug.StatusQueryConfig
 org.apache.skywalking.oap.query.graphql.GraphQLQueryConfig
 org.apache.skywalking.oap.query.logql.LogQLConfig
 org.apache.skywalking.oap.query.promql.PromQLConfig
+org.apache.skywalking.oap.query.traceql.TraceQLConfig
 org.apache.skywalking.oap.query.zipkin.ZipkinQueryConfig
 org.apache.skywalking.oap.server.ai.pipeline.AIPipelineConfig
 org.apache.skywalking.oap.server.analyzer.agent.kafka.module.KafkaFetcherConfig
diff --git a/changes/changes.md b/changes/changes.md
index 9836004..a31ea23 100644
--- a/changes/changes.md
+++ b/changes/changes.md
@@ -32,16 +32,27 @@ Upgrade to the latest Apache SkyWalking OAP server, with 
documentation restructu
 - `release/full-release.sh`: end-to-end release script.
 - Generate vote email template with GPG signer info and submodule commit IDs.
 
+### New Module
+
+- Add TraceQL module (Tempo-compatible trace query API) with Zipkin and 
SkyWalking datasource support.
+
 ### Testing
 
 - Replacement class staleness detector: add auto-discovery coverage check for 
untracked same-FQCN replacements in `oap-libs-for-graalvm/`.
 
 ### E2E Tests
 
+- Add PromQL e2e test case (Prometheus-compatible query API).
+- Add LogQL e2e test case (Loki-compatible log query API).
+- Add TraceQL e2e test case (Tempo-compatible trace query API with Zipkin 
datasource).
 - Update BanyanDB to `e1ba421` (fixes Zipkin `minDuration` trace query).
 - Bump Istio to 1.28.0.
 - Add Baseline e2e test case.
 
+### Build
+
+- Fix Armeria handler scan to detect inherited `@Get`/`@Path` annotations 
(precompiler).
+
 ## 0.1.0
 
 ### Highlights
diff --git a/docs/distro-policy.md b/docs/distro-policy.md
index 6168eb4..dcbd9e5 100644
--- a/docs/distro-policy.md
+++ b/docs/distro-policy.md
@@ -18,7 +18,7 @@ Build and package Apache SkyWalking OAP server as a GraalVM 
native image on JDK
 | **Configuration** | ConfigurationModule | Kubernetes |
 | **Receivers** | SharingServerModule, TraceModule, JVMModule, 
MeterReceiverModule, LogModule, RegisterModule, ProfileModule, BrowserModule, 
EventModule, OtelMetricReceiverModule, MeshReceiverModule, 
EnvoyMetricReceiverModule, ZipkinReceiverModule, ZabbixReceiverModule, 
TelegrafReceiverModule, AWSFirehoseReceiverModule, CiliumFetcherModule, 
EBPFReceiverModule, AsyncProfilerModule, PprofModule, CLRModule, 
ConfigurationDiscoveryModule, KafkaFetcherModule | default providers |
 | **Analyzers** | AnalyzerModule, LogAnalyzerModule, EventAnalyzerModule | 
default providers |
-| **Query** | QueryModule (GraphQL), PromQLModule, LogQLModule, 
ZipkinQueryModule, StatusQueryModule | default providers |
+| **Query** | QueryModule (GraphQL), PromQLModule, LogQLModule, TraceQLModule, 
ZipkinQueryModule, StatusQueryModule | default providers |
 | **Alarm** | AlarmModule | default |
 | **Telemetry** | TelemetryModule | Prometheus |
 | **Other** | ExporterModule, HealthCheckerModule, AIPipelineModule | default 
providers |
@@ -289,7 +289,7 @@ All four DSL compilers (OAL/MAL/LAL/Hierarchy) use ANTLR4 + 
Javassist v2 engines
 
 ### Remaining Verification
 - Verify all receiver plugins work (gRPC + HTTP endpoints)
-- Verify all query APIs work (GraphQL, PromQL, LogQL, Zipkin)
+- Verify all query APIs work (GraphQL, PromQL, LogQL, TraceQL, Zipkin)
 - Verify cluster mode (K8s)
 - Verify alarm module
 - Performance benchmarking vs JVM
diff --git a/oap-graalvm-server/pom.xml b/oap-graalvm-server/pom.xml
index ef5ed9b..ec00bdc 100644
--- a/oap-graalvm-server/pom.xml
+++ b/oap-graalvm-server/pom.xml
@@ -316,6 +316,10 @@
             <groupId>org.apache.skywalking</groupId>
             <artifactId>zipkin-query-plugin</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>traceql-plugin</artifactId>
+        </dependency>
         <!-- Alarm -->
         <dependency>
             <groupId>org.apache.skywalking</groupId>
diff --git 
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
 
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
index ff31bd3..be81a02 100644
--- 
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
+++ 
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/graalvm/GraalVMOAPServerStartUp.java
@@ -111,6 +111,8 @@ import org.apache.skywalking.oap.query.promql.PromQLModule;
 import org.apache.skywalking.oap.query.promql.PromQLProvider;
 import org.apache.skywalking.oap.query.logql.LogQLModule;
 import org.apache.skywalking.oap.query.logql.LogQLProvider;
+import org.apache.skywalking.oap.query.traceql.TraceQLModule;
+import org.apache.skywalking.oap.query.traceql.TraceQLProvider;
 import org.apache.skywalking.oap.query.debug.StatusQueryModule;
 import org.apache.skywalking.oap.query.debug.StatusQueryProvider;
 // Exporter
@@ -252,6 +254,9 @@ public class GraalVMOAPServerStartUp {
         }
         manager.register(new PromQLModule(), new PromQLProvider());
         manager.register(new LogQLModule(), new LogQLProvider());
+        if (configuration.has("traceQL")) {
+            manager.register(new TraceQLModule(), new TraceQLProvider());
+        }
         manager.register(new StatusQueryModule(), new StatusQueryProvider());
 
         // Alarm
diff --git 
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
 
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
index a300b77..4b9b479 100644
--- 
a/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
+++ 
b/oap-graalvm-server/src/main/java/org/apache/skywalking/oap/server/library/util/YamlConfigLoaderUtils.java
@@ -31,6 +31,7 @@ import 
org.apache.skywalking.oap.query.debug.StatusQueryConfig;
 import org.apache.skywalking.oap.query.graphql.GraphQLQueryConfig;
 import org.apache.skywalking.oap.query.logql.LogQLConfig;
 import org.apache.skywalking.oap.query.promql.PromQLConfig;
+import org.apache.skywalking.oap.query.traceql.TraceQLConfig;
 import org.apache.skywalking.oap.query.zipkin.ZipkinQueryConfig;
 import org.apache.skywalking.oap.server.ai.pipeline.AIPipelineConfig;
 import 
org.apache.skywalking.oap.server.analyzer.agent.kafka.module.KafkaFetcherConfig;
@@ -148,6 +149,8 @@ public class YamlConfigLoaderUtils {
             copyToPromQLConfig((PromQLConfig) dest, src, moduleName, 
providerName);
         } else if (dest instanceof LogQLConfig) {
             copyToLogQLConfig((LogQLConfig) dest, src, moduleName, 
providerName);
+        } else if (dest instanceof TraceQLConfig) {
+            copyToTraceQLConfig((TraceQLConfig) dest, src, moduleName, 
providerName);
         } else if (dest instanceof PrometheusConfig) {
             copyToPrometheusConfig((PrometheusConfig) dest, src, moduleName, 
providerName);
         } else if (dest instanceof ExporterSetting) {
@@ -850,6 +853,48 @@ public class YamlConfigLoaderUtils {
         }
     }
 
+    @SuppressWarnings("unchecked")
+    private static void copyToTraceQLConfig(
+            final TraceQLConfig cfg, final Properties src,
+            final String moduleName, final String providerName) {
+        final Enumeration<?> propertyNames = src.propertyNames();
+        while (propertyNames.hasMoreElements()) {
+            final String key = (String) propertyNames.nextElement();
+            final Object value = src.get(key);
+            log.debug("{}.{} config: {} = {}", moduleName, providerName, key, 
value);
+            switch (key) {
+                case "restHost":
+                    cfg.setRestHost((String) value);
+                    break;
+                case "restPort":
+                    cfg.setRestPort(((Number) value).intValue());
+                    break;
+                case "enableDatasourceZipkin":
+                    cfg.setEnableDatasourceZipkin((boolean) value);
+                    break;
+                case "enableDatasourceSkywalking":
+                    cfg.setEnableDatasourceSkywalking((boolean) value);
+                    break;
+                case "restContextPathZipkin":
+                    cfg.setRestContextPathZipkin((String) value);
+                    break;
+                case "restContextPathSkywalking":
+                    cfg.setRestContextPathSkywalking((String) value);
+                    break;
+                case "restIdleTimeOut":
+                    cfg.setRestIdleTimeOut(((Number) value).longValue());
+                    break;
+                case "restAcceptQueueSize":
+                    cfg.setRestAcceptQueueSize(((Number) value).intValue());
+                    break;
+                default:
+                    log.warn("{} setting is not supported in {} provider of {} 
module",
+                        key, providerName, moduleName);
+                    break;
+            }
+        }
+    }
+
     @SuppressWarnings("unchecked")
     private static void copyToPrometheusConfig(
             final PrometheusConfig cfg, final Properties src,
diff --git a/oap-graalvm-server/src/main/resources/application.yml 
b/oap-graalvm-server/src/main/resources/application.yml
index 1248b0a..ab08eaf 100644
--- a/oap-graalvm-server/src/main/resources/application.yml
+++ b/oap-graalvm-server/src/main/resources/application.yml
@@ -300,6 +300,18 @@ logql:
     restIdleTimeOut: ${SW_LOGQL_REST_IDLE_TIMEOUT:30000}
     restAcceptQueueSize: ${SW_LOGQL_REST_QUEUE_SIZE:0}
 
+traceQL:
+  selector: ${SW_TRACEQL:-}
+  default:
+    restHost: ${SW_TRACEQL_REST_HOST:0.0.0.0}
+    restPort: ${SW_TRACEQL_REST_PORT:3200}
+    enableDatasourceZipkin: ${SW_TRACEQL_ENABLE_DATASOURCE_ZIPKIN:false}
+    enableDatasourceSkywalking: 
${SW_TRACEQL_ENABLE_DATASOURCE_SKYWALKING:false}
+    restContextPathZipkin: ${SW_TRACEQL_REST_CONTEXT_PATH_ZIPKIN:/zipkin}
+    restContextPathSkywalking: 
${SW_TRACEQL_REST_CONTEXT_PATH_SKYWALKING:/skywalking}
+    restIdleTimeOut: ${SW_TRACEQL_REST_IDLE_TIMEOUT:30000}
+    restAcceptQueueSize: ${SW_TRACEQL_REST_QUEUE_SIZE:0}
+
 alarm:
   selector: ${SW_ALARM:default}
   default:
diff --git a/pom.xml b/pom.xml
index e0d97d6..e8733c1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -295,6 +295,11 @@
                 <artifactId>logql-plugin</artifactId>
                 <version>${skywalking.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.skywalking</groupId>
+                <artifactId>traceql-plugin</artifactId>
+                <version>${skywalking.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.apache.skywalking</groupId>
                 <artifactId>zipkin-query-plugin</artifactId>
diff --git a/test/e2e/cases/logql/docker-compose.yml 
b/test/e2e/cases/logql/docker-compose.yml
new file mode 100644
index 0000000..cfa4b50
--- /dev/null
+++ b/test/e2e/cases/logql/docker-compose.yml
@@ -0,0 +1,162 @@
+# 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.
+
+services:
+  banyandb:
+    extends:
+      file: 
../../../../skywalking/test/e2e-v2/script/docker-compose/base-compose.yml
+      service: banyandb
+    ports:
+      - 17912
+
+  oap:
+    image: skywalking-oap-native:latest
+    expose:
+      - 11800
+      - 12800
+      - 3100
+    networks:
+      - e2e
+    ports:
+      - 12800
+      - 3100
+    environment:
+      SW_HEALTH_CHECKER: default
+      SW_STORAGE_BANYANDB_TARGETS: banyandb:17912
+      SW_CONFIGURATION: none
+      SW_LOG_LAL_FILES: default
+      SW_LOG_MAL_FILES: ""
+    depends_on:
+      banyandb:
+        condition: service_healthy
+    healthcheck:
+      test: ["CMD-SHELL", "nc -nz 127.0.0.1 11800 || exit 1"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+  # Init containers: copy pre-built service JARs into a shared volume
+  provider-jar:
+    image: 
"ghcr.io/apache/skywalking/e2e-service-provider:${SW_E2E_SERVICE_COMMIT}"
+    entrypoint: ["cp", "/app.jar", "/jars/services_provider.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+
+  consumer-jar:
+    image: 
"ghcr.io/apache/skywalking/e2e-service-consumer:${SW_E2E_SERVICE_COMMIT}"
+    entrypoint: ["cp", "/app.jar", "/jars/services_consumer.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+
+  provider:
+    image: 
"ghcr.io/apache/skywalking-java/skywalking-java:${SW_AGENT_JAVA_COMMIT}-java${SW_AGENT_JDK_VERSION}"
+    command: ["java", "-jar", "/jars/services_provider.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+    expose:
+      - 9090
+    ports:
+      - 9090
+    environment:
+      SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+      SW_LOGGING_OUTPUT: CONSOLE
+      SW_AGENT_NAME: e2e-service-provider
+      SW_AGENT_INSTANCE_NAME: provider1
+      SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL: 1
+      SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL: 1
+      SW_METER_ACTIVE: 'false'
+    healthcheck:
+      test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9090"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    depends_on:
+      oap:
+        condition: service_healthy
+      provider-jar:
+        condition: service_completed_successfully
+
+  provider2:
+    image: 
"ghcr.io/apache/skywalking-java/skywalking-java:${SW_AGENT_JAVA_COMMIT}-java${SW_AGENT_JDK_VERSION}"
+    command: ["java", "-jar", "/jars/services_provider.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+    expose:
+      - 9090
+    ports:
+      - 9090
+    environment:
+      SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+      SW_LOGGING_OUTPUT: CONSOLE
+      SW_AGENT_NAME: e2e-service-provider
+      SW_AGENT_INSTANCE_NAME: provider2
+      SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL: 1
+      SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL: 1
+      SW_METER_ACTIVE: 'false'
+    healthcheck:
+      test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9090"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    depends_on:
+      oap:
+        condition: service_healthy
+      provider-jar:
+        condition: service_completed_successfully
+
+  consumer:
+    image: 
"ghcr.io/apache/skywalking-java/skywalking-java:${SW_AGENT_JAVA_COMMIT}-java${SW_AGENT_JDK_VERSION}"
+    command: ["java", "-jar", "/jars/services_consumer.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+    expose:
+      - 9092
+    ports:
+      - 9092
+    environment:
+      SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+      SW_LOGGING_OUTPUT: CONSOLE
+      PROVIDER_URL: http://provider:9090
+      SW_AGENT_NAME: e2e-service-consumer
+      SW_AGENT_INSTANCE_NAME: consumer1
+      SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL: 1
+      SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL: 1
+      SW_METER_ACTIVE: 'false'
+    healthcheck:
+      test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9092"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    depends_on:
+      provider:
+        condition: service_healthy
+      consumer-jar:
+        condition: service_completed_successfully
+
+volumes:
+  service-jars:
+
+networks:
+  e2e:
diff --git a/test/e2e/cases/logql/e2e.yaml b/test/e2e/cases/logql/e2e.yaml
new file mode 100644
index 0000000..1e76432
--- /dev/null
+++ b/test/e2e/cases/logql/e2e.yaml
@@ -0,0 +1,51 @@
+# 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.
+
+# LogQL E2E — native OAP with BanyanDB
+# Tests the Loki-compatible log query API (LogQL module).
+# Upstream uses Elasticsearch but LogQL is storage-agnostic;
+# BanyanDB supports the same log query operations.
+# Reuses upstream verification cases and expected files.
+
+setup:
+  env: compose
+  file: docker-compose.yml
+  timeout: 20m
+  init-system-environment: ../../script/env
+  steps:
+    - name: set PATH
+      command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
+    - name: install yq
+      command: bash 
skywalking/test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
+    - name: install swctl
+      command: bash 
skywalking/test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
+
+trigger:
+  action: http
+  interval: 3s
+  times: -1
+  url: http://${consumer_host}:${consumer_9092}/users
+  method: POST
+  body: '{"id":"123","name":"skywalking"}'
+  headers:
+    "Content-Type": "application/json"
+
+verify:
+  retry:
+    count: 20
+    interval: 3s
+  cases:
+    - includes:
+        - ../../../../skywalking/test/e2e-v2/cases/logql/logql-cases.yaml
diff --git a/test/e2e/cases/promql/docker-compose.yml 
b/test/e2e/cases/promql/docker-compose.yml
new file mode 100644
index 0000000..7d334ac
--- /dev/null
+++ b/test/e2e/cases/promql/docker-compose.yml
@@ -0,0 +1,130 @@
+# 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.
+
+services:
+  banyandb:
+    extends:
+      file: 
../../../../skywalking/test/e2e-v2/script/docker-compose/base-compose.yml
+      service: banyandb
+    ports:
+      - 17912
+
+  oap:
+    image: skywalking-oap-native:latest
+    expose:
+      - 11800
+      - 12800
+      - 9090
+    networks:
+      - e2e
+    ports:
+      - 12800
+      - 9090
+    environment:
+      SW_HEALTH_CHECKER: default
+      SW_STORAGE_BANYANDB_TARGETS: banyandb:17912
+      SW_CONFIGURATION: none
+    depends_on:
+      banyandb:
+        condition: service_healthy
+    healthcheck:
+      test: ["CMD-SHELL", "nc -nz 127.0.0.1 11800 || exit 1"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+  # Init containers: copy pre-built service JARs into a shared volume
+  provider-jar:
+    image: 
"ghcr.io/apache/skywalking/e2e-service-provider:${SW_E2E_SERVICE_COMMIT}"
+    entrypoint: ["cp", "/app.jar", "/jars/services_provider.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+
+  consumer-jar:
+    image: 
"ghcr.io/apache/skywalking/e2e-service-consumer:${SW_E2E_SERVICE_COMMIT}"
+    entrypoint: ["cp", "/app.jar", "/jars/services_consumer.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+
+  provider:
+    image: 
"ghcr.io/apache/skywalking-java/skywalking-java:${SW_AGENT_JAVA_COMMIT}-java${SW_AGENT_JDK_VERSION}"
+    command: ["java", "-jar", "/jars/services_provider.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+    expose:
+      - 9090
+    ports:
+      - 9090
+    environment:
+      SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+      SW_LOGGING_OUTPUT: CONSOLE
+      SW_AGENT_NAME: e2e-service-provider
+      SW_AGENT_INSTANCE_NAME: provider1
+      SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL: 1
+      SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL: 1
+      SW_METER_ACTIVE: 'false'
+    healthcheck:
+      test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9090"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    depends_on:
+      oap:
+        condition: service_healthy
+      provider-jar:
+        condition: service_completed_successfully
+
+  consumer:
+    image: 
"ghcr.io/apache/skywalking-java/skywalking-java:${SW_AGENT_JAVA_COMMIT}-java${SW_AGENT_JDK_VERSION}"
+    command: ["java", "-jar", "/jars/services_consumer.jar"]
+    volumes:
+      - service-jars:/jars
+    networks:
+      - e2e
+    expose:
+      - 9092
+    ports:
+      - 9092
+    environment:
+      SW_AGENT_COLLECTOR_BACKEND_SERVICES: oap:11800
+      SW_LOGGING_OUTPUT: CONSOLE
+      PROVIDER_URL: http://provider:9090
+      SW_AGENT_NAME: e2e-service-consumer
+      SW_AGENT_INSTANCE_NAME: consumer1
+      SW_AGENT_COLLECTOR_GET_PROFILE_TASK_INTERVAL: 1
+      SW_AGENT_COLLECTOR_GET_AGENT_DYNAMIC_CONFIG_INTERVAL: 1
+      SW_METER_ACTIVE: 'false'
+    healthcheck:
+      test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/9092"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+    depends_on:
+      provider:
+        condition: service_healthy
+      consumer-jar:
+        condition: service_completed_successfully
+
+volumes:
+  service-jars:
+
+networks:
+  e2e:
diff --git a/test/e2e/cases/promql/e2e.yaml b/test/e2e/cases/promql/e2e.yaml
new file mode 100644
index 0000000..455f158
--- /dev/null
+++ b/test/e2e/cases/promql/e2e.yaml
@@ -0,0 +1,51 @@
+# 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.
+
+# PromQL E2E — native OAP with BanyanDB
+# Tests the Prometheus-compatible query API (PromQL module).
+# Reuses upstream verification cases and expected files.
+# Note: upstream mounts a custom core.oal but our native image uses
+# pre-compiled OAL which is a superset — all queried metrics exist.
+
+setup:
+  env: compose
+  file: docker-compose.yml
+  timeout: 20m
+  init-system-environment: ../../script/env
+  steps:
+    - name: set PATH
+      command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
+    - name: install yq
+      command: bash 
skywalking/test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
+    - name: install swctl
+      command: bash 
skywalking/test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
+
+trigger:
+  action: http
+  interval: 3s
+  times: -1
+  url: http://${consumer_host}:${consumer_9092}/users
+  method: POST
+  body: '{"id":"123","name":"skywalking"}'
+  headers:
+    "Content-Type": "application/json"
+
+verify:
+  retry:
+    count: 20
+    interval: 3s
+  cases:
+    - includes:
+        - promql-cases.yaml
diff --git a/test/e2e/cases/promql/promql-cases.yaml 
b/test/e2e/cases/promql/promql-cases.yaml
new file mode 100644
index 0000000..6b87bea
--- /dev/null
+++ b/test/e2e/cases/promql/promql-cases.yaml
@@ -0,0 +1,155 @@
+# 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.
+
+# PromQL E2E cases for native image distro.
+# Based on upstream promql-cases.yaml but excludes service_percentile_old cases
+# (that metric requires a custom core.oal which native image cannot load at 
runtime).
+
+cases:
+  # traffics query
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=service_traffic{layer="GENERAL"}&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-traffic.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=service_traffic{layer="GENERAL"}&limit=1&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-traffic-limit.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=service_traffic{layer="GENERAL",limit="1"}&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-traffic-limit.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=service_traffic{layer="GENERAL",service=~".*-provider"}&start='$(($(date
 +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-traffic-limit.yml
+    #RFC3339
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=service_traffic{layer="GENERAL"}&start='$(($(date 
+%s)-1800))'&end='$(date -u +%Y-%m-%dT%H:%M:%S.111Z)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-traffic.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=instance_traffic{layer="GENERAL", 
service="e2e-service-provider"}&limit=1&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-traffic.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=instance_traffic{layer="GENERAL", service="e2e-service-provider", 
service_instance=~"provider1|provider2"}&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-traffic.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=endpoint_traffic{layer="GENERAL", service="e2e-service-provider", 
keyword="POST:/users"}&limit=1&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-traffic.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=endpoint_traffic{layer="GENERAL", service="e2e-service-provider", 
endpoint=~"^POST:.*"}&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-traffic.yml
+  # metrics series
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=service_cpm&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-series.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=service_instance_cpm&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-metric-series.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/series -d 
'match[]=endpoint_cpm&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-metric-series.yml
+  # traffic names query
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/service/values -d 
'match[]=service_traffic{layer="GENERAL"}&start='$(($(date 
+%s)-1800))'&end='$(date -u +%Y-%m-%dT%H:%M:%S.111Z)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-names.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/service/values -d 
'match[]=service_traffic{layer="GENERAL",limit="1"}&start='$(($(date 
+%s)-1800))'&end='$(date -u +%Y-%m-%dT%H:%M:%S.111Z)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-names-limit.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/service/values -d 
'match[]=service_traffic{layer="GENERAL"}&limit=1'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-names-limit.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/service/values -d 
'match[]=service_traffic{layer="GENERAL",service=~".*-provider"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-names-limit.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/service_instance/values -d 
'match[]=instance_traffic{layer="GENERAL", 
service="e2e-service-provider"}&limit=1'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-names.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/service_instance/values -d 
'match[]=instance_traffic{layer="GENERAL", service="e2e-service-provider", 
service_instance=~"provider1|provider2"}&limit=1'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-names.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/endpoint/values -d 
'match[]=endpoint_traffic{layer="GENERAL", service="e2e-service-provider", 
keyword="POST:/users"}&limit=1'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-names.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/endpoint/values -d 
'match[]=endpoint_traffic{layer="GENERAL", service="e2e-service-provider", 
endpoint=~"^POST:.*"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-names.yml
+  # metrics names query
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/__name__/values
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/metrics-names.yml
+  - query: curl -X GET 
http://${oap_host}:${oap_9090}/api/v1/label/__name__/values -d 
'start='$(($(date +%s)-1800))'&end='$(date -u +%Y-%m-%dT%H:%M:%S.111Z)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/metrics-names.yml
+  # labels query
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/labels -d 
'match[]=service_cpm'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-label.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/labels -d 
'match[]=service_cpm&start='$(($(date +%s)-1800))'&end='$(date -u 
+%Y-%m-%dT%H:%M:%S.111Z)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-label.yml
+  - query: |
+      sleep 30;
+      curl -X GET http://${oap_host}:${oap_9090}/api/v1/labels -d 
'match[]=service_percentile'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-labeled-metric-label-p.yml
+  # NOTE: service_percentile_old case excluded — requires custom core.oal not 
available in native image
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/labels -d 
'match[]=service_instance_cpm'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-metric-label.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/labels -d 
'match[]=endpoint_cpm'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-metric-label.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/labels -d 
'match[]=endpoint_percentile'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-labeled-metric-label.yml
+  # metadata query
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/metadata -d 
'metric=service_cpm&limit=10'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/metric-metadata.yml
+  # metrics query
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_sla{service="e2e-service-consumer", layer="GENERAL"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-vector.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_sla{service="e2e-service-consumer", layer="GENERAL"}[30m]'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-matrix.yml
+    #RFC3339
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_sla{service="e2e-service-consumer", 
layer="GENERAL"}[30m]&time='$(date -u +%Y-%m-%dT%H:%M:%SZ)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-matrix.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_percentile{service="e2e-service-consumer", layer="GENERAL", 
p="50,75,90"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-labeled-vector.yml
+  # NOTE: service_percentile_old case excluded — requires custom core.oal not 
available in native image
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_percentile{service="e2e-service-consumer", layer="GENERAL", 
p="50,75,90"}[30m]'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_cpm{layer="GENERAL",top_n="10", order="DES"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-sort-vector.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_cpm{layer="GENERAL",top_n="10", order="DES"}[30m]'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-sort-matrix.yml
+  ## multiple metrics operation query
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_sla{service="e2e-service-consumer", layer="GENERAL"} %2B 
service_sla{service="e2e-service-consumer", layer="GENERAL"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-vector-add.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_sla{service="e2e-service-consumer", layer="GENERAL"}[30m] %2B 
service_sla{service="e2e-service-consumer", layer="GENERAL"}[30m]'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-matrix-add.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_sla{service="e2e-service-consumer", layer="GENERAL"}[30m] == 
service_sla{service="e2e-service-consumer", layer="GENERAL"}[30m]'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-matrix-compare.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_percentile{service="e2e-service-consumer", layer="GENERAL", 
p="99"} - service_percentile{service="e2e-service-consumer", layer="GENERAL", 
p="99"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-labeled-compare-matrix.yml
+  ## query_range
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=service_sla{service="e2e-service-consumer", 
layer="GENERAL"}&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-matrix.yml
+    #RFC3339
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=service_sla{service="e2e-service-consumer", 
layer="GENERAL"}&start='$(($(date +%s)-1800))'&end='$(date -u 
+%Y-%m-%dT%H:%M:%S.0Z)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-matrix.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=service_percentile{service="e2e-service-consumer", layer="GENERAL", 
p="50,75,90"}&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=sum by (p) (service_percentile{service="e2e-service-consumer", 
layer="GENERAL", p="50,75,90"})&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-by-p.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=sum by (p) (service_percentile{service="e2e-service-consumer", 
layer="GENERAL", p="50,75,90"}[30m])'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-by-p.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=sum without (p) (service_percentile{service="e2e-service-consumer", 
layer="GENERAL", p="50,75,90"})&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-labeled-matrix-aggregate-without-p.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=service_cpm{layer="GENERAL",top_n="10", order="DES"}&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/service-metric-sort-matrix.yml
+  ## instance
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_instance_sla{service="e2e-service-consumer", layer="GENERAL", 
service_instance="consumer1"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-metric-vector.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=service_instance_sla{service="e2e-service-consumer", layer="GENERAL", 
service_instance="consumer1"}&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-metric-matrix.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=service_instance_cpm{parent_service="e2e-service-consumer", 
layer="GENERAL",top_n="10", order="DES"}&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/instance-metric-sort-matrix.yml
+  ## endpoint
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=endpoint_sla{service="e2e-service-consumer", layer="GENERAL", 
endpoint="POST:/users"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-metric-vector.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=endpoint_sla{service="e2e-service-consumer", layer="GENERAL", 
endpoint="POST:/users"}&start='$(($(date +%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-metric-matrix.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=endpoint_percentile{service="e2e-service-consumer", layer="GENERAL", 
p="50,75,90", endpoint="POST:/users"}&start='$(($(date +%s)-1800))'&end='$(date 
+%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-metric-labeled-matrix.yml
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query_range -d 
'query=endpoint_cpm{parent_service="e2e-service-consumer", 
layer="GENERAL",top_n="10", order="DES"}&start='$(($(date 
+%s)-1800))'&end='$(date +%s)
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/endpoint-metric-sort-matrix.yml
+  ## ServiceRelation
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_relation_client_cpm{service="e2e-service-consumer", 
dest_service="e2e-service-provider",layer="GENERAL", dest_layer="GENERAL"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/relation-metric-vector.yml
+  ## ServiceInstanceRelation
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=service_instance_relation_client_cpm{service="e2e-service-consumer", 
dest_service="e2e-service-provider",layer="GENERAL", 
dest_layer="GENERAL",dest_service_instance="provider1",service_instance="consumer1"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/relation-metric-vector.yml
+  ## EndPointRelation
+  - query: curl -X GET http://${oap_host}:${oap_9090}/api/v1/query -d 
'query=endpoint_relation_cpm{service="e2e-service-consumer", 
dest_service="e2e-service-provider",layer="GENERAL", 
dest_layer="GENERAL",dest_endpoint="POST:/users",endpoint="POST:/users"}'
+    expected: 
../../../../skywalking/test/e2e-v2/cases/promql/expected/relation-metric-vector.yml
diff --git a/test/e2e/cases/traceql/docker-compose.yml 
b/test/e2e/cases/traceql/docker-compose.yml
new file mode 100644
index 0000000..5a1ad54
--- /dev/null
+++ b/test/e2e/cases/traceql/docker-compose.yml
@@ -0,0 +1,74 @@
+# 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.
+
+services:
+  banyandb:
+    extends:
+      file: 
../../../../skywalking/test/e2e-v2/script/docker-compose/base-compose.yml
+      service: banyandb
+    ports:
+      - 17912
+
+  oap:
+    image: skywalking-oap-native:latest
+    expose:
+      - 11800
+      - 12800
+      - 9411
+      - 3200
+    networks:
+      - e2e
+    ports:
+      - 9412
+      - 3200
+    environment:
+      SW_HEALTH_CHECKER: default
+      SW_STORAGE_BANYANDB_TARGETS: banyandb:17912
+      SW_CONFIGURATION: none
+      SW_QUERY_ZIPKIN: default
+      SW_RECEIVER_ZIPKIN: default
+      SW_TRACEQL: default
+      SW_TRACEQL_ENABLE_DATASOURCE_ZIPKIN: "true"
+    depends_on:
+      banyandb:
+        condition: service_healthy
+    healthcheck:
+      test: ["CMD-SHELL", "nc -nz 127.0.0.1 11800 || exit 1"]
+      interval: 5s
+      timeout: 60s
+      retries: 120
+
+  frontend:
+    extends:
+      file: 
../../../../skywalking/test/e2e-v2/cases/zipkin/docker-compose-brave.yml
+      service: frontend
+    depends_on:
+      backend:
+        condition: service_healthy
+      oap:
+        condition: service_healthy
+    ports:
+      - 8081
+
+  backend:
+    extends:
+      file: 
../../../../skywalking/test/e2e-v2/cases/zipkin/docker-compose-brave.yml
+      service: backend
+    depends_on:
+      oap:
+        condition: service_healthy
+
+networks:
+  e2e:
diff --git a/test/e2e/cases/traceql/e2e.yaml b/test/e2e/cases/traceql/e2e.yaml
new file mode 100644
index 0000000..ca9046c
--- /dev/null
+++ b/test/e2e/cases/traceql/e2e.yaml
@@ -0,0 +1,48 @@
+# 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.
+
+# TraceQL E2E — native OAP with BanyanDB
+# Tests the Tempo-compatible TraceQL query API with Zipkin datasource.
+# Reuses upstream verification cases and expected files.
+
+setup:
+  env: compose
+  file: docker-compose.yml
+  timeout: 20m
+  init-system-environment: ../../script/env
+  steps:
+    - name: set PATH
+      command: export PATH=/tmp/skywalking-infra-e2e/bin:$PATH
+    - name: install yq
+      command: bash 
skywalking/test/e2e-v2/script/prepare/setup-e2e-shell/install.sh yq
+    - name: install swctl
+      command: bash 
skywalking/test/e2e-v2/script/prepare/setup-e2e-shell/install.sh swctl
+    - name: install jq
+      command: bash 
skywalking/test/e2e-v2/script/prepare/setup-e2e-shell/install.sh jq
+
+trigger:
+  action: http
+  interval: 3s
+  times: -1
+  url: http://${frontend_host}:${frontend_8081}/
+  method: POST
+
+verify:
+  retry:
+    count: 20
+    interval: 10s
+  cases:
+    - includes:
+        - 
../../../../skywalking/test/e2e-v2/cases/traceql/zipkin/traceql-cases.yaml

Reply via email to