From 266fb1d004e6c6f66c257cac3cf9b83ffbe3ee76 Mon Sep 17 00:00:00 2001 From: "Joseph.Rawlings" Date: Mon, 1 Dec 2025 14:17:43 -0500 Subject: [PATCH] feat: enhance firewall log loading in Proxmox component with improved response handling and error logging for better reliability and debugging --- .../Servers/Proxmox/Livewire/Firewall.php | 82 ++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/extensions/Servers/Proxmox/Livewire/Firewall.php b/extensions/Servers/Proxmox/Livewire/Firewall.php index 460c2723e..9aa16123a 100644 --- a/extensions/Servers/Proxmox/Livewire/Firewall.php +++ b/extensions/Servers/Proxmox/Livewire/Firewall.php @@ -766,16 +766,83 @@ class Firewall extends Component public function loadFirewallLogs(): void { try { + // Try the firewall log endpoint $response = $this->firewallRequest( '/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/firewall/log', 'get', ['limit' => $this->logLimit] ); - $rawLogs = $response->json()['data'] ?? []; + + // Check if response is successful + if (!$response->successful()) { + \Log::warning('Firewall log API returned non-success status', [ + 'status' => $response->status(), + 'body' => $response->body() + ]); + $this->firewallLogs = []; + return; + } + + $responseData = $response->json(); + + // Proxmox firewall log API can return data in different formats + // Try multiple possible response structures + $rawLogs = []; + + if (isset($responseData['data']) && is_array($responseData['data'])) { + $rawLogs = $responseData['data']; + } elseif (is_array($responseData) && !isset($responseData['data'])) { + // Response might be the array directly + $rawLogs = $responseData; + } + + // If still empty, try to get logs from the response body as text + if (empty($rawLogs)) { + $body = $response->body(); + if (!empty($body) && is_string($body)) { + // Try to parse as JSON first + $jsonData = json_decode($body, true); + if (json_last_error() === JSON_ERROR_NONE && is_array($jsonData)) { + $rawLogs = $jsonData['data'] ?? $jsonData; + } else { + // If not JSON, try to split by newlines (plain text format) + $lines = explode("\n", trim($body)); + $rawLogs = array_filter($lines, function($line) { + return !empty(trim($line)); + }); + } + } + } + + \Log::debug('Firewall logs raw response', [ + 'raw_logs_count' => count($rawLogs), + 'sample_entry' => !empty($rawLogs) ? (is_array($rawLogs[0]) ? $rawLogs[0] : substr($rawLogs[0], 0, 100)) : null + ]); $this->firewallLogs = []; + foreach ($rawLogs as $logEntry) { - $logText = $logEntry['n'] ?? $logEntry['t'] ?? ''; + $logText = null; + + // Try different possible field names for the log text + if (is_string($logEntry)) { + // If the entry is a string directly, use it + $logText = trim($logEntry); + } elseif (is_array($logEntry)) { + // Try common field names + $logText = $logEntry['n'] ?? $logEntry['t'] ?? $logEntry['text'] ?? $logEntry['log'] ?? $logEntry['message'] ?? $logEntry['line'] ?? ''; + + // If still empty, try to get the first string value + if (empty($logText)) { + foreach ($logEntry as $value) { + if (is_string($value) && !empty(trim($value))) { + $logText = trim($value); + break; + } + } + } + } + if (empty($logText)) { continue; } @@ -786,7 +853,18 @@ class Firewall extends Component $this->firewallLogs[] = $parsed; } } + + \Log::debug('Firewall logs parsed', [ + 'parsed_count' => count($this->firewallLogs) + ]); } catch (\Exception $e) { + // Log the error for debugging + \Log::error('Failed to load firewall logs: ' . $e->getMessage(), [ + 'server_id' => $this->server->id, + 'vm_id' => $this->server->vm_id, + 'node' => $this->server->node->name ?? 'unknown', + 'trace' => $e->getTraceAsString() + ]); $this->firewallLogs = []; } }