CLI: enable log prefixing

This adds a commandline option which enables log level prefixing.
These prefixes enable log level-based filtering in journalctl when
present so long as logs are going to the journal, and
`SyslogLevelPrefix=` is set to `true` (which it is by default).

For documentation: https://manpages.debian.org/testing/libsystemd-dev/sd-daemon.3.en.html
This commit is contained in:
Misty De Méo 2025-02-24 14:53:13 -08:00 committed by Misty De Méo
parent f384d0b830
commit af0f3ed378
3 changed files with 52 additions and 18 deletions

View File

@ -74,6 +74,12 @@ def add_common_options(arg_parser, argv=None):
const=logging.DEBUG,
help=("very verbose logging"),
)
arg_parser.add_argument(
"--syslogd-log-prefix",
dest="syslogd_log_prefix",
action="store_true",
help="add syslogd log level prefix for journalctl filtering",
)
# arg_parser.add_argument(
# '-s', '--silent', dest='log_level', action='store_const',
# default=logging.INFO, const=logging.CRITICAL)
@ -131,24 +137,48 @@ def decorate_logger_name(a, b, event_dict):
return event_dict
# https://manpages.debian.org/testing/libsystemd-dev/sd-daemon.3.en.html
def _systemd_log_prefix(_, level, log):
SYSLOG_MAP = {
"critical": 2,
"error": 3,
"exception": 3,
"warn": 3,
"warning": 3,
"info": 6,
"debug": 7,
"notset": 7,
}
prefix = SYSLOG_MAP.get(level)
if prefix is not None:
log = f"<{prefix}>{log}"
return log
def configure_logging(args):
processors = [
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.StackInfoRenderer(),
structlog.dev.set_exc_info,
structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S", utc=True),
structlog.processors.CallsiteParameterAdder(
[
structlog.processors.CallsiteParameter.FILENAME,
structlog.processors.CallsiteParameter.FUNC_NAME,
structlog.processors.CallsiteParameter.LINENO,
],
),
decorate_logger_name,
structlog.dev.ConsoleRenderer(),
]
if args.syslogd_log_prefix:
processors.append(_systemd_log_prefix)
structlog.configure(
processors=[
structlog.contextvars.merge_contextvars,
structlog.processors.add_log_level,
structlog.processors.StackInfoRenderer(),
structlog.dev.set_exc_info,
structlog.processors.TimeStamper(fmt="%Y-%m-%d %H:%M:%S", utc=True),
structlog.processors.CallsiteParameterAdder(
[
structlog.processors.CallsiteParameter.FILENAME,
structlog.processors.CallsiteParameter.FUNC_NAME,
structlog.processors.CallsiteParameter.LINENO,
],
),
decorate_logger_name,
structlog.dev.ConsoleRenderer(),
],
processors=processors,
wrapper_class=structlog.make_filtering_bound_logger(args.log_level),
context_class=dict,
logger_factory=structlog.PrintLoggerFactory(),

View File

@ -29,7 +29,9 @@ import json
import threading
import socket
args = argparse.Namespace()
arg_parser = argparse.ArgumentParser()
brozzler.cli.add_common_options(arg_parser)
args = arg_parser.parse_args([])
args.log_level = logging.INFO
brozzler.cli.configure_logging(args)

View File

@ -28,7 +28,9 @@ import pytest
import brozzler
args = argparse.Namespace()
arg_parser = argparse.ArgumentParser()
brozzler.cli.add_common_options(arg_parser)
args = arg_parser.parse_args([])
args.log_level = logging.INFO
brozzler.cli.configure_logging(args)