Enhance logging and timing in CLI and session operations
- Updated the `_print_checks` function to replace console prints with logging functions for better traceability. - Introduced timing functionality in the `doctor`, `dry_run`, and `up` functions to log the duration of preflight checks. - Modified the `wait_ssh` function to accept a logging callback, improving SSH wait feedback. - Enhanced the `mark` method in `PhaseTimes` to log phase durations, aiding in performance analysis. - Updated various remote scripts to ensure error messages are printed to stderr for better error handling.
This commit is contained in:
+16
-2
@@ -171,7 +171,12 @@ def probe_ssh(cfg: Config, host: str, attempts: int = 3) -> str:
|
||||
return "auth" if auth_seen else "down"
|
||||
|
||||
|
||||
def wait_ssh(cfg: Config, host: str, timeout: float = 900.0) -> None:
|
||||
def wait_ssh(
|
||||
cfg: Config,
|
||||
host: str,
|
||||
timeout: float = 900.0,
|
||||
log: Callable[[str], None] | None = None,
|
||||
) -> None:
|
||||
"""Wait until sshd accepts our key. Paramiko banner noise is muted.
|
||||
|
||||
AuthenticationException is normal while cloud-init injects keys: keep
|
||||
@@ -183,6 +188,8 @@ def wait_ssh(cfg: Config, host: str, timeout: float = 900.0) -> None:
|
||||
logging.getLogger("paramiko").setLevel(logging.CRITICAL)
|
||||
logging.getLogger("paramiko.transport").setLevel(logging.CRITICAL)
|
||||
|
||||
emit = log if log is not None else print
|
||||
|
||||
# sshd may answer before authorized_keys is ready (boot-from-volume / user_data).
|
||||
auth_give_up = 180.0
|
||||
|
||||
@@ -223,7 +230,7 @@ def wait_ssh(cfg: Config, host: str, timeout: float = 900.0) -> None:
|
||||
except Exception:
|
||||
pass
|
||||
if attempt == 1 or attempt % 6 == 0:
|
||||
print(f"жду SSH {cfg.ssh_user}@{host}… ({name})", flush=True)
|
||||
emit(f"жду SSH {cfg.ssh_user}@{host}… ({name})")
|
||||
if (
|
||||
is_auth
|
||||
and auth_streak_started is not None
|
||||
@@ -323,6 +330,10 @@ def run_script_sudo(
|
||||
_stream_pty_output(stdout, log=log, chunks=chunks)
|
||||
code = stdout.channel.recv_exit_status()
|
||||
err = stderr.read().decode("utf-8", errors="replace") if not stdout.channel.closed else ""
|
||||
# PTY usually merges stderr; if anything remains, don't drop it past timed log.
|
||||
if log and err.strip():
|
||||
for line in err.strip().splitlines():
|
||||
log(line)
|
||||
out = "".join(chunks)
|
||||
if code != 0:
|
||||
raise CloudError(f"remote script exit {code}: {err or out[-2000:]}")
|
||||
@@ -354,6 +365,9 @@ def run_python(
|
||||
_stream_pty_output(stdout, log=log, chunks=chunks)
|
||||
code = stdout.channel.recv_exit_status()
|
||||
err = stderr.read().decode("utf-8", errors="replace") if not stdout.channel.closed else ""
|
||||
if log and err.strip():
|
||||
for line in err.strip().splitlines():
|
||||
log(line)
|
||||
out = "".join(chunks)
|
||||
if code != 0:
|
||||
raise CloudError(f"remote python exit {code}: {err or out[-2000:]}")
|
||||
|
||||
Reference in New Issue
Block a user