From ed753a047064a72466a4c95d3d7838b978cbb228 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Mon, 3 Mar 2025 22:20:21 -0500 Subject: [PATCH] Updated ticket aesthetics --- hwmonDaemon.py | 147 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 126 insertions(+), 21 deletions(-) diff --git a/hwmonDaemon.py b/hwmonDaemon.py index 1c4944e..5f00740 100644 --- a/hwmonDaemon.py +++ b/hwmonDaemon.py @@ -187,20 +187,29 @@ class SystemHealthMonitor: return drive_details def _generate_detailed_description(self, issue: str, health_report: Dict[str, Any]) -> str: - # Keep existing banner and initial description - banner = """ - ================================================================= - AUTOMATED TICKET - Generated by Hardware Monitoring Service (hwmonDaemon) - Host: {} - Generated: {} - ================================================================= - - """.format(socket.gethostname(), datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) - - description = banner + issue + "\n\n" + hostname = socket.gethostname() + timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + priority = "⚠ HIGH" if "CRITICAL" in issue else "● MEDIUM" - # Add issue explanation section - description += "=== Issue Details ===\n" + # Calculate maximum width based on content + content_width = max( + len(hostname), + len(timestamp), + len(priority), + len("HARDWARE MONITORING ALERT TICKET") + ) + 10 # Add padding + + banner = f""" + ┏{'━' * content_width}┓ + ┃{' HARDWARE MONITORING ALERT TICKET '.center(content_width)}┃ + ┣{'━' * content_width}┫ + ┃ Host : {hostname:<{content_width-13}}┃ + ┃ Generated : {timestamp:<{content_width-13}}┃ + ┃ Priority : {priority:<{content_width-13}}┃ + ┗{'━' * content_width}┛ + """ + + description = banner + "\n" + "┏━ ISSUE SUMMARY " + "━" * 50 + "\n" + issue + "\n\n" # Add SMART attribute explanations SMART_DESCRIPTIONS = { @@ -388,13 +397,109 @@ class SystemHealthMonitor: if "Drive" in issue: device = re.search(r'/dev/[a-zA-Z0-9]+', issue).group(0) drive_details = self._get_drive_details(device) - description += "\n=== Drive Details ===\n" - description += f"Device: {device}\n" - description += f"Model: {drive_details['model']}\n" - description += f"Serial Number: {drive_details['serial']}\n" - description += f"Capacity: {drive_details['capacity']}\n" - description += f"Firmware: {drive_details['firmware']}\n" - description += f"Type: {drive_details['type']}\n" + drive_info = next((d for d in health_report['drives_health']['drives'] if d['device'] == device), None) + + description += """ + ┏━ DRIVE SPECIFICATIONS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃ Device Path │ {:<60} ┃ + ┃ Model │ {:<60} ┃ + ┃ Serial │ {:<60} ┃ + ┃ Capacity │ {:<60} ┃ + ┃ Type │ {:<60} ┃ + ┃ Firmware │ {:<60} ┃ + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + """.format( + device, + drive_details['model'], + drive_details['serial'], + drive_details['capacity'], + drive_details['type'], + drive_details['firmware'] + ) + + if drive_info: + perf_metrics = { + 'read_speed': drive_info.get('performance_metrics', {}).get('read_speed', 'N/A'), + 'write_speed': drive_info.get('performance_metrics', {}).get('write_speed', 'N/A'), + 'access_time': drive_info.get('performance_metrics', {}).get('access_time', 'N/A'), + 'iops': drive_info.get('performance_metrics', {}).get('iops', 'N/A') + } + + description += f""" + ┏━ PERFORMANCE METRICS ━{'━' * 48}┓ + ┃ Read Speed │ {perf_metrics['read_speed']} MB/s {' ' * 45}┃ + ┃ Write Speed │ {perf_metrics['write_speed']} MB/s {' ' * 45}┃ + ┃ Access Time │ {perf_metrics['access_time']} ms {' ' * 47}┃ + ┃ IOPS │ {perf_metrics['iops']}{' ' * 52}┃ + ┗{'━' * 71}┛ + """ + power_on_hours = smart_health['attributes'].get('Power_On_Hours', 'N/A') + last_test_date = smart_health.get('last_test_date', 'N/A') + age = f"{int(power_on_hours/24/365) if isinstance(power_on_hours, (int, float)) else 'N/A'} years" if power_on_hours != 'N/A' else 'N/A' + + description += """ + ┏━ DRIVE TIMELINE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃ Power-On Hours │ {:<56} ┃ + ┃ Last SMART Test │ {:<56} ┃ + ┃ Drive Age │ {:<56} ┃ + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + """.format( + f"{power_on_hours} hours" if power_on_hours != 'N/A' else 'N/A', + last_test_date, + age + ) + + for drive in health_report.get('drives_health', {}).get('drives', []): + if drive['device'] == device: + description += """ + ┏━ SMART STATUS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ + ┃ Status │ {:<60} ┃ + ┃ Temperature │ {:<60} ┃ + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + """.format( + drive['smart_status'], + f"{drive.get('temperature')}°C" if drive.get('temperature') else 'N/A' + ) + + if drive.get('smart_attributes'): + description += "\n┏━ SMART ATTRIBUTES " + "━" * 48 + "┓\n" + for attr, value in drive['smart_attributes'].items(): + description += "┃ {:<25} │ {:<37} ┃\n".format( + attr.replace('_', ' '), value + ) + description += "┗" + "━" * 71 + "┛\n" + + if drive.get('partitions'): + for partition in drive['partitions']: + usage_percent = partition['usage_percent'] + blocks = int(usage_percent / 5) # 20 blocks total = 100% + usage_meter = '█' * blocks + '░' * (20 - blocks) + + description += """ + ┏━ PARTITION [{:<60}] ━┓ + ┃ Filesystem │ {:<60} ┃ + ┃ Usage Meter │ [{:<58}] ┃ + ┃ Total Space │ {:<60} ┃ + ┃ Used Space │ {:<60} ┃ + ┃ Free Space │ {:<60} ┃ + ┃ Usage │ {:<60} ┃ + ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ + """.format( + partition['mountpoint'], + partition['fstype'], + usage_meter, + partition['total_space'], + partition['used_space'], + partition['free_space'], + f"{usage_percent}%" + ) + + firmware_info = self._check_disk_firmware(device) + if firmware_info['is_problematic']: + description += "\n┏━ FIRMWARE ALERTS " + "━" * 48 + "┓\n" + for issue in firmware_info['known_issues']: + description += "┃ ⚠ {:<67} ┃\n".format(issue) + description += "┗" + "━" * 71 + "┛\n" if "Temperature" in issue: description += """ @@ -469,7 +574,7 @@ class SystemHealthMonitor: if drive_details['capacity']: drive_size = f"[{drive_details['capacity']}] " - ticket_title = f"[{hostname}]{action_type}{hardware_type} {issue} {scope}{environment}{ticket_type}" + ticket_title = f"[{hostname}] {action_type} {hardware_type} {drive_size}{issue} {scope} {environment} {ticket_type}" description = self._generate_detailed_description(issue, health_report) ticket_payload = {