From 00b26621a293f993a2c4e7d5887ce9739bc92766 Mon Sep 17 00:00:00 2001 From: Vincent Renaville Date: Thu, 20 Feb 2025 14:30:32 +0100 Subject: [PATCH] feat: add memory monitoring for prometheus (#479) --- .pre-commit-config.yaml | 24 ++++++------ .../controllers/prometheus_metrics.py | 3 ++ monitoring_prometheus/models/__init__.py | 1 + .../models/psutils_helpers.py | 39 +++++++++++++++++++ 4 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 monitoring_prometheus/models/psutils_helpers.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 970386f..8da5029 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ exclude: | (LICENSE.*|COPYING.*) default_language_version: python: python3 - node: "14.18.0" + node: "16.17.0" repos: - repo: local hooks: @@ -34,14 +34,14 @@ repos: language: fail files: '[a-zA-Z0-9_]*/i18n/en\.po$' - repo: https://github.com/oca/maintainer-tools - rev: dfba427ba03900b69e0a7f2c65890dc48921d36a + rev: 4cd2b852214dead80822e93e6749b16f2785b2fe hooks: # update the NOT INSTALLABLE ADDONS section above - id: oca-update-pre-commit-excluded-addons - id: oca-fix-manifest-website args: ["https://github.com/camptocamp/odoo-cloud-platform"] - repo: https://github.com/myint/autoflake - rev: v1.4 + rev: v1.6.1 hooks: - id: autoflake args: @@ -52,22 +52,22 @@ repos: - --remove-duplicate-keys - --remove-unused-variables - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 22.8.0 hooks: - id: black - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.4.1 + rev: v2.7.1 hooks: - id: prettier name: prettier (with plugin-xml) additional_dependencies: - - "prettier@2.4.1" - - "@prettier/plugin-xml@1.1.0" + - "prettier@2.7.1" + - "@prettier/plugin-xml@2.2.0" args: - --plugin=@prettier/plugin-xml files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ - repo: https://github.com/pre-commit/mirrors-eslint - rev: v7.32.0 + rev: v8.24.0 hooks: - id: eslint verbose: true @@ -75,7 +75,7 @@ repos: - --color - --fix - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + rev: v4.3.0 hooks: - id: trailing-whitespace # exclude autogenerated files @@ -97,7 +97,7 @@ repos: - id: mixed-line-ending args: ["--fix=lf"] - repo: https://github.com/asottile/pyupgrade - rev: v2.29.0 + rev: v2.38.2 hooks: - id: pyupgrade args: ["--keep-percent-format"] @@ -114,13 +114,13 @@ repos: hooks: - id: setuptools-odoo-make-default - repo: https://github.com/PyCQA/flake8 - rev: 3.9.2 + rev: 5.0.4 hooks: - id: flake8 name: flake8 additional_dependencies: ["flake8-bugbear==21.9.2"] - repo: https://github.com/OCA/pylint-odoo - rev: 7.0.2 + rev: v8.0.19 hooks: - id: pylint_odoo name: pylint with optional checks diff --git a/monitoring_prometheus/controllers/prometheus_metrics.py b/monitoring_prometheus/controllers/prometheus_metrics.py index 4aa4996..e3e4cdb 100644 --- a/monitoring_prometheus/controllers/prometheus_metrics.py +++ b/monitoring_prometheus/controllers/prometheus_metrics.py @@ -5,8 +5,11 @@ from prometheus_client import generate_latest from odoo.http import Controller, route +from ..models.psutils_helpers import get_process_info + class PrometheusController(Controller): @route("/metrics", auth="public") def metrics(self): + get_process_info() return generate_latest() diff --git a/monitoring_prometheus/models/__init__.py b/monitoring_prometheus/models/__init__.py index 9a5eb71..15f6add 100644 --- a/monitoring_prometheus/models/__init__.py +++ b/monitoring_prometheus/models/__init__.py @@ -1 +1,2 @@ from . import ir_http +from . import psutils_helpers diff --git a/monitoring_prometheus/models/psutils_helpers.py b/monitoring_prometheus/models/psutils_helpers.py new file mode 100644 index 0000000..5b14e33 --- /dev/null +++ b/monitoring_prometheus/models/psutils_helpers.py @@ -0,0 +1,39 @@ +import psutil +from prometheus_client import Gauge + +MEMORY_USAGE_VMS = Gauge( + "odoo_worker_memory_user_vms_mb", "Memory usage in MB", ["process", "pid"] +) + +MEMORY_USAGE_RSS = Gauge( + "odoo_worker_memory_user_rss_mb", "Memory usage in MB", ["process", "pid"] +) + + +def get_process_info(): + for process in psutil.process_iter( + ["pid", "name", "memory_full_info", "cmdline", "nice"] + ): + try: + if process.info["memory_full_info"]: + if process.info["nice"] == 10: + ProcessLabel = "workercron" + elif process.info["pid"] == 1: + ProcessLabel = "dispatcher" + elif any("gevent" in x for x in process.info["cmdline"]): + ProcessLabel = "gevent" + elif any("odoo" in x for x in process.info["cmdline"]): + ProcessLabel = "workerhttp" + elif any("shell" in x for x in process.cmdline()): + ProcessLabel = "OdooShell" + else: + ProcessLabel = "other" + MEMORY_USAGE_VMS.labels(ProcessLabel, process.info["pid"]).set( + process.info["memory_full_info"].rss // 1000000 + ) + MEMORY_USAGE_RSS.labels(ProcessLabel, process.info["pid"]).set( + process.info["memory_full_info"].vms // 1000000 + ) + + except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + continue