feat: redesign the service logs page (#11506)

* feat: redesign the service logs page

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: drop a stale jump after a cached host switch and remove unused max_lines

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: keep focus on url sync and expose host selection and new logs to assistive tech

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: reset the tail on dropdown host picks, resume refresh after search, key log cache by host

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix: clear the pending jump when a host switch needs no fetch

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Guilhem
2026-10-03 20:18:44 +02:00
committed by GitHub
co-authored by Claude Opus 5.5
parent d4a423f567
commit 0f65df24d2
3 changed files with 680 additions and 445 deletions
@@ -36,9 +36,10 @@
let html = highlightSnippet(untrack(() => content))
</script>
<button onclick={onClick} class="font-light !m-0 !p-0">
<pre
class="bg-surface-secondary hover:bg-surface px-2 py-1 text-secondary text-xs w-[100%] whitespace-pre border min-w-full text-start">
{@html html}
</pre>
</button>
<button
type="button"
onclick={onClick}
title="Show in context"
class="block w-full min-w-full px-3 py-0.5 text-left font-mono text-2xs text-primary whitespace-pre hover:bg-surface-hover focus-visible:bg-surface-hover focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-border-accent"
>{@html html}</button
>
File diff suppressed because it is too large Load Diff
@@ -1,72 +1,34 @@
<script lang="ts">
import { page } from '$app/state'
import { Alert } from '$lib/components/common'
import Popover from '$lib/components/Popover.svelte'
import ServiceLogsInner from '$lib/components/ServiceLogsInner.svelte'
import Tooltip from '$lib/components/Tooltip.svelte'
import { devopsRole } from '$lib/stores'
import { Search, AlertTriangle } from 'lucide-svelte'
let searchTerm = $state(page.url.searchParams.get('query') ?? '')
let queryParseErrors: string[] | undefined = $state(undefined)
// `query` is what the global search links with; `searchTerm` is what the page writes back.
let searchTerm = $state(
page.url.searchParams.get('searchTerm') ?? page.url.searchParams.get('query') ?? ''
)
</script>
<div class="flex flex-col w-full h-screen max-h-screen max-w-screen px-2">
<div class="px-2">
<div class="flex items-center space-x-2 flex-row justify-between">
<div class="flex flex-row flex-wrap justify-between py-2 my-4 px-4 gap-1 items-center">
<h1 class="!text-2xl font-semibold leading-6 tracking-tight">Service logs</h1>
<Tooltip>Explore and search Windmill service logs from within Windmill!</Tooltip>
</div>
</div>
{#snippet title()}
<div class="flex items-center gap-2">
<h1 class="text-2xl font-semibold text-emphasis whitespace-nowrap">Service logs</h1>
<Tooltip documentationLink="https://www.windmill.dev/docs/core_concepts/service_logs">
Logs written by the servers, workers and indexers of this instance, grouped by host.
</Tooltip>
</div>
{/snippet}
<div class="flex flex-col w-full min-w-0 h-screen max-h-screen px-4">
{#if $devopsRole == false}
<Alert title="Service logs are only available to superadmins" type="warning">
Service logs are only available to superadmins (or devops)
</Alert>
{:else}
<div class="m-1 px-2 flex flex-row gap-1 items-center border-2 rounded-lg">
<Search size="16" />
<!-- svelte-ignore a11y_autofocus -->
<input
id="quickSearchInput"
type="text"
class="quick-search-input !bg-surface"
bind:value={searchTerm}
autocomplete="off"
autofocus
/>
{#if searchTerm !== '' && queryParseErrors && queryParseErrors.length > 0}
<Popover notClickable placement="bottom-start">
<AlertTriangle size={16} class="text-yellow-500" />
{#snippet text()}
Some of your search terms have been ignored because one or more parse errors:<br /><br
/>
{#if queryParseErrors}
<ul>
{#each queryParseErrors as msg}
<li>- {msg}</li>
{/each}
</ul>
{/if}
{/snippet}
</Popover>
{/if}
<div class="flex flex-col gap-2 pt-4">
{@render title()}
<Alert title="Service logs are only available to superadmins and devops users" type="warning">
Ask one of them to look at the logs, or to grant you the devops role.
</Alert>
</div>
<ServiceLogsInner {searchTerm} bind:queryParseErrors />
{:else}
<ServiceLogsInner bind:searchTerm {title} />
{/if}
</div>
<style>
.quick-search-input {
outline: none;
border: none !important;
box-shadow: none !important;
}
.quick-search-input:focus-visible {
outline: none !important;
}
</style>