From dad7c24bff876964d6ac85c3feeb6d863328185b Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Thu, 16 Apr 2026 08:09:12 -0400 Subject: [PATCH] Fix hwmonDaemon hash collisions and automated comment formatting - source_type (auto vs manual) added to dedup hash so automated tickets never collide with manually created ones - OSD-specific subtype (osd_down_N) so each OSD gets its own ticket - Description refreshed on every automated update (current sensor data) - Comments on worsening condition only fire on meaningful changes - ASCII art descriptions wrapped in fenced code blocks in comments - Reopen comment also uses fenced code block Co-Authored-By: Claude Sonnet 4.6 --- create_ticket_api.php | 64 +++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/create_ticket_api.php b/create_ticket_api.php index f6e3c48..05a4038 100644 --- a/create_ticket_api.php +++ b/create_ticket_api.php @@ -152,15 +152,24 @@ function generateTicketHash($data) { $issueSubtype = 'clock_skew'; } elseif (stripos($title, 'cluster usage') !== false) { $issueSubtype = 'usage'; - } elseif (stripos($title, 'OSD down') !== false) { - $issueSubtype = 'osd_down'; + } elseif (stripos($title, 'OSD down') !== false || preg_match('/osd\.\d+\s+is\s+DOWN/i', $title)) { + // Include the specific OSD ID so each individual OSD gets its own ticket + if (preg_match('/osd\.(\d+)/i', $title, $osdMatch)) { + $issueSubtype = 'osd_down_' . $osdMatch[1]; + } else { + $issueSubtype = 'osd_down'; + } } elseif (stripos($title, 'HEALTH_ERR') !== false) { $issueSubtype = 'health_err'; } } + // Include source type so automated tickets never collide with manual ones + $sourceType = stripos($title, '[auto]') !== false ? 'auto' : 'manual'; + // Build stable components $stableComponents = [ + 'source_type' => $sourceType, 'issue_category' => $issueCategory, 'issue_subtype' => $issueSubtype, 'environment_tags' => array_values(array_filter( @@ -212,8 +221,8 @@ if ($existing) { $newPriority = (int)$priority; if ($existingStatus !== 'Closed') { - // Ticket is still active — update title and escalate priority if the new - // report is more severe (lower number = higher severity). + // Ticket is still active — update title, escalate priority, and refresh + // description with latest sensor data. $changes = []; $updateSql = "UPDATE tickets SET updated_at = NOW(), updated_by = ?"; $bindTypes = "i"; @@ -233,6 +242,14 @@ if ($existing) { $changes['priority'] = ['from' => $existingPriority, 'to' => $newPriority]; } + // Always refresh the description so the ticket body shows current sensor data + if (!empty($description)) { + $updateSql .= ", description = ?"; + $bindTypes .= "s"; + $bindVals[] = $description; + $changes['description_refreshed'] = true; + } + if (!empty($changes)) { $updateSql .= " WHERE ticket_id = ?"; $bindTypes .= "s"; @@ -243,25 +260,30 @@ if ($existing) { $updStmt->execute(); $updStmt->close(); - // Comment summarising what changed - $changeLines = []; - if (isset($changes['title'])) { - $changeLines[] = "- **Title updated** to reflect current issue"; + // Only add a comment when something meaningful changed (not just a description refresh) + $meaningfulChanges = array_diff_key($changes, ['description_refreshed' => true]); + if (!empty($meaningfulChanges)) { + $changeLines = []; + if (isset($changes['title'])) { + $changeLines[] = "- **Title updated** to reflect current issue"; + } + if (isset($changes['priority'])) { + $changeLines[] = "- **Priority escalated** from P{$changes['priority']['from']} to P{$changes['priority']['to']}"; + } + // Wrap description in a fenced code block so ASCII art / box-drawing + // characters render correctly instead of collapsing into a paragraph blob + $commentText = "**hwmonDaemon reported a worsened condition — ticket updated automatically.**\n\n" . + implode("\n", $changeLines) . "\n\nLatest report:\n\n```\n" . $description . "\n```"; + $commentStmt = $conn->prepare( + "INSERT INTO ticket_comments (ticket_id, user_id, user_name, comment_text, markdown_enabled) VALUES (?, ?, 'hwmonDaemon', ?, 1)" + ); + $commentStmt->bind_param("sis", $existingId, $userId, $commentText); + $commentStmt->execute(); + $commentStmt->close(); } - if (isset($changes['priority'])) { - $changeLines[] = "- **Priority escalated** from P{$changes['priority']['from']} to P{$changes['priority']['to']}"; - } - $commentText = "**hwmonDaemon reported a worsened condition — ticket updated automatically.**\n\n" . - implode("\n", $changeLines) . "\n\nLatest report:\n\n" . $description; - $commentStmt = $conn->prepare( - "INSERT INTO ticket_comments (ticket_id, user_id, user_name, comment_text, markdown_enabled) VALUES (?, ?, 'hwmonDaemon', ?, 1)" - ); - $commentStmt->bind_param("sis", $existingId, $userId, $commentText); - $commentStmt->execute(); - $commentStmt->close(); $auditLog->log($userId, 'update', 'ticket', $existingId, array_merge( - $changes, + array_diff_key($changes, ['description_refreshed' => true]), ['reason' => 'auto-updated by hwmonDaemon (condition worsened)'] )); @@ -299,7 +321,7 @@ if ($existing) { $reopenStmt->close(); $commentText = "**Issue recurred — ticket reopened automatically.**\n\n" . - "New report received from hwmonDaemon:\n\n" . $description; + "New report received from hwmonDaemon:\n\n```\n" . $description . "\n```"; $commentStmt = $conn->prepare( "INSERT INTO ticket_comments (ticket_id, user_id, user_name, comment_text, markdown_enabled) VALUES (?, ?, 'hwmonDaemon', ?, 1)" );