Skip to content

Commit

Permalink
7407 check_elasticsearch_query: New active check to query elasticsearch
Browse files Browse the repository at this point in the history
You can now query the occurrence of log messages in elasticsearch for a
specified interval. It is possible to set warn/crit level on the message
count.

It is possible to use free-text search or set a defined index and/or fieldname
to search.

Change-Id: Ia098a3ff432c36572275513cb789911067aabe37
  • Loading branch information
makanakoeln committed Apr 24, 2019
1 parent 859e8d5 commit eeea584
Show file tree
Hide file tree
Showing 5 changed files with 415 additions and 0 deletions.
15 changes: 15 additions & 0 deletions .werks/7407
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Title: check_elasticsearch_query: New active check to query elasticsearch
Level: 2
Component: checks
Compatible: compat
Edition: cre
Version: 1.6.0i1
Date: 1555185570
Class: feature

You can now query the occurrence of log messages in elasticsearch for a
specified interval. It is possible to set warn/crit level on the message
count.

It is possible to use free-text search or set a defined index and/or fieldname
to search.
197 changes: 197 additions & 0 deletions active_checks/check_elasticsearch_query
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#!/usr/bin/env python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# | ____ _ _ __ __ _ __ |
# | / ___| |__ ___ ___| | __ | \/ | |/ / |
# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
# | | |___| | | | __/ (__| < | | | | . \ |
# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
# | |
# | Copyright Mathias Kettner 2019 mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation in version 2. check_mk is distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more de-
# tails. You should have received a copy of the GNU General Public
# License along with GNU Make; see the file COPYING. If not, write
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA.

import argparse
import sys
import urlparse
import requests
import urllib3
from cmk.notification_plugins.utils import retrieve_from_passwordstore
from cmk.utils.defines import service_state_name
from cmk.utils.exceptions import MKGeneralException

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)


def main():

args = parse_arguments()

try:
msg, state, perfdata = handle_request(args)
except Exception as exc:
sys.stdout.write("UNKNOWN - %s\n" % exc)
return 3

sys.stdout.write("%s - %s | %s\n" % (service_state_name(state), msg, perfdata))
sys.exit(state)


def handle_request(args):

url = urlparse.urlunparse((args.protocol, "%s:%d" % (args.hostname, args.port),
"%s/_count" % args.index.replace(" ", ","), None, None, None))

query = {
"query": {
"bool": {
"must": [
{
"query_string": {
"query": args.pattern
}
},
{
"range": {
"@timestamp": {
"gte": "now-%ds" % args.timerange,
"lt": "now"
}
}
},
]
}
},
}

if args.fieldname:
query['query']['bool']['must'][0]['query_string']['fields'] = args.fieldname.split(" ")

if args.user and retrieve_from_passwordstore(args.password):
raw_response = requests.get(url, json=query, auth=(args.user, args.password))
else:
raw_response = requests.get(url, json=query)

msg, state, perfdata = handle_query(raw_response, args.warn, args.crit, args.timerange)

return msg, state, perfdata


def handle_query(raw_response, warn, crit, timerange):
response_data = raw_response.json()

if "count" not in response_data:
raise MKGeneralException("Missing section count in raw response data")

state = 0
value = response_data["count"]
perfdata = "count=%s" % value
msg = "%s messages found" % value

if crit and warn:
msg += " (warn/crit at %d/%d)" % (warn, crit)
if value >= crit:
state = 2
elif value >= warn:
state = 1

return msg, state, perfdata


def parse_arguments(argv=None):
if argv is None:
argv = sys.argv[1:]

parser = argparse.ArgumentParser(
description=__doc__, formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument(
"-u",
"--user",
default=None,
help="Username for elasticsearch login",
)
parser.add_argument(
"-s",
"--password",
default=None,
help="Password for easticsearch login",
)
parser.add_argument(
"-P",
"--protocol",
default="https",
help="Use 'http' or 'https' for connection to elasticsearch (default=https)",
)
parser.add_argument(
"-p",
"--port",
type=int,
default=9200,
help="Use alternative port (default: 9200)",
)
parser.add_argument(
"-q",
"--pattern",
help=("Search pattern"),
)
parser.add_argument(
"-f",
"--fieldname",
default=None,
help=("Fieldname to query"),
)
parser.add_argument(
"-i",
"--index",
help=("Index to query"),
default="_all",
)
parser.add_argument(
"-t",
"--timerange",
type=int,
default=60,
help=("The timerange to query, eg. x minutes from now."),
)
parser.add_argument(
"--debug",
action="store_true",
help=("Debug mode: let Python exceptions come through"),
)
parser.add_argument(
"--warn",
type=int,
default=None,
help=("number of log messages above which the check will warn"),
)
parser.add_argument(
"--crit",
type=int,
default=None,
help=("number of log messages above which the check will become critical"),
)
parser.add_argument(
"-H",
"--hostname",
help=("Defines the elasticsearch instances to query."),
)

return parser.parse_args()


if __name__ == "__main__":
sys.exit(main())
8 changes: 8 additions & 0 deletions checkman/check_elasticsearch_query
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
title: Elasticsearch query
agents: active
catalog: app/omd
license: GPL
distribution: check_mk
description:
Checks for occurrence of defined log messages in a defined interval.
Warn/Crit level can be set on message count
66 changes: 66 additions & 0 deletions checks/check_elasticsearch_query
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# | ____ _ _ __ __ _ __ |
# | / ___| |__ ___ ___| | __ | \/ | |/ / |
# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
# | | |___| | | | __/ (__| < | | | | . \ |
# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
# | |
# | Copyright Mathias Kettner 2014 mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation in version 2. check_mk is distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY; with-
# out even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more de-
# tails. You should have received a copy of the GNU General Public
# License along with GNU Make; see the file COPYING. If not, write
# to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301 USA.


def check_elasticsearch_query_arguments(params):

args = []

if "protocol" in params:
args += ["-P", params["protocol"]]
if "user" in params:
args += ["-u", params["user"]]
if "password" in params:
args += ["-s", passwordstore_get_cmdline("%s", params["password"])]
if "port" in params:
args += ["-p", params["port"]]

if "index" in params:
args += ["-i", ' '.join(params["index"])]
if "pattern" in params:
args += ["-q", params["pattern"]]
if "fieldname" in params:
args += ["-f", ' '.join(params["fieldname"])]
if "timerange" in params:
args += ["-t", params["timerange"]]
if 'count' in params:
args.append('--warn=%d' % params['count'][0])
args.append('--crit=%d' % params['count'][1])

if 'hostname' in params:
args += ["-H", quote_shell_string(params["hostname"])]
else:
args += ["-H", "$HOSTADDRESS$"]

return args


active_check_info['elasticsearch_query'] = {
"command_line": '$USER1$/check_elasticsearch_query $ARG1$',
"argument_function": check_elasticsearch_query_arguments,
"service_description": lambda params: "Elasticsearch Query %s" % params['svc_item'],
"has_perfdata": True,
}
Loading

0 comments on commit eeea584

Please sign in to comment.