Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a helper function for systemd's SyslogLevelPrefix #249

Open
paravoid opened this issue Feb 28, 2020 · 2 comments
Open

Add a helper function for systemd's SyslogLevelPrefix #249

paravoid opened this issue Feb 28, 2020 · 2 comments

Comments

@paravoid
Copy link

From systemd.exec(5):

SyslogLevelPrefix=

Takes a boolean argument. If true and StandardOutput= or StandardError= are set to syslog, kmsg or journal, log lines written by the executed process that are prefixed with a log level will be passed on to syslog with this log level set but the prefix removed. If set to false, the interpretation of these prefixes is disabled and the logged lines are passed on as-is. For details about this prefixing see sd-daemon(3). Defaults to true.

i.e. for the simple case where a service emits output to stdout, and systemd picks that up, it may be helpful to add a prefix with the syslog log level. systemd will also pick that up, strip it from its output, and use it as the log level, by default.

There are two parts to this:

  1. Adding the syslog log level to event_dict, i.e. "4" (or syslog.LOG_WARNING) for "warn"/"warning", etc. Python's logging.handlers.SysLogHandler has code for that, and python-systemd is trying to do something more clever to cover custom log levels. Neither are reusable, but should be simple to implement. It should be similar to the existing add_log_level_number processor.
  2. A simple processor that prepends the event message with said level. I'm guessing that will be more controversial though. Alternatively, it could also be an argument to PrintLogger.

The "syslog" log level will also be useful in case one e.g. wants to write a processor using the stdlib syslog module (i.e. without involving logging).

@paravoid
Copy link
Author

(1) would probably be something like that. Let me know what you think :)

diff --git a/src/structlog/stdlib.py b/src/structlog/stdlib.py
index edaeccd..03e5fe6 100644
--- a/src/structlog/stdlib.py
+++ b/src/structlog/stdlib.py
@@ -343,6 +343,18 @@ _NAME_TO_LEVEL = {
     "notset": NOTSET,
 }
 
+# see syslog(3) and logging.handler.SysLogHandler for a similar mapping
+_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
+}
+
 _LEVEL_TO_NAME = {
     v: k
     for k, v in _NAME_TO_LEVEL.items()
@@ -406,6 +418,14 @@ def add_log_level_number(logger, method_name, event_dict):
     return event_dict
 
 
+def add_syslog_level(logger, method_name, event_dict):
+    """
+    Add the syslog level (0-7) to the event dict.
+    """
+    event_dict["syslog_level"] = _NAME_TO_SYSLOG_LEVEL[method_name]
+    return event_dict
+
+
 def add_logger_name(logger, method_name, event_dict):
     """
     Add the logger name to the event dict.

@hynek
Copy link
Owner

hynek commented Mar 7, 2020

Looks useful I guess? 🤔 Any idea how to test that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants