From fd062f0508f7132bba680402f72aa2c35ab5463b Mon Sep 17 00:00:00 2001 From: Philipp Lemke Date: Wed, 12 Aug 2026 18:28:54 +0200 Subject: [PATCH] fix: show comment for host notification results in log views PainterLogComment.render() used a hardcoded threshold of 6 ";"-separated fields to decide whether a notification log line carries a trailing comment. That threshold only matches the layout of SERVICE notification log lines, which have an extra ";" segment (7 fields with a comment). HOST notification log lines lack that segment, so even with a comment present they only ever reach 6 fields and never cross the "> 6" bar -- the comment column silently stays empty for every host notification, regardless of what the notification plugin wrote to stdout. Extract the threshold into _log_comment_min_fields(log_type), which returns 6 for service log types and 5 for host log types, and have PainterLogComment request the log_type column (already used by the neighboring PainterLogPluginOutput) to pick the right one. --- cmk/gui/painter/v0/painters.py | 17 ++++++- .../cmk/gui/plugins/views/test_painters.py | 46 ++++++++++++++++++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/cmk/gui/painter/v0/painters.py b/cmk/gui/painter/v0/painters.py index 2c198d3bd4c..3636b18cdd1 100644 --- a/cmk/gui/painter/v0/painters.py +++ b/cmk/gui/painter/v0/painters.py @@ -5835,6 +5835,19 @@ def render(self, row: Row, cell: Cell, user: LoggedInUser) -> CellSpec: return ("", row["log_options"]) +def _log_comment_min_fields(log_type: str) -> int: + """Minimum number of ";"-separated fields in a notification log line + before a trailing comment field is present. + + Host notification log lines have one field fewer than service + notification log lines (they lack the ";" segment), so the + threshold below which no comment field can be present differs between + the two. See cmk.events.log_to_history._format_notification_message, + which is the counterpart producing these log lines. + """ + return 6 if "SERVICE" in log_type else 5 + + class PainterLogComment(Painter): @property @override @@ -5852,14 +5865,14 @@ def short_title(self, cell: Cell) -> str: @property @override def columns(self) -> Sequence[ColumnName]: - return ["log_options"] + return ["log_options", "log_type"] @override def render(self, row: Row, cell: Cell, user: LoggedInUser) -> CellSpec: msg = row["log_options"] if ";" in msg: parts = msg.split(";") - if len(parts) > 6: + if len(parts) > _log_comment_min_fields(row.get("log_type", "")): return ("", parts[-1]) return ("", "") diff --git a/tests/unit/cmk/gui/plugins/views/test_painters.py b/tests/unit/cmk/gui/plugins/views/test_painters.py index 31aa76dbe4b..96d9a766844 100644 --- a/tests/unit/cmk/gui/plugins/views/test_painters.py +++ b/tests/unit/cmk/gui/plugins/views/test_painters.py @@ -23,7 +23,7 @@ from cmk.gui.http import request from cmk.gui.logged_in import user from cmk.gui.painter.v0 import all_painters -from cmk.gui.painter.v0.painters import _paint_custom_notes +from cmk.gui.painter.v0.painters import _log_comment_min_fields, _paint_custom_notes from cmk.gui.type_defs import ColumnSpec, DynamicIconName, Row from cmk.gui.utils.html import HTML from cmk.gui.utils.roles import UserPermissions @@ -1655,3 +1655,47 @@ def test_paint_custom_notes_file_inclusion_and_html_tags( expected_string = str(HTML.without_escaping("
".join(expected_notes))) assert expected_string == notes_as_string + + +@pytest.mark.parametrize( + "log_type, log_options, expected_comment", + [ + # Host notification log lines have no ";" segment, so with + # a comment present they only ever reach 6 fields, not 7. + pytest.param( + "HOST NOTIFICATION RESULT", + "cmkadmin;myhost;CRITICAL;my_plugin;some output;the comment", + "the comment", + id="host-with-comment", + ), + pytest.param( + "HOST NOTIFICATION RESULT", + "cmkadmin;myhost;CRITICAL;my_plugin;some output", + "", + id="host-without-comment", + ), + pytest.param( + "SERVICE NOTIFICATION RESULT", + "cmkadmin;myhost;My Service;CRITICAL;my_plugin;some output;the comment", + "the comment", + id="service-with-comment", + ), + pytest.param( + "SERVICE NOTIFICATION RESULT", + "cmkadmin;myhost;My Service;CRITICAL;my_plugin;some output", + "", + id="service-without-comment", + ), + ], +) +def test_log_comment_field_count( + log_type: str, log_options: str, expected_comment: str +) -> None: + # Regression test for the comment field being silently dropped for host + # notifications: PainterLogComment.render used a hardcoded threshold of + # 6 fields that only matches the (one field longer) service notification + # log line layout. + parts = log_options.split(";") + min_fields = _log_comment_min_fields(log_type) + actual_comment = parts[-1] if len(parts) > min_fields else "" + assert actual_comment == expected_comment