Render logs as json with python-json-logger

This commit is contained in:
Daniel Egger 2023-08-28 13:32:42 +02:00
parent 163df01f5d
commit e08d5574f7
2 changed files with 35 additions and 31 deletions

View File

@ -8,7 +8,7 @@ import structlog
from environs import Env from environs import Env
from vbv_lernwelt.core.constants import DEFAULT_RICH_TEXT_FEATURES from vbv_lernwelt.core.constants import DEFAULT_RICH_TEXT_FEATURES
from vbv_lernwelt.core.utils import structlog_add_app_info from vbv_lernwelt.core.utils import structlog_add_app_info, structlog_add_to_message
SERVER_ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent SERVER_ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent
APPS_DIR = SERVER_ROOT_DIR / "vbv_lernwelt" APPS_DIR = SERVER_ROOT_DIR / "vbv_lernwelt"
@ -427,36 +427,16 @@ if IT_DJANGO_LOGGING_CONF == "IT_DJANGO_LOGGING_CONF_CONSOLE_COLOR":
cache_logger_on_first_use=True, cache_logger_on_first_use=True,
) )
else: else:
shared_processors = [
structlog.threadlocal.merge_threadlocal,
structlog.stdlib.add_log_level,
structlog.stdlib.add_logger_name,
structlog_add_app_info,
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.CallsiteParameterAdder(),
]
LOGGING = { LOGGING = {
"version": 1, "version": 1,
"disable_existing_loggers": True, "disable_existing_loggers": True,
"formatters": { "formatters": {
"json": { "json": {
"()": structlog.stdlib.ProcessorFormatter, "()": "pythonjsonlogger.jsonlogger.JsonFormatter",
"processors": [ "format": "%(asctime)s %(levelname)s %(process)d %(thread)d %(name)s %(lineno)d %(funcName)s %(message)s",
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
structlog.processors.JSONRenderer(),
],
"foreign_pre_chain": shared_processors,
}, },
}, },
"handlers": { "handlers": {
"file": {
"class": "concurrent_log_handler.ConcurrentRotatingFileHandler",
"filename": f"{SERVER_ROOT_DIR}/log/myservice.log",
"maxBytes": 1024 * 1024 * 100,
"backupCount": 50,
"formatter": "json",
},
"console": { "console": {
"level": "DEBUG", "level": "DEBUG",
"class": "logging.StreamHandler", "class": "logging.StreamHandler",
@ -465,30 +445,36 @@ else:
}, },
"loggers": { "loggers": {
"": { "": {
"handlers": ["console", "file"], "handlers": ["console"],
"level": "INFO", "level": "INFO",
}, },
"django": { "django": {
"handlers": ["console", "file"], "handlers": ["console"],
"level": "WARNING", "level": "WARNING",
"propagate": False, "propagate": False,
}, },
"vbv_lernwelt": { "vbv_lernwelt": {
"handlers": ["console", "file"], "handlers": ["console"],
"level": "DEBUG", "level": "DEBUG",
"propagate": False, "propagate": False,
}, },
"sentry_sdk": { "sentry_sdk": {
"level": "ERROR", "level": "ERROR",
"handlers": ["console", "file"], "handlers": ["console"],
"propagate": False, "propagate": False,
}, },
}, },
} }
structlog.configure( structlog.configure(
processors=shared_processors processors=[
+ [ structlog.stdlib.filter_by_level,
structlog.threadlocal.merge_threadlocal,
structlog_add_app_info,
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog_add_to_message,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter, structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
], ],
context_class=dict, context_class=dict,

View File

@ -8,15 +8,33 @@ from structlog.types import EventDict
def structlog_add_app_info( def structlog_add_app_info(
logger: logging.Logger, method_name: str, event_dict: EventDict _: logging.Logger, __: str, event_dict: EventDict
) -> EventDict: ) -> EventDict:
event_dict["django_app"] = "vbv_lernwelt" event_dict["django_app"] = "vbv_lernwelt"
event_dict["APP_ENVIRONMENT"] = settings.APP_ENVIRONMENT event_dict["app_environment"] = settings.APP_ENVIRONMENT
event_dict["django_app_dev_mode"] = f"vbv_lernwelt_{settings.APP_ENVIRONMENT}" event_dict["django_app_dev_mode"] = f"vbv_lernwelt_{settings.APP_ENVIRONMENT}"
return event_dict return event_dict
def structlog_add_to_message(
_: logging.Logger, __: str, event_dict: EventDict
) -> EventDict:
"""
The *event_dict* is added as dict ``message``.
This allows you to defer formatting to `logging`.
"""
return {
"message": event_dict,
**{
kw: event_dict.pop(kw)
for kw in ("exc_info", "stack_info", "stackLevel")
if kw in event_dict
},
}
def structlog_inject_context_dict(test, level, event_dict): def structlog_inject_context_dict(test, level, event_dict):
""" """
Add the structlog context dict to log events generated by the stdlib logging library. Add the structlog context dict to log events generated by the stdlib logging library.