155 lines
5.0 KiB
Python
Executable File
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())
|