beUI Pro pour mobile est disponible : 50 blocs et écrans React Native
Log Explorer
1 variante
A compact execution log with severity filters, search, pause and resume, live following, and morphing payload details.
Execution logs
log-explorer.tsxInspect a live log stream with counted severity tabs, searchable entries, frozen pause snapshots, and copyable inline payloads.
Execution logs
event-pipeline · stagingTSXcomponents/previews/premium/log-explorer-preview.tsx
"use client";
import { RotateCcw } from "lucide-react";
import { useEffect, useState } from "react";
import { Button } from "@/components/motion/button";
import {
type LogEntry,
LogExplorer,
} from "@/components/premium/log-explorer/log-explorer";
import { MorphicTooltip } from "@/components/premium/morphic-tooltip";
const initialEntries: LogEntry[] = [
{
id: "log-1",
time: "09:18:10",
level: "info",
message: "Source connected",
context: "source=events",
payload: { source: "events", transport: "https", connected: true },
},
{
id: "log-2",
time: "09:18:11",
level: "info",
message: "Batch received",
context: "batch=bt_420 size=32",
payload: { batchId: "bt_420", records: 32, queue: "ingestion" },
},
{
id: "log-3",
time: "09:18:11",
level: "info",
message: "Schema validated",
context: "version=3 duration=42ms",
payload: {
schema: "workspace.event",
version: 3,
valid: true,
durationMs: 42,
},
},
{
id: "log-4",
time: "09:18:12",
level: "warn",
message: "Delivery delayed",
context: "destination=warehouse retry=1",
payload: {
destination: "warehouse",
attempt: 1,
retryAfterMs: 2000,
reason: "Temporary upstream delay",
},
},
{
id: "log-5",
time: "09:18:14",
level: "info",
message: "Delivery recovered",
context: "attempt=2 duration=184ms",
payload: {
batchId: "bt_420",
attempt: 2,
delivered: true,
durationMs: 184,
},
},
{
id: "log-6",
time: "09:18:15",
level: "info",
message: "Batch indexed",
context: "records=32 partition=2026-10",
payload: { records: 32, partition: "2026-10", index: "workspace-events" },
},
{
id: "log-7",
time: "09:18:16",
level: "error",
message: "Record rejected",
context: "record=ev_912 missing=workspaceId",
payload: {
recordId: "ev_912",
status: 422,
error: {
code: "MISSING_FIELD",
field: "workspaceId",
message: "A workspace ID is required.",
},
},
},
{
id: "log-8",
time: "09:18:17",
level: "info",
message: "Checkpoint saved",
context: "offset=14820",
payload: { offset: 14820, source: "events", persisted: true },
},
{
id: "log-9",
time: "09:18:18",
level: "warn",
message: "Buffer nearing capacity",
context: "used=76% limit=500",
payload: { used: 380, limit: 500, utilization: 0.76 },
},
{
id: "log-10",
time: "09:18:19",
level: "info",
message: "Buffer drained",
context: "remaining=24",
payload: { processed: 356, remaining: 24 },
},
{
id: "log-11",
time: "09:18:20",
level: "error",
message: "Destination unavailable",
context: "sink=archive status=503",
payload: {
destination: "archive",
status: 503,
requestId: "rq_742",
retryable: true,
},
},
{
id: "log-12",
time: "09:18:21",
level: "info",
message: "Health check passed",
context: "worker=ingest-02 latency=28ms",
payload: { worker: "ingest-02", healthy: true, latencyMs: 28 },
},
];
const incoming: Omit<LogEntry, "id" | "time">[] = [
{
level: "info",
message: "Batch received",
context: "queue=ingestion size=16",
payload: { queue: "ingestion", records: 16 },
},
{
level: "info",
message: "Transformation finished",
context: "duration=64ms",
payload: { stage: "normalize", durationMs: 64, transformed: 16 },
},
{
level: "warn",
message: "Slow destination response",
context: "sink=warehouse duration=840ms",
payload: { destination: "warehouse", durationMs: 840, thresholdMs: 500 },
},
{
level: "info",
message: "Checkpoint saved",
context: "source=events",
payload: { source: "events", persisted: true },
},
{
level: "error",
message: "Record rejected",
context: "reason=invalid timestamp",
payload: {
status: 422,
error: { field: "occurredAt", message: "Expected an ISO timestamp." },
},
},
{
level: "info",
message: "Health check passed",
context: "worker=ingest-02",
payload: { worker: "ingest-02", healthy: true },
},
];
function demoTime(index: number) {
const seconds = 21 + index * 2;
return `09:${String(18 + Math.floor(seconds / 60)).padStart(2, "0")}:${String(seconds % 60).padStart(2, "0")}`;
}
export function LogExplorerPreview() {
const [entries, setEntries] = useState(initialEntries);
const [paused, setPaused] = useState(false);
const [version, setVersion] = useState(0);
useEffect(() => {
let next = 0;
const timer = setInterval(() => {
const index = next++;
const entry: LogEntry = {
...incoming[index % incoming.length],
id: `stream-${version}-${index}`,
time: demoTime(index + 1),
};
setEntries((current) => [...current.slice(-79), entry]);
}, 2000);
return () => clearInterval(timer);
}, [version]);
return (
<div className="flex w-full justify-center p-3 sm:p-6">
<LogExplorer
entries={entries}
service="event-pipeline"
environment="staging"
paused={paused}
onPausedChange={setPaused}
headerActions={
<MorphicTooltip content="Reset demo">
<Button
tabIndex={0}
variant="ghost"
size="icon"
aria-label="Reset demo"
className="size-9 rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
onClick={() => {
setEntries(initialEntries);
setPaused(false);
setVersion((current) => current + 1);
}}
>
<RotateCcw aria-hidden className="size-3.5" />
</Button>
</MorphicTooltip>
}
/>
</div>
);
}
Le code source est verrouillé
Obtenez un accès pour installer les composants premium et voir tout le code source.
Ouvrir le tableau de bordInstallation
$ bunx --bun shadcn add @beui-pro/log-explorer