JournalHandler: Sanitize extra fields to be valid journald fields
ypid-geberit opened this issue · 0 comments
I noticed an incontinence with JournalHandler when using it in an existing code base. I already use the Python logging module and all my logging already includes structured data like this:
LOG.info('test', extra={'structured_data': 23})The structured_data field does not make it into journald and is silently omitted. I checked https://github.com/mosquito/cysystemd and it has sanitation code which works for me:
As the status of this project and relationship with https://github.com/mosquito/cysystemd is not clear I just wanted to document this here.
Edit:
I ended up using python-systemd instead of cysystemd mainly because of the less cluttered fields it outputs so I needed to work around the issue described here. I needed to workaround another limitation which is that journald cannot handle nested fields so I combined the two workarounds into this (also I want to log sets so it includes a workaround for this as well):
import logging
import json
from systemd.journal import JournalHandler
class SetJSONEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj)
return json.JSONEncoder.default(self, obj)
class LogExtraAsJsonDataAdapter(logging.LoggerAdapter):
def process(self, msg, kwargs):
if 'extra' in kwargs:
kwargs['extra'] = {'JSON_SD': json.dumps(kwargs['extra'], cls=SetJSONEncoder)}
return msg, kwargs
_LOG = logging.getLogger(__name__)
_LOG.addHandler(JournalHandler())
LOG = LogExtraAsJsonDataAdapter(_LOG, {})The idea here is that Journalbeat sends those logs to Logstash where JSON_SD is JSON decoded and included into the log event.