#!/usr/bin/env pmpython # # Copyright (C) 2018 Red Hat. # Copyright (C) 2017 Marko Myllynen # # This program 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; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # pylint: disable=line-too-long, too-many-return-statements # pylint: disable=too-many-statements, too-many-branches, too-many-lines # pylint: disable=broad-except, too-many-instance-attributes """ Performance Metrics Domain Agent exporting Elasticsearch metrics. """ import os import sys import json try: import ConfigParser except ImportError: import configparser as ConfigParser try: import urllib.request as httprequest except Exception: import urllib2 as httprequest from ctypes import c_int from pcp.pmda import PMDA, pmdaMetric, pmdaIndom from pcp.pmapi import pmUnits from pcp.pmapi import pmContext as PCP from cpmapi import PM_INDOM_NULL from cpmapi import PM_TYPE_32, PM_TYPE_U32, PM_TYPE_U64, PM_TYPE_STRING, PM_TYPE_FLOAT from cpmapi import PM_SEM_COUNTER, PM_SEM_INSTANT, PM_SEM_DISCRETE from cpmapi import PM_COUNT_ONE, PM_SPACE_BYTE, PM_TIME_MSEC from cpmapi import PM_ERR_PMID, PM_ERR_APPVERSION from cpmda import PMDA_FETCH_NOVALUES DEFAULT_PORT = 9200 DEFAULT_URL = f"http://localhost:{DEFAULT_PORT}/" DEFAULT_VERSION = 2 DEFAULT_USER = "root" def _is_pmda_setup(): """checks if PMDA is in setup state""" return os.environ.get('PCP_PYTHON_DOMAIN') or os.environ.get('PCP_PYTHON_PMNS') def _setup_urllib(url, auth, pasw): """ Setup urllib """ passman = httprequest.HTTPPasswordMgrWithDefaultRealm() passman.add_password(None, url, auth, pasw) authhandler = httprequest.HTTPBasicAuthHandler(passman) opener = httprequest.build_opener(authhandler) httprequest.install_opener(opener) return httprequest class ElasticsearchPMDA(PMDA): """ PCP Elasticsearch PMDA """ def __init__(self, name, domain): """ Constructor """ PMDA.__init__(self, name, domain) self.user = DEFAULT_USER self.baseurl = DEFAULT_URL self.auth = None self.password = None self.request = None self.error = False self.version = DEFAULT_VERSION self.read_config() # statistics dicts self.cluster = {} self.nodes = {} self.node_info = {} self.info = {} self.stat = {} self.search = {} self.perindex = {} self.master_node = None self.index = {} if self.user != DEFAULT_USER and not _is_pmda_setup(): self.log(f"Switching to user '{self.user}'") self.set_user(self.user) self.connect_pmcd() if not _is_pmda_setup(): try: self.request = _setup_urllib(self.baseurl, self.auth, self.password) request = self.request.urlopen(self.baseurl) request.read() request.close() except (BaseException, Exception): self.log(f"Failed Elasticsearch connection attempt at {self.baseurl}") # metrics setup self.cluster_indom = PM_INDOM_NULL self.cluster_cluster = 0 self.cluster_metrics = [ # Name - type - semantics - units - help [ 'cluster.cluster_name', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Name of the elasticsearch cluster' ], # 0 [ 'cluster.status.colour', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Status (green,yellow,red) of the elasticsearch cluster' ], # 1 [ 'cluster.timed_out', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Timed out status (0:false,1:true) of the elasticsearch cluster' ], # 2 [ 'cluster.number_of_nodes', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of nodes in the elasticsearch cluster' ], # 3 [ 'cluster.number_of_data_nodes', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of data nodes in the elasticsearch cluster' ], # 4 [ 'cluster.active_primary_shards', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of active primary shards in the elasticsearch cluster' ], # 5 [ 'cluster.active_shards', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of primary shards in the elasticsearch cluster' ], # 6 [ 'cluster.relocating_shards', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of relocating shards in the elasticsearch cluster' ], # 7 [ 'cluster.initializing_shards', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of initializing shards in the elasticsearch cluster' ], # 8 [ 'cluster.unassigned_shards', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of unassigned shards in the elasticsearch cluster' ], # 9 [ 'cluster.status.code', PM_TYPE_32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Status code (0:green,1:yellow,2:red) of the elasticsearch cluster' ], # 10 ] for item, metric in enumerate(self.cluster_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.cluster_cluster, item), metric[1], self.cluster_indom, metric[2], metric[3]), metric[4], metric[4]) self.nodes_indom = self.indom(0) self.nodes_insts = pmdaIndom(self.nodes_indom, {}) self.add_indom(self.nodes_insts, 'elasticsearch cluster nodes') self.nodes_cluster = 1 self.nodes_metrics = [ # Name - type - semantics - units - help [ 'nodes.indices.size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 0 - deprecated (now item 47) [ 'nodes.indices.docs.count', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 1 [ 'nodes.indices.docs.num_docs', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 2 - bad metric [ 'nodes.indices.cache.field_evictions', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 3 - bad metric [ 'nodes.indices.cache.field_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 4 - bad metric [ 'nodes.indices.cache.filter_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 5 - bad metric [ 'nodes.indices.cache.filter_evictions', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 6 - bad metric [ 'nodes.indices.cache.filter_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 7 - bad metric [ 'nodes.indices.merges.current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 8 [ 'nodes.indices.merges.total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 9 [ 'nodes.indices.merges.total_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 10 [ 'nodes.jvm.uptime_in_millis', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 11 [ 'nodes.jvm.uptime', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 12 - bad metric [ 'nodes.jvm.mem.heap_used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 13 [ 'nodes.jvm.mem.heap_committed_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 14 [ 'nodes.jvm.mem.non_heap_used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 15 [ 'nodes.jvm.mem.non_heap_committed_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 16 [ 'nodes.jvm.threads.count', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 17 [ 'nodes.jvm.threads.peak_count', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 18 [ 'nodes.jvm.gc.collection_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 19 - bad metric [ 'nodes.jvm.gc.collection_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 20 - bad metric [ 'nodes.jvm.gc.collectors.Copy.collection_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 21 - bad metric [ 'nodes.jvm.gc.collectors.Copy.collection_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 22 - bad metric [ 'nodes.jvm.gc.collectors.ParNew.collection_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 23 - bad metric [ 'nodes.jvm.gc.collectors.ParNew.collection_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 24 - bad metric [ 'nodes.jvm.gc.collectors.ConcurrentMarkSweep.collection_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 25 - bad metric [ 'nodes.jvm.gc.collectors.ConcurrentMarkSweep.collection_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 26 - bad metric [ 'nodes.indices.docs.deleted', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 27 [ 'nodes.indices.indexing.index_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 28 [ 'nodes.indices.indexing.index_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 29 [ 'nodes.indices.indexing.delete_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 30 [ 'nodes.indices.indexing.delete_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 31 [ 'nodes.indices.merges.current_docs', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 32 [ 'nodes.indices.merges.current_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 33 [ 'nodes.indices.merges.total_docs', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 34 [ 'nodes.indices.merges.total_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 35 [ 'nodes.indices.refresh.total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 36 [ 'nodes.indices.refresh.total_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 37 [ 'nodes.indices.flush.total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 38 [ 'nodes.indices.flush.total_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 39 [ 'nodes.process.timestamp', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 40 - not usable [ 'nodes.process.open_file_descriptors', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 41 [ 'nodes.process.cpu.percent', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 42 [ 'nodes.process.cpu.sys_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 43 [ 'nodes.process.cpu.user_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 44 [ 'nodes.process.mem.resident_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 45 [ 'nodes.process.mem.total_virtual_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 46 [ 'nodes.indices.store.size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 47 [ 'nodes.indices.get.total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 48 [ 'nodes.indices.get.time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 49 [ 'nodes.indices.get.exists_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 50 [ 'nodes.indices.get.exists_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 51 [ 'nodes.indices.get.missing_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 52 [ 'nodes.indices.get.missing_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 53 [ 'nodes.indices.search.query_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 54 [ 'nodes.indices.search.query_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 55 [ 'nodes.indices.search.fetch_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 56 [ 'nodes.indices.search.fetch_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 57 [ 'nodes.transport.server_open', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 58 [ 'nodes.transport.rx_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 59 [ 'nodes.transport.rx_size_in_bytes', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 60 [ 'nodes.transport.tx_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 61 [ 'nodes.transport.tx_size_in_bytes', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 62 [ 'nodes.http.current_open', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 63 [ 'nodes.http.total_opened', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 64 [ 'nodes.jvm.mem.pools.old.max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 65 [ 'nodes.jvm.mem.pools.old.peak_max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 66 [ 'nodes.jvm.mem.pools.old.peak_used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 67 [ 'nodes.jvm.mem.pools.old.used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 68 [ 'nodes.jvm.mem.pools.survivor.max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 69 [ 'nodes.jvm.mem.pools.survivor.peak_max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 70 [ 'nodes.jvm.mem.pools.survivor.peak_used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 71 [ 'nodes.jvm.mem.pools.survivor.used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 72 [ 'nodes.jvm.mem.pools.young.max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 73 [ 'nodes.jvm.mem.pools.young.peak_max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 74 [ 'nodes.jvm.mem.pools.young.peak_used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 75 [ 'nodes.jvm.mem.pools.young.used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 76 [ 'nodes.jvm.gc.collectors.old.collection_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 77 [ 'nodes.jvm.gc.collectors.old.collection_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 78 [ 'nodes.jvm.gc.collectors.young.collection_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 79 [ 'nodes.jvm.gc.collectors.young.collection_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 80 [ 'nodes.jvm.buffer_pools.direct.count', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 81 [ 'nodes.jvm.buffer_pools.direct.used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 82 [ 'nodes.jvm.buffer_pools.direct.total_capacity_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 83 [ 'nodes.jvm.buffer_pools.mapped.count', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 84 [ 'nodes.jvm.buffer_pools.mapped.used_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 85 [ 'nodes.jvm.buffer_pools.mapped.total_capacity_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 86 [ 'nodes.indices.search.query_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 87 [ 'nodes.indices.search.fetch_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 88 [ 'nodes.indices.search.open_contexts', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 89 [ 'nodes.indices.get.current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 90 [ 'nodes.indices.indexing.index_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 91 [ 'nodes.indices.indexing.delete_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 92 [ 'nodes.indices.indexing.noop_update_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 93 [ 'nodes.indices.indexing.is_throttled', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 94 [ 'nodes.indices.indexing.throttle_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 95 [ 'nodes.indices.store.throttle_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 96 [ 'nodes.indices.warmer.current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 97 [ 'nodes.indices.warmer.total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 98 [ 'nodes.indices.warmer.total_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 99 [ 'nodes.indices.filter_cache.memory_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 100 [ 'nodes.indices.filter_cache.evictions', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 101 [ 'nodes.indices.id_cache.memory_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 102 [ 'nodes.indices.fielddata.memory_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 103 [ 'nodes.indices.fielddata.evictions', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 104 [ 'nodes.indices.percolate.total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 105 [ 'nodes.indices.percolate.time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 106 [ 'nodes.indices.percolate.current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 107 [ 'nodes.indices.percolate.memory_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 108 [ 'nodes.indices.percolate.queries', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 109 [ 'nodes.indices.completion.size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 110 [ 'nodes.indices.segments.count', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 111 [ 'nodes.indices.segments.memory_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 112 [ 'nodes.indices.segments.index_writer_memory_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 113 [ 'nodes.indices.segments.index_writer_max_memory_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 114 [ 'nodes.indices.segments.version_map_memory_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 115 [ 'nodes.indices.segments.fixed_bit_set_memory_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 116 [ 'nodes.indices.translog.operations', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 117 [ 'nodes.indices.translog.size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 118 [ 'nodes.indices.suggest.total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 119 [ 'nodes.indices.suggest.time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 120 [ 'nodes.indices.suggest.current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 121 [ 'nodes.indices.query_cache.memory_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 122 [ 'nodes.indices.query_cache.evictions', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 123 [ 'nodes.indices.query_cache.hit_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 124 [ 'nodes.indices.query_cache.miss_count', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 125 [ 'nodes.indices.recovery.current_as_source', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 126 [ 'nodes.indices.recovery.current_as_target', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 127 [ 'nodes.indices.recovery.throttle_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), '' ], # 128 [ 'nodes.network.tcp.active_opens', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 129 [ 'nodes.network.tcp.passive_opens', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 130 [ 'nodes.network.tcp.curr_estab', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 131 [ 'nodes.network.tcp.in_segs', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 132 [ 'nodes.network.tcp.out_segs', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 133 [ 'nodes.network.tcp.retrans_segs', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 134 [ 'nodes.network.tcp.estab_resets', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 135 [ 'nodes.network.tcp.attempt_fails', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 136 [ 'nodes.network.tcp.in_errs', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 137 [ 'nodes.network.tcp.out_rsts', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 138 [ 'nodes.fs.total.total_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 139 [ 'nodes.fs.total.free_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 140 # Not sure difference between "free_in_bytes" and "available_in_bytes" [ 'nodes.fs.total.available_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 141 [ 'nodes.fs.total.disk_reads', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 142 [ 'nodes.fs.total.disk_writes', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 143 [ 'nodes.fs.total.disk_io_op', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], # 144 [ 'nodes.fs.total.disk_read_size_in_bytes', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 145 [ 'nodes.fs.total.disk_write_size_in_bytes', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 146 [ 'nodes.fs.total.disk_io_size_in_bytes', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 147 ] self.network_map = { 129: 'active_opens', 130: 'passive_opens', 131: 'curr_estab', 132: 'in_segs', 133: 'out_segs', 134: 'retrans_segs', 135: 'estab_resets', 136: 'attempt_fails', 137: 'in_errs', 138: 'out_rsts', } self.fs_map = { 139: 'total_in_bytes', 140: 'free_in_bytes', 141: 'available_in_bytes', 142: 'disk_reads', 143: 'disk_writes', 144: 'disk_io_op', 145: 'disk_read_size_in_bytes', 146: 'disk_write_size_in_bytes', 147: 'disk_io_size_in_bytes', } # 148 - 159 (3 x 4) idx = 148 self.breaker_map = {} for breaker in [ "request", "fielddata", "parent" ]: metrics = [ [ f'nodes.breakers.{breaker}.limit_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], [ f'nodes.breakers.{breaker}.estimated_size_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], [ f'nodes.breakers.{breaker}.overhead', PM_TYPE_FLOAT, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], [ f'nodes.breakers.{breaker}.tripped', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], ] self.nodes_metrics.extend(metrics) self.breaker_map[idx] = ( breaker, 'limit_size_in_bytes' ) self.breaker_map[idx+1] = ( breaker, 'estimated_size_in_bytes' ) self.breaker_map[idx+2] = ( breaker, 'overhead' ) self.breaker_map[idx+3] = ( breaker, 'tripped' ) idx += 4 # 160 - 261 (17 x 6) self.thread_pool_map = {} for thread_pool in [ "generic", "index", "fetch_shard_store", "get", "snapshot", "merge", "suggest", "bulk", "optimize", "warmer", "flush", "search", "fetch_shard_started", "listener", "percolate", "management", "refresh" ]: metrics = [ [ f'nodes.thread_pool.{thread_pool}.threads', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], [ f'nodes.thread_pool.{thread_pool}.queue', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], [ f'nodes.thread_pool.{thread_pool}.active', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], [ f'nodes.thread_pool.{thread_pool}.rejected', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], [ f'nodes.thread_pool.{thread_pool}.largest', PM_TYPE_U32, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], [ f'nodes.thread_pool.{thread_pool}.completed', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), '' ], ] self.nodes_metrics.extend(metrics) self.thread_pool_map[idx] = ( thread_pool, 'threads' ) self.thread_pool_map[idx+1] = ( thread_pool, 'queue' ) self.thread_pool_map[idx+2] = ( thread_pool, 'active' ) self.thread_pool_map[idx+3] = ( thread_pool, 'rejected' ) self.thread_pool_map[idx+4] = ( thread_pool, 'largest' ) self.thread_pool_map[idx+5] = ( thread_pool, 'completed' ) idx += 6 for item, metric in enumerate(self.nodes_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.nodes_cluster, item), metric[1], self.nodes_indom, metric[2], metric[3]), metric[4], metric[4]) self.node_info_indom = self.indom(1) self.node_info_insts = pmdaIndom(self.node_info_indom, {}) self.add_indom(self.node_info_insts, 'elasticsearch cluster nodes') self.node_info_cluster = 2 self.node_info_metrics = [ # Name - type - semantics - units - help [ 'nodes.jvm.pid', PM_TYPE_U32, PM_SEM_DISCRETE, pmUnits(0,0,0,0,0,0), '' ], # 0 [ 'nodes.jvm.version', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 1 [ 'nodes.jvm.vm_name', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 2 [ 'nodes.jvm.vm_version', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), '' ], # 3 [ 'nodes.jvm.mem.heap_init_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 4 [ 'nodes.jvm.mem.heap_max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 5 [ 'nodes.jvm.mem.non_heap_init_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 6 [ 'nodes.jvm.mem.non_heap_max_in_bytes', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(1,0,0,PM_SPACE_BYTE,0,0), '' ], # 7 [ 'nodes.process.max_file_descriptors', PM_TYPE_U64, PM_SEM_DISCRETE, pmUnits(0,0,0,0,0,0), '' ], # 8 ] for item, metric in enumerate(self.node_info_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.node_info_cluster, item), metric[1], self.node_info_indom, metric[2], metric[3]), metric[4], metric[4]) self.version_indom = PM_INDOM_NULL self.version_cluster = 3 self.version_metrics = [ # Name - type - semantics - units - help [ 'version.number', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Version number of elasticsearch' ], # 0 ] for item, metric in enumerate(self.version_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.version_cluster, item), metric[1], self.version_indom, metric[2], metric[3]), metric[4], metric[4]) self.search_indom = PM_INDOM_NULL self.search_cluster = 4 self.search_metrics = [ # Name - type - semantics - units - help [ 'search.shards.total', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of shards in the elasticsearch cluster' ], # 0 [ 'search.shards.successful', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of successfully searched shards in the elasticsearch cluster' ], # 1 [ 'search.shards.failed', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of failed shards in searches in the elasticsearch cluster' ], # 2 [ 'search.all.primaries.search.query_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search queries to all primary shards' ], # 3 [ 'search.all.primaries.search.query_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search queries to all primary shards' ], # 4 [ 'search.all.primaries.search.fetch_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search fetches to all primary shards' ], # 5 [ 'search.all.total.search.query_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search queries to all index shards' ], # 6 [ 'search.all.total.search.query_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search queries to all index shards' ], # 7 [ 'search.all.total.search.fetch_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search fetches to all index shards' ], # 8 [ 'search.all.total.fetch_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search fetches to all index shards (deprecated)' ], # 9 [ 'search.all.total.search.fetch_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search fetches to all index shards' ], # 10 [ 'search.all.primaries.search.fetch_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search queries to all primary shards' ], # 11 ] for item, metric in enumerate(self.search_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.search_cluster, item), metric[1], self.search_indom, metric[2], metric[3]), metric[4], metric[4]) self.perindex_indom = self.indom(2) self.perindex_insts = pmdaIndom(self.perindex_indom, {}) self.add_indom(self.perindex_insts, 'elasticsearch indices') self.perindex_cluster = 5 self.perindex_metrics = [ # Name - type - semantics - units - help [ 'search.perindex.primaries.search.query_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search queries to all index primary shards' ], # 0 [ 'search.perindex.primaries.search.query_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search queries to all index primary shards' ], # 1 [ 'search.perindex.primaries.search.fetch_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search fetches to all index primary shards' ], # 2 [ 'search.perindex.primaries.search.fetch_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search fetches to all index primary shards' ], # 3 [ 'search.perindex.total.search.query_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search queries to all index shards' ], # 4 [ 'search.perindex.total.search.query_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search queries to all index shards' ], # 5 [ 'search.perindex.total.search.fetch_total', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,0,1,0,0,PM_COUNT_ONE), 'Number of search fetches to all index shards' ], # 6 [ 'search.perindex.total.search.fetch_time_in_millis', PM_TYPE_U64, PM_SEM_COUNTER, pmUnits(0,1,0,0,PM_TIME_MSEC,0), 'Time spent in search fetches to all index shards' ], # 7 [ 'search.perindex.primaries.search.open_contexts', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Current number of open search contexts for primary shards' ], # 8 [ 'search.perindex.primaries.search.query_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Current number of search queries to all index primary shards' ], # 9 [ 'search.perindex.primaries.search.fetch_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Current number of search fetches to all index primary shards' ], # 10 [ 'search.perindex.total.search.open_contexts', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Current number of open search contexts for all index shards' ], # 11 [ 'search.perindex.total.search.query_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Current number of search queries to all index shards' ], # 12 [ 'search.perindex.total.search.fetch_current', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Current number of search fetches to all index shards' ], # 13 ] for item, metric in enumerate(self.perindex_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.perindex_cluster, item), metric[1], self.perindex_indom, metric[2], metric[3]), metric[4], metric[4]) self.master_node_indom = PM_INDOM_NULL self.master_node_cluster = 6 self.master_node_metrics = [ # Name - type - semantics - units - help [ 'cluster.master_node', PM_TYPE_STRING, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Internal identifier of the master node of the cluster' ], # 0 ] for item, metric in enumerate(self.master_node_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.master_node_cluster, item), metric[1], self.master_node_indom, metric[2], metric[3]), metric[4], metric[4]) self.index_indom = self.indom(3) self.index_insts = pmdaIndom(self.index_indom, {}) self.add_indom(self.index_insts, 'elasticsearch indices') self.index_cluster = 7 self.index_metrics = [ # Name - type - semantics - units - help [ 'index.settings.gateway_snapshot_interval', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Interval between gateway snapshots (deprecated)' ], # 0 [ 'index.settings.number_of_replicas', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of replicas of shards index setting' ], # 1 [ 'index.settings.number_of_shards', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Number of shards index setting' ], # 2 [ 'index.settings.version_created', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'The version stamp at time of index creation (deprecated)' ], # 3 [ 'index.settings.gateway.snapshot_interval', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'Interval between gateway snapshots' ], # 4 [ 'index.settings.version.created', PM_TYPE_U64, PM_SEM_INSTANT, pmUnits(0,0,0,0,0,0), 'The version stamp at time of index creation' ], # 5 ] for item, metric in enumerate(self.index_metrics): self.add_metric(name + '.' + metric[0], pmdaMetric(self.pmid(self.index_cluster, item), metric[1], self.index_indom, metric[2], metric[3]), metric[4], metric[4]) self.set_refresh(self.elasticsearch_refresh) self.set_fetch_callback(self.elasticsearch_fetch_callback) def read_config(self): """ Read Configuration file """ configdir = PCP.pmGetConfig('PCP_PMDAS_DIR') configdir += '/' + self.read_name() # Retain es.conf name from original version of the PMDA configfile = configdir + '/' + 'es.conf' if not os.path.exists(configfile): configfile = configdir + '/' + 'elasticsearch.conf' # Python < 3.2 compat if sys.version_info[0] >= 3 and sys.version_info[1] >= 2: config = ConfigParser.ConfigParser() else: config = ConfigParser.SafeConfigParser() config.read(configfile) if config.has_section('pmda'): for opt in config.options('pmda'): if opt == 'user': self.user = config.get('pmda', opt) elif opt == 'baseurl': self.baseurl = config.get('pmda', opt) elif opt == 'auth': self.auth = config.get('pmda', opt) elif opt == 'password': self.password = config.get('pmda', opt) else: self.log(f"Ignoring directive '{opt}' in {configfile}.") def get_url(self, url): """ Perform HTTP GET """ # self.log(f"url: {url}") req = None try: req = self.request.urlopen(url) self.error = False except (BaseException, Exception): if not self.error: self.log(f"Failed to get URL {url}") self.error = True if not req: if self.cluster: self.cluster = {} if self.nodes: self.nodes = {} if self.node_info: self.node_info = {} if self.info: self.info = {} if self.stat: self.stat = {} if self.search: self.search = {} if self.perindex: self.perindex = {} if self.master_node: self.master_node = None if self.index: self.index = {} return req def elasticsearch_refresh(self, cluster): """ Refresh """ if cluster == self.cluster_cluster: request = self.get_url(self.baseurl + "_cluster/health") if request: self.cluster = json.loads(request.read()) request.close() return if cluster == self.nodes_cluster: temp = {} insts = {} request = self.get_url(self.baseurl + "_nodes/stats") if request: temp = json.loads(request.read()) request.close() try: self.nodes = {} for _id, stats in temp['nodes'].items(): name = stats['name'] insts[name] = c_int(1) self.nodes[name] = stats except KeyError: pass self.nodes_insts.set_instances(self.nodes_indom, insts) self.replace_indom(self.nodes_indom, insts) return if cluster in (self.node_info_cluster, self.master_node_cluster): temp = {} insts = {} request = self.get_url(self.baseurl + "_nodes") if request: temp = json.loads(request.read()) request.close() if cluster == self.master_node_cluster: self.master_node = None try: for _id, info in temp['nodes'].items(): if info['attributes']['master'] == "true": self.master_node = str(info['name']) except KeyError: pass else: try: self.node_info = {} for _id, info in temp['nodes'].items(): name = info['name'] insts[name] = c_int(1) self.node_info[name] = info except KeyError: pass self.node_info_insts.set_instances(self.node_info_indom, insts) self.replace_indom(self.node_info_indom, insts) return if cluster == self.version_cluster: request = self.get_url(self.baseurl) if request: self.info = json.loads(request.read()) request.close() return if cluster in (self.search_cluster, self.perindex_cluster): temp = {} insts = {} request = self.get_url(self.baseurl + "_stats/search") if request: temp = json.loads(request.read()) request.close() if cluster == self.search_cluster: self.search = temp else: try: self.perindex = temp['indices'] for index in temp['indices']: insts[index] = c_int(1) except KeyError: pass self.perindex_insts.set_instances(self.perindex_indom, insts) self.replace_indom(self.perindex_indom, insts) return if cluster == self.index_cluster: temp = {} insts = {} request = self.get_url(self.baseurl + "_cluster/state/metadata") if request: temp = json.loads(request.read()) request.close() try: self.index = temp['metadata']['indices'] for index in temp['metadata']['indices']: insts[index] = c_int(1) except KeyError: pass self.index_insts.set_instances(self.index_indom, insts) self.replace_indom(self.index_indom, insts) def elasticsearch_fetch_callback(self, cluster, item, inst): """ Fetch Callback """ if cluster == self.cluster_cluster: if not self.cluster: return [PMDA_FETCH_NOVALUES, 0] try: if item == 0: return [str(self.cluster['cluster_name']), 1] if item == 1: return [str(self.cluster['status']), 1] if item == 2: return [self.cluster['timed_out'], 1] if item == 3: return [self.cluster['number_of_nodes'], 1] if item == 4: return [self.cluster['number_of_data_nodes'], 1] if item == 5: return [self.cluster['active_primary_shards'], 1] if item == 6: return [self.cluster['active_shards'], 1] if item == 7: return [self.cluster['relocating_shards'], 1] if item == 8: return [self.cluster['initializing_shards'], 1] if item == 9: return [self.cluster['unassigned_shards'], 1] if item == 10: if self.cluster['status'] == 'green': return [0, 1] if self.cluster['status'] == 'yellow': return [1, 1] if self.cluster['status'] == 'red': return [2, 1] except KeyError: return [PM_ERR_APPVERSION, 0] elif cluster == self.nodes_cluster: if not self.nodes: return [PMDA_FETCH_NOVALUES, 0] try: node = self.nodes_insts.inst_name_lookup(inst) data = self.nodes[node] if item in (0, 47): return [data['indices']['store']['size_in_bytes'], 1] if item == 1: return [data['indices']['docs']['count'], 1] if item == 2: # The 'nodes.indices.docs.num_docs', item #2, does not # exist in the '_nodes/stats' API JSON payload # (Elasticsearch V1 or V7). # [data['indices']['docs']['num_docs'], 1] return [PM_ERR_APPVERSION, 0] if item in (3, 4, 5, 6, 7): # The 'nodes.indices.cache.field_evictions', # '.field_size_in_bytes', '.filter_count', # '.filter_evictions', and '.filter_size_in_bytes', items # #3 thru #7, do not exist in the '_nodes/stats' API JSON # payload (Elasticsearch V1 or V7). # [data['indices']['cache']['field_evictions'], 1] # [data['indices']['cache']['field_size_in_bytes'], 1] # [data['indices']['cache']['filter_count'], 1] # [data['indices']['cache']['filter_evictions'], 1] # [data['indices']['cache']['filter_size_in_bytes'], 1] return [PM_ERR_APPVERSION, 0] if item == 8: return [data['indices']['merges']['current'], 1] if item == 9: return [data['indices']['merges']['total'], 1] if item == 10: return [data['indices']['merges']['total_time_in_millis'], 1] if item == 11: return [data['jvm']['uptime_in_millis'], 1] if item == 12: # The 'nodes.jvm.uptime', item #12, does not exist in # the '_nodes/stats' API JSON payload (Elasticsearch V1 or V7). return [PM_ERR_APPVERSION, 0] if item == 13: return [data['jvm']['mem']['heap_used_in_bytes'], 1] if item == 14: return [data['jvm']['mem']['heap_committed_in_bytes'], 1] if item == 15: return [data['jvm']['mem']['non_heap_used_in_bytes'], 1] if item == 16: return [data['jvm']['mem']['non_heap_committed_in_bytes'], 1] if item == 17: return [data['jvm']['threads']['count'], 1] if item == 18: return [data['jvm']['threads']['peak_count'], 1] if item in (19, 20, 21, 22, 23, 24, 25, 26): # The 'nodes.jvm.gc.collection_count', # '.collection_time_in_millis', # '.collectors.{Copy|ParNew|ConcurrentMarkSweep}.collection_count', # and # '.collectors.{Copy|ParNew|ConcurrentMarkSweep}.collection_time_in_millis', # items #19 thru #26, do not exist in the '_nodes/stats' # API JSON payload (Elasticsearch V1 or V7). # [data['jvm']['gc']['collection_count'], 1] # [data['jvm']['gc']['collection_time_in_millis'], 1] # [data['jvm']['gc']['collectors']['Copy']['collection_count'], 1] # [data['jvm']['gc']['collectors']['Copy']['collection_time_in_millis'], 1] # [data['jvm']['gc']['collectors']['ParNew']['collection_count'], 1] # [data['jvm']['gc']['collectors']['ParNew']['collection_time_in_millis'], 1] # [data['jvm']['gc']['collectors']['ConcurrentMarkSweep']['collection_count'], 1] # [data['jvm']['gc']['collectors']['ConcurrentMarkSweep']['collection_time_in_millis'], 1] return [PM_ERR_APPVERSION, 0] if item == 27: return [data['indices']['docs']['deleted'], 1] if item == 28: return [data['indices']['indexing']['index_total'], 1] if item == 29: return [data['indices']['indexing']['index_time_in_millis'], 1] if item == 30: return [data['indices']['indexing']['delete_total'], 1] if item == 31: return [data['indices']['indexing']['delete_time_in_millis'], 1] if item == 32: return [data['indices']['merges']['current_docs'], 1] if item == 33: return [data['indices']['merges']['current_size_in_bytes'], 1] if item == 34: return [data['indices']['merges']['total_docs'], 1] if item == 35: return [data['indices']['merges']['total_size_in_bytes'], 1] if item == 36: return [data['indices']['refresh']['total'], 1] if item == 37: return [data['indices']['refresh']['total_time_in_millis'], 1] if item == 38: return [data['indices']['flush']['total'], 1] if item == 39: return [data['indices']['flush']['total_time_in_millis'], 1] if item == 40: # The '_nodes/stats' JSON payload contains "timestamp" # fields for each sub-section report marking the time at # which each of those fields was actually gathered before # placing into the JSON payload. This is not a usable metric # and was never setup properly. # # [data['process']['timestamp'], 1] return [PM_ERR_APPVERSION, 0] if item == 41: return [data['process']['open_file_descriptors'], 1] if item == 42: return [data['process']['cpu']['percent'], 1] if item == 43: return [data['process']['cpu']['sys_in_millis'], 1] if item == 44: return [data['process']['cpu']['user_in_millis'], 1] if item == 45: return [data['process']['mem']['resident_in_bytes'], 1] if item == 46: return [data['process']['mem']['total_virtual_in_bytes'], 1] # Item 47 is the same as item 0. if item == 48: return [data['indices']['get']['total'], 1] if item == 49: return [data['indices']['get']['time_in_millis'], 1] if item == 50: return [data['indices']['get']['exists_total'], 1] if item == 51: return [data['indices']['get']['exists_time_in_millis'], 1] if item == 52: return [data['indices']['get']['missing_total'], 1] if item == 53: return [data['indices']['get']['missing_time_in_millis'], 1] if item == 54: return [data['indices']['search']['query_total'], 1] if item == 55: return [data['indices']['search']['query_time_in_millis'], 1] if item == 56: return [data['indices']['search']['fetch_total'], 1] if item == 57: return [data['indices']['search']['fetch_time_in_millis'], 1] if item == 58: return [data['transport']['server_open'], 1] if item == 59: return [data['transport']['rx_count'], 1] if item == 60: return [data['transport']['rx_size_in_bytes'], 1] if item == 61: return [data['transport']['tx_count'], 1] if item == 62: return [data['transport']['tx_size_in_bytes'], 1] if item == 63: return [data['http']['current_open'], 1] if item == 64: return [data['http']['total_opened'], 1] if item == 65: return [data['jvm']['mem']['pools']['old']['max_in_bytes'], 1] if item == 66: return [data['jvm']['mem']['pools']['old']['peak_max_in_bytes'], 1] if item == 67: return [data['jvm']['mem']['pools']['old']['peak_used_in_bytes'], 1] if item == 68: return [data['jvm']['mem']['pools']['old']['used_in_bytes'], 1] if item == 69: return [data['jvm']['mem']['pools']['survivor']['max_in_bytes'], 1] if item == 70: return [data['jvm']['mem']['pools']['survivor']['peak_max_in_bytes'], 1] if item == 71: return [data['jvm']['mem']['pools']['survivor']['peak_used_in_bytes'], 1] if item == 72: return [data['jvm']['mem']['pools']['survivor']['used_in_bytes'], 1] if item == 73: return [data['jvm']['mem']['pools']['young']['max_in_bytes'], 1] if item == 74: return [data['jvm']['mem']['pools']['young']['peak_max_in_bytes'], 1] if item == 75: return [data['jvm']['mem']['pools']['young']['peak_used_in_bytes'], 1] if item == 76: return [data['jvm']['mem']['pools']['young']['used_in_bytes'], 1] if item == 77: return [data['jvm']['gc']['collectors']['old']['collection_count'], 1] if item == 78: return [data['jvm']['gc']['collectors']['old']['collection_time_in_millis'], 1] if item == 79: return [data['jvm']['gc']['collectors']['young']['collection_count'], 1] if item == 80: return [data['jvm']['gc']['collectors']['young']['collection_time_in_millis'], 1] if item == 81: return [data['jvm']['buffer_pools']['direct']['count'], 1] if item == 82: return [data['jvm']['buffer_pools']['direct']['used_in_bytes'], 1] if item == 83: return [data['jvm']['buffer_pools']['direct']['total_capacity_in_bytes'], 1] if item == 84: return [data['jvm']['buffer_pools']['mapped']['count'], 1] if item == 85: return [data['jvm']['buffer_pools']['mapped']['used_in_bytes'], 1] if item == 86: return [data['jvm']['buffer_pools']['mapped']['total_capacity_in_bytes'], 1] if item == 87: return [data['indices']['search']['query_current'], 1] if item == 88: return [data['indices']['search']['fetch_current'], 1] if item == 89: return [data['indices']['search']['open_contexts'], 1] if item == 90: return [data['indices']['get']['current'], 1] if item == 91: return [data['indices']['indexing']['index_current'], 1] if item == 92: return [data['indices']['indexing']['delete_current'], 1] if item == 93: return [data['indices']['indexing']['noop_update_total'], 1] if item == 94: return [data['indices']['indexing']['is_throttled'], 1] if item == 95: return [data['indices']['indexing']['throttle_time_in_millis'], 1] if item == 96: return [data['indices']['store']['throttle_time_in_millis'], 1] if item == 97: return [data['indices']['warmer']['current'], 1] if item == 98: return [data['indices']['warmer']['total'], 1] if item == 99: return [data['indices']['warmer']['total_time_in_millis'], 1] if item == 100: return [data['indices']['filter_cache']['memory_size_in_bytes'], 1] if item == 101: return [data['indices']['filter_cache']['evictions'], 1] if item == 102: return [data['indices']['id_cache']['memory_size_in_bytes'], 1] if item == 103: return [data['indices']['fielddata']['memory_size_in_bytes'], 1] if item == 104: return [data['indices']['fielddata']['evictions'], 1] if item == 105: return [data['indices']['percolate']['total'], 1] if item == 106: return [data['indices']['percolate']['time_in_millis'], 1] if item == 107: return [data['indices']['percolate']['current'], 1] if item == 108: return [data['indices']['percolate']['memory_size_in_bytes'], 1] if item == 109: return [data['indices']['percolate']['queries'], 1] if item == 110: return [data['indices']['completion']['size_in_bytes'], 1] if item == 111: return [data['indices']['segments']['count'], 1] if item == 112: return [data['indices']['segments']['memory_in_bytes'], 1] if item == 113: return [data['indices']['segments']['index_writer_memory_in_bytes'], 1] if item == 114: return [data['indices']['segments']['index_writer_max_memory_in_bytes'], 1] if item == 115: return [data['indices']['segments']['version_map_memory_in_bytes'], 1] if item == 116: return [data['indices']['segments']['fixed_bit_set_memory_in_bytes'], 1] if item == 117: return [data['indices']['translog']['operations'], 1] if item == 118: return [data['indices']['translog']['size_in_bytes'], 1] if item == 119: return [data['indices']['suggest']['total'], 1] if item == 120: return [data['indices']['suggest']['time_in_millis'], 1] if item == 121: return [data['indices']['suggest']['current'], 1] if item == 122: return [data['indices']['query_cache']['memory_size_in_bytes'], 1] if item == 123: return [data['indices']['query_cache']['evictions'], 1] if item == 124: return [data['indices']['query_cache']['hit_count'], 1] if item == 125: return [data['indices']['query_cache']['miss_count'], 1] if item == 126: return [data['indices']['recovery']['current_as_source'], 1] if item == 127: return [data['indices']['recovery']['current_as_target'], 1] if item == 128: return [data['indices']['recovery']['throttle_time_in_millis'], 1] if item in self.network_map: metric = self.network_map[item] return [data['network']['tcp'][metric], 1] if item in self.fs_map: metric = self.fs_map[item] return [data['fs']['total'][metric], 1] if item in self.breaker_map: breaker, metric = self.breaker_map[item] return [data['breakers'][breaker][metric], 1] if item in self.thread_pool_map: thread_pool, metric = self.thread_pool_map[item] return [data['thread_pool'][thread_pool][metric], 1] except KeyError: return [PM_ERR_APPVERSION, 0] elif cluster == self.node_info_cluster: if not self.node_info: return [PMDA_FETCH_NOVALUES, 0] try: node = self.node_info_insts.inst_name_lookup(inst) data = self.node_info[node] if item == 0: return [data['jvm']['pid'], 1] if item == 1: return [str(data['jvm']['version']), 1] if item == 2: return [str(data['jvm']['vm_name']), 1] if item == 3: return [str(data['jvm']['vm_version']), 1] if item == 4: return [data['jvm']['mem']['heap_init_in_bytes'], 1] if item == 5: return [data['jvm']['mem']['heap_max_in_bytes'], 1] if item == 6: return [data['jvm']['mem']['non_heap_init_in_bytes'], 1] if item == 7: return [data['jvm']['mem']['non_heap_max_in_bytes'], 1] if item == 8: return [data['process']['max_file_descriptors'], 1] except KeyError: return [PM_ERR_APPVERSION, 0] elif cluster == self.version_cluster: if not self.info: return [PMDA_FETCH_NOVALUES, 0] try: if item == 0: return [str(self.info['version']['number']), 1] except KeyError: return [PM_ERR_APPVERSION, 0] elif cluster == self.search_cluster: if not self.search: return [PMDA_FETCH_NOVALUES, 0] try: if item == 0: return [self.search['_shards']['total'], 1] if item == 1: return [self.search['_shards']['successful'], 1] if item == 2: return [self.search['_shards']['failed'], 1] if item == 3: return [self.search['_all']['primaries']['search']['query_total'], 1] if item == 4: return [self.search['_all']['primaries']['search']['query_time_in_millis'], 1] if item == 5: return [self.search['_all']['primaries']['search']['fetch_total'], 1] if item == 6: return [self.search['_all']['total']['search']['query_total'], 1] if item == 7: return [self.search['_all']['total']['search']['query_time_in_millis'], 1] if item == 8: return [self.search['_all']['total']['search']['fetch_total'], 1] if item in (9, 10): return [self.search['_all']['total']['search']['fetch_time_in_millis'], 1] if item == 11: return [self.search['_all']['primaries']['search']['fetch_time_in_millis'], 1] except KeyError: return [PM_ERR_APPVERSION, 0] elif cluster == self.perindex_cluster: if not self.search: return [PMDA_FETCH_NOVALUES, 0] try: index = self.perindex_insts.inst_name_lookup(inst) data = self.perindex[index] if item == 0: return [data['primaries']['search']['query_total'], 1] if item == 1: return [data['primaries']['search']['query_time_in_millis'], 1] if item == 2: return [data['primaries']['search']['fetch_total'], 1] if item == 3: return [data['primaries']['search']['fetch_time_in_millis'], 1] if item == 4: return [data['total']['search']['query_total'], 1] if item == 5: return [data['total']['search']['query_time_in_millis'], 1] if item == 6: return [data['total']['search']['fetch_total'], 1] if item == 7: return [data['total']['search']['fetch_time_in_millis'], 1] if item == 8: return [data['primaries']['search']['open_contexts'], 1] if item == 9: return [data['primaries']['search']['query_current'], 1] if item == 10: return [data['primaries']['search']['fetch_current'], 1] if item == 11: return [data['total']['search']['open_contexts'], 1] if item == 12: return [data['total']['search']['query_current'], 1] if item == 13: return [data['total']['search']['fetch_current'], 1] except KeyError: return [PM_ERR_APPVERSION, 0] elif cluster == self.master_node_cluster: if not self.master_node: return [PMDA_FETCH_NOVALUES, 0] if item == 0: return [self.master_node, 1] elif cluster == self.index_cluster: if not self.index: return [PMDA_FETCH_NOVALUES, 0] try: index = self.index_insts.inst_name_lookup(inst) data = self.index[index]['settings']['index'] if item in (0, 4): return [int(data['gateway']['snapshot_interval']), 1] if item == 1: return [int(data['number_of_replicas']), 1] if item == 2: return [int(data['number_of_shards']), 1] if item in (3, 5): return [int(data['version']['created']), 1] except KeyError: return [PM_ERR_APPVERSION, 0] return [PM_ERR_PMID, 0] if __name__ == '__main__': ElasticsearchPMDA('elasticsearch', 108).run()