Skip to content

Commit

Permalink
Add columns to ConsoleRenderer for more control how k/vs are formatted (
Browse files Browse the repository at this point in the history
#577)

* dev: add columns to ConsoleRenderer for more control how k/vs are formatted

* Add PR#

* Wordsmith

* update readme screenshot
  • Loading branch information
hynek authored Dec 29, 2023
1 parent fe4cd56 commit f336f50
Show file tree
Hide file tree
Showing 9 changed files with 541 additions and 159 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,23 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/

### Added

- The colorful development logger is now even more configurable!
Choose freely your colors and the order of the key-value pairs!
Implement your own formatters for certain keys!

Implementing the output on top of the new columns API has changed the default very slightly, but shouldn't be noticeable.
[#577](https://github.com/hynek/structlog/issues/577)

- Async log methods (those starting with an `a`) now also support the collection of callsite information using `structlog.processors.CallsiteParameterAdder`.
[#565](https://github.com/hynek/structlog/issues/565)


### Changed

- `structlog.stdlib.recreate_defaults()` now also adds `structlog.stdlib.add_logger_name` to the processors.
Check out the updated screenshot in the README!


### Fixed

- The return value from `get_logger()` (a `BoundLoggerLazyProxy`) now passes `isinstance`-checks against `structlog.typing.BindableLogger` on Python 3.12.
Expand Down
Binary file modified docs/_static/console_renderer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ API Reference
.. autoclass:: ConsoleRenderer
:members: get_default_level_styles

.. autoclass:: Column
.. autoclass:: ColumnFormatter(typing.Protocol)
:members: __call__
.. autoclass:: KeyValueColumnFormatter
.. autoclass:: LogLevelColumnFormatter

.. autofunction:: plain_traceback
.. autoclass:: RichTracebackFormatter
.. autofunction:: rich_traceback
Expand Down
92 changes: 73 additions & 19 deletions docs/console-output.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,90 @@ For pretty exceptions to work, {func}`~structlog.processors.format_exc_info` mus
:::

*structlog*'s default configuration already uses {class}`~structlog.dev.ConsoleRenderer`, therefore if you want nice colorful output on the console, you don't have to do anything except installing Rich or *better-exceptions* (and Colorama on Windows).
If you want to use it along with standard library logging, we suggest the following configuration:
If you want to use it along with standard library logging, there's the {func}`structlog.stdlib.recreate_defaults` helper.

:::{seealso}
{doc}`exceptions` for more information on how to configure exception rendering.
For the console and beyond.
:::

(columns-config)=

## Console Output Configuration

:::{versionadded} 23.3.0
:::

You can freely configure how the key-value pairs are formatted: colors, order, and how values are stringified.

For that {class}`~structlog.dev.ConsoleRenderer` accepts the *columns* parameter that takes a list of {class}`~structlog.dev.Column`s.
It allows you to assign a formatter to each key and a default formatter for the rest (by passing an empty key name).
The order of the column definitions is the order in which the columns are rendered;
the rest is -- depending on the *sort_keys* argument to {class}`~structlog.dev.ConsoleRenderer` -- either sorted alphabetically or in the order of the keys in the event dictionary.

You can use a column definition to drop a key-value pair from the output by returning an empty string from the formatter.

When the API talks about "styles", it means ANSI control strings.
You can find them, for example, in [Colorama](https://github.com/tartley/colorama).


It's best demonstrated by an example:

```python
import structlog

structlog.configure(
processors=[
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M.%S"),
structlog.processors.StackInfoRenderer(),
structlog.dev.ConsoleRenderer() # <===
],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
cache_logger_on_first_use=True,
import colorama

cr = structlog.dev.ConsoleRenderer(
columns=[
# Render the timestamp without the key name in yellow.
structlog.dev.Column(
"timestamp",
structlog.dev.KeyValueColumnFormatter(
key_style=None,
value_style=colorama.Fore.YELLOW,
reset_style=colorama.Style.RESET_ALL,
value_repr=str,
),
),
# Render the event without the key name in bright magenta.
structlog.dev.Column(
"event",
structlog.dev.KeyValueColumnFormatter(
key_style=None,
value_style=colorama.Style.BRIGHT + colorama.Fore.MAGENTA,
reset_style=colorama.Style.RESET_ALL,
value_repr=str,
),
),
# Default formatter for all keys not explicitly mentioned. The key is
# cyan, the value is green.
structlog.dev.Column(
"",
structlog.dev.KeyValueColumnFormatter(
key_style=colorama.Fore.CYAN,
value_style=colorama.Fore.GREEN,
reset_style=colorama.Style.RESET_ALL,
value_repr=str,
),
),
]
)

structlog.configure(processors=structlog.get_config()["processors"][:-1]+[cr])
```

:::{seealso}
{doc}`exceptions` for more information on how to configure exception rendering.
For the console and beyond.
:::{hint}
You can replace only the last processor using:

```python
structlog.configure(processors=structlog.get_config()["processors"][:-1]+[cr])
```
:::


## Standard Environment Variables

*structlog*'s default configuration uses colors if standard out is a TTY (i.e. an interactive session).
*structlog*'s default configuration uses colors if standard out is a TTY (that is, an interactive session).

It's possible to override this behavior by setting two standard environment variables to any value except an empty string:

Expand Down
2 changes: 2 additions & 0 deletions show_off.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class SomeClass:
y: str


structlog.stdlib.recreate_defaults() # so we have logger names

log = structlog.get_logger("some_logger")

log.debug("debugging is hard", a_list=[1, 2, 3])
Expand Down
Loading

0 comments on commit f336f50

Please sign in to comment.