Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b2d8e4d03 | |||
| 7fb60a365e | |||
| fb3b607bd1 | |||
| dad7c24bff | |||
| 9e9d8a33e3 |
+47
-20
@@ -129,6 +129,21 @@ function generateTicketHash($data)
|
|||||||
|
|
||||||
if (stripos($title, 'SMART issues') !== false) {
|
if (stripos($title, 'SMART issues') !== false) {
|
||||||
$issueCategory = 'smart';
|
$issueCategory = 'smart';
|
||||||
|
} elseif (stripos($title, 'ZFS pool') !== false) {
|
||||||
|
$issueCategory = 'zfs';
|
||||||
|
// Extract pool name so each pool gets its own ticket
|
||||||
|
if (preg_match("/ZFS pool '([^']+)'/i", $title, $poolMatch)) {
|
||||||
|
$poolName = strtolower(preg_replace('/[^a-z0-9_]/i', '_', $poolMatch[1]));
|
||||||
|
if (stripos($title, 'state:') !== false || preg_match('/DEGRADED|FAULTED|UNAVAIL|OFFLINE/i', $title)) {
|
||||||
|
$issueSubtype = 'pool_state_' . $poolName;
|
||||||
|
} elseif (stripos($title, 'usage') !== false) {
|
||||||
|
$issueSubtype = 'pool_usage_' . $poolName;
|
||||||
|
} elseif (stripos($title, 'errors') !== false) {
|
||||||
|
$issueSubtype = 'pool_errors_' . $poolName;
|
||||||
|
} else {
|
||||||
|
$issueSubtype = 'pool_' . $poolName;
|
||||||
|
}
|
||||||
|
}
|
||||||
} elseif (stripos($title, 'LXC') !== false || stripos($title, 'storage usage') !== false) {
|
} elseif (stripos($title, 'LXC') !== false || stripos($title, 'storage usage') !== false) {
|
||||||
$issueCategory = 'storage';
|
$issueCategory = 'storage';
|
||||||
// Include the LXC container ID so each container gets its own ticket
|
// Include the LXC container ID so each container gets its own ticket
|
||||||
@@ -158,15 +173,24 @@ function generateTicketHash($data)
|
|||||||
$issueSubtype = 'clock_skew';
|
$issueSubtype = 'clock_skew';
|
||||||
} elseif (stripos($title, 'cluster usage') !== false) {
|
} elseif (stripos($title, 'cluster usage') !== false) {
|
||||||
$issueSubtype = 'usage';
|
$issueSubtype = 'usage';
|
||||||
} elseif (stripos($title, 'OSD down') !== false) {
|
} elseif (stripos($title, 'OSD down') !== false || preg_match('/osd\.\d+\s+is\s+DOWN/i', $title)) {
|
||||||
$issueSubtype = 'osd_down';
|
// 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) {
|
} elseif (stripos($title, 'HEALTH_ERR') !== false) {
|
||||||
$issueSubtype = 'health_err';
|
$issueSubtype = 'health_err';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include source type so automated tickets never collide with manual ones
|
||||||
|
$sourceType = stripos($title, '[auto]') !== false ? 'auto' : 'manual';
|
||||||
|
|
||||||
// Build stable components
|
// Build stable components
|
||||||
$stableComponents = [
|
$stableComponents = [
|
||||||
|
'source_type' => $sourceType,
|
||||||
'issue_category' => $issueCategory,
|
'issue_category' => $issueCategory,
|
||||||
'issue_subtype' => $issueSubtype,
|
'issue_subtype' => $issueSubtype,
|
||||||
'environment_tags' => array_values(array_filter(
|
'environment_tags' => array_values(array_filter(
|
||||||
@@ -218,8 +242,8 @@ if ($existing) {
|
|||||||
$newPriority = (int)$priority;
|
$newPriority = (int)$priority;
|
||||||
|
|
||||||
if ($existingStatus !== 'Closed') {
|
if ($existingStatus !== 'Closed') {
|
||||||
// Ticket is still active — update title and escalate priority if the new
|
// Ticket is still active — update title, escalate priority, and refresh
|
||||||
// report is more severe (lower number = higher severity).
|
// description with latest sensor data.
|
||||||
$changes = [];
|
$changes = [];
|
||||||
$updateSql = "UPDATE tickets SET updated_at = NOW(), updated_by = ?";
|
$updateSql = "UPDATE tickets SET updated_at = NOW(), updated_by = ?";
|
||||||
$bindTypes = "i";
|
$bindTypes = "i";
|
||||||
@@ -239,6 +263,14 @@ if ($existing) {
|
|||||||
$changes['priority'] = ['from' => $existingPriority, 'to' => $newPriority];
|
$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)) {
|
if (!empty($changes)) {
|
||||||
$updateSql .= " WHERE ticket_id = ?";
|
$updateSql .= " WHERE ticket_id = ?";
|
||||||
$bindTypes .= "s";
|
$bindTypes .= "s";
|
||||||
@@ -249,25 +281,20 @@ if ($existing) {
|
|||||||
$updStmt->execute();
|
$updStmt->execute();
|
||||||
$updStmt->close();
|
$updStmt->close();
|
||||||
|
|
||||||
// Comment summarising what changed
|
// Only post a comment on priority escalation — title and description updates
|
||||||
$changeLines = [];
|
// are silent (title changes like rising counters would spam a comment every run)
|
||||||
if (isset($changes['title'])) {
|
|
||||||
$changeLines[] = "- **Title updated** to reflect current issue";
|
|
||||||
}
|
|
||||||
if (isset($changes['priority'])) {
|
if (isset($changes['priority'])) {
|
||||||
$changeLines[] = "- **Priority escalated** from P{$changes['priority']['from']} to P{$changes['priority']['to']}";
|
$commentText = "**hwmonDaemon escalated this ticket from P{$changes['priority']['from']} to P{$changes['priority']['to']}.**\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();
|
||||||
}
|
}
|
||||||
$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(
|
$auditLog->log($userId, 'update', 'ticket', $existingId, array_merge(
|
||||||
$changes,
|
array_diff_key($changes, ['description_refreshed' => true]),
|
||||||
['reason' => 'auto-updated by hwmonDaemon (condition worsened)']
|
['reason' => 'auto-updated by hwmonDaemon (condition worsened)']
|
||||||
));
|
));
|
||||||
|
|
||||||
@@ -305,7 +332,7 @@ if ($existing) {
|
|||||||
$reopenStmt->close();
|
$reopenStmt->close();
|
||||||
|
|
||||||
$commentText = "**Issue recurred — ticket reopened automatically.**\n\n" .
|
$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(
|
$commentStmt = $conn->prepare(
|
||||||
"INSERT INTO ticket_comments (ticket_id, user_id, user_name, comment_text, markdown_enabled) VALUES (?, ?, 'hwmonDaemon', ?, 1)"
|
"INSERT INTO ticket_comments (ticket_id, user_id, user_name, comment_text, markdown_enabled) VALUES (?, ?, 'hwmonDaemon', ?, 1)"
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user