[REF] monitoring_prometheus: merge prometheus.gatherer into prometheus.metric

The abstract model held no state, it was only an extension point.
This commit is contained in:
David Gallay committed 2026-10-01 11:41:39 +02:00
1 parent 6f17f3c9e9
commit 93d934d676
7 files changed
+42 -55

No files matched your search

+2 -2
View File
@@ -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 remains public and reads the records with ``sudo()`` so Prometheus can keep scraping it
without authentication. without authentication.
To publish new metrics, extend ``_gather_metrics`` on the ``prometheus.gatherer`` To publish new metrics, extend ``_gather_metrics`` on the ``prometheus.metric``
abstract model and return the result of ``super()`` extended with your own entries:: model and return the result of ``super()`` extended with your own entries::
{ {
"name": "odoo_some_metric", "name": "odoo_some_metric",
+1 -1
View File
@@ -2,7 +2,7 @@
<odoo noupdate="1"> <odoo noupdate="1">
<record id="cron_prometheus_gather_metrics" model="ir.cron"> <record id="cron_prometheus_gather_metrics" model="ir.cron">
<field name="name">Prometheus: gather metrics</field> <field name="name">Prometheus: gather metrics</field>
<field name="model_id" ref="model_prometheus_gatherer" /> <field name="model_id" ref="model_prometheus_metric" />
<field name="state">code</field> <field name="state">code</field>
<field name="code">model._cron_gather_metrics()</field> <field name="code">model._cron_gather_metrics()</field>
<field name="interval_number">15</field> <field name="interval_number">15</field>
-1
View File
@@ -1,3 +1,2 @@
from . import ir_http from . import ir_http
from . import prometheus_gatherer
from . import prometheus_metric from . import prometheus_metric
@@ -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
@@ -9,7 +9,11 @@ from odoo import api, fields, models
class PrometheusMetric(models.Model): 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 A record is stored per metric name/labels combination, because a single
metric name can be reported several times with different labels (e.g. metric name can be reported several times with different labels (e.g.
@@ -57,6 +61,37 @@ class PrometheusMetric(models.Model):
self._check_upsert_context() self._check_upsert_context()
return super().write(vals) 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 @api.model
def _create_or_update_metric(self, metric): def _create_or_update_metric(self, metric):
"""Create or update the record matching ``metric``, return it.""" """Create or update the record matching ``metric``, return it."""
@@ -1 +1 @@
from . import prometheus_gatherer from . import prometheus_metric
@@ -8,8 +8,8 @@ GAUGE_NAME = "odoo_queue_job_count"
GAUGE_DOC = "Number of queue jobs per state and channel" GAUGE_DOC = "Number of queue jobs per state and channel"
class PrometheusGatherer(models.AbstractModel): class PrometheusMetric(models.Model):
_inherit = "prometheus.gatherer" _inherit = "prometheus.metric"
@api.model @api.model
def _gather_metrics(self): def _gather_metrics(self):
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.