From: John Spray Date: Tue, 29 Aug 2017 15:55:28 +0000 (-0400) Subject: mgr: add get_all_perf_counters to MgrModule interface X-Git-Tag: v12.2.2~61^2~71 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=802cd49bae2cce6c55eddd68feb617df893e1046;p=ceph.git mgr: add get_all_perf_counters to MgrModule interface This is for use by modules that dump counters in bulk, e.g. to a TSDB. Signed-off-by: John Spray (cherry picked from commit 9a42d4255d9d968d6162b53b71db292d9d3de2e4) --- diff --git a/src/pybind/mgr/mgr_module.py b/src/pybind/mgr/mgr_module.py index 0806c9e1c55d..cce9826dee67 100644 --- a/src/pybind/mgr/mgr_module.py +++ b/src/pybind/mgr/mgr_module.py @@ -6,8 +6,16 @@ import ceph_crushmap #noqa import json import logging import threading +from collections import defaultdict +# Priority definitions for perf counters +PRIO_CRITICAL = 10 +PRIO_INTERESTING = 8 +PRIO_USEFUL = 5 +PRIO_UNINTERESTING = 2 +PRIO_DEBUGONLY = 0 + class CommandResult(object): """ Use with MgrModule.send_command @@ -145,6 +153,19 @@ class MgrModule(object): self._version = ceph_state.get_version() + self._perf_schema_cache = None + + def update_perf_schema(self, daemon_type, daemon_name): + """ + For plugins that use get_all_perf_counters, call this when + receiving a notification of type 'perf_schema_update', to + prompt MgrModule to update its cache of counter schemas. + + :param daemon_type: + :param daemon_name: + :return: + """ + @property def log(self): return self._logger @@ -395,3 +416,60 @@ class MgrModule(object): :return: OSDMap """ return OSDMap(ceph_state.get_osdmap()) + + def get_all_perf_counters(self, prio_limit=PRIO_USEFUL): + """ + Return the perf counters currently known to this ceph-mgr + instance, filtered by priority equal to or greater than `prio_limit`. + + The result us a map of string to dict, associating services + (like "osd.123") with their counters. The counter + dict for each service maps counter paths to a counter + info structure, which is the information from + the schema, plus an additional "value" member with the latest + value. + """ + + result = defaultdict(dict) + + # TODO: improve C++->Python interface to return just + # the latest if that's all we want. + def get_latest(daemon_type, daemon_name, counter): + data = self.get_counter(daemon_type, daemon_name, counter)[counter] + if data: + return data[-1][1] + else: + return 0 + + for server in self.list_servers(): + for service in server['services']: + if service['type'] not in ("mds", "osd", "mon"): + continue + + schema = self.get_perf_schema(service['type'], service['id']) + if not schema: + self.log.warn("No perf counter schema for {0}.{1}".format( + service['type'], service['id'] + )) + continue + + # Value is returned in a potentially-multi-service format, + # get just the service we're asking about + svc_full_name = "{0}.{1}".format(service['type'], service['id']) + schema = schema[svc_full_name] + + # Populate latest values + for counter_path, counter_schema in schema.items(): + # self.log.debug("{0}: {1}".format( + # counter_path, json.dumps(counter_schema) + # )) + if counter_schema['priority'] < prio_limit: + continue + + counter_info = counter_schema + counter_info['value'] = get_latest(service['type'], service['id'], counter_path) + result[svc_full_name][counter_path] = counter_info + + self.log.debug("returning {0} counter".format(len(result))) + + return result