From 3d9e54f4708ab1b48b143bd64513204797eb6c55 Mon Sep 17 00:00:00 2001 From: Marsell Kukuljevic Date: Thu, 8 Feb 2024 14:16:13 +0100 Subject: [PATCH] Add Graylog Input Metrics plugin for CheckMK 2.2.0. --- .../graylog_input_metrics-0.0.3.mkp | Bin 0 -> 5753 bytes .../check_parameters/graylog_input_metrics.py | 92 +++++++++++ .../agent_graylog_input_metrics.py | 154 ++++++++++++++++++ .../special/agent_graylog_input_metrics | 11 ++ .../checks/agent_graylog_input_metrics | 39 +++++ .../check_mk/checks/graylog_input_metrics | 81 +++++++++ .../web/plugins/wato/graylog_input_metrics.py | 97 +++++++++++ 7 files changed, 474 insertions(+) create mode 100644 check_mk-graylog_metrics/graylog_input_metrics-0.0.3.mkp create mode 100644 check_mk-graylog_metrics/local/lib/python3/cmk/gui/plugins/wato/check_parameters/graylog_input_metrics.py create mode 100755 check_mk-graylog_metrics/local/lib/python3/cmk/special_agents/agent_graylog_input_metrics.py create mode 100755 check_mk-graylog_metrics/local/share/check_mk/agents/special/agent_graylog_input_metrics create mode 100644 check_mk-graylog_metrics/local/share/check_mk/checks/agent_graylog_input_metrics create mode 100644 check_mk-graylog_metrics/local/share/check_mk/checks/graylog_input_metrics create mode 100644 check_mk-graylog_metrics/local/share/check_mk/web/plugins/wato/graylog_input_metrics.py diff --git a/check_mk-graylog_metrics/graylog_input_metrics-0.0.3.mkp b/check_mk-graylog_metrics/graylog_input_metrics-0.0.3.mkp new file mode 100644 index 0000000000000000000000000000000000000000..739ebdc91c435013dfa679f82149d9bc95d9332f GIT binary patch literal 5753 zcma*rWm^*ffB;|+1S#q6uF(ynI~63I1EfZGO$q4`q&qfRP^7!NOTf`cgET0)v3u@5 z-F>*{?)@1r^XC^B{{`z5{Ly2zwf=nbiK3H_s_tAi-X7#{^PQUKVR*e+Ic;O8Ujlom z*tTFa)hwxWqjwWEeZgv2f5Nf8nt#e0y5t7%lIDonO{R!Zy-kgFvMF~*?&cL?(fob9 zL(r`-{u6?)#)KA{2d^^uSBKgA!F<1;)yf5_$ZiViKCj0fHyBMTqvsZX;s0};@~ME$ zVlL+#M^msF>p;{Wq3nBfx5cMhz^QK=nu$CWug#2U?kagIa#Jd>MG;5;vR)c`VE+3d z35;&oTeNKN=?2QmLuakmDiu;Hx>kPH8 ze^V!0O%}DsDC_+cY)-g{{ptb5eU%$6?vLf23&wuZi%vNftd+I8!^?TZEJCJaink%5HF679Crqh)X-!w(`wP6=ypNPfZ`5h-@vw)q@xw-d8e5;awiC z5m#y=lMUl|%yHpHsG7QnU1 ziNXMV1ixZuI!?(ic z;sWP1+8mXfb$ij&PHt_w7Lg{WJU}sr`tbtkdm&WDF;qnVlX-d4!o0?3hNoPJUH?_z za_KT399e;c$QF3-n2u_w4BPcHkqmED&P~Gto4Ih(E&=!nPN1SmXCA{r`>Im4A@zb% zL%jmsT-k;)YNb3!Iz>!yN+DdVT!0C>VjYT<5vgS(bX8Gtknu6igcS)7Z|Uqs{e2Uq zOv5G0%jx zz}OV=p32Mo+ZA?WTpA)^4TSKBm+j_rG7@U~6;@@gOjRB?ou1NS@nm_jpR|N^?wwrM zJUAP|zcu)lkzA=JHKOVC6C3%Y zIC)A%5AsU4`VS4K@8U^g2M5zM77Z)UB@+(050ukB+F- zXLoDyvZ<#;0 z;4VlL5P6HWdh!yZYYT&?of~XYHIPD0DEQTpt*#ePNPQS}gr>b56>f2b0e zqhrcTCMEFp4EkBuo=nQ?Yf>(M-D;~^z0A$HdbS)f6LMp0)anJX(9YrVK8?3uKqymM-hkZCL@cfm$W#@CDBB|LA5 zi~UMg+iV5;u)#m*teR@!jrS&AUa)_5JSqb)$*|` zRstxD7RnE1DJP7bdCfHiOf6TjgWM#m7DPoAqLSAWpq&~UH$Qm3Pjq2}RP*eLU{|39 zP^#%#`Du2^ZdDh6X}i9OR3l!c0+WTV;-Hn!p;Yf|AbtNX9_~7)0g)gt;r1!MRL7(~ z6j;x{*31r)f&RN3C96AT=O4#Ss{-!t_3qsa(KS{!jAptY4lexjbS|Qr@_7@G*9La5 zH2W?;=^_fEsJ_b1`pblbukQxcth1D?2D?2YvTawV(4_soy8I^37X+1d=pVB-VfHbA zGw6+KrZxRo)&DF{qsW<$1L7iZDo%A2GnuOrj?g|Sn53CvoDA&wO_%tJB@b$DS?_<8 zaY$4apo1A|Dr(NfH<9O8BD1&rwBHmrl)rCvs!emoP38XdhYb^qr4mXk|r<~#oZWAup)n-)Px2Eg%q3q zt=@S}=P0`eH%SIRytlDA5NTK-_C~;vk23tLl_v(wbCEXckeLYTXyKD7FbG)oRriL8Q>b8F(%(yP8@t@D@8 z)ORf&{mPMlB$<`_eeIk1jP2`ZVy}Ulnr#&Lq->}742FGW&HQwy^7JsH*kbg#GxUDr z#H~rnb!p>vT;IrOG#0}RM|-Wua?i78tn%M6p4HBi*nrzF z?(E-fbc~#Cmp!)t6rTJ{vo{MUT;$mv6O^YkjPz1YT>5hiGl_b@!IdfW$bdPr_%#W- ztObtv3A}{4Di)qDWF`<%iJN2EYp)I8hxbcQJLcf+z-SYLXPiVcaXn5Y>N=wgVZ2ON;tqq)XzPYrTkx9}zK`_He z>PV^{wdG$A(AubO)b%F%-z1(B2HMqsLd z=U$y@NUjO0vk!lKXGNIXsRqJ1p8?cnJs#d3vO`nH#LpZSn}oDS~rMe(aok02j~U679P@U#Q^b> z9yZma6gGtuJN|~&Z1Vm^!;@~%Hy3p%^wZaeP3v{9)s8_qCxjZ|k%&vo7P$zYJKvdz znl)gKQUvFCcf6w$Z392)ac-@`!l%>aH2fI2h4&@Ne{#yquhEv%P(y&@p(W{UHm{_k z$fiTkQW%WfHi>IQS}q6<$6nIv4UFyEy6%1-HWYRlr{0VC`}!BgKj=YrFWUf5KO4bT zkiz!6o8hpcgpn=PWeCHBf*DRj*Rn%`q++Q~D2dW6di2^V^A|cPyrz&}frV&)7ttKB z&@(g~w1w_bto`sxcKrvDu1fIJF)18{=0E5e+~Sq$wtLy9Bj_=7Zdb4Xy$B^%E#fvX zk28~&FVfB(g=8Cksz2S^3iSV6z$jJ*`Vezp;~|b+c61+v?=z5e#-UHE)HBJG=f=4Y zO1=VoKGH1AmEN0oKG}Bno*7*j3*MKSdmBR4TasU1aOopHRs4FpS1rT}Ls5tF5g7*S zF>eo9!kz;s(8sy|T zoq1&PaarQ;my}U(p{MqI2d;1Z%~~9aDV| z5+c2d@ePZuD{R9Qcf7(hB>}Qq(nH7SNnbqth)xZ>7oq7(kU>%jYPE^I0y@rd@mLqK z1Aq^MU+UHJ{hW-LyBr7RiQ;T>_`Mu;^2;y{_e~}~pVp>HWW3FNP7A`~Nfp5lsD|d} z;=gG#<@1nJ=twT9>?9vi$*cZVI*_D4*1@DkNHs05ah20K$M?~MGQIdV6$vo951xxL zPHGm89HapEwd+JR8hTW~d25@CB(Lq+YKl*u{l%-2?d$uBzh>QJuT++QA8I&2;XCt* zyr$WX)IJQ?ZTuD783Mp%^6<@mmi6M{ji%gj`c%$_G5Ki&pXn2*%`WEczTNq@ zonm@gQ<@1=eFZ`6F)n=QN^qF2;@FFEkiM?i=yH#*9HA#xiTcU`Q5dpG%f|-msSbRp zr)Zsc=}je2sWrtN$*9;x%sCI23U5lnZ zD{j$Vr$BMoeci37y5mc+E%a)l&wSjg1Z#44A5aoE8TT`WT)x)j zT-&B5HsM<|3^BZlqZ6)M`Xn2WTV!oUjZ;3_i9<#{|jGIj6bMJzoEl zPB3Dk(0FO-yjNTH&WWy2%q&yTW-N7P*3gBQoj{O?j7DL5sWa}quN$4vj&%Io$HxN_ zM$nrw-P4?(9SYxfb! zGqIiInpV#uPO)FrWZPr*g`Q<9DMeA=r{FsnOF429W-7jITFC0^hHbQjrVvrFhxc26EIVnGOpyr z`!acO!tD5T2HUDGt)XG_#c*F9-1A*@$o5B9C_j0(=D7F0d+k^b!NgeI<^I6({UhYu za-Vlwit>pve%}OOf@><*Zf2fWX1wTPY$JC5^7A1AdvEdj#qg3#s%CefT~j;Hv}%Ybd1J+=x^-5 zOjR6&v^H#w1y|qPtUn7_qq;arZPqoz>5MI*WQu}z$HLh}>e4N@UtW0h8gv6Itc?6k zzfLlWeW}2=<4UdKDeXCHle4AX(&0X~mpKbqN2PZr?S3((PsH;gmW{y4noYMLd+-Sy z!tMj}6R_*mWwABbbbq)(A_qnk^Qncb|PQe#)-#PgY&%*u%?xp zA-7oltJ0Iw9Jvbzn}8OS`?nyr<{TWEp5kLWV9LIN1~g5t&TMIGE_ju=hjsqjWdTeo z5q0*M==|%Nu@)?dJbss+B^pJa^F8J|oL$wC%!pvrE;8fy^XgU}p*ox5tzQ*iP1VR* zzT;)@io+c@d5KzXE>a%DlkaKTiMqtcM0=iS7o#kgp)oJW&_c3je#cnrEV1qk?eEHt zFZrdk4kaz3-1h3q3-1+BW{A4A3G^R6dE85fpDdqfiKrK|IQy+Sw7AZbQU?bW9d{JzaUAli>L4HO7sWw~ zqnVeng9GYg6e0Ta*6a`9E8EP^=+LU{BY&Fur63kq4)iJLWtE8DeQdPsicis{NL5JB zZS6~QDvq}u$Y54eJ)PzkmiJa)Z+o(>yMWU>-^)QP-iDh46!w~7^E}T@5`g|Ado~Wd zfqp^$x^{2Z>b(&ebbqi-+P;+or|3iXIz7%&bpObY+3OY&zAe|!X{uSzmWk}gm? T{=WtBBbghrVv{j0FfjfD03TQw literal 0 HcmV?d00001 diff --git a/check_mk-graylog_metrics/local/lib/python3/cmk/gui/plugins/wato/check_parameters/graylog_input_metrics.py b/check_mk-graylog_metrics/local/lib/python3/cmk/gui/plugins/wato/check_parameters/graylog_input_metrics.py new file mode 100644 index 0000000..89e9057 --- /dev/null +++ b/check_mk-graylog_metrics/local/lib/python3/cmk/gui/plugins/wato/check_parameters/graylog_input_metrics.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# Copyright (C) 2019 tribe29 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 cmk.gui.i18n import _ +from cmk.gui.plugins.wato.utils import ( + CheckParameterRulespecWithItem, + rulespec_registry, + RulespecGroupCheckParametersDiscovery, +) +from cmk.gui.valuespec import Dictionary, Float, Tuple + +defaults={ + "im_rate_upper": 999999, + "im_rate_lower": 0, + "rs_rate_upper": 999999, + "rs_rate_lower": 0, +} +mappings={ + "im": "messages", + "rs": "bytes", + "upper": "above", + "lower": "below", +} + + +def _rate(metric, time, level): + unit=mappings[metric] + direction=mappings[level] + return ( + f"{metric}_{time}_rate_{level}", + Tuple( + title=_(f"{level.capitalize()} level"), + elements=[ + Float( + title=_(f"Warning {direction}"), + unit=f"{unit}/{time[1:]}min", + default_value=defaults[f"{metric}_rate_{level}"], + ), + Float( + title=_(f"Critical {direction}"), + unit=f"{unit}/{time[1:]}min", + default_value=defaults[f"{metric}_rate_{level}"], + ), + ], + ), + ) + + +def _element(metric, time): + return ( + f"{metric}_{time}_rate", + Dictionary( + title=_(f"Incoming {mappings[metric]} for past {time[1:]} minute"), + elements=[ + _rate(metric, time, "upper"), + _rate(metric, time, "lower") + ] + ), + ) + + +def _parameter_valuespec_graylog_input_metrics(): + matrix=[ + ("im", "m1"), ("im", "m5"), ("im", "m15"), + ("rs", "m1"), ("rs", "m5"), ("rs", "m15"), + ] + + elements=[ + _element(metric, time) for metric, time in matrix + ] + + return Dictionary( + title=_("Message and data rates"), + help=_( + "These rates are queried directly from the Graylog instance. " + "Upper and lower levels can be specified for individual metric." + ), + elements=elements + ) + + +rulespec_registry.register( + CheckParameterRulespecWithItem( + check_group_name="graylog_input_metrics", + group=RulespecGroupCheckParametersDiscovery, + match_type="dict", + parameter_valuespec=_parameter_valuespec_graylog_input_metrics, + title=lambda: _("Graylog input metrics"), + ) +) diff --git a/check_mk-graylog_metrics/local/lib/python3/cmk/special_agents/agent_graylog_input_metrics.py b/check_mk-graylog_metrics/local/lib/python3/cmk/special_agents/agent_graylog_input_metrics.py new file mode 100755 index 0000000..ae822a9 --- /dev/null +++ b/check_mk-graylog_metrics/local/lib/python3/cmk/special_agents/agent_graylog_input_metrics.py @@ -0,0 +1,154 @@ +#!/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. + +import argparse +import json +import sys +from typing import NamedTuple + +import requests +import urllib3 + +import cmk.utils.password_store + +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) +cmk.utils.password_store.replace_passwords() + + +class GraylogSection(NamedTuple): + name: str + uri: str + + +def main(argv=None): + if argv is None: + argv = sys.argv[1:] + + args = parse_arguments(argv) + + try: + handle_request(args) + except Exception: + if args.debug: + return 1 + + return 0 + + +def handle_request(args): # pylint: disable=too-many-branches + url_base = f"{args.proto}://{args.hostname}:{args.port}/api" + url = url_base + "/system/metrics" + value = handle_response(url, args).json() + + # Handle the input_metrics section. We need to merge information from + # both inputstates and input_metrics, and we do that by extracting the + # ids returned by both calls. Once merged, we return a single dictionary + # with state, name, type, port, and the various rates (either raw or + # incomingMessages). + url_inputs_data = url_base + "/cluster/inputstates" + inputs_data = handle_response(url_inputs_data, args).json() + inputs_data = tuple(inputs_data.values())[0] + metrics_data = value.get("meters") + + if inputs_data is None or metrics_data is None: + return + + # Create a dictionary, containing all metrics with substrings + # "incomingMessages" and "rawSize". + # All rates should exist, created and with values as low as "0.0". + metrics_dict = {} + for metric, metric_rate in metrics_data.items(): + metric_id = metric.split(".")[-2] + metric_type = None + if "incomingMessages" in metric: + metric_type = "im" + elif "rawSize" in metric: + metric_type = "rs" + if metric_type: + metric_key = metrics_dict.setdefault(metric_id, {}) + metric_key[f"{metric_type}_m1_rate"] = metric_rate["m1_rate"] + metric_key[f"{metric_type}_m5_rate"] = metric_rate["m5_rate"] + metric_key[f"{metric_type}_m15_rate"] = metric_rate["m15_rate"] + + # Create a dictionary with all inputs and add the rates from + # the previous dictionary, metrics_dict. This is passed as output. + # Some inputs don't have a "port", so we handle this with .get("port"). + inputs_dict = {} + for inputs in inputs_data: + message_input = inputs["message_input"] + input_id = inputs["id"] + input_state = inputs["state"] + input_name = message_input["title"] + input_type = message_input["name"] + input_port = message_input["attributes"].get("port") + input_rate = metrics_dict[input_id] + inputs_dict[input_id] = { + "input_state": input_state, + "input_name": input_name, + "input_type": input_type, + "input_port": input_port, + "im_m1_rate": input_rate["im_m1_rate"], + "im_m5_rate": input_rate["im_m5_rate"], + "im_m15_rate": input_rate["im_m15_rate"], + "rs_m1_rate": input_rate["rs_m1_rate"], + "rs_m5_rate": input_rate["rs_m5_rate"], + "rs_m15_rate": input_rate["rs_m15_rate"] + } + + if inputs_dict: + handle_output(inputs_dict) + + +def handle_response(url, args): + try: + return requests.get(url, auth=(args.user, args.password), verify=not args.no_cert_check) + except requests.exceptions.RequestException as e: + sys.stderr.write("Error: %s\n" % e) + if args.debug: + raise + + +def handle_output(value): + sys.stdout.write("<<>>\n") + if isinstance(value, list): + for entry in value: + sys.stdout.write("%s\n" % json.dumps(entry)) + return + + sys.stdout.write("%s\n" % json.dumps(value)) + + return + + +def parse_arguments(argv): + parser = argparse.ArgumentParser(description=__doc__) + + parser.add_argument("-u", "--user", default=None, help="Username for graylog login") + parser.add_argument("-s", "--password", default=None, help="Password for graylog login") + parser.add_argument( + "-P", + "--proto", + default="https", + help="Use 'http' or 'https' for connection to graylog (default=https)", + ) + parser.add_argument( + "-p", "--port", default=443, type=int, help="Use alternative port (default: 443)" + ) + parser.add_argument( + "--debug", action="store_true", help="Debug mode: let Python exceptions come through" + ) + parser.add_argument( + "--no-cert-check", action="store_true", help="Disable SSL certificate validation" + ) + + parser.add_argument( + "hostname", metavar="HOSTNAME", help="Name of the graylog instance to query." + ) + + return parser.parse_args(argv) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/check_mk-graylog_metrics/local/share/check_mk/agents/special/agent_graylog_input_metrics b/check_mk-graylog_metrics/local/share/check_mk/agents/special/agent_graylog_input_metrics new file mode 100755 index 0000000..c9ca597 --- /dev/null +++ b/check_mk-graylog_metrics/local/share/check_mk/agents/special/agent_graylog_input_metrics @@ -0,0 +1,11 @@ +#!/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. + +import sys + +from cmk.special_agents.agent_graylog_input_metrics import main + +if __name__ == "__main__": + sys.exit(main()) diff --git a/check_mk-graylog_metrics/local/share/check_mk/checks/agent_graylog_input_metrics b/check_mk-graylog_metrics/local/share/check_mk/checks/agent_graylog_input_metrics new file mode 100644 index 0000000..163f59a --- /dev/null +++ b/check_mk-graylog_metrics/local/share/check_mk/checks/agent_graylog_input_metrics @@ -0,0 +1,39 @@ +#!/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. +# +# { +# 'proto': 'http', +# 'port': 9000, +# 'user': 'hell', +# 'password': 'yeah', +# } + +from typing import Any, Mapping, Optional, Sequence, Union + + +def agent_graylog_input_metrics_arguments( + params: Mapping[str, Any], hostname: str, ipaddress: Optional[str] +) -> Sequence[Union[str, tuple[str, str, str]]]: + args = [ + "-P", + params["protocol"], + "-u", + params["user"], + "-s", + passwordstore_get_cmdline("%s", params["password"]), + ] + + if "port" in params: + args += ["-p", params["port"]] + + if "no-cert-check" in params: + args += ["--no-cert-check"] + + args.append(params["instance"]) + + return args + + +special_agent_info["graylog_input_metrics"] = agent_graylog_input_metrics_arguments diff --git a/check_mk-graylog_metrics/local/share/check_mk/checks/graylog_input_metrics b/check_mk-graylog_metrics/local/share/check_mk/checks/graylog_input_metrics new file mode 100644 index 0000000..f02f1e8 --- /dev/null +++ b/check_mk-graylog_metrics/local/share/check_mk/checks/graylog_input_metrics @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +# 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. + +# NOTE: Careful when replacing the *-import below with a more specific import. This can cause +# problems because it might remove variables from the check-context which are necessary for +# resolving legacy discovery results such as [("SUMMARY", "diskstat_default_levels")]. Furthermore, +# it might also remove variables needed for accessing discovery rulesets. +import json + +#<<>> +# {"641e88d05d447a677efde199": {"input_state": "FAILED", "input_name": "kafka_cef_test", +# "input_type": "CEF Kafka", "input_port": null, "im_m1_rate": 0.0, "im_m5_rate": 0.0, +# "im_m15_rate": 0.0, "rs_m1_rate": 0.0, "rs_m5_rate": 0.0, "rs_m15_rate": 0.0}, +# "641e32885d447a677efd2dbf": {"input_state": "RUNNING", "input_name": "UDP-test", +# "input_type": "Syslog UDP", "input_port": 1514, "im_m1_rate": 1.0846244336700077, +# "im_m5_rate": 1.3700826278955827, "im_m15_rate": 1.254406787430692, "rs_m1_rate": 145.45579305762527, +# "rs_m5_rate": 180.6486220431909, "rs_m15_rate": 165.26666376319292}, +# "641e32795d447a677efd2d9e": {"input_state": "RUNNING", "input_name": "testTCP", "input_type": "Syslog TCP", +# "input_port": 1515, "im_m1_rate": 1.057872514816615, "im_m5_rate": 1.364957693749168, +# "im_m15_rate": 1.2528742858546844, "rs_m1_rate": 140.4719944116262, "rs_m5_rate": 178.57816158901215, +# "rs_m15_rate": 163.80530659055356}} + +def parse_graylog_input_metrics(section): + parsed = json.loads(section[0][0]) + return parsed + + +def inventory_graylog_input_metrics(parsed): + for input_id, input_info in parsed.items(): + input_name = input_info["input_name"] + yield Service(f"{input_name} ({input_id})") + + +def check_graylog_input_metrics(item, params, parsed): +# if parsed is None: return + + item_id = item.split()[-1][1:-1] + input_info = parsed[item_id] + input_state = input_info["input_state"] + + state = 1 + if input_state == "RUNNING": state = 0 + elif input_state == "FAILED": state = 2 + + yield state, "State: %s" % input_state + yield 0, "Type: %s" % input_info["input_type"] + + if input_info["input_port"]: + yield 0, "Port: %s" % input_info["input_port"] + + for key, dsname, unit, unit_func, infotext in [ + ("im_m1_rate", "im_m1_rate", "/1min", float, "Incoming messages"), + ("im_m5_rate", "im_m5_rate", "/5min", float, ""), + ("im_m15_rate", "im_m15_rate", "/15min", float, ""), + ("rs_m1_rate", "rs_m1_rate", "/1min", get_bytes_human_readable, "Incoming data"), + ("rs_m5_rate", "rs_m5_rate", "/5min", get_bytes_human_readable, ""), + ("rs_m15_rate", "rs_m15_rate", "/15min", get_bytes_human_readable, ""), + ]: + + value = parsed[item_id][key] + value = round(value, 2) + rate_upper = params.get(key, {}).get("%s_upper" % key, (None, None)) + rate_lower = params.get(key, {}).get("%s_lower" % key, (None, None)) + yield check_levels( + value, + dsname, + rate_upper + rate_lower, + human_readable_func=unit_func, + unit=unit, + infoname=infotext + ) + +check_info["graylog_input_metrics"] = { + "parse_function": parse_graylog_input_metrics, + "check_function": check_graylog_input_metrics, + "inventory_function": inventory_graylog_input_metrics, + "service_description": "Graylog Input %s", + "has_perfdata": True, + "group": "graylog_input_metrics", +} diff --git a/check_mk-graylog_metrics/local/share/check_mk/web/plugins/wato/graylog_input_metrics.py b/check_mk-graylog_metrics/local/share/check_mk/web/plugins/wato/graylog_input_metrics.py new file mode 100644 index 0000000..706f3ad --- /dev/null +++ b/check_mk-graylog_metrics/local/share/check_mk/web/plugins/wato/graylog_input_metrics.py @@ -0,0 +1,97 @@ +#!/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. + + +from cmk.gui.i18n import _ +from cmk.gui.plugins.wato.special_agents.common import RulespecGroupDatasourceProgramsApps +from cmk.gui.plugins.wato.utils import HostRulespec, IndividualOrStoredPassword, rulespec_registry +from cmk.gui.valuespec import Age, Dictionary, DropdownChoice, Integer, ListChoice, TextInput +from cmk.gui.watolib.rulespecs import Rulespec + + +def _factory_default_special_agents_graylog_input_metrics(): + # No default, do not use setting if no rule matches + return Rulespec.FACTORY_DEFAULT_UNUSED + + +def _valuespec_special_agents_graylog_input_metrics(): + return Dictionary( + title=_("Graylog Input Metrics"), + help=_("Requests input metrics data from a Graylog instance."), + optional_keys=["port", "no-cert-check"], + elements=[ + ( + "instance", + TextInput( + title=_("Graylog instance to query"), + help=_( + "Use this option to set which instance should be " + "checked by the special agent. Please add the " + "hostname here, eg. my_graylog.com." + ), + size=32, + allow_empty=False, + ), + ), + ( + "user", + TextInput( + title=_("Username"), + help=_( + "The username that should be used for accessing the " + "Graylog API. Has to have read permissions at least." + ), + size=32, + allow_empty=False, + ), + ), + ( + "password", + IndividualOrStoredPassword( + title=_("Password of the user"), + allow_empty=False, + ), + ), + ( + "protocol", + DropdownChoice( + title=_("Protocol"), + choices=[ + ("http", "HTTP"), + ("https", "HTTPS"), + ], + default_value="https", + ), + ), + ( + "port", + Integer( + title=_("Port"), + help=_( + "Use this option to query a port which is different from standard port 443." + ), + default_value=443, + ), + ), + ( + "no-cert-check", + FixedValue( + True, + title=_("Disable SSL certificate validation"), + totext=_("SSL certificate validation is disabled"), + ), + ), + ], + ) + + +rulespec_registry.register( + HostRulespec( + factory_default=_factory_default_special_agents_graylog_input_metrics(), + group=RulespecGroupDatasourceProgramsApps, + name="special_agents:graylog_input_metrics", + valuespec=_valuespec_special_agents_graylog_input_metrics, + ) +)