mirror of
https://github.com/camptocamp/odoo-cloud-platform.git
synced 2026-10-22 21:51:57 +00:00
fixup! [ADD] monitoring_prometheus_queue_job
This commit is contained in:
1 parent
33bfbfef57
commit
47add4311f
5 files changed
+29
-26
No files matched your search
@@ -20,11 +20,16 @@ Gathering metrics from the database
|
||||
-----------------------------------
|
||||
|
||||
Metrics that require a database query are collected by the *Prometheus: gather metrics*
|
||||
scheduled action, which runs every 15 minutes and stores its result as JSON in the
|
||||
``monitoring_prometheus.metrics`` system parameter. The */metrics* endpoint reads that
|
||||
parameter and publishes the entries as gauges. This indirection is required because the
|
||||
cron and the HTTP workers run in separate processes and cannot share the Prometheus
|
||||
registry.
|
||||
scheduled action, which runs every 15 minutes and stores its result as
|
||||
``prometheus.metric`` records (one per metric name/labels combination). The */metrics*
|
||||
endpoint reads those records and publishes them as gauges. This indirection is required
|
||||
because the cron and the HTTP workers run in separate processes and cannot share the
|
||||
Prometheus registry.
|
||||
|
||||
By default, only users in the *Administration / Settings* group (``base.group_system``)
|
||||
can read ``prometheus.metric`` records through the ORM/UI. The */metrics* endpoint
|
||||
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::
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"category": "category",
|
||||
"depends": ["base", "web", "server_environment"],
|
||||
"website": "https://github.com/camptocamp/odoo-cloud-platform",
|
||||
"data": ["data/ir_cron.xml"],
|
||||
"data": ["security/ir.model.access.csv", "data/ir_cron.xml"],
|
||||
"external_dependencies": {"python": ["prometheus_client"]},
|
||||
"installable": True,
|
||||
}
|
||||
@@ -8,8 +8,6 @@ from prometheus_client import Gauge, generate_latest
|
||||
|
||||
from odoo.http import Controller, request, route
|
||||
|
||||
from ..models.prometheus_gatherer import METRICS_PARAM
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
# Gauges must be instantiated only once per process, registering the same
|
||||
@@ -27,23 +25,23 @@ def _get_gauge(name, documentation, label_names):
|
||||
|
||||
class PrometheusController(Controller):
|
||||
def _publish_gathered_metrics(self):
|
||||
param = request.env["ir.config_parameter"].sudo().get_param(METRICS_PARAM)
|
||||
if not param:
|
||||
records = request.env["prometheus.metric"].sudo().search([])
|
||||
if not records:
|
||||
return
|
||||
|
||||
cleared = set()
|
||||
for metric in json.loads(param):
|
||||
name = metric["name"]
|
||||
labels = metric.get("labels") or {}
|
||||
gauge = _get_gauge(name, metric.get("documentation", ""), sorted(labels))
|
||||
for record in records:
|
||||
name = record.name
|
||||
labels = json.loads(record.labels or "{}")
|
||||
gauge = _get_gauge(name, record.documentation or "", sorted(labels))
|
||||
if name not in cleared:
|
||||
# drop the series that disappeared since the last collection
|
||||
gauge.clear()
|
||||
cleared.add(name)
|
||||
if labels:
|
||||
gauge.labels(**labels).set(metric["value"])
|
||||
gauge.labels(**labels).set(record.value)
|
||||
else:
|
||||
gauge.set(metric["value"])
|
||||
gauge.set(record.value)
|
||||
|
||||
@route("/metrics", auth="public")
|
||||
def metrics(self):
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
from . import ir_http
|
||||
from . import prometheus_metric
|
||||
from . import prometheus_gatherer
|
||||
@@ -1,19 +1,15 @@
|
||||
# Copyright 2016-2021 Camptocamp SA
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)
|
||||
|
||||
import json
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
METRICS_PARAM = "monitoring_prometheus.metrics"
|
||||
|
||||
|
||||
class PrometheusGatherer(models.AbstractModel):
|
||||
"""Collect application metrics to be exposed on the /metrics endpoint.
|
||||
|
||||
Metrics are gathered by a cron and stored as JSON in an
|
||||
``ir.config_parameter``, because crons and HTTP workers run in
|
||||
separate processes and cannot share the Prometheus registry.
|
||||
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"
|
||||
@@ -42,7 +38,10 @@ class PrometheusGatherer(models.AbstractModel):
|
||||
|
||||
@api.model
|
||||
def _cron_gather_metrics(self):
|
||||
self.env["ir.config_parameter"].sudo().set_param(
|
||||
METRICS_PARAM, json.dumps(self._gather_metrics())
|
||||
)
|
||||
Metric = self.env["prometheus.metric"].sudo()
|
||||
touched = self.env["prometheus.metric"]
|
||||
for metric in self._gather_metrics():
|
||||
touched |= Metric._update_metric(metric)
|
||||
# drop the series that disappeared since the last collection
|
||||
(Metric.search([]) - touched).unlink()
|
||||
return True
|
||||