From b8a83ca6d72f6d9e624469120ca0077473916cf6 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 24 Nov 2025 17:39:57 +0530 Subject: [PATCH] feat: capture app name in monitor logs --- frappe/api/__init__.py | 14 ++++++++++- frappe/modules/utils.py | 14 +++++++++++ frappe/pulse/app_heartbeat_event.py | 39 +++-------------------------- 3 files changed, 31 insertions(+), 36 deletions(-) diff --git a/frappe/api/__init__.py b/frappe/api/__init__.py index db7f96da50..3c0906e039 100644 --- a/frappe/api/__init__.py +++ b/frappe/api/__init__.py @@ -9,6 +9,8 @@ from werkzeug.wrappers import Request, Response import frappe from frappe import _ +from frappe.modules.utils import get_doctype_app_map +from frappe.monitor import add_data_to_monitor from frappe.pulse.app_heartbeat_event import capture_app_heartbeat from frappe.utils.response import build_response @@ -67,7 +69,17 @@ def handle(request: Request): data = build_response("json") with suppress(Exception): - capture_app_heartbeat(arguments) + method = arguments.get("method") or frappe.form_dict.get("method") + doctype = arguments.get("doctype") or frappe.form_dict.get("doctype") + if method or doctype: + app_name = None + if doctype: + app_name = get_doctype_app_map().get(doctype) + elif method and "." in method: + app_name = method.split(".", 1)[0] + if app_name: + add_data_to_monitor(app=app_name) + capture_app_heartbeat(app_name) return data diff --git a/frappe/modules/utils.py b/frappe/modules/utils.py index 924b874be9..64aaeeddb5 100644 --- a/frappe/modules/utils.py +++ b/frappe/modules/utils.py @@ -14,6 +14,7 @@ from typing import TYPE_CHECKING, Union import frappe from frappe import _, get_module_path, scrub from frappe.utils import cint, cstr, now_datetime +from frappe.utils.caching import site_cache if TYPE_CHECKING: from types import ModuleType @@ -280,6 +281,19 @@ def get_module_app(module: str) -> str: return app +@site_cache +def get_doctype_app_map(): + DocType = frappe.qb.DocType("DocType") + Module = frappe.qb.DocType("Module Def") + return dict( + frappe.qb.from_(DocType) + .left_join(Module) + .on(DocType.module == Module.name) + .select(DocType.name, Module.app_name) + .run() + ) + + def get_app_publisher(module: str) -> str: app = get_module_app(module) if not app: diff --git a/frappe/pulse/app_heartbeat_event.py b/frappe/pulse/app_heartbeat_event.py index 9499ab85a1..e971a5b860 100644 --- a/frappe/pulse/app_heartbeat_event.py +++ b/frappe/pulse/app_heartbeat_event.py @@ -1,27 +1,20 @@ import frappe -from frappe.modules import get_doctype_module from frappe.pulse.utils import get_app_version, get_frappe_version -from frappe.utils.caching import site_cache from .client import capture, is_enabled -def capture_app_heartbeat(req_params): +def capture_app_heartbeat(app): if not should_capture(): return - method, doctype = get_method_and_doctype(req_params) - if not method and not doctype: - return - - app_name = get_app_name(method, doctype) - if app_name and app_name != "frappe": + if app and app != "frappe": capture( event_name="app_heartbeat", site=frappe.local.site, - app=app_name, + app=app, properties={ - "app_version": get_app_version(app_name), + "app_version": get_app_version(app), "frappe_version": get_frappe_version(), }, interval="6h", @@ -37,27 +30,3 @@ def should_capture(): return False return True - - -def get_method_and_doctype(req_params): - method = req_params.get("method") or frappe.form_dict.get("method") - doctype = req_params.get("doctype") or frappe.form_dict.get("doctype") - return method, doctype - - -def get_app_name(method, doctype): - app_name = None - if method and "." in method and not method.startswith("frappe."): - app_name = method.split(".", 1)[0] - - if not app_name and doctype: - module = get_doctype_module(doctype) - app_name = app_module_map().get(module) - - return app_name - - -@site_cache() -def app_module_map(): - defs = frappe.get_all("Module Def", fields=["name", "app_name"]) - return {d.name: d.app_name for d in defs}