Skip to content

Commit

Permalink
Map method name in capture_logs as well (#628)
Browse files Browse the repository at this point in the history
* Map method name in capture_logs as well

* Added docstring

* Updated changelog

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add test case

* Fix changelog

* Fixes

* Transplant comments

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Hynek Schlawack <hs@ox.cx>
  • Loading branch information
3 people committed Jul 13, 2024
1 parent 6090ff6 commit e28bbfe
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 8 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ You can find our backwards-compatibility policy [here](https://github.com/hynek/

## [Unreleased](https://github.com/hynek/structlog/compare/24.2.0...HEAD)

### Changed

- `structlog.testing.capture_logs()` now maps the `exception` log level to `error` (as it's elsewhere).
[#628](https://github.com/hynek/structlog/pull/628)


## [24.2.0](https://github.com/hynek/structlog/compare/24.1.0...24.2.0) - 2024-05-27

Expand Down
20 changes: 13 additions & 7 deletions src/structlog/_log_levels.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,18 @@
_NAME_TO_LEVEL = NAME_TO_LEVEL


def map_method_name(method_name: str) -> str:
# warn is just a deprecated alias in the stdlib.
if method_name == "warn":
return "warning"

# Calling exception("") is the same as error("", exc_info=True)
if method_name == "exception":
return "error"

return method_name


def add_log_level(
logger: logging.Logger, method_name: str, event_dict: EventDict
) -> EventDict:
Expand All @@ -63,13 +75,7 @@ def add_log_level(
.. versionchanged:: 24.1.0
Added mapping from "exception" to "error"
"""
if method_name == "warn":
# The stdlib has an alias
method_name = "warning"
elif method_name == "exception":
# exception("") method is the same as error("", exc_info=True)
method_name = "error"

event_dict["level"] = method_name
event_dict["level"] = map_method_name(method_name)

return event_dict
7 changes: 6 additions & 1 deletion src/structlog/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from typing import Any, Generator, NamedTuple, NoReturn

from ._config import configure, get_config
from ._log_levels import map_method_name
from .exceptions import DropEvent
from .typing import EventDict, WrappedLogger

Expand All @@ -41,6 +42,10 @@ class LogCapture:
:ivar List[structlog.typing.EventDict] entries: The captured log entries.
.. versionadded:: 20.1.0
.. versionchanged:: 24.3.0
Added mapping from "exception" to "error"
Added mapping from "warn" to "warning"
"""

entries: list[EventDict]
Expand All @@ -51,7 +56,7 @@ def __init__(self) -> None:
def __call__(
self, _: WrappedLogger, method_name: str, event_dict: EventDict
) -> NoReturn:
event_dict["log_level"] = method_name
event_dict["log_level"] = map_method_name(method_name)
self.entries.append(event_dict)

raise DropEvent
Expand Down
31 changes: 31 additions & 0 deletions tests/test_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import pytest

import structlog

from structlog import get_config, get_logger, testing
from structlog.testing import (
CapturedCall,
Expand Down Expand Up @@ -85,6 +87,35 @@ def test_captures_bound_logers(self):
}
]

def test_captures_log_level_mapping(self):
"""
exceptions and warn log levels are mapped like in regular loggers.
"""
structlog.configure(
processors=[
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
)
with testing.capture_logs() as logs:
get_logger().exception("hello", answer=42)
get_logger().warn("again", answer=23)

assert [
{
"event": "hello",
"answer": 42,
"exc_info": True,
"log_level": "error",
},
{
"answer": 23,
"event": "again",
"log_level": "warning",
},
] == logs


class TestReturnLogger:
# @pytest.mark.parametrize("method", stdlib_log_methods)
Expand Down

0 comments on commit e28bbfe

Please sign in to comment.