checkmk-plugins/check_mk-graylog_metrics/local/lib/python3/cmk/special_agents/agent_graylog_input_metrics.py

155 lines
5.0 KiB
Python
Executable File

#!/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("<<<graylog_input_metrics:sep(0)>>>\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())