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)
|
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
|
"""build the formatter for the chosen output format
|
||||||
|
|
||||||
`output="text"` (default) returns the human-readable text formatter, honoring
|
`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
|
structured `JsonLinesFormatter` (which ignores `fmt`/`datefmt` - it builds
|
||||||
fields, not a format string). an unrecognized `output` falls back to text and
|
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.
|
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":
|
if output == "json":
|
||||||
return JsonLinesFormatter()
|
return JsonLinesFormatter()
|
||||||
if output != "text":
|
if output != "text":
|
||||||
logging.getLogger(__name__).warning(
|
message = "log_setup: unknown output %r; falling back to 'text'"
|
||||||
"log_setup: unknown output %r; falling back to 'text'", output
|
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)
|
return logging.Formatter(fmt or DEFAULT_FORMAT, datefmt or DEFAULT_DATEFMT)
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ def setup_logging(
|
|||||||
_apply_module_levels(module_levels, warnings)
|
_apply_module_levels(module_levels, warnings)
|
||||||
_clear_owned(root, warnings)
|
_clear_owned(root, warnings)
|
||||||
|
|
||||||
formatter = build_formatter(output, fmt, datefmt)
|
formatter = build_formatter(output, fmt, datefmt, warnings)
|
||||||
stem = _normalize_name(name)
|
stem = _normalize_name(name)
|
||||||
live_path = f"{stem}.log"
|
live_path = f"{stem}.log"
|
||||||
# history_name if given, else the cwd basename; falls back to the live stem for a
|
# history_name if given, else the cwd basename; falls back to the live stem for a
|
||||||
|
|||||||
Reference in New Issue
Block a user