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 eefd5fa531..6081ab5f6c 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.json +++ b/frappe/desk/doctype/system_health_report/system_health_report.json @@ -41,7 +41,14 @@ "binary_logging", "cache_tab", "cache_keys", - "cache_memory_usage" + "cache_memory_usage", + "storage_tab", + "storage_usage_column", + "public_files_size", + "private_files_size", + "backups_column", + "onsite_backups", + "backups_size" ], "fields": [ { @@ -227,6 +234,41 @@ "fieldname": "cache_memory_usage", "fieldtype": "Data", "label": "Memory Usage" + }, + { + "fieldname": "storage_tab", + "fieldtype": "Tab Break", + "label": "Storage and Backups" + }, + { + "fieldname": "backups_size", + "fieldtype": "Float", + "label": "Backups (MB)" + }, + { + "fieldname": "private_files_size", + "fieldtype": "Float", + "label": "Private Files (MB)" + }, + { + "fieldname": "public_files_size", + "fieldtype": "Float", + "label": "Public Files (MB)" + }, + { + "fieldname": "storage_usage_column", + "fieldtype": "Column Break", + "label": "Storage Usage" + }, + { + "fieldname": "backups_column", + "fieldtype": "Column Break", + "label": "Backups" + }, + { + "fieldname": "onsite_backups", + "fieldtype": "Int", + "label": "Number of onsite backups" } ], "hide_toolbar": 1, @@ -234,7 +276,7 @@ "is_virtual": 1, "issingle": 1, "links": [], - "modified": "2024-04-18 19:58:14.550430", + "modified": "2024-04-18 20:15:04.989641", "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 5101542ea5..7bef050ebc 100644 --- a/frappe/desk/doctype/system_health_report/system_health_report.py +++ b/frappe/desk/doctype/system_health_report/system_health_report.py @@ -9,7 +9,8 @@ Metrics: - [x] Email queue flush and pull - [x] Error logs status - [x] Database - storage usage and top tables, version -- [ ] Storage - files usage +- [x] Cache +- [x] Storage - files usage - [ ] Backups - [ ] Log cleanup status - [ ] User - new users, sessions stats, failed login attempts @@ -20,6 +21,7 @@ Metrics: """ +import os from collections import defaultdict import frappe @@ -42,6 +44,7 @@ class SystemHealthReport(Document): from frappe.types import DF background_workers: DF.Table[SystemHealthWorkers] + backups_size: DF.Float binary_logging: DF.Data | None bufferpool_size: DF.Data | None cache_keys: DF.Int @@ -51,7 +54,10 @@ class SystemHealthReport(Document): db_storage_usage: DF.Float failed_emails: DF.Int handled_emails: DF.Int + onsite_backups: DF.Int pending_emails: DF.Int + private_files_size: DF.Float + public_files_size: DF.Float queue_status: DF.Table[SystemHealthQueue] scheduler_status: DF.Data | None socketio_ping_check: DF.Literal["Fail", "Pass"] @@ -74,6 +80,7 @@ class SystemHealthReport(Document): self.fetch_errors() self.fetch_database_details() self.fetch_cache_details() + self.fetch_storage_details() def fetch_background_workers(self): self.scheduler_status = get_scheduler_status().get("status") @@ -157,6 +164,29 @@ class SystemHealthReport(Document): self.cache_keys = len(frappe.cache.get_keys("")) self.cache_memory_usage = frappe.cache.execute_command("INFO", "MEMORY").get("used_memory_human") + @classmethod + def get_directory_size(cls, *path): + folder = os.path.abspath(frappe.get_site_path(*path)) + # Copied as is from agent + total_size = os.path.getsize(folder) + for item in os.listdir(folder): + itempath = os.path.join(folder, item) + + if not os.path.islink(itempath): + if os.path.isfile(itempath): + total_size += os.path.getsize(itempath) + elif os.path.isdir(itempath): + total_size += cls.get_directory_size(itempath) + return total_size / (1024 * 1024) + + def fetch_storage_details(self): + from frappe.desk.page.backups.backups import get_context + + self.backups_size = self.get_directory_size("private", "backups") + self.private_files_size = self.get_directory_size("private", "files") + self.public_files_size = self.get_directory_size("public", "files") + self.onsite_backups = len(get_context({}).get("files", [])) + def db_update(self): raise NotImplementedError diff --git a/frappe/desk/page/backups/backups.py b/frappe/desk/page/backups/backups.py index f3dd5f2975..6f0fface42 100644 --- a/frappe/desk/page/backups/backups.py +++ b/frappe/desk/page/backups/backups.py @@ -29,9 +29,6 @@ def get_context(context): files = [x for x in os.listdir(path) if os.path.isfile(os.path.join(path, x))] backup_limit = get_scheduled_backup_limit() - if len(files) > backup_limit: - cleanup_old_backups(path, files, backup_limit) - files = [ ( "/backups/" + _file,