diff --git a/src/structlog/stdlib.py b/src/structlog/stdlib.py index 2906598d..aa1024bf 100644 --- a/src/structlog/stdlib.py +++ b/src/structlog/stdlib.py @@ -60,6 +60,7 @@ "add_log_level", "add_log_level_number", "add_logger_name", + "add_syslog_level", "filter_by_level", "get_logger", "recreate_defaults", @@ -865,6 +866,38 @@ def add_log_level_number( return event_dict +# syslog(3) / logging.handlers.SysLogHandler priority values (0-7). +_NAME_TO_SYSLOG_LEVEL = { + "critical": 2, # LOG_CRIT + "error": 3, # LOG_ERR + "exception": 3, # LOG_ERR + "warn": 4, # LOG_WARNING + "warning": 4, # LOG_WARNING + "info": 6, # LOG_INFO + "debug": 7, # LOG_DEBUG + "notset": 7, # LOG_DEBUG +} + + +def add_syslog_level( + logger: logging.Logger, method_name: str, event_dict: EventDict +) -> EventDict: + """ + Add the syslog severity (0–7) to the event dict under ``syslog_level``. + + Useful when feeding plain stdout/stderr to *systemd* with + ``SyslogLevelPrefix=yes`` (see :manpage:`systemd.exec(5)` / *sd-daemon*), + or when writing processors that talk to the stdlib ``syslog`` module. + + The mapping follows :class:`logging.handlers.SysLogHandler` and + :manpage:`syslog(3)`. + + .. versionadded:: NEXT + """ + event_dict["syslog_level"] = _NAME_TO_SYSLOG_LEVEL[method_name] + return event_dict + + def add_logger_name( logger: logging.Logger, method_name: str, event_dict: EventDict ) -> EventDict: diff --git a/tests/test_stdlib.py b/tests/test_stdlib.py index 655cadb4..d624733b 100644 --- a/tests/test_stdlib.py +++ b/tests/test_stdlib.py @@ -43,6 +43,7 @@ add_log_level, add_log_level_number, add_logger_name, + add_syslog_level, filter_by_level, get_logger, recreate_defaults, @@ -530,6 +531,29 @@ def test_log_level_number_added(self, level, number): assert number == event_dict["level_number"] +class TestAddSyslogLevel: + @pytest.mark.parametrize( + ("level", "priority"), + [ + ("critical", 2), + ("error", 3), + ("exception", 3), + ("warn", 4), + ("warning", 4), + ("info", 6), + ("debug", 7), + ("notset", 7), + ], + ) + def test_syslog_level_added(self, level, priority): + """ + The syslog severity (0-7) is added to the event dict (#249). + """ + event_dict = add_syslog_level(None, level, {}) + + assert priority == event_dict["syslog_level"] + + class TestAddLogLevel: def test_log_level_added(self): """