Updated ticket aesthetics

This commit is contained in:
2025-03-03 22:20:21 -05:00
parent 43e4178703
commit ed753a0470
+126 -21
View File
@@ -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 = {