Set event loggers to INFO in configure_logging; DEBUG with debug=True

Kanta output is now visible without any application logging setup: the
event loggers Kanta owns (kanta.bootstrap/migration/transaction) are
set to INFO instead of inheriting the root level, which defaults to
WARNING and hid INFO transaction logs.  The plain kanta diagnostics
logger stays unset so root controls its verbosity.  Tests that relied
on INFO events being suppressed now scope their caplog assertions to
the relevant logger.
This commit is contained in:
LeoVasanko committed 2026-09-28 01:45:08 +00:00
1 parent 5c32e495e9
commit 7b132bda28
4 files changed
+33 -20

No files matched your search

+1 -1
View File
@@ -210,7 +210,7 @@ def resolve_user_key(value: str) -> str | None:
- By default a transaction is logged with an `action by user` header followed by the diff lines. Added paths are colored green, deleted paths red. ANSI color codes are stripped after formatting when the standard error stream does not support color: `NO_COLOR` disables colors, `FORCE_COLOR` forces them, otherwise a tty check and a journald (`JOURNAL_STREAM`) check decide. The CLI (`python -m kanta`) strips its output the same way.
- `kanta.transaction(..., extra=...)` accepts a display-only value that is shown after the action in the header. Anything other than `None` is printed str-converted (colored by Kanta), unless a custom logemit handler does something else with it; it is never persisted in the `ChangeRecord`.
- `kanta.transaction(..., logdiff=False)` skips building and printing the diff body and logs only the header, which is useful for large or noisy changesets. Diff output can also be disabled globally with `configure_logging(diff=False)`; diff lines are emitted on the `kanta.transaction.diff` child logger so applications can route or silence them separately from the headers.
- The event loggers `kanta.bootstrap`, `kanta.migration` and `kanta.transaction` are configured at import time (via `configure_logging()`, callable again to change the toggles): a plain stderr handler with no prefix and `propagate = False`, since Kanta renders this output itself. No levels are set, so they inherit the effective root level — a framework switching root between INFO in development and WARNING in production governs Kanta output too. Operational diagnostics (integrity errors, flush failures, rotation notes) use the plain `kanta` logger instead, propagating to the root logger and following the application's normal logging configuration.
- The event loggers `kanta.bootstrap`, `kanta.migration` and `kanta.transaction` are configured at import time (via `configure_logging()`, callable again to change the toggles): a plain stderr handler with no prefix and `propagate = False`, since Kanta renders this output itself. They are set to INFO so Kanta output is visible without any application logging setup (`debug=True` lifts the DEBUG-emitting bootstrap/migration loggers to DEBUG); only loggers Kanta owns are touched. Operational diagnostics (integrity errors, flush failures, rotation notes) use the plain `kanta` logger instead, which is left unset — propagating to the root logger and following the application's normal logging configuration.
#### Log Emitters
+8 -7
View File
@@ -605,10 +605,11 @@ def configure_logging(
and ``kanta.transaction`` carry Kanta-rendered output (colored headers,
diffs) and print it bare through a plain stderr handler with
``propagate = False``. Diagnostic messages use the plain ``kanta``
logger and follow the application's root logging configuration.
logger, which is left untouched so the application's root logging
configuration controls its verbosity.
No levels are set by default: the event loggers inherit the effective
level of the root logger.
The event loggers are set to ``INFO`` so Kanta output is visible without
any application logging setup; only loggers Kanta owns are touched.
Args:
skiproot: If ``True`` (default), event loggers print through Kanta's
@@ -625,7 +626,7 @@ def configure_logging(
debug: Whether to set the event loggers that emit DEBUG-level output
(bootstrap and migration) to ``DEBUG``, revealing output such as
the file-opened summary and migration diffs. ``False`` resets
them to inheriting the root level.
all event loggers to ``INFO``.
"""
logging.getLogger("kanta.transaction.diff").disabled = not diff
@@ -636,11 +637,11 @@ def configure_logging(
):
logging.getLogger(name).disabled = not enabled
for name in _DEBUG_LOGGERS:
logging.getLogger(name).setLevel(logging.DEBUG if debug else logging.NOTSET)
for name in EVENT_LOGGERS:
logger = logging.getLogger(name)
logger.setLevel(
logging.DEBUG if debug and name in _DEBUG_LOGGERS else logging.INFO
)
if skiproot:
logger.propagate = False
_ensure_plain_handler(logger)
+15 -3
View File
@@ -769,7 +769,11 @@ async def test_transaction_log_false_suppresses_log(tmp_path, format_config, cap
await kanta.close()
info_messages = [r for r in caplog.records if r.levelno == logging.INFO]
info_messages = [
r
for r in caplog.records
if r.levelno == logging.INFO and r.name.startswith("kanta.transaction")
]
assert not info_messages
@@ -787,7 +791,11 @@ async def test_transaction_logdiff_false_logs_header_only(
await kanta.close()
messages = [r.message for r in caplog.records if r.levelno == logging.INFO]
messages = [
r.message
for r in caplog.records
if r.levelno == logging.INFO and r.name.startswith("kanta.transaction")
]
assert len(messages) == 1
assert "inc" in messages[0]
assert "counter" not in messages[0]
@@ -808,7 +816,11 @@ async def test_transaction_log_custom_logger(tmp_path, format_config, caplog):
await kanta.close()
info_messages = [r for r in caplog.records if r.levelno == logging.INFO]
info_messages = [
r
for r in caplog.records
if r.levelno == logging.INFO and r.name.startswith("custom.transaction")
]
assert len(info_messages) >= 1
assert "inc" in info_messages[0].message
+9 -9
View File
@@ -42,11 +42,18 @@ def test_configure_logging_defaults():
configure_logging()
for name in ("kanta.bootstrap", "kanta.migration", "kanta.transaction"):
logger = logging.getLogger(name)
assert logger.level == logging.NOTSET # inherits the root level
assert logger.level == logging.INFO # visible without app logging setup
assert not logger.propagate
assert logger.handlers
def test_configure_logging_debug_lifts_debug_loggers():
configure_logging(debug=True)
assert logging.getLogger("kanta.bootstrap").level == logging.DEBUG
assert logging.getLogger("kanta.migration").level == logging.DEBUG
assert logging.getLogger("kanta.transaction").level == logging.INFO
def test_configure_logging_disables_specific_loggers():
configure_logging(bootstrap=False, migration=False, transaction=False)
assert logging.getLogger("kanta.bootstrap").disabled
@@ -63,14 +70,8 @@ def test_configure_logging_skiproot_false_routes_via_root():
def _setup_logging(**kwargs):
"""Default kanta logging with the event loggers lifted to INFO.
Event loggers inherit the root level (WARNING under pytest); output
assertions need INFO.
"""
"""Default kanta logging; the event loggers are INFO out of the box."""
configure_logging(**kwargs)
for name in ("kanta.bootstrap", "kanta.migration", "kanta.transaction"):
logging.getLogger(name).setLevel(logging.INFO)
def test_log_change_no_diff(capsys):
@@ -114,7 +115,6 @@ def test_configure_logging_diff_false(capsys):
def test_configure_logging_diff_true_reenables(capsys):
_setup_logging(diff=False)
configure_logging(diff=True)
logging.getLogger("kanta.transaction").setLevel(logging.INFO)
log_change("update", {"counter": 5}, previous={})
captured = capsys.readouterr()
assert "counter" in captured.err