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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3b44e000403 [fix](fe) Preserve effective Compute Group for audit logs 
(#66281)
3b44e000403 is described below

commit 3b44e000403c729d907e47b1de69bf57325a8cd8
Author: deardeng <[email protected]>
AuthorDate: Mon Aug 3 14:22:48 2026 +0800

    [fix](fe) Preserve effective Compute Group for audit logs (#66281)
    
    Problem Summary: In Cloud mode, a per-query SET_VAR(cloud_cluster=...)
    temporarily changes the session variable used by query scheduling.
    StmtExecutor reverted this value before AuditLogHelper built the audit
    event, so ComputeGroupName and related per-Compute-Group query, error,
    and latency metrics were attributed to the session's original Compute
    Group even though the query ran on the hinted group. Preserve the
    query-scoped effective Compute Group before reverting SET_VAR and use it
    for both audit events and metrics, with fallback to the existing session
    resolution path.
---
 .../java/org/apache/doris/qe/AuditLogHelper.java   | 12 +++-
 .../java/org/apache/doris/qe/ConnectContext.java   | 11 ++++
 .../java/org/apache/doris/qe/StmtExecutor.java     |  6 ++
 .../org/apache/doris/qe/AuditLogHelperTest.java    |  9 +++
 ...test_audit_log_hint_compute_group_docker.groovy | 64 ++++++++++++++++++++++
 5 files changed, 99 insertions(+), 3 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java
index fddc42ecd60..32fa15d1bce 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/AuditLogHelper.java
@@ -227,7 +227,7 @@ public class AuditLogHelper {
         String cloudCluster = "";
         try {
             if (Config.isCloudMode()) {
-                cloudCluster = ctx.getCloudCluster(false);
+                cloudCluster = getCloudClusterForAudit(ctx);
             }
         } catch (ComputeGroupException e) {
             LOG.warn("Failed to get cloud cluster", e);
@@ -413,6 +413,13 @@ public class AuditLogHelper {
         return queueToken == null ? -1 : queueToken.getQueueEndTime() - 
queueToken.getQueueStartTime();
     }
 
+    static String getCloudClusterForAudit(ConnectContext ctx) throws 
ComputeGroupException {
+        if (!Strings.isNullOrEmpty(ctx.getEffectiveCloudCluster())) {
+            return ctx.getEffectiveCloudCluster();
+        }
+        return ctx.getCloudCluster(false);
+    }
+
     /**
      * Update query metrics without writing audit log. This is used when
      * enable_prepared_stmt_audit_log is disabled, to ensure QPS metrics
@@ -448,7 +455,7 @@ public class AuditLogHelper {
         String physicalClusterName = "";
         try {
             if (Config.isCloudMode()) {
-                cloudCluster = ctx.getCloudCluster(false);
+                cloudCluster = getCloudClusterForAudit(ctx);
                 physicalClusterName = ((CloudSystemInfoService) 
Env.getCurrentSystemInfo())
                     .getPhysicalCluster(cloudCluster);
                 if (!cloudCluster.equals(physicalClusterName)) {
@@ -512,4 +519,3 @@ public class AuditLogHelper {
         }
     }
 }
-
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
index ab5b37162c2..2b910dfa796 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectContext.java
@@ -216,6 +216,9 @@ public class ConnectContext {
 
     // cloud cluster name
     protected volatile String cloudCluster = null;
+    // The compute group selected for the statement currently being executed. 
Unlike cloudCluster,
+    // this value is query-scoped and remains available after a per-query 
SET_VAR is reverted.
+    protected volatile String effectiveCloudCluster = null;
 
     // If set to true, the nondeterministic function will not be rewrote to 
constant.
     private boolean notEvalNondeterministicFunction = false;
@@ -1446,6 +1449,14 @@ public class ConnectContext {
         this.getSessionVariable().setCloudCluster(cluster);
     }
 
+    public String getEffectiveCloudCluster() {
+        return effectiveCloudCluster;
+    }
+
+    public void setEffectiveCloudCluster(String cluster) {
+        this.effectiveCloudCluster = cluster;
+    }
+
     public String getCloudCluster() throws ComputeGroupException {
         return getCloudCluster(true);
     }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 7bad37645b7..b117b334f61 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -672,6 +672,7 @@ public class StmtExecutor {
 
     public void execute(TUniqueId queryId) throws Exception {
         SessionVariable sessionVariable = context.getSessionVariable();
+        context.setEffectiveCloudCluster(null);
         if (context.getConnectType() == ConnectType.ARROW_FLIGHT_SQL) {
             context.setReturnResultFromLocal(true);
         }
@@ -698,6 +699,11 @@ public class StmtExecutor {
                 throw e;
             }
         } finally {
+            // Preserve the effective per-query compute group before SET_VAR 
values are reverted.
+            // Audit logging runs after this method returns and otherwise sees 
the session value.
+            if (Config.isCloudMode()) {
+                
context.setEffectiveCloudCluster(sessionVariable.getCloudCluster());
+            }
             // Snapshot changed session variables (including SET_VAR hint 
values) BEFORE revert,
             // so the audit log (logged after execute() returns, i.e. after 
the revert below) can
             // reflect what was actually in effect for this statement instead 
of the reverted values.
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/qe/AuditLogHelperTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/qe/AuditLogHelperTest.java
index e1b6b8c961c..82afc4a02a1 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/qe/AuditLogHelperTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/qe/AuditLogHelperTest.java
@@ -101,4 +101,13 @@ public class AuditLogHelperTest {
             Config.enable_bdbje_debug_mode = original;
         }
     }
+
+    @Test
+    public void testGetCloudClusterForAuditPrefersEffectiveCluster() throws 
Exception {
+        ConnectContext ctx = createMockContext(true, false);
+        ctx.getSessionVariable().setCloudCluster("session_cluster");
+        ctx.setEffectiveCloudCluster("hint_cluster");
+
+        Assert.assertEquals("hint_cluster", 
AuditLogHelper.getCloudClusterForAudit(ctx));
+    }
 }
diff --git 
a/regression-test/suites/audit/test_audit_log_hint_compute_group_docker.groovy 
b/regression-test/suites/audit/test_audit_log_hint_compute_group_docker.groovy
new file mode 100644
index 00000000000..ce223bd110f
--- /dev/null
+++ 
b/regression-test/suites/audit/test_audit_log_hint_compute_group_docker.groovy
@@ -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.
+
+import org.apache.doris.regression.suite.ClusterOptions
+
+suite("test_audit_log_hint_compute_group_docker", "docker") {
+    def options = new ClusterOptions(cloudMode: true, feNum: 1, beNum: 1, 
msNum: 1)
+    options.feConfigs += ['cloud_cluster_check_interval_second=1']
+
+    docker(options) {
+        def hintComputeGroup = "audit_hint_compute_group"
+        cluster.addBackend(1, hintComputeGroup)
+
+        def computeGroups = sql_return_maparray "SHOW CLUSTERS"
+        assertEquals(2, computeGroups.size())
+        def sessionComputeGroup = computeGroups.find { it.is_current == "TRUE" 
}.cluster
+        assertNotNull(sessionComputeGroup)
+        assertTrue(computeGroups.any { it.cluster == hintComputeGroup })
+
+        try {
+            sql "set global enable_audit_plugin = true"
+            sql "use @${sessionComputeGroup}"
+            sql "truncate table __internal_schema.audit_log"
+
+            def marker = "audit_hint_cg_docker_marker_7F3A2B"
+            sql """select /*+ SET_VAR(cloud_cluster = '${hintComputeGroup}') */
+                       1, '${marker}'"""
+
+            def retry = 60
+            def query = """select count(*)
+                            from __internal_schema.audit_log
+                            where stmt like '%${marker}%'
+                              and compute_group = '${hintComputeGroup}'"""
+            def found = (sql "${query}")[0][0] as long
+            while (found == 0) {
+                if (retry-- < 0) {
+                    throw new RuntimeException("audit_log row for the hint 
query was not found in the "
+                            + "hint Compute Group")
+                }
+                sleep(3000)
+                sql "call flush_audit_log()"
+                found = (sql "${query}")[0][0] as long
+            }
+
+            assertTrue(found >= 1)
+        } finally {
+            sql "set global enable_audit_plugin = false"
+        }
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to