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

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


The following commit(s) were added to refs/heads/master by this push:
     new 68a9630ad IMPALA-14284: Log the actual log files instead of symlinks 
in start-impala-cluster.py
68a9630ad is described below

commit 68a9630adcf9bf064ba64304efab788f6e2a165d
Author: stiga-huang <[email protected]>
AuthorDate: Fri Dec 12 17:27:30 2025 +0800

    IMPALA-14284: Log the actual log files instead of symlinks in 
start-impala-cluster.py
    
    It's not that easy to find log files of a custom-cluster test. All
    custom-cluster tests use the same log dir and the test output just shows
    the symlink of the log files, e.g. "Starting State Store logging to
    .../logs/custom_cluster_tests/statestored.INFO".
    
    This patch prints the actual log file names after the cluster launchs.
    An example output:
    
    15:17:19 MainThread: Starting State Store logging to /tmp/statestored.INFO
    15:17:19 MainThread: Starting Catalog Service logging to /tmp/catalogd.INFO
    15:17:19 MainThread: Starting Impala Daemon logging to /tmp/impalad.INFO
    15:17:19 MainThread: Starting Impala Daemon logging to 
/tmp/impalad_node1.INFO
    15:17:19 MainThread: Starting Impala Daemon logging to 
/tmp/impalad_node2.INFO
    ...
    15:17:24 MainThread: Total wait: 2.54s
    15:17:24 MainThread: Actual log file names:
    15:17:24 MainThread: statestored.INFO -> 
statestored.quanlong-Precision-3680.quanlong.log.INFO.20251216-151719.1094348
    15:17:24 MainThread: catalogd.INFO -> 
catalogd.quanlong-Precision-3680.quanlong.log.INFO.20251216-151719.1094368
    15:17:24 MainThread: impalad.INFO -> 
impalad.quanlong-Precision-3680.quanlong.log.INFO.20251216-151719.1094466
    15:17:24 MainThread: impalad_node1.INFO -> 
impalad.quanlong-Precision-3680.quanlong.log.INFO.20251216-151719.1094468
    15:17:24 MainThread: impalad_node2.INFO -> 
impalad.quanlong-Precision-3680.quanlong.log.INFO.20251216-151719.1094470
    15:17:24 MainThread: Impala Cluster Running with 3 nodes (3 coordinators, 3 
executors).
    
    Tests
     - Ran the script locally.
     - Ran a failed custom-cluster test and verified the actual file names
       are printed in the output.
    
    Change-Id: Id76c0a8bdfb221ab24ee315e2e273abca4257398
    Reviewed-on: http://gerrit.cloudera.org:8080/23781
    Reviewed-by: Impala Public Jenkins <[email protected]>
    Tested-by: Quanlong Huang <[email protected]>
---
 bin/start-impala-cluster.py | 50 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 40 insertions(+), 10 deletions(-)

diff --git a/bin/start-impala-cluster.py b/bin/start-impala-cluster.py
index e6042417f..e7d2be2b9 100755
--- a/bin/start-impala-cluster.py
+++ b/bin/start-impala-cluster.py
@@ -249,6 +249,21 @@ def check_process_exists(binary, attempts=1):
   return False
 
 
+def print_actual_log_file(log_symlink, timeout=5):
+  """Resolve the log symlink to get the actual log file name."""
+  symlink_name = os.path.basename(log_symlink)
+  for _ in range(timeout):
+    if os.path.exists(log_symlink):
+      try:
+        actual_path = os.path.realpath(log_symlink)
+        actual_file = os.path.basename(actual_path)
+        LOG.info("{0} -> {1}".format(symlink_name, actual_file))
+        return
+      except OSError as e:
+        LOG.error("Error resolving log symlink {0}: {1}".format(log_symlink, 
e))
+        return
+    sleep(1)
+
 def run_daemon_with_options(daemon_binary, args, output_file, 
jvm_debug_port=None):
   """Wrapper around run_daemon() with options determined from command-line 
options."""
   env_vars = {"JAVA_TOOL_OPTIONS": build_java_tool_options(jvm_debug_port)}
@@ -762,6 +777,10 @@ class MiniClusterOperations(object):
   implementation.
   TODO: much of this logic could be moved into ImpalaCluster.
   """
+  def __init__(self):
+    # Track log symlinks to print after cluster is ready
+    self.log_symlinks = []
+
   def get_cluster(self):
     """Return an ImpalaCluster instance."""
     return 
ImpalaCluster(use_admission_service=options.enable_admission_service,
@@ -790,15 +809,15 @@ class MiniClusterOperations(object):
     statestored_arg_lists = build_statestored_arg_list(num_statestored, 
remap_ports=True)
     for i in range(num_statestored):
       service_name = statestored_service_name(i)
-      LOG.info(
-          "Starting State Store logging to 
{log_dir}/{service_name}.INFO".format(
-              log_dir=options.log_dir, service_name=service_name))
+      log_symlink = os.path.join(options.log_dir, 
"{0}.INFO".format(service_name))
+      LOG.info("Starting State Store logging to {0}".format(log_symlink))
       output_file = os.path.join(
           options.log_dir, 
"{service_name}-out.log".format(service_name=service_name))
       run_daemon_with_options("statestored", statestored_arg_lists[i], 
output_file)
       if not check_process_exists("statestored", 10):
         raise RuntimeError("Unable to start statestored. Check log or file 
permissions"
                            " for more details.")
+      self.log_symlinks.append(log_symlink)
 
   def start_catalogd(self):
     if options.no_catalogd:
@@ -810,9 +829,8 @@ class MiniClusterOperations(object):
     catalogd_arg_lists = build_catalogd_arg_list(num_catalogd, 
remap_ports=True)
     for i in range(num_catalogd):
       service_name = catalogd_service_name(i)
-      LOG.info(
-          "Starting Catalog Service logging to 
{log_dir}/{service_name}.INFO".format(
-              log_dir=options.log_dir, service_name=service_name))
+      log_symlink = os.path.join(options.log_dir, 
"{0}.INFO".format(service_name))
+      LOG.info("Starting Catalog Service logging to {0}".format(log_symlink))
       output_file = os.path.join(
           options.log_dir, 
"{service_name}-out.log".format(service_name=service_name))
       run_daemon_with_options("catalogd", catalogd_arg_lists[i], output_file,
@@ -820,15 +838,17 @@ class MiniClusterOperations(object):
       if not check_process_exists("catalogd", 10):
         raise RuntimeError("Unable to start catalogd. Check log or file 
permissions"
                            " for more details.")
+      self.log_symlinks.append(log_symlink)
 
   def start_admissiond(self):
-    LOG.info("Starting Admission Control Service logging to 
{log_dir}/admissiond.INFO"
-        .format(log_dir=options.log_dir))
+    log_symlink = os.path.join(options.log_dir, "admissiond.INFO")
+    LOG.info("Starting Admission Control Service logging to 
{0}".format(log_symlink))
     output_file = os.path.join(options.log_dir, "admissiond-out.log")
     run_daemon_with_options("admissiond", build_admissiond_arg_list(), 
output_file)
     if not check_process_exists("admissiond", 10):
       raise RuntimeError("Unable to start admissiond. Check log or file 
permissions"
                          " for more details.")
+    self.log_symlinks.append(log_symlink)
 
   def start_impalads(self, cluster_size, num_coordinators, 
use_exclusive_coordinators,
                      start_idx=0):
@@ -849,12 +869,13 @@ class MiniClusterOperations(object):
     assert cluster_size == len(impalad_arg_lists)
     for i in range(start_idx, start_idx + cluster_size):
       service_name = impalad_service_name(i)
-      LOG.info("Starting Impala Daemon logging to 
{log_dir}/{service_name}.INFO".format(
-          log_dir=options.log_dir, service_name=service_name))
+      log_symlink = os.path.join(options.log_dir, 
"{0}.INFO".format(service_name))
+      LOG.info("Starting Impala Daemon logging to {0}".format(log_symlink))
       output_file = os.path.join(
           options.log_dir, 
"{service_name}-out.log".format(service_name=service_name))
       run_daemon_with_options("impalad", impalad_arg_lists[i - start_idx],
           jvm_debug_port=DEFAULT_IMPALAD_JVM_DEBUG_PORT + i, 
output_file=output_file)
+      self.log_symlinks.append(log_symlink)
 
 
 class DockerMiniClusterOperations(object):
@@ -873,6 +894,8 @@ class DockerMiniClusterOperations(object):
   """
   def __init__(self, network_name):
     self.network_name = network_name
+    # Track log symlinks to print after cluster is ready (not used in docker 
mode)
+    self.log_symlinks = []
     # Make sure that the network actually exists.
     check_call(["docker", "network", "inspect", network_name])
 
@@ -1262,6 +1285,13 @@ if __name__ == "__main__":
       expected_num_ready_impalads = options.cluster_size
       expected_cluster_size = options.cluster_size
     impala_cluster.wait_until_ready(expected_cluster_size, 
expected_num_ready_impalads)
+
+    # Print actual log files after cluster is ready
+    if cluster_ops.log_symlinks:
+      LOG.info("Actual log file names:")
+      for log_symlink in cluster_ops.log_symlinks:
+        print_actual_log_file(log_symlink)
+
   except Exception as e:
     LOG.exception("Error starting cluster")
     sys.exit(1)

Reply via email to