diff --git a/resources/js/runtime-logs.js b/resources/js/runtime-logs.js index c5ff280f33..c067d8ac36 100644 --- a/resources/js/runtime-logs.js +++ b/resources/js/runtime-logs.js @@ -83,6 +83,23 @@ export function isFindShortcut(event) { return Boolean(event.ctrlKey || event.metaKey) && !event.altKey && !event.shiftKey && event.key?.toLowerCase() === 'f'; } +const DEFAULT_LOG_FILTERS = { error: true, warning: true, debug: true, info: true }; + +/** Read saved level filters. Invalid saved values fall back to the defaults. */ +export function readLogFilters(saved) { + const filters = { ...DEFAULT_LOG_FILTERS }; + let parsed; + try { + parsed = JSON.parse(saved); + } catch { + return filters; + } + for (const level of Object.keys(filters)) { + if (typeof parsed?.[level] === 'boolean') filters[level] = parsed[level]; + } + return filters; +} + export function filterLogLines(lines, filters, query) { const needle = query.trim().toLowerCase(); return lines.filter((line) => filters[line.level] !== false && (!needle || line.lower.includes(needle))); @@ -170,7 +187,7 @@ export function initializeRuntimeLogsComponent() { scrollDebounce: null, destroyed: false, colorLogs: localStorage.getItem('coolify-color-logs') === 'true', - logFilters: JSON.parse(localStorage.getItem('coolify-log-filters')) || { error: true, warning: true, debug: true, info: true }, + logFilters: readLogFilters(localStorage.getItem('coolify-log-filters')), searchQuery: '', appliedQuery: '', matchCount: 0, diff --git a/tests/v4/Browser/RuntimeLogsVirtualizationTest.php b/tests/v4/Browser/RuntimeLogsVirtualizationTest.php index 8b849859e2..97073a034b 100644 --- a/tests/v4/Browser/RuntimeLogsVirtualizationTest.php +++ b/tests/v4/Browser/RuntimeLogsVirtualizationTest.php @@ -124,3 +124,23 @@ it('streams only new lines and appends them to the loaded log', function () { $page->screenshot(filename: 'runtime-logs-virtualized-stream'); }); + +it('falls back to the default level filters when the saved filters are invalid', function () { + $page = visit('/login') + ->fill('email', 'test@example.com') + ->fill('password', 'password') + ->click('Login') + ->assertSee('Dashboard'); + + $page->script('localStorage.setItem("coolify-log-filters", "{")'); + $page->navigate("/server/{$this->stack['server']->uuid}/sentinel/logs") + ->assertSee('log line 00001'); + + // A valid saved preference is still applied. + $page->script('localStorage.setItem("coolify-log-filters", JSON.stringify({ info: false }))'); + $page->navigate("/server/{$this->stack['server']->uuid}/sentinel/logs") + ->wait(1) + ->assertDontSee('log line 00001'); + + $page->screenshot(filename: 'runtime-logs-invalid-saved-filters'); +});