From 7c38baf6fb46b87a3d7999b9a86aedd71662be0c Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Sat, 26 Jul 2025 13:14:28 +1000 Subject: [PATCH 1/2] Correctly propagate message templates when publishing log records to Seq tintoy/seqlog#88 --- seqlog/structured_logging.py | 38 ++++++++++++++++++++++++++++++++++-- tests/test_configuration.py | 1 + 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/seqlog/structured_logging.py b/seqlog/structured_logging.py index 3e091bb..fb12876 100644 --- a/seqlog/structured_logging.py +++ b/seqlog/structured_logging.py @@ -164,6 +164,30 @@ def getMessage(self): else: return self.msg + def getMessageTemplate(self): + """ + Get the raw (unformatted) message template used to generate the message for the log record (used in cases where formatting will be performed by the target that receives the published log record). + :return: The message template. + """ + + if self.msg is None: + warnings.warn('You just passed a None as a message content!', UserWarning) + self.msg = '' + + # See https://docs.python.org/3/library/logging.html#logging.LogRecord.getMessage for details + if not isinstance(self.msg, str): + self.msg = str(self.msg) + + if self.args: + # Not using {NamedHole}-style formatting, so we still return the formatted log message (since we don't have a _compatible_ message template). + return self.getMessage() + elif self.log_props: + # We're using using {NamedHole}-style formatting, so msg is the message template. + return self.msg + else: + # in this case, we have no message template, and so we can safely assume that the message itself is the message template. + return self.msg + class StructuredLogger(logging.Logger): """ @@ -521,10 +545,15 @@ def _build_event_data_ingest(self, record): logger_name = record.name if record.name else None + if isinstance(record, StructuredLogRecord): + message_template = record.getMessageTemplate() + else: + message_template = record.getMessage() + event_data = { "Timestamp": _get_local_timestamp(record), "Level": logging.getLevelName(record.levelno), - "MessageTemplate": record.getMessage(), + "MessageTemplate": message_template, "Properties": get_global_log_properties(logger_name) } @@ -579,10 +608,15 @@ def _build_event_data_clef(self, record): logger_name = record.name if record.name else None + if isinstance(record, StructuredLogRecord): + message_template = record.getMessageTemplate() + else: + message_template = record.getMessage() + event_data = { "@t": _get_local_timestamp(record, True), "@l": logging.getLevelName(record.levelno), - "@mt": record.getMessage(), + "@mt": message_template, } props = {} for key, value in get_global_log_properties(logger_name).items(): diff --git a/tests/test_configuration.py b/tests/test_configuration.py index 7200ead..2735909 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -38,6 +38,7 @@ format: '[%(levelname)s] %(asctime)s %(name)s: %(message)s' """ + class TestConfiguration(object): def test_valid_config(self): try: From bfe975c8478a2c3c463dd5b1b72419ef7d41f07e Mon Sep 17 00:00:00 2001 From: Adam Friedman Date: Sat, 26 Jul 2025 13:30:37 +1000 Subject: [PATCH 2/2] v0.4.2 --- HISTORY.rst | 5 +++++ meta.yaml | 2 +- seqlog/__init__.py | 2 +- setup.py | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 9376d94..638b878 100755 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -2,6 +2,11 @@ History ======= +0.4.2 (2025-07-26) +------------------ + +* A bugfix to correctly propagate `MessageTemplate` / `@mt` to Seq (tintoy/seqlog#88). + 0.4.1 (2025-05-11) ------------------ diff --git a/meta.yaml b/meta.yaml index d48981f..99fe795 100644 --- a/meta.yaml +++ b/meta.yaml @@ -1,6 +1,6 @@ package: name: seqlog - version: 0.4.1 + version: 0.4.2 requirements: host: diff --git a/seqlog/__init__.py b/seqlog/__init__.py index 7191edc..ae749eb 100644 --- a/seqlog/__init__.py +++ b/seqlog/__init__.py @@ -16,7 +16,7 @@ __author__ = 'Adam Friedman' __email__ = 'tintoy@tintoy.io' -__version__ = '0.4.1' +__version__ = '0.4.2' def configure_from_file(file_name, override_root_logger=True, support_extra_properties=False, support_stack_info=False, ignore_seq_submission_errors=False, diff --git a/setup.py b/setup.py index 157afcf..01bb9ec 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ def normalize_line_endings(text: str): setup( name='seqlog', - version='0.4.1', + version='0.4.2', description="SeqLog enables logging from Python to Seq.", long_description=readme + '\n\n' + history, long_description_content_type='text/x-rst',