Hello,
We were in need of a way to check for shards growing above 50gb, found this Nagios plugin => https://github.com/DennyZhang/elasticsearch-cli-tool/blob/master/monitoring/check_elasticsearch_shard.py
But it didn't use the Elasticsearch Python client and it had no options to authenticate. So I made some changes:
import argparse
import logging
import re
import requests
import socket
import sys
from elasticsearch import Elasticsearch
from ssl import create_default_context
logger = logging.getLogger('check_elasticsearch_shards')
#logging.basicConfig(level=logging.DEBUG)
NAGIOS_OK=0
NAGIOS_WARNING=1
NAGIOS_CRITICAL=2
NAGIOS_UNKNOWN=3
def get_gb_size_from_string(string):
# 10.5gb -> 10.5
# 1.2tb -> 1200
val = 0
if string.endswith("gb"):
val = float(string.replace("gb", ""))
elif string.endswith("tb"):
val = float(string.replace("tb", "")) * 1000
elif string.endswith("mb"):
val = float(string.replace("mb", "")) * 0.001
elif string.endswith("kb"):
val = float(string.replace("kb", "")) * 0.001 * 0.001
elif string.endswith("b"):
val = float(string.replace("b", "")) * 0.001 * 0.001 * 0.001
else:
print("ERROR: unexpected. size string: %s" % (string))
sys.exit(NAGIOS_CRITICAL)
return val
def parse_index_info(es_index_info):
index_list = []
for line in es_index_info.split("\n"):
if line == '' or " index " in line or " close " in line:
continue
else:
line = " ".join(line.split())
l = line.split()
index = l[2]
pri = l[3]
pri_store_size = l[7]
index_list.append([index, pri, pri_store_size])
return index_list
def confirm_es_shard_count(es_host, es_port, es_index_list, min_shard_count):
failed_index_list = []
for l in es_index_list:
index_name = l[0]
number_of_shards = int(l[1])
if number_of_shards < min_shard_count:
print("CRITICAL: Index(%s) only has %d shards, less than %d." \
% (index_name, number_of_shards, min_shard_count))
failed_index_list.append(index_name)
return failed_index_list
def confirm_es_shard_size(es_host, es_port, es_index_list, max_shard_size):
failed_index_list = []
for i in es_index_list:
index_name = i[0]
number_of_shards = int(i[1])
pri_store_size = i[2]
avg_shard_size_gb = get_gb_size_from_string(pri_store_size)/number_of_shards
if avg_shard_size_gb > max_shard_size:
failed_index_list.append(index_name)
return failed_index_list
def parse_args():
parser = argparse.ArgumentParser(description="Check Elasticsearch Shards")
parser.add_argument('--es_host', required=True, help="ES ip or hostname", type=str)
parser.add_argument('--es_port', default='9200', required=False, help="ES port", type=str)
parser.add_argument('--es_user', default='monitoring_user', required=True, help="ES user", type=str)
parser.add_argument('--es_pass', default='', required=True, help="ES password for user", type=str)
parser.add_argument('--es_index', required=False, default='', help="ES index name", type=str)
parser.add_argument('--ca_file', required=False, default='', help="CA certificate file", type=str)
parser.add_argument('--min_shard_count', default='3', required=False, help='minimal shards', type=str)
parser.add_argument('--max_shard_size', default='50gb', required=False, help='maximum shards size', type=str)
return parser.parse_args()
if __name__ == '__main__':
l = parse_args()
es_host = l.es_host
es_port = l.es_port
es_user = l.es_user
es_pass = l.es_pass
es_index = l.es_index
ca_file = l.ca_file
min_shard_count = int(l.min_shard_count)
max_shard_size = get_gb_size_from_string(l.max_shard_size)
context = create_default_context(cafile=str(ca_file))
es = Elasticsearch(
[str(es_host)],
http_auth = (str(es_user), str(es_pass)),
scheme = "https",
port = int(es_port),
ssl_context = context
)
es_index_cat_raw = es.cat.indices(es_index, h=("h","s","i","p","r","dc","ss","pri.store.size","creation.date.string"), s="i")
es_index_cat_list = parse_index_info(es_index_cat_raw)
failed_index_list = confirm_es_shard_size(es_host, es_port, es_index_cat_list, max_shard_size)
if len(failed_index_list) != 0:
if len(failed_index_list) == 1:
print("CRITICAL: Index %s has shards bigger than %s GB!" % (failed_index_list[0], max_shard_size))
elif len(failed_index_list) > 1:
index_string = "%s indices" % (len(failed_index_list))
print("CRITICAL: %s indices have shards bigger than %s GB!\n%s" % (len(failed_index_list), max_shard_size, ", ".join(failed_index_list)))
es.transport.close()
sys.exit(NAGIOS_CRITICAL)
else:
print("OK: All shards for indices (pattern \"%s\") are less then %s GB." % (es_index, max_shard_size))
es.transport.close()
sys.exit(NAGIOS_OK)
But for some reason I get a pylint error on the es object:
Anyone an idea why I get 'unepexted keyword argument h & v ? The plugin works fine, but this syntax error is working on my nerves..
(disclaimer: only started learning Python this weekend)
Grtz
Willem