Updated ticket aesthetics
This commit is contained in:
147
hwmonDaemon.py
147
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 = {
|
||||
|
||||
Reference in New Issue
Block a user