From 5b70060d73012a9d89271ecf9e651a34be839ee0 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Thu, 18 Apr 2024 20:27:10 +0530 Subject: [PATCH] feat: system health - users --- .../system_health_report.json | 72 ++++++++++++++++--- .../system_health_report.py | 50 ++++++++++--- .../test_system_health_report.py | 5 +- 3 files changed, 104 insertions(+), 23 deletions(-) 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 6081ab5f6c1..17a38ee53b4 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.json +++ b/frappe/desk/doctype/system_health_report/system_health_report.json @@ -14,10 +14,10 @@ "queue_status", "column_break_wjoz", "background_workers", - "realtime_tab", - "socketio_ping_check", - "column_break_hgay", - "socketio_transport_mode", + "errors_tab", + "errors_generated_in_last_1_day_section", + "total_errors", + "top_errors", "emails_tab", "outgoing_emails_column", "total_outgoing_emails", @@ -26,10 +26,6 @@ "incoming_emails_last_7_days_column", "handled_emails", "unhandled_emails", - "errors_tab", - "errors_generated_in_last_1_day_section", - "total_errors", - "top_errors", "database_tab", "database", "database_version", @@ -48,7 +44,20 @@ "private_files_size", "backups_column", "onsite_backups", - "backups_size" + "backups_size", + "users_tab", + "total_users", + "column_break_yfwd", + "new_users", + "security_and_sessions_section", + "failed_logins", + "column_break_ybhh", + "active_sessions", + "last_10_active_users", + "realtime_tab", + "socketio_ping_check", + "column_break_hgay", + "socketio_transport_mode" ], "fields": [ { @@ -269,6 +278,49 @@ "fieldname": "onsite_backups", "fieldtype": "Int", "label": "Number of onsite backups" + }, + { + "fieldname": "users_tab", + "fieldtype": "Tab Break", + "label": "Users" + }, + { + "fieldname": "total_users", + "fieldtype": "Int", + "label": "Total Users" + }, + { + "fieldname": "column_break_yfwd", + "fieldtype": "Column Break" + }, + { + "fieldname": "new_users", + "fieldtype": "Int", + "label": "New Users (Last 30 days)" + }, + { + "fieldname": "security_and_sessions_section", + "fieldtype": "Section Break", + "label": "Security and Sessions" + }, + { + "fieldname": "failed_logins", + "fieldtype": "Int", + "label": "Failed Logins (Last 30 days)" + }, + { + "fieldname": "active_sessions", + "fieldtype": "Int", + "label": "Active Sessions" + }, + { + "fieldname": "column_break_ybhh", + "fieldtype": "Column Break" + }, + { + "fieldname": "last_10_active_users", + "fieldtype": "Code", + "label": "Last 10 active users" } ], "hide_toolbar": 1, @@ -276,7 +328,7 @@ "is_virtual": 1, "issingle": 1, "links": [], - "modified": "2024-04-18 20:15:04.989641", + "modified": "2024-04-18 20:41:48.420334", "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 7bef050ebc4..eba14bfa6a3 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.py +++ b/frappe/desk/doctype/system_health_report/system_health_report.py @@ -4,17 +4,15 @@ Basic system health check report to see how everything on site is functioning in one single page. Metrics: -- [x] Background jobs, workers and scheduler summary, queue stats -- [x] SocketIO works (using basic ping test) -- [x] Email queue flush and pull -- [x] Error logs status -- [x] Database - storage usage and top tables, version -- [x] Cache -- [x] Storage - files usage -- [ ] Backups -- [ ] Log cleanup status -- [ ] User - new users, sessions stats, failed login attempts -- [ ] Updates / Security updates ? +- Background jobs, workers and scheduler summary, queue stats +- SocketIO works (using basic ping test) +- Email queue flush and pull +- Error logs status +- Database - storage usage and top tables, version +- Cache +- Storage - files usage +- Backups +- User - new users, sessions stats, failed login attempts @@ -43,6 +41,7 @@ class SystemHealthReport(Document): from frappe.desk.doctype.system_health_workers.system_health_workers import SystemHealthWorkers from frappe.types import DF + active_sessions: DF.Int background_workers: DF.Table[SystemHealthWorkers] backups_size: DF.Float binary_logging: DF.Data | None @@ -53,7 +52,10 @@ class SystemHealthReport(Document): database_version: DF.Data | None db_storage_usage: DF.Float failed_emails: DF.Int + failed_logins: DF.Int handled_emails: DF.Int + last_10_active_users: DF.Code | None + new_users: DF.Int onsite_backups: DF.Int pending_emails: DF.Int private_files_size: DF.Float @@ -67,6 +69,7 @@ class SystemHealthReport(Document): total_background_workers: DF.Int total_errors: DF.Int total_outgoing_emails: DF.Int + total_users: DF.Int unhandled_emails: DF.Int # end: auto-generated types @@ -81,6 +84,7 @@ def load_from_db(self): self.fetch_database_details() self.fetch_cache_details() self.fetch_storage_details() + self.fetch_user_stats() def fetch_background_workers(self): self.scheduler_status = get_scheduler_status().get("status") @@ -187,6 +191,30 @@ def fetch_storage_details(self): self.public_files_size = self.get_directory_size("public", "files") self.onsite_backups = len(get_context({}).get("files", [])) + def fetch_user_stats(self): + threshold = add_to_date(None, days=-30, as_datetime=True) + self.total_users = frappe.db.count("User", {"enabled": 1}) + self.new_users = frappe.db.count("User", {"enabled": 1, "creation": (">", threshold)}) + self.failed_logins = frappe.db.count( + "Activity Log", + { + "operation": "login", + "status": "Failed", + "creation": (">", threshold), + "modified": (">", threshold), + }, + ) + self.active_sessions = frappe.db.count("Sessions") + self.last_10_active_users = "\n".join( + frappe.get_all( + "User", + {"enabled": 1}, + order_by="last_active desc", + limit=10, + pluck="name", + ) + ) + def db_update(self): raise NotImplementedError diff --git a/frappe/desk/doctype/system_health_report/test_system_health_report.py b/frappe/desk/doctype/system_health_report/test_system_health_report.py index f1c2f57fdfe..34d930db31b 100644 --- a/frappe/desk/doctype/system_health_report/test_system_health_report.py +++ b/frappe/desk/doctype/system_health_report/test_system_health_report.py @@ -1,9 +1,10 @@ # Copyright (c) 2024, Frappe Technologies and Contributors # See license.txt -# import frappe +import frappe from frappe.tests.utils import FrappeTestCase class TestSystemHealthReport(FrappeTestCase): - pass + def test_it_works(self): + frappe.get_doc("System Health Report")