diff --git a/cmk/base/legacy_checks/winperf_ts_sessions.py b/cmk/base/legacy_checks/winperf_ts_sessions.py deleted file mode 100644 index eb4757bad12..00000000000 --- a/cmk/base/legacy_checks/winperf_ts_sessions.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2 -# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and -# conditions defined in the file COPYING, which is part of this source code package. - -# Example output from agent: -# <<>> -# 1385714515.93 2102 -# 2 20 rawcount -# 4 18 rawcount -# 6 2 rawcount - -# Counters, relative to the base ID (e.g. 2102) -# 2 Total number of Terminal Services sessions. -# 4 Number of active Terminal Services sessions. -# 6 Number of inactive Terminal Services sessions. -from collections.abc import Iterable, Mapping -from typing import Any - -from cmk.agent_based.legacy.v0_unstable import LegacyCheckDefinition -from cmk.agent_based.v2 import StringTable - -check_info = {} - - -def inventory_winperf_ts_sessions( - info: StringTable, -) -> Iterable[tuple[str | None, Mapping[str, Any]]]: - if len(info) > 1: - return [(None, {})] - return [] - - -def check_winperf_ts_sessions(_unused, params, info): - if not info or len(info) == 1: - return 3, "Performance counters not available" - total, active, inactive = (int(l[1]) for l in info[1:4]) - - # Tom Moore said, that the order of the columns has recently changed - # in newer Windows versions (hooray!) and is now active, inactive, total. - # We try to accommodate for that. - if active + inactive != total: - active, inactive, total = total, active, inactive - - state = 0 - state_txt = [] - for val, key, title in [(active, "active", "Active"), (inactive, "inactive", "Inactive")]: - txt = "%d %s" % (val, title) - if key in params: - if val > params[key][1]: - state = 2 - txt += "(!!)" - elif val > params[key][0]: - state = max(state, 1) - txt += "(!)" - state_txt.append(txt) - - perfdata = [("active", active), ("inactive", inactive)] - return state, ", ".join(state_txt), perfdata - - -def parse_winperf_ts_sessions(string_table: StringTable) -> StringTable: - return string_table - - -check_info["winperf_ts_sessions"] = LegacyCheckDefinition( - name="winperf_ts_sessions", - parse_function=parse_winperf_ts_sessions, - service_name="Sessions", - discovery_function=inventory_winperf_ts_sessions, - check_function=check_winperf_ts_sessions, - check_ruleset_name="winperf_ts_sessions", -) diff --git a/cmk/plugins/winperf/agent_based/winperf_ts_sessions.py b/cmk/plugins/winperf/agent_based/winperf_ts_sessions.py new file mode 100644 index 00000000000..3ef2c92f5e0 --- /dev/null +++ b/cmk/plugins/winperf/agent_based/winperf_ts_sessions.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +# Copyright (C) 2019 Checkmk GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. + +# Example output from agent: +# <<>> +# 1385714515.93 2102 +# 2 20 rawcount +# 4 18 rawcount +# 6 2 rawcount + +# Counters, relative to the base ID (e.g. 2102) +# 2 Total number of Terminal Services sessions. +# 4 Number of active Terminal Services sessions. +# 6 Number of inactive Terminal Services sessions. +from collections.abc import Mapping +from typing import Any + +from cmk.agent_based.v2 import ( + AgentSection, + check_levels, + CheckPlugin, + CheckResult, + DiscoveryResult, + Result, + Service, + State, + StringTable, +) + + +def discovery_winperf_ts_sessions( + section: StringTable, +) -> DiscoveryResult: + if len(section) > 1: + yield Service() + + +def check_winperf_ts_sessions(params: Mapping[str, Any], section: StringTable) -> CheckResult: + if not section or len(section) == 1: + yield Result(state=State.UNKNOWN, summary="Performance counters not available") + total, active, inactive = (int(l[1]) for l in section[1:4]) + + # Tom Moore said, that the order of the columns has recently changed + # in newer Windows versions (hooray!) and is now active, inactive, total. + # We try to accommodate for that. + if active + inactive != total: + active, inactive, total = total, active, inactive + + limit_active = params.get("active", None) + limit_inactive = params.get("inactive", None) + + yield from check_levels( + value=active, + metric_name="active", + levels_upper=("fixed", limit_active) if limit_active else ("no_levels", limit_active), + render_func=lambda x: f"{x} Active", + ) + yield from check_levels( + value=inactive, + metric_name="inactive", + levels_upper=("fixed", limit_inactive) if limit_inactive else ("no_levels", limit_inactive), + render_func=lambda x: f"{x} Inactive", + ) + + +def parse_winperf_ts_sessions(string_table: StringTable) -> StringTable: + return string_table + + +agent_section_winperf_ts_sessions = AgentSection( + name="winperf_ts_sessions", parse_function=parse_winperf_ts_sessions +) +check_plugin_winperf_ts_sessions = CheckPlugin( + name="winperf_ts_sessions", + service_name="Sessions", + discovery_function=discovery_winperf_ts_sessions, + check_function=check_winperf_ts_sessions, + check_ruleset_name="winperf_ts_sessions", + check_default_parameters={}, +) diff --git a/cmk/plugins/collection/checkman/winperf_ts_sessions b/cmk/plugins/winperf/checkman/winperf_ts_sessions similarity index 88% rename from cmk/plugins/collection/checkman/winperf_ts_sessions rename to cmk/plugins/winperf/checkman/winperf_ts_sessions index 8c67c53fc86..35131edadde 100644 --- a/cmk/plugins/collection/checkman/winperf_ts_sessions +++ b/cmk/plugins/winperf/checkman/winperf_ts_sessions @@ -12,7 +12,7 @@ description: file to forward the terminal service session related counters. Take a look at the windows monitoring documentation for details. - It allows to set WARN and CRIT tresholds on the active and idle session. + It allows to set WARN and CRIT thresholds on the active and idle session. discovery: One service is created for each host. diff --git a/tests/unit/checks/test_generic_legacy_conversion.py b/tests/unit/checks/test_generic_legacy_conversion.py index cf2c550a976..5ecfc84fe50 100644 --- a/tests/unit/checks/test_generic_legacy_conversion.py +++ b/tests/unit/checks/test_generic_legacy_conversion.py @@ -1201,7 +1201,6 @@ def test_no_new_or_vanished_legacy_checks(fix_plugin_legacy: FixPluginLegacy) -> "winperf_cpuusage", "winperf_diskstat", "winperf_mem", - "winperf_ts_sessions", "wmi_webservices", "wmic_process", "wut_webtherm", diff --git a/tests/unit/cmk/base/legacy_checks/test_winperf_ts_sessions.py b/tests/unit/cmk/base/legacy_checks/test_winperf_ts_sessions.py deleted file mode 100644 index 56844c15310..00000000000 --- a/tests/unit/cmk/base/legacy_checks/test_winperf_ts_sessions.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (C) 2025 Checkmk GmbH - License: GNU General Public License v2 -# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and -# conditions defined in the file COPYING, which is part of this source code package. -from collections.abc import Iterable, Mapping -from typing import Any - -from pytest import mark, param - -from cmk.base.legacy_checks.winperf_ts_sessions import ( - check_winperf_ts_sessions, - inventory_winperf_ts_sessions, -) - -from cmk.agent_based.v2 import StringTable - -_SECTION = [[1385714515.93, 2102], [2, 20, "rawcount"], [4, 18, "rawcount"], [6, 2, "rawcount"]] -_NEW_SECTION = [[1385714515.93, 2102], [4, 18, "rawcount"], [6, 2, "rawcount"], [2, 20, "rawcount"]] -_PERFDATA = [("active", 18), ("inactive", 2)] - - -@mark.parametrize("section, expected", [[_SECTION, [(None, {})]], [[], []]]) -def test_inventory_winperf_ts_sessions( - section: StringTable, expected: Iterable[tuple[str | None, Mapping[str, Any]]] -) -> None: - assert list(inventory_winperf_ts_sessions(section)) == expected - - -@mark.parametrize( - "section,params,expected", - [ - param(_SECTION, {}, (0, "18 Active, 2 Inactive", _PERFDATA)), - param(_SECTION, {"active": (10, 20)}, (1, "18 Active(!), 2 Inactive", _PERFDATA)), - param(_SECTION, {"inactive": (1, 20)}, (1, "18 Active, 2 Inactive(!)", _PERFDATA)), - param(_NEW_SECTION, {}, (0, "18 Active, 2 Inactive", _PERFDATA)), - param(_NEW_SECTION, {"active": (10, 20)}, (1, "18 Active(!), 2 Inactive", _PERFDATA)), - param(_NEW_SECTION, {"inactive": (1, 20)}, (1, "18 Active, 2 Inactive(!)", _PERFDATA)), - ], -) -def test_check_winperf_ts_sessions(section, params, expected): - assert check_winperf_ts_sessions(None, params, section) == expected diff --git a/tests/unit/cmk/plugins/winperf/agent_based/test_winperf_ts_sessions.py b/tests/unit/cmk/plugins/winperf/agent_based/test_winperf_ts_sessions.py new file mode 100644 index 00000000000..d4bf6370242 --- /dev/null +++ b/tests/unit/cmk/plugins/winperf/agent_based/test_winperf_ts_sessions.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +# Copyright (C) 2025 Checkmk GmbH - License: GNU General Public License v2 +# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and +# conditions defined in the file COPYING, which is part of this source code package. +from collections.abc import Mapping +from typing import Any + +from pytest import mark, param + +from cmk.agent_based.v2 import ( + CheckResult, + DiscoveryResult, + Metric, + Result, + Service, + State, + StringTable, +) +from cmk.plugins.winperf.agent_based.winperf_ts_sessions import ( + check_winperf_ts_sessions, + discovery_winperf_ts_sessions, +) + +# Note: The order of columns was changed in Windows. For more details, see comment in plugin code. +_SECTION = [[1385714515.93, 2102], [2, 20, "rawcount"], [4, 18, "rawcount"], [6, 2, "rawcount"]] +_NEW_SECTION = [[1385714515.93, 2102], [4, 18, "rawcount"], [6, 2, "rawcount"], [2, 20, "rawcount"]] + +METRIC_ACTIVE_OK = Metric(name="active", value=18) +METRIC_ACTIVE_WARN = Metric(name="active", value=18, levels=(10.0, 20.0)) +METRIC_INACTIVE_OK = Metric(name="inactive", value=2) +METRIC_INACTIVE_WARN = Metric(name="inactive", value=2, levels=(1.0, 20.0)) + +RESULT_ACTIVE_OK = Result(state=State.OK, summary="18 Active") +RESULT_ACTIVE_WARN = Result( + state=State.WARN, summary="18 Active (warn/crit at 10 Active/20 Active)" +) +RESULT_INACTIVE_OK = Result(state=State.OK, summary="2 Inactive") +RESULT_INACTIVE_WARN = Result( + state=State.WARN, summary="2 Inactive (warn/crit at 1 Inactive/20 Inactive)" +) +_PERFDATA = [Metric("active", 18), Metric("inactive", 2)] + + +@mark.parametrize("section, expected", [[_SECTION, [Service()]], [[], []]]) +def test_discovery_winperf_ts_sessions(section: StringTable, expected: DiscoveryResult) -> None: + assert list(discovery_winperf_ts_sessions(section)) == expected + + +@mark.parametrize( + "section,params,expected", + [ + param( + _SECTION, + {}, + [RESULT_ACTIVE_OK, METRIC_ACTIVE_OK, RESULT_INACTIVE_OK, METRIC_INACTIVE_OK], + id="all ok (old column order)", + ), + param( + _SECTION, + {"active": (10, 20)}, + [RESULT_ACTIVE_WARN, METRIC_ACTIVE_WARN, RESULT_INACTIVE_OK, METRIC_INACTIVE_OK], + id="number of active sessions exceeds warn threshold (old column order)", + ), + param( + _SECTION, + {"inactive": (1, 20)}, + [RESULT_ACTIVE_OK, METRIC_ACTIVE_OK, RESULT_INACTIVE_WARN, METRIC_INACTIVE_WARN], + id="number of inactive sessions exceeds warn threshold (old column order)", + ), + param( + _SECTION, + {"active": (10, 20), "inactive": (1, 20)}, + [RESULT_ACTIVE_WARN, METRIC_ACTIVE_WARN, RESULT_INACTIVE_WARN, METRIC_INACTIVE_WARN], + id="both warn thresholds exceeded (old column order)", + ), + param( + _NEW_SECTION, + {}, + [RESULT_ACTIVE_OK, METRIC_ACTIVE_OK, RESULT_INACTIVE_OK, METRIC_INACTIVE_OK], + id="all ok (new column order)", + ), + param( + _NEW_SECTION, + {"active": (10, 20)}, + [RESULT_ACTIVE_WARN, METRIC_ACTIVE_WARN, RESULT_INACTIVE_OK, METRIC_INACTIVE_OK], + id="number of active sessions exceeds warn threshold (new column order)", + ), + param( + _NEW_SECTION, + {"inactive": (1, 20)}, + [RESULT_ACTIVE_OK, METRIC_ACTIVE_OK, RESULT_INACTIVE_WARN, METRIC_INACTIVE_WARN], + id="number of inactive sessions exceeds warn threshold (new column order)", + ), + param( + _NEW_SECTION, + {"active": (10, 20), "inactive": (1, 20)}, + [RESULT_ACTIVE_WARN, METRIC_ACTIVE_WARN, RESULT_INACTIVE_WARN, METRIC_INACTIVE_WARN], + id="both warn thresholds exceeded (new column order)", + ), + ], +) +def test_check_winperf_ts_sessions( + section: StringTable, params: Mapping[str, Any], expected: CheckResult +) -> None: + assert list(check_winperf_ts_sessions(params, section)) == expected