Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions cmk/gui/painter/v0/painters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 ";<service>" 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
Expand All @@ -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 ("", "")

Expand Down
46 changes: 45 additions & 1 deletion tests/unit/cmk/gui/plugins/views/test_painters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -1655,3 +1655,47 @@ def test_paint_custom_notes_file_inclusion_and_html_tags(
expected_string = str(HTML.without_escaping("<hr>".join(expected_notes)))

assert expected_string == notes_as_string


@pytest.mark.parametrize(
"log_type, log_options, expected_comment",
[
# Host notification log lines have no ";<service>" 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
Loading