diff --git a/monitoring_prometheus/README.rst b/monitoring_prometheus/README.rst index 813dae2..cf44e53 100644 --- a/monitoring_prometheus/README.rst +++ b/monitoring_prometheus/README.rst @@ -31,8 +31,8 @@ can read ``prometheus.metric`` records through the ORM/UI. The */metrics* endpoi remains public and reads the records with ``sudo()`` so Prometheus can keep scraping it without authentication. -To publish new metrics, extend ``_gather_metrics`` on the ``prometheus.gatherer`` -abstract model and return the result of ``super()`` extended with your own entries:: +To publish new metrics, extend ``_gather_metrics`` on the ``prometheus.metric`` +model and return the result of ``super()`` extended with your own entries:: { "name": "odoo_some_metric", diff --git a/monitoring_prometheus/data/ir_cron.xml b/monitoring_prometheus/data/ir_cron.xml index 82b5aba..b094bae 100644 --- a/monitoring_prometheus/data/ir_cron.xml +++ b/monitoring_prometheus/data/ir_cron.xml @@ -2,7 +2,7 @@ Prometheus: gather metrics - + code model._cron_gather_metrics() 15 diff --git a/monitoring_prometheus/models/__init__.py b/monitoring_prometheus/models/__init__.py index 472b8a2..d4d94ce 100644 --- a/monitoring_prometheus/models/__init__.py +++ b/monitoring_prometheus/models/__init__.py @@ -1,3 +1,2 @@ from . import ir_http -from . import prometheus_gatherer from . import prometheus_metric diff --git a/monitoring_prometheus/models/prometheus_gatherer.py b/monitoring_prometheus/models/prometheus_gatherer.py deleted file mode 100644 index 22f6641..0000000 --- a/monitoring_prometheus/models/prometheus_gatherer.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright 2016-2021 Camptocamp SA -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) - -from odoo import api, models - - -class PrometheusGatherer(models.AbstractModel): - """Collect application metrics to be exposed on the /metrics endpoint. - - Metrics are gathered by a cron and stored in ``prometheus.metric`` - records, because crons and HTTP workers run in separate processes and - cannot share the Prometheus registry. - """ - - _name = "prometheus.gatherer" - _description = "Prometheus Metrics Gatherer" - - @api.model - def _gather_metrics(self): - """Return the metrics as a list of dicts. - - Each entry is of the form:: - - { - "name": "odoo_some_metric", - "documentation": "What this metric measures", - "labels": {"label_name": "label_value"}, - "value": 42, - } - - ``labels`` may be omitted for an unlabelled metric. All the entries - sharing a ``name`` must declare the same label names. - - Modules extending this method must return the result of ``super()`` - extended with their own entries. - """ - return [] - - @api.model - def _cron_gather_metrics(self): - Metric = self.env["prometheus.metric"].sudo() - touched = self.env["prometheus.metric"] - for metric in self._gather_metrics(): - touched |= Metric._create_or_update_metric(metric) - # drop the series that disappeared since the last collection - (Metric.search([]) - touched).unlink() - return True diff --git a/monitoring_prometheus/models/prometheus_metric.py b/monitoring_prometheus/models/prometheus_metric.py index 30039ec..7e8e05e 100644 --- a/monitoring_prometheus/models/prometheus_metric.py +++ b/monitoring_prometheus/models/prometheus_metric.py @@ -9,7 +9,11 @@ from odoo import api, fields, models class PrometheusMetric(models.Model): - """Store the metrics gathered by ``prometheus.gatherer``. + """Application metrics gathered by a cron and exposed on ``/metrics``. + + Metrics are gathered by ``_cron_gather_metrics`` and stored as records, + because crons and HTTP workers run in separate processes and cannot share + the Prometheus registry. A record is stored per metric name/labels combination, because a single metric name can be reported several times with different labels (e.g. @@ -57,6 +61,37 @@ class PrometheusMetric(models.Model): self._check_upsert_context() return super().write(vals) + @api.model + def _gather_metrics(self): + """Return the metrics as a list of dicts. + + Each entry is of the form:: + + { + "name": "odoo_some_metric", + "documentation": "What this metric measures", + "labels": {"label_name": "label_value"}, + "value": 42, + } + + ``labels`` may be omitted for an unlabelled metric. All the entries + sharing a ``name`` must declare the same label names. + + Modules extending this method must return the result of ``super()`` + extended with their own entries. + """ + return [] + + @api.model + def _cron_gather_metrics(self): + Metric = self.sudo() + touched = Metric.browse() + for metric in Metric._gather_metrics(): + touched |= Metric._create_or_update_metric(metric) + # drop the series that disappeared since the last collection + (Metric.search([]) - touched).unlink() + return True + @api.model def _create_or_update_metric(self, metric): """Create or update the record matching ``metric``, return it.""" diff --git a/monitoring_prometheus_queue_job/models/__init__.py b/monitoring_prometheus_queue_job/models/__init__.py index 18bb3bc..726183e 100644 --- a/monitoring_prometheus_queue_job/models/__init__.py +++ b/monitoring_prometheus_queue_job/models/__init__.py @@ -1 +1 @@ -from . import prometheus_gatherer +from . import prometheus_metric diff --git a/monitoring_prometheus_queue_job/models/prometheus_gatherer.py b/monitoring_prometheus_queue_job/models/prometheus_metric.py similarity index 94% rename from monitoring_prometheus_queue_job/models/prometheus_gatherer.py rename to monitoring_prometheus_queue_job/models/prometheus_metric.py index be493f7..3353b9b 100644 --- a/monitoring_prometheus_queue_job/models/prometheus_gatherer.py +++ b/monitoring_prometheus_queue_job/models/prometheus_metric.py @@ -8,8 +8,8 @@ GAUGE_NAME = "odoo_queue_job_count" GAUGE_DOC = "Number of queue jobs per state and channel" -class PrometheusGatherer(models.AbstractModel): - _inherit = "prometheus.gatherer" +class PrometheusMetric(models.Model): + _inherit = "prometheus.metric" @api.model def _gather_metrics(self):