Skip to content

Commit 713b337

Browse files
committed
libtmux(fix[logging]): fix log formatting, structured context, and diagnostics
why: Bring logging calls into compliance with AGENTS.md logging standards. what: - common.py: Replace f-string and .format() in log calls with lazy formatting and structured extra; guard DEBUG with isEnabledFor; use logger.error() instead of logger.exception() for catch-log-reraise - server.py: Add structured extra to session lifecycle log calls, fix message style to lowercase past tense - hooks.py: Replace f-string with lazy %s formatting - query_list.py: Replace traceback.print_stack() with logger.debug() using stack_info=True; remove traceback import - pytest_plugin.py: Add structured extra to test session cleanup log call - options.py: Change logger.exception() to logger.warning(exc_info=True) for recoverable parse failures; add structured extra with tmux_option_key
1 parent c179f22 commit 713b337

6 files changed

Lines changed: 79 additions & 23 deletions

File tree

src/libtmux/_internal/query_list.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
import logging
1111
import re
12-
import traceback
1312
import typing as t
1413
from collections.abc import Callable, Iterable, Mapping, Sequence
1514

@@ -105,9 +104,13 @@ def keygetter(
105104
elif hasattr(dct, sub_field):
106105
dct = getattr(dct, sub_field)
107106

108-
except Exception as e:
109-
traceback.print_stack()
110-
logger.debug("The above error was %s", e)
107+
except Exception:
108+
logger.debug(
109+
"key lookup failed for path: %s",
110+
path,
111+
exc_info=True,
112+
stack_info=True,
113+
)
111114
return None
112115

113116
return dct
@@ -146,9 +149,13 @@ def parse_lookup(
146149
field_name = path.split(lookup, maxsplit=1)[0]
147150
if field_name is not None:
148151
return keygetter(obj, field_name)
149-
except Exception as e:
150-
traceback.print_stack()
151-
logger.debug("The above error was %s", e)
152+
except Exception:
153+
logger.debug(
154+
"lookup parsing failed for path: %s",
155+
path,
156+
exc_info=True,
157+
stack_info=True,
158+
)
152159
return None
153160

154161

src/libtmux/common.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,13 @@ def __init__(self, *args: t.Any) -> None:
270270
stdout, stderr = self.process.communicate()
271271
returncode = self.process.returncode
272272
except Exception:
273-
logger.exception(f"Exception for {subprocess.list2cmdline(cmd)}")
273+
logger.error(
274+
"tmux subprocess failed",
275+
exc_info=True,
276+
extra={
277+
"tmux_cmd": subprocess.list2cmdline(cmd),
278+
},
279+
)
274280
raise
275281

276282
self.returncode = returncode
@@ -288,12 +294,17 @@ def __init__(self, *args: t.Any) -> None:
288294
else:
289295
self.stdout = stdout_split
290296

291-
logger.debug(
292-
"self.stdout for {cmd}: {stdout}".format(
293-
cmd=" ".join(cmd),
294-
stdout=self.stdout,
295-
),
296-
)
297+
if logger.isEnabledFor(logging.DEBUG):
298+
logger.debug(
299+
"tmux command completed",
300+
extra={
301+
"tmux_cmd": subprocess.list2cmdline(cmd),
302+
"tmux_exit_code": self.returncode,
303+
"tmux_stdout": self.stdout[:100],
304+
"tmux_stderr": self.stderr[:100],
305+
"tmux_stdout_len": len(self.stdout),
306+
},
307+
)
297308

298309

299310
def get_version() -> LooseVersion:

src/libtmux/hooks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ def show_hooks(
305305
elif len(parts) == 1:
306306
key, val = parts[0], None
307307
else:
308-
logger.warning(f"Error extracting hook: {item}")
308+
logger.warning("failed to extract hook: %s", item)
309309
continue
310310

311311
if isinstance(val, str) and val.isdigit():

src/libtmux/options.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,11 @@ def explode_arrays(
429429
options[key][0] = val
430430
else:
431431
options[key] = val
432-
logger.exception("Error parsing options")
432+
logger.warning(
433+
"tmux options parse failed",
434+
exc_info=True,
435+
extra={"tmux_option_key": key},
436+
)
433437
return options
434438

435439

@@ -513,7 +517,11 @@ def explode_complex(
513517
term, features = item.split(":", maxsplit=1)
514518
new_val[term] = features.split(":")
515519
except Exception: # NOQA: PERF203
516-
logger.exception("Error parsing options")
520+
logger.warning(
521+
"tmux options parse failed",
522+
exc_info=True,
523+
extra={"tmux_option_key": key},
524+
)
517525
options[key] = new_val
518526
continue
519527
if isinstance(val, SparseArray) and key == "terminal-overrides":
@@ -537,7 +545,11 @@ def explode_complex(
537545
elif feature:
538546
new_overrides[term][feature] = None
539547
except Exception: # NOQA: PERF203
540-
logger.exception("Error parsing options")
548+
logger.warning(
549+
"tmux options parse failed",
550+
exc_info=True,
551+
extra={"tmux_option_key": key},
552+
)
541553
options[key] = new_overrides
542554
continue
543555
if isinstance(val, SparseArray) and key == "command-alias":
@@ -553,15 +565,23 @@ def explode_complex(
553565
options[key] = {}
554566
new_aliases[alias] = command
555567
except Exception: # NOQA: PERF203
556-
logger.exception("Error parsing options")
568+
logger.warning(
569+
"tmux options parse failed",
570+
exc_info=True,
571+
extra={"tmux_option_key": key},
572+
)
557573
options[key] = new_aliases
558574
continue
559575
options[key] = val
560576
continue
561577

562578
except Exception:
563579
options[key] = val
564-
logger.exception("Error parsing options")
580+
logger.warning(
581+
"tmux options parse failed",
582+
exc_info=True,
583+
extra={"tmux_option_key": key},
584+
)
565585
return options
566586

567587

src/libtmux/pytest_plugin.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,13 @@ def session(
251251
server.switch_client(target_session=session_id)
252252

253253
for old_test_session in old_test_sessions:
254-
logger.debug("Old test test session %s found. Killing it.", old_test_session)
254+
logger.debug(
255+
"old test session found, killing",
256+
extra={
257+
"tmux_session": old_test_session,
258+
"tmux_subcommand": "kill-session",
259+
},
260+
)
255261
server.kill_session(old_test_session)
256262
assert session.session_name == TEST_SESSION_NAME
257263
assert TEST_SESSION_NAME != "tmuxp"

src/libtmux/server.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,14 +525,26 @@ def new_session(
525525
if self.has_session(session_name):
526526
if kill_session:
527527
self.cmd("kill-session", target=session_name)
528-
logger.info("session %s exists. killed it.", session_name)
528+
logger.info(
529+
"existing session killed",
530+
extra={
531+
"tmux_session": session_name,
532+
"tmux_subcommand": "kill-session",
533+
},
534+
)
529535
else:
530536
msg = f"Session named {session_name} exists"
531537
raise exc.TmuxSessionExists(
532538
msg,
533539
)
534540

535-
logger.debug("creating session %s", session_name)
541+
logger.debug(
542+
"creating session",
543+
extra={
544+
"tmux_session": session_name,
545+
"tmux_subcommand": "new-session",
546+
},
547+
)
536548

537549
env = os.environ.get("TMUX")
538550

0 commit comments

Comments
 (0)