From: Kefu Chai Date: Mon, 15 Mar 2021 09:11:55 +0000 (+0800) Subject: Merge pull request #36298 from p-se/mgr-prom-collect-time-metric X-Git-Tag: v17.1.0~2623 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3ef8116b8409b392cd249b51b770e39cc3f3bfbd;p=ceph.git Merge pull request #36298 from p-se/mgr-prom-collect-time-metric mgr/prometheus: introduce metric for collection time Reviewed-by: Mykola Golub Reviewed-by: Ernesto Puerta Reviewed-by: Kefu Chai --- 3ef8116b8409b392cd249b51b770e39cc3f3bfbd diff --cc src/pybind/mgr/prometheus/module.py index ea4b59c24398,3f29b175d871..fd1fa59487c4 --- a/src/pybind/mgr/prometheus/module.py +++ b/src/pybind/mgr/prometheus/module.py @@@ -187,8 -184,27 +187,26 @@@ class Metric(object) return expfmt + class MetricCounter(Metric): + def __init__(self, name, desc, labels=None): + super(MetricCounter, self).__init__('counter', name, desc, labels) + self.value = defaultdict(lambda: 0) + + def clear(self): + pass # Skip calls to clear as we want to keep the counters here. + + def set(self, value, labelvalues=None): + msg = 'This method must not be used for instances of MetricCounter class' + raise NotImplementedError(msg) + + def add(self, value, labelvalues=None): + # labelvalues must be a tuple + labelvalues = labelvalues or ('',) + self.value[labelvalues] += value + + class MetricCollectionThread(threading.Thread): - def __init__(self, module): - # type: (Module) -> None + def __init__(self, module: 'Module') -> None: self.mod = module self.active = True self.event = threading.Event() @@@ -1101,8 -1124,34 +1121,34 @@@ class Module(MgrModule) self.metrics.update(new_metrics) + def get_collect_time_metrics(self): + if 'prometheus_collect_duration_seconds_sum' not in self.metrics: + self.metrics['prometheus_collect_duration_seconds_sum'] = MetricCounter( + 'prometheus_collect_duration_seconds_sum', + 'The sum of seconds took to collect all metrics of this exporter', + ('method',), + ) + if 'prometheus_collect_duration_seconds_count' not in self.metrics: + self.metrics['prometheus_collect_duration_seconds_count'] = MetricCounter( + 'prometheus_collect_duration_seconds_count', + 'The amount of metrics gathered for this exporter', + ('method',), + ) + + # Collect all timing data and make it available as metric, excluding the + # `collect` method because it has not finished at this point and hence + # there's no `_execution_duration` attribute to be found. The + # `_execution_duration` attribute is added by the `profile_method` + # decorator. + for method_name, method in Module.__dict__.items(): + if hasattr(method, '_execution_duration'): + self.metrics['prometheus_collect_duration_seconds_sum'].add( + method._execution_duration, (method_name, )) + self.metrics['prometheus_collect_duration_seconds_count'].add( + 1, (method_name, )) + @profile_method(True) - def collect(self): + def collect(self) -> str: # Clear the metrics before scraping for k in self.metrics.keys(): self.metrics[k].clear()