Skip to content

Commit 92c483e

Browse files
Feature: add an option for a custom formatter in logging setup (#10)
* feat(logging): setup support user-given formatters Allow the user to provide a custom formatter class to replace the default `logging.Formatter`. This should allow more flexibility to customize the logs output. The `format` argument is kept for backward compatibility. * test(logging): ensure setup's formatter is handled Test that the user can set a custom formatter in `clapper.logging.setup`
1 parent d17d303 commit 92c483e

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/clapper/logging.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def setup(
2626
format: str = "[%(levelname)s] %(message)s (%(name)s, %(asctime)s)", # noqa: A002
2727
low_level_stream: typing.TextIO = sys.stdout,
2828
high_level_stream: typing.TextIO = sys.stderr,
29+
formatter: logging.Formatter | None = None,
2930
) -> logging.Logger:
3031
"""Return a logger object that is ready for console logging.
3132
@@ -40,10 +41,13 @@ def setup(
4041
and above to the text-I/O stream ``high_level_stream``, with an internal
4142
level set to ``logging.WARNING``.
4243
43-
A new formatter, with the format string as defined by the ``format``
44-
argument is set on both handlers. In this way, the global logger level can
45-
still be controlled from one single place. If output is generated, then it
46-
is sent to the right stream.
44+
If you do not provide a ``formatter`` argument, a new formatter, with the
45+
format string as defined by the ``format`` argument is set on both handlers.
46+
In this way, the global logger level can still be controlled from one single
47+
place. If output is generated, then it is sent to the right stream.
48+
49+
You can provide a custom formatter if ``format`` is not sufficient to
50+
customize the looks of your logs (e.g. you want to add colors).
4751
4852
Parameters
4953
----------
@@ -52,11 +56,13 @@ def setup(
5256
format
5357
The format of the logs, see :py:class:`logging.LogRecord` for more
5458
details. By default, the log contains the logger name, the log time,
55-
the log level and the massage.
59+
the log level and the message. *Ignored if ``formatter`` is set*.
5660
low_level_stream
5761
The stream where to output info messages and below
5862
high_level_stream
5963
The stream where to output warning messages and above
64+
formatter
65+
A formatter to replace the default :py:class:`logging.Formatter`.
6066
6167
Returns
6268
-------
@@ -66,7 +72,8 @@ def setup(
6672

6773
logger = logging.getLogger(logger_name)
6874

69-
formatter = logging.Formatter(format)
75+
if formatter is None:
76+
formatter = logging.Formatter(format)
7077

7178
handlers_installed = {k.name: k for k in logger.handlers}
7279
debug_logger_name = f"debug_info+{logger_name}"

tests/test_logging.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,32 @@ def test_logger_setup():
3535
assert hi.getvalue() == "warning message\nerror message\n"
3636

3737

38+
def test_logger_setup_formatter():
39+
log_output = io.StringIO()
40+
41+
custom_formatter = logging.Formatter(fmt="custom {message:s}", style="{")
42+
43+
logger = clapper.logging.setup(
44+
"awesome.logger",
45+
low_level_stream=log_output,
46+
high_level_stream=log_output,
47+
formatter=custom_formatter,
48+
)
49+
logger.setLevel(logging.DEBUG)
50+
51+
logger.debug("debug message")
52+
logger.info("info message")
53+
logger.warning("warning message")
54+
logger.error("error message")
55+
56+
assert log_output.getvalue() == (
57+
"custom debug message\n"
58+
"custom info message\n"
59+
"custom warning message\n"
60+
"custom error message\n"
61+
)
62+
63+
3864
def test_logger_click_no_v():
3965
lo = io.StringIO()
4066
hi = io.StringIO()

0 commit comments

Comments
 (0)