feat: container logs viewer with SSE streaming and line limiter
- Add GET /api/projects/{id}/stages/{stage}/instances/{iid}/logs endpoint
- Supports JSON mode (returns array of lines) and SSE mode (streams in real-time)
- Docker log stream header (8-byte prefix) stripped automatically
- ContainerLogs component with:
- Tail line selector (50/200/500/1000)
- Follow button for real-time streaming via SSE
- Auto-scroll to bottom
- Dark terminal-style display
- Close button
- Logs button (events icon) on each instance card
- i18n keys in EN and RU
This commit is contained in:
@@ -5,8 +5,9 @@
|
||||
import type { Instance } from '$lib/types';
|
||||
import StatusBadge from './StatusBadge.svelte';
|
||||
import ContainerStats from './ContainerStats.svelte';
|
||||
import ContainerLogs from './ContainerLogs.svelte';
|
||||
import ConfirmDialog from './ConfirmDialog.svelte';
|
||||
import { IconPlay, IconStop, IconRestart, IconTrash, IconExternalLink } from '$lib/components/icons';
|
||||
import { IconPlay, IconStop, IconRestart, IconTrash, IconExternalLink, IconEvents } from '$lib/components/icons';
|
||||
import { t } from '$lib/i18n';
|
||||
import * as api from '$lib/api';
|
||||
|
||||
@@ -22,6 +23,7 @@
|
||||
let loading = $state(false);
|
||||
let error = $state('');
|
||||
let confirmAction = $state<'stop' | 'restart' | 'remove' | null>(null);
|
||||
let showLogs = $state(false);
|
||||
|
||||
const subdomainUrl = $derived(
|
||||
instance.subdomain && domain
|
||||
@@ -133,6 +135,14 @@
|
||||
<IconPlay size={16} />
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg p-2 text-[var(--text-tertiary)] hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-800 dark:hover:text-gray-300 transition-all duration-150"
|
||||
title={$t('logs.title')}
|
||||
onclick={() => { showLogs = !showLogs; }}
|
||||
>
|
||||
<IconEvents size={16} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-lg p-2 text-[var(--text-tertiary)] hover:bg-red-50 hover:text-red-600 disabled:opacity-50 transition-all duration-150 active:animate-press"
|
||||
@@ -149,6 +159,17 @@
|
||||
<ContainerStats projectId={projectId} stageId={instance.stage_id} instanceId={instance.id} />
|
||||
{/if}
|
||||
|
||||
{#if showLogs}
|
||||
<div class="mt-2">
|
||||
<ContainerLogs
|
||||
{projectId}
|
||||
stageId={instance.stage_id}
|
||||
instanceId={instance.id}
|
||||
onclose={() => { showLogs = false; }}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if error}
|
||||
<p class="mt-2 text-xs text-[var(--color-danger)]">{error}</p>
|
||||
{/if}
|
||||
|
||||
Reference in New Issue
Block a user