fix: build_formatter routes the unknown-output warning through the setup buffer
build_formatter warned immediately via getLogger(__name__).warning, but setup_logging calls it after _clear_owned strips the lib's handlers and before any new handler attaches - so the warning hit a handler-less root and landed on stderr via lastResort, never reaching the configured log. The v0.6.0 warnings buffer already threads this class of setup-time warning through for an unknown rotate value; build_formatter now takes the same warnings list and appends to it instead of emitting inline, so setup_logging can flush it once handlers are attached like the others. Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
@@ -54,7 +54,7 @@ class JsonLinesFormatter(logging.Formatter):
|
||||
return json.dumps(payload, default=str)
|
||||
|
||||
|
||||
def build_formatter(output: str = "text", fmt=None, datefmt=None) -> logging.Formatter:
|
||||
def build_formatter(output: str = "text", fmt=None, datefmt=None, warnings: list = None) -> logging.Formatter:
|
||||
"""build the formatter for the chosen output format
|
||||
|
||||
`output="text"` (default) returns the human-readable text formatter, honoring
|
||||
@@ -62,11 +62,19 @@ def build_formatter(output: str = "text", fmt=None, datefmt=None) -> logging.For
|
||||
structured `JsonLinesFormatter` (which ignores `fmt`/`datefmt` - it builds
|
||||
fields, not a format string). an unrecognized `output` falls back to text and
|
||||
warns, never raising - a bad format arg must not take the app down.
|
||||
|
||||
`warnings` is the setup-time buffer (see `setup_logging`): passing it appends
|
||||
the unknown-output warning there instead of emitting immediately, so it lands
|
||||
in the configured log like the other setup-time warnings rather than only
|
||||
stderr. `None` (default) preserves the old immediate-emit behavior for direct
|
||||
callers outside `setup_logging`.
|
||||
"""
|
||||
if output == "json":
|
||||
return JsonLinesFormatter()
|
||||
if output != "text":
|
||||
logging.getLogger(__name__).warning(
|
||||
"log_setup: unknown output %r; falling back to 'text'", output
|
||||
)
|
||||
message = "log_setup: unknown output %r; falling back to 'text'"
|
||||
if warnings is None:
|
||||
logging.getLogger(__name__).warning(message, output)
|
||||
else:
|
||||
warnings.append((message, output))
|
||||
return logging.Formatter(fmt or DEFAULT_FORMAT, datefmt or DEFAULT_DATEFMT)
|
||||
|
||||
@@ -266,7 +266,7 @@ def setup_logging(
|
||||
_apply_module_levels(module_levels, warnings)
|
||||
_clear_owned(root, warnings)
|
||||
|
||||
formatter = build_formatter(output, fmt, datefmt)
|
||||
formatter = build_formatter(output, fmt, datefmt, warnings)
|
||||
stem = _normalize_name(name)
|
||||
live_path = f"{stem}.log"
|
||||
# history_name if given, else the cwd basename; falls back to the live stem for a
|
||||
|
||||
Reference in New Issue
Block a user