From 2df9e2ea5545c83d1ef64daf01ab72f7944447d3 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 18 Apr 2024 18:53:19 +0530 Subject: [PATCH] feat: email health checks --- .../system_health_report.js | 1 + .../system_health_report.json | 52 ++++++++++++++++++- .../system_health_report.py | 23 +++++++- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/frappe/desk/doctype/system_health_report/system_health_report.js b/frappe/desk/doctype/system_health_report/system_health_report.js index 7e73e125b4..ba09e99511 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.js +++ b/frappe/desk/doctype/system_health_report/system_health_report.js @@ -12,5 +12,6 @@ frappe.ui.form.on("System Health Report", { ); }); frappe.realtime.emit("ping"); + frm.disable_save(); }, }); diff --git a/frappe/desk/doctype/system_health_report/system_health_report.json b/frappe/desk/doctype/system_health_report/system_health_report.json index 47f60c1e71..65899b4c21 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.json +++ b/frappe/desk/doctype/system_health_report/system_health_report.json @@ -16,7 +16,15 @@ "realtime_tab", "socketio_ping_check", "column_break_hgay", - "socketio_transport_mode" + "socketio_transport_mode", + "emails_tab", + "outgoing_emails_column", + "total_outgoing_emails", + "pending_emails", + "failed_emails", + "incoming_emails_last_7_days_column", + "handled_emails", + "unhandled_emails" ], "fields": [ { @@ -84,6 +92,46 @@ "fieldtype": "Select", "label": "SocketIO Transport Mode", "options": "Polling\nWebsocket" + }, + { + "fieldname": "emails_tab", + "fieldtype": "Tab Break", + "label": "Emails" + }, + { + "fieldname": "outgoing_emails_column", + "fieldtype": "Column Break", + "label": "Outgoing Emails (Last 7 days)" + }, + { + "fieldname": "failed_emails", + "fieldtype": "Int", + "label": "Failed Emails" + }, + { + "fieldname": "total_outgoing_emails", + "fieldtype": "Int", + "label": "Total Outgoing Emails" + }, + { + "fieldname": "pending_emails", + "fieldtype": "Int", + "label": "Pending Emails" + }, + { + "fieldname": "incoming_emails_last_7_days_column", + "fieldtype": "Column Break", + "label": "Incoming Emails (Last 7 days)" + }, + { + "fieldname": "unhandled_emails", + "fieldtype": "Int", + "label": "Unhandled Emails" + }, + { + "fieldname": "handled_emails", + "fieldtype": "Int", + "label": "Handled Emails" } ], "hide_toolbar": 1, @@ -91,7 +139,7 @@ "is_virtual": 1, "issingle": 1, "links": [], - "modified": "2024-04-18 18:11:05.830332", + "modified": "2024-04-18 18:50:33.486009", "modified_by": "Administrator", "module": "Desk", "name": "System Health Report", diff --git a/frappe/desk/doctype/system_health_report/system_health_report.py b/frappe/desk/doctype/system_health_report/system_health_report.py index 51d8939caa..20b4a881f7 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.py +++ b/frappe/desk/doctype/system_health_report/system_health_report.py @@ -5,8 +5,8 @@ Basic system health check report to see how everything on site is functioning in Metrics: - [x] Background jobs, workers and scheduler summary, queue stats -- [ ] SocketIO works (using basic ping test) -- [ ] Email queue flush and pull +- [x] SocketIO works (using basic ping test) +- [x] Email queue flush and pull - [ ] Error logs status - [ ] Database - storage usage and top tables, version - [ ] Storage - files usage @@ -25,6 +25,7 @@ from collections import defaultdict import frappe from frappe.model.document import Document from frappe.utils.background_jobs import get_queue, get_queue_list +from frappe.utils.data import add_to_date from frappe.utils.scheduler import get_scheduler_status @@ -40,11 +41,16 @@ class SystemHealthReport(Document): from frappe.types import DF background_workers: DF.Table[SystemHealthWorkers] + failed_emails: DF.Int + handled_emails: DF.Int + pending_emails: DF.Int queue_status: DF.Table[SystemHealthQueue] scheduler_status: DF.Data | None socketio_ping_check: DF.Literal["Fail", "Pass"] socketio_transport_mode: DF.Literal["Polling", "Websocket"] total_background_workers: DF.Int + total_outgoing_emails: DF.Int + unhandled_emails: DF.Int # end: auto-generated types def db_insert(self, *args, **kwargs): @@ -53,6 +59,7 @@ class SystemHealthReport(Document): def load_from_db(self): super(Document, self).__init__({}) self.fetch_background_workers() + self.fetch_email_stats() def fetch_background_workers(self): self.scheduler_status = get_scheduler_status().get("status") @@ -84,6 +91,18 @@ class SystemHealthReport(Document): }, ) + def fetch_email_stats(self): + threshold = add_to_date(None, days=-1, as_datetime=True) + filters = {"creation": (">", threshold), "modified": (">", threshold)} + self.total_outgoing_emails = frappe.db.count("Email Queue", filters) + self.pending_emails = frappe.db.count("Email Queue", {"status": "Not Sent", **filters}) + self.failed_emails = frappe.db.count("Email Queue", {"status": "Error", **filters}) + self.unhandled_emails = frappe.db.count("Unhandled Email", filters) + self.handled_emails = frappe.db.count( + "Communication", + {"sent_or_received": "Received", "communication_type": "Communication", **filters}, + ) + def db_update(self): raise NotImplementedError