diff --git a/README.md b/README.md index b848c4d4c4f59c4ab2966a0a4f1ef262ad6ba5b4..652b58e2c7c285b32310b035b846eeb393c73c78 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[PACKAGE]: ../../raw/master/mkp/squid-2.0.4-2023-09-21.mkp "squid-2.0.4-2023-09-21.mkp" +[PACKAGE]: ../../raw/master/mkp/squid-2.1.0-20231202.mkp "squid-2.1.0-20231202.mkp" # Squid Web Proxy This CheckMK plugin monitors the performance of the _**Squid Web Proxy**_. This plugin is intended to use with the Agent Bakery of CheckMK. diff --git a/agent_based/squid.py b/agent_based/squid.py index 2fdd9c3d4d27c47253275b8bc5df1da92249d021..3ea93826460a9ab72c99b60f47d86fcb06c153b0 100644 --- a/agent_based/squid.py +++ b/agent_based/squid.py @@ -13,8 +13,9 @@ # # 2023-05-20: moved to ~/local/lib/check_mk/base/plugins/agent_based/utils # renamed from check_squid.include to squid.py -# - +# 2023-12-02: fixed crash on empty section or missing value +# added swap section +# added file descriptors section # !/usr/bin/env python3 # -*- coding: utf-8 -*- @@ -32,7 +33,7 @@ # ToDo: add support for multiple instances -from typing import Dict +from typing import Dict, Optional from cmk.base.plugins.agent_based.agent_based_api.v1 import ( register, check_levels, @@ -58,7 +59,6 @@ def parse_squid(string_table) -> Dict[str, float]: if 'kbytes' in entry: value = value * 1024 + 8 # change kbytes to bits section[entry] = value - return section @@ -68,10 +68,44 @@ register.agent_section( ) +def parse_squid_file_descriptors(string_table) -> Dict[str, float]: + """ + Maximum number of file descriptors: 1024 + Available number of file descriptors: 1018 + Reserved number of file descriptors: 100 + + Args: + string_table: + + Returns: + + """ + section = {} + for line in string_table: + entry, value = line[0].split(':') + entry = entry.lower().strip().replace(' ', '_') + try: + value = float(value.strip()) + except ValueError: + continue + section[entry] = value + return section + + +register.agent_section( + name='squid_file_descriptors', + parse_function=parse_squid_file_descriptors, +) + + def render_per_second(value: float) -> str: return f'{value:0.2f}/s' +def render_count(value: float) -> str: + return f'{int(value)}' + + squid_map = { 'Client': { 'client_http.requests': { @@ -152,36 +186,87 @@ squid_map = { 'metric_name': 'dns_median_svc_time', 'render_func': render.timespan, }}, + 'Swap': { + 'swap.outs': { + 'label': 'Out', + 'levels_upper': 'swap_out', + 'metric_name': 'swap_out', + 'render_func': render_per_second, + }, + 'swap.ins': { + 'label': 'In', + 'levels_upper': 'swap_in', + 'metric_name': 'swap_in', + 'render_func': render_per_second, + }, + 'swap.files_cleaned': { + 'label': 'Files cleaned', + 'levels_upper': 'swap_files_cleaned', + 'metric_name': 'swap_files_cleaned', + 'render_func': render_per_second, + }, + }, + 'File descriptors': { + 'maximum_number_of_file_descriptors': { + 'label': 'Maximum', + 'levels_upper': 'maximum_number_of_file_descriptors', + 'metric_name': 'maximum_number_of_file_descriptors', + 'render_func': render_count, + }, + 'available_number_of_file_descriptors': { + 'label': 'Available', + 'levels_upper': 'available_number_of_file_descriptors', + 'metric_name': 'available_number_of_file_descriptors', + 'render_func': render_count, + }, + 'reserved_number_of_file_descriptors': { + 'label': 'Reserved', + 'levels_upper': 'reserved_number_of_file_descriptors', + 'metric_name': 'reserved_number_of_file_descriptors', + 'render_func': render_count, + }, + } } -def discovery_squid(section: Dict[str, float]) -> DiscoveryResult: +def discovery_squid( + section_squid: Optional[Dict[str, float]], + section_squid_file_descriptors: Optional[Dict[str, float]] +) -> DiscoveryResult: for item in squid_map.keys(): yield Service(item=item) -def check_squid(item, params, section: Dict[str, float]) -> CheckResult: +def check_squid( + item, + params, + section_squid: Optional[Dict[str, float]], + section_squid_file_descriptors: Optional[Dict[str, float]], +) -> CheckResult: + section_squid.update(section_squid_file_descriptors) for value in squid_map[item].keys(): entry = squid_map[item][value] levels_upper = params.get(entry['levels_upper'], None) - yield from check_levels_predictive( - label=entry['label'], - value=section[value], - levels=levels_upper, - render_func=entry['render_func'], - metric_name=entry['metric_name'], - ) if isinstance(levels_upper, dict) else check_levels( - label=entry['label'], - value=section[value], - levels_upper=levels_upper, - render_func=entry['render_func'], - metric_name=entry['metric_name'], - ) + if section_squid.get(value) is not None: + yield from check_levels_predictive( + label=entry['label'], + value=section_squid[value], + levels=levels_upper, + render_func=entry['render_func'], + metric_name=entry['metric_name'], + ) if isinstance(levels_upper, dict) else check_levels( + label=entry['label'], + value=section_squid[value], + levels_upper=levels_upper, + render_func=entry['render_func'], + metric_name=entry['metric_name'], + ) register.check_plugin( name='squid', service_name='Squid %s', + sections=['squid', 'squid_file_descriptors'], discovery_function=discovery_squid, check_function=check_squid, check_default_parameters={ diff --git a/agents/plugins/squid b/agents/plugins/squid index d88aaf6bcd80929610765801849e729b913f3557..475c7a0a5e8035784137416f3b363621e330f98d 100755 --- a/agents/plugins/squid +++ b/agents/plugins/squid @@ -9,6 +9,7 @@ # 2023-05-20: changed separator to :sep(0) # changed section from check_squid to squid # 2023-05-22: fixed missing "<" in section name +# 2023-12-02: added -l "$ip_address" option # MK_CONFDIR="/etc/check_mk" @@ -21,12 +22,17 @@ if [ -z "$port" ]; then port=$(ss -tlpn | grep squid | tr -s ' ' | cut -d' ' -f 4 | cut -d':' -f 2) fi +if [ -z "$ip_address" ]; then + ip_address=localhost +fi if type squidclient > /dev/null 2>&1 ; then - echo "<<<squid:sep(0)>>>" + echo "<<<squid_file_descriptors:sep(0)>>>" + squidclient -p "$port" -l "$ip_address" -T2 mgr:info | grep "file descriptors" + echo "<<<squid:sep(0)>>>" # one squid instance - squidclient -p "$port" -T2 mgr:5min | grep = + squidclient -p "$port" -l "$ip_address" -T2 mgr:5min | grep = # multiple squid instances # instance names must be without spaces and with colon char at the end diff --git a/gui/metrics/squid.py b/gui/metrics/squid.py index 41df441db452795685dcc32f1397997897f34a1e..6a9d0e15ad8e279640f83ab0122dc7522afcc30a 100644 --- a/gui/metrics/squid.py +++ b/gui/metrics/squid.py @@ -25,6 +25,12 @@ check_metrics['check_mk-squid'] = { 'predict_client_hits_per_second': {'auto_graph': False}, 'predict_server_all_requests': {'auto_graph': False}, 'predict_util': {'auto_graph': False}, + # 'swap_out': {'auto_graph': False}, + # 'swap_in': {'auto_graph': False}, + # 'swap_files_cleaned': {'auto_graph': False}, + # 'maximum_number_of_file_descriptors': {'auto_graph': False}, + # 'available_number_of_file_descriptors': {'auto_graph': False}, + # 'reserved_number_of_file_descriptors': {'auto_graph': False}, } metric_info['client_hits_per_second'] = {'title': _('Cache hits'), 'unit': '1/s', 'color': '11/a', } @@ -125,3 +131,45 @@ perfometer_info.append({ 'half_value': 2, 'exponent': 2, }) + + +metric_info['swap_out'] = {'title': _('Out'), 'unit': '1/s', 'color': '26/a', } +metric_info['swap_in'] = {'title': _('In'), 'unit': '1/s', 'color': '26/b', } +metric_info['swap_files_cleaned'] = {'title': _('Files cleaned'), 'unit': '1/s', 'color': '26/b', } + +graph_info['squid_swap'] = { + 'title': _('Squid Swap'), + 'metrics': [ + ('swap_out', 'line'), + ('swap_in', 'line'), + ('swap_files_cleaned', 'line'), + ], + # 'scalars': [ + # 'swap_files_cleaned:warn', + # 'swap_files_cleaned:crit', + # ], +} + +metric_info['maximum_number_of_file_descriptors'] = {'title': _('Maximum'), 'unit': 'count', 'color': '31/a', } +metric_info['available_number_of_file_descriptors'] = {'title': _('Available'), 'unit': 'count', 'color': '26/a', } +metric_info['reserved_number_of_file_descriptors'] = {'title': _('Reserved'), 'unit': 'count', 'color': '14/a', } + +graph_info['squid_file_descriptors'] = { + 'title': _('Squid File Descriptors'), + 'metrics': [ + ('maximum_number_of_file_descriptors', 'line'), + ('available_number_of_file_descriptors', 'line'), + ('reserved_number_of_file_descriptors', 'line'), + ], + 'scalars': [ + 'available_number_of_file_descriptors:warn', + 'available_number_of_file_descriptors:crit', + ], +} + +perfometer_info.append({ + 'type': 'logarithmic', + 'metric': 'available_number_of_file_descriptors', + 'half_value': 1000, + 'exponent': 2, +}) \ No newline at end of file diff --git a/gui/wato/squid.py b/gui/wato/squid.py index cf7e3f9938fb19d48bde5d918335531b2f86620c..e7b47919a3d83630e21f5299f45d2fddada1d548 100644 --- a/gui/wato/squid.py +++ b/gui/wato/squid.py @@ -16,6 +16,8 @@ # changed client_reqps to client_requests # changed server_reqps to server_requests # changed cpu_time to cpu_usage +# 2023-12-02: add ip_address option for agent plugin +# add available_number_of_file_descriptors for check section from cmk.gui.i18n import _ from cmk.gui.valuespec import ( @@ -70,6 +72,12 @@ def _valuespec_squid(): Float(title=_('Warning at'), default_value=2.0, unit='seconds'), Float(title=_('Critical at'), default_value=4.0, unit='seconds'), ])), + ('available_number_of_file_descriptors', + Levels( + title=_('Set levels for Squid available file descriptors'), + unit='number of', + # default_levels=(60.0, 80.0) + )), ] ) @@ -93,13 +101,18 @@ def _valuespec_agent_squid(): help=_('The plugin <tt>squid</tt> allows monitoring of Squid Web Proxies.'), title=_('Squid Web Proxy (Linux)'), elements=[ + ('ip_address', + TextInput( + title=_('IP Address'), + help=_('Thi IP-Address squidclient connects to.'), + default_value='localhost', + )), ('port', Integer( title=_('Port number'), help=_('TCP port number that squidclient connects to.'), default_value=3128, - ) - ) + )), ] ) diff --git a/lib/python3/cmk/base/cee/plugins/bakery/squid.py b/lib/python3/cmk/base/cee/plugins/bakery/squid.py index 23c3d7c5b2b502499671858b44fe30361d38fbb8..05189f7429ba15994015d97a55d6b182b6898576 100644 --- a/lib/python3/cmk/base/cee/plugins/bakery/squid.py +++ b/lib/python3/cmk/base/cee/plugins/bakery/squid.py @@ -16,6 +16,7 @@ # renamed bakery plugin from squid to squid.py # 2023-09-21: moved file to ~/local/lib/check_mk/base/cee/plugins/bakery # fix crash if port not configured in wato +# 2023-12-02: added IP-Address option from pathlib import Path from cmk.base.cee.plugins.bakery.bakery_api.v1 import ( @@ -35,12 +36,18 @@ def get_squid_files(conf) -> FileGenerator: yield PluginConfig( base_os=OS.LINUX, - lines=[f'port={conf.get("port", 3128)}'], + lines=[f'{key}={value}' for key, value in conf.items()], + # lines=[ + # f'port={conf.get("port", 3128)}', + # f'ip_address={conf.get("ip_address", "localhost")}' + # ], target=Path('squid.cfg'), include_header=False, ) + + register.bakery_plugin( name='squid', files_function=get_squid_files, diff --git a/mkp/squid-2.1.0-20231202.mkp b/mkp/squid-2.1.0-20231202.mkp new file mode 100644 index 0000000000000000000000000000000000000000..94e873f08d61ff46db3f0cb7530ec6f9c899cbd8 Binary files /dev/null and b/mkp/squid-2.1.0-20231202.mkp differ diff --git a/packages/squid b/packages/squid index 649e379142b04ea0599164fb5ff61b1a1be1ee38..23522f2389867c66ef8be60a9550407f05b084a7 100644 --- a/packages/squid +++ b/packages/squid @@ -13,7 +13,7 @@ 'lib': ['python3/cmk/base/cee/plugins/bakery/squid.py']}, 'name': 'squid', 'title': 'Squid3 Health Check', - 'version': '2.0.4-2023-09-21', + 'version': '2.1.0-20231202', 'version.min_required': '2.1.0b1', - 'version.packaged': '2.2.0p11', + 'version.packaged': '2.2.0p14', 'version.usable_until': None}