diff --git a/glances/exports/export.py b/glances/exports/export.py index 5d1544a5..bbd37306 100644 --- a/glances/exports/export.py +++ b/glances/exports/export.py @@ -152,7 +152,7 @@ class GlancesExport: d_tags = {} if tags: try: - d_tags = dict([x.split(":") for x in tags.split(",")]) + d_tags = dict(x.split(":", 1) for x in tags.split(",")) except ValueError: # one of the 'key:value' pairs was missing logger.info("Invalid tags passed: %s", tags) @@ -225,7 +225,7 @@ class GlancesExport: def is_excluded(self, field): """Return true if the field is excluded.""" - return hasattr(self, 'exclude_fields') and any(re.fullmatch(i, field, re.I) for i in self.exclude_fields) + return any(re.fullmatch(i, field, re.I) for i in (getattr(self, 'exclude_fields') or ())) def plugins_to_export(self, stats): """Return the list of plugins to export. diff --git a/glances/exports/glances_prometheus/__init__.py b/glances/exports/glances_prometheus/__init__.py index fd922eb8..85e2e5dd 100644 --- a/glances/exports/glances_prometheus/__init__.py +++ b/glances/exports/glances_prometheus/__init__.py @@ -13,11 +13,11 @@ from numbers import Number from prometheus_client import Gauge, start_http_server +from glances.api import GlancesStats from glances.exports.export import GlancesExport from glances.globals import listkeys from glances.logger import logger - class Export(GlancesExport): """This class manages the Prometheus export module.""" @@ -43,6 +43,8 @@ class Export(GlancesExport): # Perhaps a better method is possible... self._metric_dict = {} + self._stats = GlancesStats() + # Init the Prometheus Exporter self.init() @@ -61,24 +63,34 @@ class Export(GlancesExport): logger.debug(f"Export {name} stats to Prometheus exporter") # Remove non number stats and convert all to float (for Boolean) - data = {k: float(v) for k, v in zip(columns, points) if isinstance(v, Number)} + data = {str(k): float(v) for k, v in zip(columns, points) if isinstance(v, Number)} + + key_name = self._stats.get_plugin(name).get_key() # Write metrics to the Prometheus exporter - for k, v in data.items(): - # Prometheus metric name: prefix_ - metric_name = self.prefix + self.METRIC_SEPARATOR + str(name) + self.METRIC_SEPARATOR + str(k) + for metric, value in data.items(): + labels = self.labels + metric_name = self.prefix + self.METRIC_SEPARATOR + name + self.METRIC_SEPARATOR + try: + obj, stat = metric.split('.') + metric_name += stat + labels += f",{key_name}:{obj}" + except ValueError: + metric_name += metric + # Prometheus is very sensible to the metric name # See: https://prometheus.io/docs/practices/naming/ for c in ' .-/:[]': metric_name = metric_name.replace(c, self.METRIC_SEPARATOR) + # Get the labels - labels = self.parse_tags(self.labels) + labels = self.parse_tags(labels) # Manage an internal dict between metric name and Gauge if metric_name not in self._metric_dict: - self._metric_dict[metric_name] = Gauge(metric_name, k, labelnames=listkeys(labels)) + self._metric_dict[metric_name] = Gauge(metric_name, "", labelnames=listkeys(labels)) # Write the value if hasattr(self._metric_dict[metric_name], 'labels'): # Add the labels (see issue #1255) - self._metric_dict[metric_name].labels(**labels).set(v) + self._metric_dict[metric_name].labels(**labels).set(value) else: - self._metric_dict[metric_name].set(v) + self._metric_dict[metric_name].set(value)