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

yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.2 by this push:
     new 00a36cdc9ab [fix](be) Keep credentials out of fragment execution logs 
(branch-4.2) (#69543)
00a36cdc9ab is described below

commit 00a36cdc9ab4f924cf652511800da6ca4aae19e0
Author: Oliveira <[email protected]>
AuthorDate: Sat Oct 24 10:36:53 2026 +0800

    [fix](be) Keep credentials out of fragment execution logs (branch-4.2) 
(#69543)
    
    ### What problem does this PR solve?
    
    Related PR: https://github.com/apache/doris/pull/69540
    
    Problem Summary: FragmentMgr prints complete pipeline execution
    parameters at VLOG(10), including file-scan properties, descriptor
    passwords and transaction tokens. The external open path also prints a
    complete query plan at VLOG(1). Replace these dumps with query/fragment
    identifiers and instance counts without modifying execution parameters.
    
    ```diff
    - Log complete execution parameters and external query plans
    + Log fixed identifiers and instance counts
    ```
    
    ### Release note
    
    Verbose fragment execution logs no longer include full execution
    parameters, query options or external query plans that may contain
    credentials.
    
    ### Evidence
    
    - `FragmentParamsLogTest.*:FragmentMgrLogTest.*`: **5 executed, 5
    passed, 0 failed, 0 skipped** (Clang21/ASAN). Fresh GTest XML and
    unchanged source inputs were checked.
    - Tests cover synthetic S3/token/password values, unknown property keys,
    unchanged execution parameters, and real pipeline/external request log
    capture with VLOG(10) enabled.
    - clang-format 16 and whitespace checks passed.
    - Task-private build selection retained the two requested test files,
    native initialization/link support, and complete branch BE libraries.
    This validates the selected tests; full native UT and regression groups
    were not run.
    
    ### Check List (For Author)
    
    - Test:
        - [x] Unit Test: the five focused fragment log tests above.
    - Behavior changed:
    - [x] Yes. Verbose diagnostics contain fixed identifiers and counts
    instead of full parameter dumps.
    - Does this need documentation?
        - [x] No.
    
    ### Merge Danger
    
    **Door:** two-way
    
    **Blast Radius:** diagnostics
    
    Execution and protocol parameters are unchanged; only verbose log
    contents change.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 be/src/runtime/fragment_mgr.cpp           |  15 ++--
 be/src/util/debug_util.cpp                |   6 ++
 be/src/util/debug_util.h                  |   5 ++
 be/test/runtime/fragment_mgr_log_test.cpp | 143 ++++++++++++++++++++++++++++++
 be/test/util/fragment_params_log_test.cpp |  69 ++++++++++++++
 5 files changed, 228 insertions(+), 10 deletions(-)

diff --git a/be/src/runtime/fragment_mgr.cpp b/be/src/runtime/fragment_mgr.cpp
index 55aad40baac..5437711b894 100644
--- a/be/src/runtime/fragment_mgr.cpp
+++ b/be/src/runtime/fragment_mgr.cpp
@@ -628,12 +628,7 @@ std::string FragmentMgr::dump_pipeline_tasks(TUniqueId& 
query_id) {
 Status FragmentMgr::exec_plan_fragment(const TPipelineFragmentParams& params,
                                        QuerySource query_source, const 
FinishCallback& cb,
                                        const TPipelineFragmentParamsList& 
parent) {
-    VLOG_ROW << "Query: " << print_id(params.query_id) << " exec_plan_fragment 
params is "
-             << apache::thrift::ThriftDebugString(params).c_str();
-    // sometimes TPipelineFragmentParams debug string is too long and glog
-    // will truncate the log line, so print query options seperately for 
debuggin purpose
-    VLOG_ROW << "Query: " << print_id(params.query_id) << "query options is "
-             << 
apache::thrift::ThriftDebugString(params.query_options).c_str();
+    VLOG_ROW << "exec_plan_fragment " << print_fragment_params_summary(params);
 
     std::shared_ptr<QueryContext> query_ctx;
     RETURN_IF_ERROR(_get_or_create_query_ctx(params, parent, query_source, 
query_ctx));
@@ -1030,8 +1025,8 @@ Status FragmentMgr::exec_external_plan_fragment(const 
TScanOpenParams& params,
         selected_columns->emplace_back(std::move(col));
     }
 
-    VLOG_QUERY << "BackendService execute open()  TQueryPlanInfo: "
-               << apache::thrift::ThriftDebugString(t_query_plan_info);
+    VLOG_QUERY << "BackendService execute open() query_id=" << 
print_id(query_id)
+               << ", fragment_instance_id=" << print_id(fragment_instance_id);
     // assign the param used to execute PlanFragment
     TPipelineFragmentParams exec_fragment_params;
     exec_fragment_params.protocol_version = 
(PaloInternalServiceVersion::type)0;
@@ -1087,8 +1082,8 @@ Status FragmentMgr::exec_external_plan_fragment(const 
TScanOpenParams& params,
     query_options.query_type = TQueryType::EXTERNAL;
     query_options.be_exec_version = BeExecVersionManager::get_newest_version();
     exec_fragment_params.__set_query_options(query_options);
-    VLOG_ROW << "external exec_plan_fragment params is "
-             << 
apache::thrift::ThriftDebugString(exec_fragment_params).c_str();
+    VLOG_ROW << "external exec_plan_fragment "
+             << print_fragment_params_summary(exec_fragment_params);
 
     TPipelineFragmentParamsList mocked;
     return exec_plan_fragment(exec_fragment_params, 
QuerySource::EXTERNAL_CONNECTOR, mocked);
diff --git a/be/src/util/debug_util.cpp b/be/src/util/debug_util.cpp
index 7362788c169..7dac1d77d5b 100644
--- a/be/src/util/debug_util.cpp
+++ b/be/src/util/debug_util.cpp
@@ -20,6 +20,7 @@
 #include <bvar/bvar.h>
 #include <bvar/multi_dimension.h>
 #include <gen_cpp/HeartbeatService_types.h>
+#include <gen_cpp/PaloInternalService_types.h>
 #include <gen_cpp/PlanNodes_types.h>
 #include <gflags/gflags.h>
 #include <stdint.h>
@@ -41,6 +42,11 @@
 
 namespace doris {
 
+std::string print_fragment_params_summary(const TPipelineFragmentParams& 
params) {
+    return fmt::format("query_id={}, fragment_id={}, local_instances={}", 
print_id(params.query_id),
+                       params.fragment_id, params.local_params.size());
+}
+
 std::string print_plan_node_type(const TPlanNodeType::type& type) {
     std::map<int, const char*>::const_iterator i;
     i = _TPlanNodeType_VALUES_TO_NAMES.find(type);
diff --git a/be/src/util/debug_util.h b/be/src/util/debug_util.h
index 5fad41ec637..81e4bcb0c29 100644
--- a/be/src/util/debug_util.h
+++ b/be/src/util/debug_util.h
@@ -26,6 +26,11 @@
 
 namespace doris {
 
+class TPipelineFragmentParams;
+
+// Only format fixed identifiers and counts. Scan properties and descriptors 
may contain credentials.
+std::string print_fragment_params_summary(const TPipelineFragmentParams& 
params);
+
 std::string print_plan_node_type(const TPlanNodeType::type& type);
 std::string print_query_state(const QueryState::type& type);
 std::string PrintTUnit(const TUnit::type& type);
diff --git a/be/test/runtime/fragment_mgr_log_test.cpp 
b/be/test/runtime/fragment_mgr_log_test.cpp
new file mode 100644
index 00000000000..3fae2a5bd03
--- /dev/null
+++ b/be/test/runtime/fragment_mgr_log_test.cpp
@@ -0,0 +1,143 @@
+// 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.
+
+#include <gen_cpp/DorisExternalService_types.h>
+#include <gen_cpp/PaloInternalService_types.h>
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "common/config.h"
+#include "common/logging.h"
+#include "runtime/exec_env.h"
+#include "runtime/fragment_mgr.h"
+#include "util/debug_points.h"
+
+namespace doris {
+
+class FragmentMgrLogTest : public testing::Test, public google::LogSink {
+public:
+    void SetUp() override {
+        _old_debug_points = config::enable_debug_points;
+        config::enable_debug_points = true;
+        // Stop after request logging, before creating a query context or 
dispatching any work.
+        DebugPoints::instance()->add("FragmentMgr._get_query_ctx.failed");
+        _old_vlog_level = google::SetVLOGLevel("fragment_mgr", 10);
+        google::AddLogSink(this);
+        _fragment_mgr = std::make_unique<FragmentMgr>(&_exec_env);
+    }
+
+    void TearDown() override {
+        _fragment_mgr->stop();
+        _fragment_mgr.reset();
+        google::RemoveLogSink(this);
+        google::SetVLOGLevel("fragment_mgr", _old_vlog_level);
+        DebugPoints::instance()->remove("FragmentMgr._get_query_ctx.failed");
+        config::enable_debug_points = _old_debug_points;
+    }
+
+    void send(google::LogSeverity /*severity*/, const char* /*full_filename*/,
+              const char* /*base_filename*/, int /*line*/, const 
google::LogMessageTime& /*time*/,
+              const char* message, std::size_t message_len) override {
+        std::lock_guard lock(_mutex);
+        _messages.append(message, message_len);
+        _messages.push_back('\n');
+    }
+
+protected:
+    static TDescriptorTable credential_descriptors() {
+        TJdbcTable jdbc_table;
+        jdbc_table.__set_jdbc_password("synthetic-jdbc-password");
+        TTableDescriptor table;
+        table.__set_id(1);
+        table.__set_tableType(TTableType::JDBC_TABLE);
+        table.__set_jdbcTable(jdbc_table);
+        TTupleDescriptor tuple;
+        tuple.__set_id(0);
+        tuple.__set_byteSize(0);
+        tuple.__set_numNullBytes(0);
+        TDescriptorTable descriptors;
+        descriptors.__set_tupleDescriptors({tuple});
+        descriptors.__set_tableDescriptors({table});
+        return descriptors;
+    }
+
+    std::string messages() {
+        std::lock_guard lock(_mutex);
+        return _messages;
+    }
+
+    ExecEnv _exec_env;
+    std::unique_ptr<FragmentMgr> _fragment_mgr;
+
+private:
+    std::mutex _mutex;
+    std::string _messages;
+    bool _old_debug_points = false;
+    int _old_vlog_level = 0;
+};
+
+TEST_F(FragmentMgrLogTest, PipelineRequestOmitsCredentials) {
+    TPipelineFragmentParams params;
+    TUniqueId query_id;
+    query_id.__set_hi(0x1234);
+    query_id.__set_lo(0x5678);
+    params.__set_query_id(query_id);
+    params.__set_fragment_id(9);
+    params.__set_desc_tbl(credential_descriptors());
+    TFileScanRangeParams scan_params;
+    scan_params.__set_properties({{"AWS_SECRET_KEY", 
"synthetic-storage-secret"},
+                                  {"unknown_property", 
"synthetic-future-credential"}});
+    params.__set_file_scan_params({{1, scan_params}});
+    TTxnParams txn_params;
+    txn_params.__set_token("synthetic-transaction-token");
+    params.__set_txn_conf(txn_params);
+
+    const auto status = _fragment_mgr->exec_plan_fragment(params, 
QuerySource::INTERNAL_FRONTEND,
+                                                          
TPipelineFragmentParamsList {});
+    EXPECT_FALSE(status.ok());
+    EXPECT_NE(std::string::npos, 
status.to_string().find("FragmentMgr._get_query_ctx.failed"));
+    const auto log = messages();
+    EXPECT_NE(std::string::npos, log.find("exec_plan_fragment 
query_id=1234-5678, fragment_id=9"));
+    EXPECT_EQ(std::string::npos, log.find("synthetic-"));
+}
+
+TEST_F(FragmentMgrLogTest, ExternalRequestOmitsDescriptorCredentials) {
+    TQueryPlanInfo query_plan;
+    query_plan.__set_desc_tbl(credential_descriptors());
+    TUniqueId query_id;
+    query_id.__set_hi(0x1234);
+    query_id.__set_lo(0x5678);
+    TUniqueId instance_id;
+    instance_id.__set_hi(0xabcd);
+    instance_id.__set_lo(0xef01);
+    std::vector<TScanColumnDesc> selected_columns;
+
+    const auto status = _fragment_mgr->exec_external_plan_fragment(
+            TScanOpenParams {}, query_plan, query_id, instance_id, 
&selected_columns);
+    EXPECT_FALSE(status.ok());
+    EXPECT_NE(std::string::npos, 
status.to_string().find("FragmentMgr._get_query_ctx.failed"));
+    const auto log = messages();
+    EXPECT_NE(std::string::npos, log.find("query_id=1234-5678, 
fragment_instance_id=abcd-ef01"));
+    EXPECT_NE(std::string::npos, log.find("external exec_plan_fragment 
query_id=1234-5678"));
+    EXPECT_EQ(std::string::npos, log.find("synthetic-"));
+}
+
+} // namespace doris
diff --git a/be/test/util/fragment_params_log_test.cpp 
b/be/test/util/fragment_params_log_test.cpp
new file mode 100644
index 00000000000..833996c4740
--- /dev/null
+++ b/be/test/util/fragment_params_log_test.cpp
@@ -0,0 +1,69 @@
+// 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.
+
+#include <gen_cpp/PaloInternalService_types.h>
+#include <gtest/gtest.h>
+
+#include "util/debug_util.h"
+
+namespace doris {
+
+TEST(FragmentParamsLogTest, KeepsIdentifiersAndInstanceCount) {
+    TPipelineFragmentParams params;
+    TUniqueId query_id;
+    query_id.__set_hi(0x1234);
+    query_id.__set_lo(0x5678);
+    params.__set_query_id(query_id);
+    params.__set_fragment_id(9);
+    params.local_params.resize(2);
+
+    EXPECT_EQ("query_id=1234-5678, fragment_id=9, local_instances=2",
+              print_fragment_params_summary(params));
+}
+
+TEST(FragmentParamsLogTest, OmitsCredentialsWithoutChangingExecutionParams) {
+    TPipelineFragmentParams params;
+    TFileScanRangeParams scan_params;
+    scan_params.__set_properties({{"AWS_ACCESS_KEY", "synthetic-access-key"},
+                                  {"AWS_SECRET_KEY", "synthetic-secret-key"},
+                                  {"AWS_TOKEN", "synthetic-session-token"},
+                                  {"unknown_property", 
"synthetic-future-credential"}});
+    params.__set_file_scan_params({{1, scan_params}});
+
+    TJdbcTable jdbc_table;
+    jdbc_table.__set_jdbc_password("synthetic-jdbc-password");
+    TTableDescriptor table;
+    table.__set_jdbcTable(jdbc_table);
+    table.__set_tableName("synthetic-sensitive-table-name");
+    TDescriptorTable descriptors;
+    descriptors.__set_tableDescriptors({table});
+    params.__set_desc_tbl(descriptors);
+    const auto original_params = params;
+
+    // Neither known credential keys nor future free-form properties belong in 
the summary.
+    EXPECT_EQ("query_id=0-0, fragment_id=0, local_instances=0",
+              print_fragment_params_summary(params));
+    EXPECT_EQ(original_params, params);
+}
+
+TEST(FragmentParamsLogTest, HandlesAbsentOptionalParams) {
+    const TPipelineFragmentParams params;
+    EXPECT_EQ("query_id=0-0, fragment_id=0, local_instances=0",
+              print_fragment_params_summary(params));
+}
+
+} // namespace doris


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

Reply via email to