diff --git a/agent_based/squid.py b/agent_based/squid.py new file mode 100644 index 0000000000000000000000000000000000000000..b719d483e2584bfab59b69450da0a88a9856be8c --- /dev/null +++ b/agent_based/squid.py @@ -0,0 +1,199 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2023-05-20 + +# based on https://github.com/allangood/check_mk/tree/master/plugins/squid +# +# rewritten for cmk 2.x +# +# 2023-05-20: moved to ~/local/lib/check_mk/base/plugins/agent_based/utils +# renamed from check_squid.include to squid.py +# + + +# !/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2023-05-20 + +# based on https://github.com/allangood/check_mk/tree/master/plugins/squid by Allan GooD: allan.cassaro@gmail.com +# +# rewritten for cmk 2.x +# + +# ToDo: add support for multiple instances + +from typing import Dict +from cmk.base.plugins.agent_based.agent_based_api.v1 import ( + register, + check_levels, + check_levels_predictive, + Service, + render +) +from cmk.base.plugins.agent_based.agent_based_api.v1.type_defs import ( + DiscoveryResult, + CheckResult, +) + + +def parse_squid(string_table) -> Dict[str, float]: + section = {} + for line in string_table: + entry, value = line[0].split('=') + entry = entry.strip() + try: + value = float(value.split('/')[0].strip().split(' ')[0].split('%')[0]) + except ValueError: + continue + if 'kbytes' in entry: + value = value * 1024 + 8 # change kbytes to bits + section[entry] = value + + return section + + +register.agent_section( + name="squid", + parse_function=parse_squid, +) + + +def render_per_second(value: float) -> str: + return f'{value}/s' + + +def render_seconds(value: float) -> str: + return f'{value:0.4f} seconds' + + +squid_map = { + 'Client': { + 'client_http.requests': { + 'label': 'Requests', + 'levels_upper': 'client_requests', + 'metric_name': 'client_requests_per_second', + 'render_func': render_per_second, + }, + 'client_http.errors': { + 'label': 'Errors', + 'levels_upper': 'client_errors', + 'metric_name': 'client_errors_per_second', + 'render_func': render_per_second, + }, + 'client_http.hits': { + 'label': 'Cache Hits', + 'levels_upper': 'client_hits', + 'metric_name': 'client_hits_per_second', + 'render_func': render_per_second, + }, + 'client_http.kbytes_in': { + 'label': 'In', + 'levels_upper': 'client_bytes_in_out', + 'metric_name': 'if_in_bps', + 'render_func': render.networkbandwidth, + }, + 'client_http.kbytes_out': { + 'label': 'Out', + 'levels_upper': 'client_bytes_in_out', + 'metric_name': 'if_out_bps', + 'render_func': render.networkbandwidth, + }, + }, + 'Server': { + 'server.all.requests': { + 'label': 'Requests', + 'levels_upper': 'server_requests', + 'metric_name': 'server_all_requests', + 'render_func': render_per_second, + }, + 'server.all.errors': { + 'label': 'Errors', + 'levels_upper': 'server_errors', + 'metric_name': 'server_all_errors', + 'render_func': render_per_second, + }, + 'server.all.kbytes_in': { + 'label': 'In', + 'levels_upper': 'server_bytes_in_out', + 'metric_name': 'if_in_bps', + 'render_func': render.networkbandwidth, + }, + 'server.all.kbytes_out': { + 'label': 'Out', + 'levels_upper': 'server_bytes_in_out', + 'metric_name': 'if_out_bps', + 'render_func': render.networkbandwidth, + }, + }, + 'CPU': { + 'cpu_usage': { + 'label': 'Usage', + 'levels_upper': 'cpu_usage', + 'metric_name': 'util', + 'render_func': render.percent, + }, + 'cpu_time': { + 'label': 'Time', + 'levels_upper': 'cpu_time', + 'metric_name': 'cpu_time', + 'render_func': render.timespan, + }, + }, + 'DNS': { + 'dns.median_svc_time': { + 'label': 'Median response time', + 'levels_upper': 'dns_time', + 'metric_name': 'dns_median_svc_time', + 'render_func': render_seconds, + }}, +} + + +def discovery_squid(section: Dict[str, float]) -> DiscoveryResult: + for item in squid_map.keys(): + yield Service(item=item) + + +def check_squid(item, params, section: Dict[str, float]) -> CheckResult: + 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'], + ) + + +register.check_plugin( + name='squid', + service_name='Squid %s', + discovery_function=discovery_squid, + check_function=check_squid, + check_default_parameters={ + # 'client_requests': (600, 800), + # 'client_hits': (600, 800), + # 'server_requests': (600, 800), + 'dns_time': (2, 4), + 'cpu_usage': (60, 80) + }, + check_ruleset_name='squid', +) diff --git a/agents/bakery/squid.py b/agents/bakery/squid.py new file mode 100755 index 0000000000000000000000000000000000000000..25a01918671e236880819a4364f158035636e470 --- /dev/null +++ b/agents/bakery/squid.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2023-05-20 + +# based on https://github.com/allangood/check_mk/tree/master/plugins/squid +# +# rewritten for cmk 2.x +# +# 2023-05-20: moved agent plugin from ~/local/share/check_mk/agents/plugins/linux +# to ~/local/share/check_mk/agents/plugins +# renamed bakery plugin from squid to squid.py + +from pathlib import Path +from cmk.base.cee.plugins.bakery.bakery_api.v1 import ( + FileGenerator, + OS, + Plugin, + PluginConfig, + register +) + + +def get_squid_files(conf) -> FileGenerator: + yield Plugin( + base_os=OS.LINUX, + source=Path('squid'), + # interval=interval, + # timeout=timeout + ) + + yield PluginConfig( + base_os=OS.LINUX, + lines=[f'port={conf["port"]}'], + target=Path('squid.cfg'), + include_header=False, + ) + + +register.bakery_plugin( + name='squid', + files_function=get_squid_files, +) diff --git a/agents/plugins/squid b/agents/plugins/squid new file mode 100755 index 0000000000000000000000000000000000000000..03aa18458e86c568a5bd31abb1041657aed4ac72 --- /dev/null +++ b/agents/plugins/squid @@ -0,0 +1,34 @@ +#!/bin/bash + +# based on https://github.com/allangood/check_mk/tree/master/plugins/squid by Allan GooD: allan.cassaro@gmail.com +# +# 2023-05-20: changed separator to :sep(0) +# changed section from check_squid to squid +# +# https://etutorials.org/Server+Administration/Squid.+The+definitive+guide/Chapter+14.+Monitoring+Squid/14.2+The+Cache+Manager/ +# +# Table 14-1. Cache manager pages for squidclient mgr:<page> +# +MK_CONFDIR="/etc/check_mk" + + +if [ -e $MK_CONFDIR/squid.cfg ] ; then + . "$MK_CONFDIR"/squid.cfg +fi + +if [ -z "$port" ]; then + port=$(ss -tlpn | grep squid | tr -s ' ' | cut -d' ' -f 4 | cut -d':' -f 2) +fi + + +if type squidclient > /dev/null 2>&1 ; then + echo "<<squid:sep(0)>>>" + + # one squid instance + squidclient -p "$port" -T2 mgr:5min | grep = + + # multiple squid instances + # instance names must be without spaces and with colon char at the end + # squidclient -p 3128 -T2 mgr:5min | grep ' = ' | sed -e 's/^/Instance1:/' + # squidclient -p 3129 -T2 mgr:5min | grep ' = ' | sed -e 's/^/Instance2:/' +fi diff --git a/checkman/squid b/checkman/squid index 08ef898bcf6eb7a7979de60090d54f9719bbbc5b..c4e71dbfec226c0464c2937d90a91f5ce9106e80 100644 --- a/checkman/squid +++ b/checkman/squid @@ -1,45 +1,9 @@ -title: Dummy check man page - used as template for new check manuals -agents: linux, windows, aix, solaris, hpux, vms, freebsd, snmp -catalog: see modules/catalog.py for possible values +title: Check for Squid3 (www.squid-cache.org) health +agents: linux +catalog: os/misc license: GPL -distribution: check_mk +distribution: OMD description: - Describe here: (1) what the check actually does, (2) under which - circumstances it goes warning/critical, (3) which devices are supported - by the check, (4) if the check requires a separated plugin or - tool or separate configuration on the target host. + This check checks for Squid3 (www.squid-cache.org) basic health. + You need to install the plugin {squid} into the {plugins} directory of your agent. -item: - Describe the syntax and meaning of the check's item here. Provide all - information one needs if coding a manual check with {checks +=} in {main.mk}. - Give an example. If the check uses {None} as sole item, - then leave out this section. - -examples: - # Give examples for configuration in {main.mk} here. If the check has - # configuration variable, then give example for them here. - - # set default levels to 40 and 60 percent: - foo_default_values = (40, 60) - - # another configuration variable here: - inventory_foo_filter = [ "superfoo", "superfoo2" ] - -perfdata: - Describe precisely the number and meaning of performance variables - the check sends. If it outputs no performance data, then leave out this - section. - -inventory: - Describe how the inventory for the check works. Which items - will it find? Describe the influence of check specific - configuration parameters to the inventory. - -[parameters] -foofirst(int): describe the first parameter here (if parameters are grouped - as tuple) -fooother(string): describe another parameter here. - -[configuration] -foo_default_levels(int, int): Describe global configuration variable of - foo here. Important: also tell the user how they are preset. diff --git a/gui/metrics/squid.py b/gui/metrics/squid.py new file mode 100644 index 0000000000000000000000000000000000000000..a6bd6576bd2d46be0038e4888fa5cefe8241684a --- /dev/null +++ b/gui/metrics/squid.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2023-05-20 +# +# metrics plugin for squid checks +# +# + +from cmk.gui.i18n import _ + +from cmk.gui.plugins.metrics.utils import ( + check_metrics, + metric_info, + graph_info, + perfometer_info +) + +check_metrics['check_mk-squid'] = { + 'predict_client_requests_per_second': {'auto_graph': False}, + 'predict_client_hits_per_second': {'auto_graph': False}, + 'predict_server_all_requests': {'auto_graph': False}, + 'predict_util': {'auto_graph': False}, +} + + +metric_info['client_hits_per_second'] = {'title': _('Cache hits'), 'unit': '1/s', 'color': '11/a', } +metric_info['client_requests_per_second'] = {'title': _('Requests'), 'unit': '1/s', 'color': '31/a', } +metric_info['client_errors_per_second'] = {'title': _('Errors'), 'unit': '1/s', 'color': '21/a', } + +metric_info['predict_client_hits_per_second'] = {'title': _('Cache hits (Predicted)'), 'unit': '1/s', 'color': '52/a', } +metric_info['predict_client_requests_per_second'] = {'title': _('Requests (Predicted)'), 'unit': '1/s', 'color': '51/a', } + + +graph_info['squid_client'] = { + 'title': _('Squid Client statistics'), + 'metrics': [ + ('client_hits_per_second', 'line'), + ('client_errors_per_second', 'line'), + ('client_requests_per_second', 'line'), + ], + 'scalars': [ + 'client_hits_per_second:warn', + 'client_hits_per_second:crit', + ], +} + +graph_info['squid_client_predicted'] = { + 'title': _('Predicted Squid Client statistics'), + 'metrics': [ + ('predict_client_hits_per_second', '-area'), + ('predict_client_requests_per_second', 'area'), + ], + 'optional_metrics': [ + 'predict_client_hits_per_second', + 'predict_client_requests_per_second' + ], +} + +metric_info['server_all_requests'] = {'title': _('Requests'), 'unit': '1/s', 'color': '31/a', } +metric_info['server_all_errors'] = {'title': _('Errors'), 'unit': '1/s', 'color': '21/a', } + +metric_info['predict_server_all_requests'] = {'title': _('Requests (Predicted)'), 'unit': '1/s', 'color': '51/a', } + +graph_info['squid_server'] = { + 'title': _('Squid Server statistics'), + 'metrics': [ + ('server_all_errors', 'line'), + ('server_all_requests', 'line'), + + ], + 'scalars': [ + 'server_all_requests:warn', + 'server_all_requests:crit', + ], +} + +graph_info['squid_server_predicted'] = { + 'title': _('Predicted Squid Server statistics'), + 'metrics': [ + ('predict_server_all_requests', 'area'), + ], +} + +metric_info['cpu_time'] = {'title': _('CPU time'), 'unit': 's', 'color': '16/a', } +metric_info['predict_util'] = {'title': _('CPU utilization (Predicted)'), 'unit': 's', 'color': '51/a', } + +graph_info['squid_cpu_time'] = { + 'title': _('Squid CPU time'), + 'metrics': [ + ('cpu_time', 'area'), + ], + 'scalars': [ + 'cpu_time:warn', + 'cpu_time:crit', + ], +} + +graph_info['squid_cpu_util_predicted'] = { + 'title': _('Predicted Squid CPU utilization'), + 'metrics': [ + ('predict_util', 'area'), + ], +} + +metric_info['dns_median_svc_time'] = {'title': _('DNS response time'), 'unit': 's', 'color': '26/a', } + +graph_info['squid_dns_median_svc_time'] = { + 'title': _('Squid DNS median response time'), + 'metrics': [ + ('dns_median_svc_time', 'area'), + ], + 'scalars': [ + 'dns_median_svc_time:warn', + 'dns_median_svc_time:crit', + ], +} + +perfometer_info.append({ + 'type': 'logarithmic', + 'metric': 'dns_median_svc_time', + 'half_value': 2, + 'exponent': 2, +}) diff --git a/gui/wato/squid.py b/gui/wato/squid.py new file mode 100644 index 0000000000000000000000000000000000000000..50bc02aef334c28cacd8f925d0e0134c12dce73e --- /dev/null +++ b/gui/wato/squid.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# License: GNU General Public License v2 +# +# Author: thl-cmk[at]outlook[dot]com +# URL : https://thl-cmk.hopto.org +# Date : 2023-05-20 + +# based on https://github.com/allangood/check_mk/tree/master/plugins/squid +# +# rewritten for cmk 2.x +# +# 2023-05-20: moved to ~/local/lib/check_mk/gui/plugins/wato +# renamed from check_squid.py to squid-py +# changed client_reqps to client_requests +# changed server_reqps to server_requests +# changed cpu_time to cpu_usage + +from cmk.gui.i18n import _ +from cmk.gui.valuespec import ( + Dictionary, + Integer, + Tuple, + TextInput, + Float, +) +from cmk.gui.plugins.wato.utils import ( + rulespec_registry, + HostRulespec, + RulespecGroupCheckParametersApplications, + CheckParameterRulespecWithItem, + Levels, +) + +from cmk.gui.cee.plugins.wato.agent_bakery.rulespecs.utils import ( + RulespecGroupMonitoringAgentsAgentPlugins, +) + + +def _valuespec_squid(): + return Dictionary( + title=_('Squid Web Proxy (Linux)'), + elements=[ + # ('client_requests', + # Tuple( + # title=_('Set levels for Client Requests'), + # elements=[ + # Integer(title=_('Warning at'), default_value=600, unit='/s'), + # Integer(title=_('Critical at'), default_value=800, unit='/s'), + # ])), + # not sure if client hits as upper levels are use full + # ('client_hits', + # Tuple( + # title=_('Set levels for Client Hits'), + # elements=[ + # Integer(title=_('Warning at'), default_value=600, unit='/s'), + # Integer(title=_('Critical at'), default_value=800, unit='/s'), + # ])), + # ('server_requests', + # Tuple( + # title=_('Set levels for Server Requests'), + # elements=[ + # Integer(title=_('Warning at'), default_value=600, unit='/s'), + # Integer(title=_('Critical at'), default_value=800, unit='/s'), + # ])), + # ('cpu_usage', + # Tuple( + # title=_('Set levels for Squid CPU usage'), + # elements=[ + # Float(title=_('Warning at'), default_value=60.0, unit='%'), + # Float(title=_('Critical at'), default_value=80.0, unit='%') + # ])), + ('client_requests', + Levels( + title=_('Set levels for Client Requests'), + unit='/s', + )), + ('client_hits', + Levels( + title=_('Set levels for Client Hits'), + unit='/s' + )), + ('server_requests', + Levels( + title=_('Set levels for Server Requests'), + unit='/s', + )), + ('cpu_usage', + Levels( + title=_('Set levels for Squid CPU usage'), + unit='%', + default_levels=(60.0, 80.0) + )), + ('dns_time', + Tuple( + title=_('Set levels for DNS response time'), + elements=[ + Float(title=_('Warning at'), default_value=2.0, unit='seconds'), + Float(title=_('Critical at'), default_value=4.0, unit='seconds'), + ])), + ] + ) + + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name='squid', + group=RulespecGroupCheckParametersApplications, + match_type='dict', + parameter_valuespec=_valuespec_squid, + title=lambda: _('Squid Web Proxy'), + item_spec=lambda: TextInput( + title="Squid counter", + help='Service name without "Squid" i.e. "DNS response time"', + ), + )) + + +def _valuespec_agent_squid(): + return Dictionary( + help=_('The plugin <tt>squid</tt> allows monitoring of Squid Web Proxies.'), + title=_('Squid Web Proxy (Linux)'), + elements=[ + ('port', + Integer( + title=_('Port number'), + help=_('TCP port number that squidclient connects to.'), + default_value=3128, + ) + ) + ] + ) + + +rulespec_registry.register( + HostRulespec( + group=RulespecGroupMonitoringAgentsAgentPlugins, + name='agent_config:squid', + valuespec=_valuespec_agent_squid, + ) +) diff --git a/packages/squid b/packages/squid new file mode 100644 index 0000000000000000000000000000000000000000..f3fa9cfa86a2777ecd3f9a475c21e8d46eb6fb10 --- /dev/null +++ b/packages/squid @@ -0,0 +1,18 @@ +{'author': 'Th.L. (thl-cmk[at]outlook[dot]com)', + 'description': 'Squid3 Health Check\n' + '\n' + 'based on Allan GooD - allan.cassaro@gmail.com work. \n' + 'See https://github.com/allangood/check_mk\n' + '\n' + 'Rewritten for CMK 2.1.x\n', + 'download_url': 'https://thl-cmk.hopto.org', + 'files': {'agent_based': ['squid.py'], + 'agents': ['bakery/squid.py', 'plugins/squid'], + 'checkman': ['squid'], + 'gui': ['wato/squid.py', 'metrics/squid.py']}, + 'name': 'squid', + 'title': 'Squid3 Health Check', + 'version': '2.0.2-2023-05-21', + 'version.min_required': '2.1.0b1', + 'version.packaged': '2.1.0p21', + 'version.usable_until': None} \ No newline at end of file diff --git a/squid-2.0.2-2023-05-21.mkp b/squid-2.0.2-2023-05-21.mkp new file mode 100644 index 0000000000000000000000000000000000000000..368a74d4dd298243d899efaa2fea6214f20e0870 Binary files /dev/null and b/squid-2.0.2-2023-05-21.mkp differ diff --git a/squid.mkp b/squid.mkp new file mode 100644 index 0000000000000000000000000000000000000000..368a74d4dd298243d899efaa2fea6214f20e0870 Binary files /dev/null and b/squid.mkp differ