Add additional info like python-systemd does

Upstream python-systemd has a journald logging handler that also adds
some exception information, as well as thread information.

  https://github.com/systemd/python-systemd/blob/master/systemd/journal.py#L581-L589

While OpenStack doesn't use a lot of threads, we might as well support it
since it's no cost. Also, add PROCESS_NAME just to be compatible with
other programs that might use python journald logging. Not entirely sure
if record.processName and the results of our self.binary_name will be
different.

The exception info is the fun stuff though.

Change-Id: Ibf0d7dae7587639737e0327f0338f30cdfc6aba1
This commit is contained in:
Monty Taylor 2017-04-19 08:47:15 -05:00
parent 8593e2e8b7
commit a5ee482cee
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
3 changed files with 43 additions and 2 deletions

View File

@ -58,8 +58,17 @@ known at the time of logging the message.
CODE_FILE=, CODE_LINE=, CODE_FUNC= CODE_FILE=, CODE_LINE=, CODE_FUNC=
The code location generating this message, if known. Contains the The code location generating this message, if known. Contains the
source filename, the line number and the function name. (This is source filename, the line number and the function name. (This is the
the same as systemd uses) same as systemd uses)
THREAD_NAME=, PROCESS_NAME=
Information about the thread and process, if known. (This is the same
as systemd uses)
EXCEPTION_TEXT=, EXCEPTION_INFO=
Information about an exception, if an exception has been logged.
LOGGER_NAME= LOGGER_NAME=

View File

@ -123,12 +123,20 @@ class OSJournalHandler(logging.Handler):
'CODE_FILE': record.pathname, 'CODE_FILE': record.pathname,
'CODE_LINE': record.lineno, 'CODE_LINE': record.lineno,
'CODE_FUNC': record.funcName, 'CODE_FUNC': record.funcName,
'THREAD_NAME': record.threadName,
'PROCESS_NAME': record.processName,
'LOGGER_NAME': record.name, 'LOGGER_NAME': record.name,
'LOGGER_LEVEL': record.levelname, 'LOGGER_LEVEL': record.levelname,
'SYSLOG_IDENTIFIER': self.binary_name, 'SYSLOG_IDENTIFIER': self.binary_name,
'PRIORITY': priority 'PRIORITY': priority
} }
if record.exc_text:
extras['EXCEPTION_TEXT'] = record.exc_text
if record.exc_info:
extras['EXCEPTION_INFO'] = record.exc_info
for field in self.custom_fields: for field in self.custom_fields:
value = record.__dict__.get(field) value = record.__dict__.get(field)
if value: if value:

View File

@ -334,6 +334,30 @@ class OSJournalHandlerTestCase(BaseTestCase):
SYSLOG_IDENTIFIER=mock.ANY, SYSLOG_IDENTIFIER=mock.ANY,
REQUEST_ID=mock.ANY, REQUEST_ID=mock.ANY,
PROJECT_NAME='mytenant', PROJECT_NAME='mytenant',
PROCESS_NAME='MainProcess',
THREAD_NAME='MainThread',
USER_NAME='myuser'))
def test_emit_exception(self):
l = log.getLogger('nova-exception.foo')
local_context = _fake_new_context()
try:
raise Exception("Some exception")
except Exception:
l.exception("Foo", context=local_context)
self.assertEqual(
self.journal.send.call_args,
mock.call(mock.ANY, CODE_FILE=mock.ANY,
CODE_FUNC='test_emit_exception',
CODE_LINE=mock.ANY, LOGGER_LEVEL='ERROR',
LOGGER_NAME='nova-exception.foo', PRIORITY=3,
SYSLOG_IDENTIFIER=mock.ANY,
REQUEST_ID=mock.ANY,
EXCEPTION_INFO=mock.ANY,
EXCEPTION_TEXT=mock.ANY,
PROJECT_NAME='mytenant',
PROCESS_NAME='MainProcess',
THREAD_NAME='MainThread',
USER_NAME='myuser')) USER_NAME='myuser'))