Log viewer
Shows a run's or an eval's output line by line as it streams, with levels, search and follow.
Examples
Log for run_01J9ZKQX8M2V4E7Q9 lines1 failed
1 failed line
Log for run_01J9ZKQX8M2V4E7Q3 linesStreaming
Chrome
- Full5 lines
fulldefault
bare
States
- Empty0 lines
empty
- Waiting0 linesStreaming
waiting
- Streaming3 linesStreaming
streaming
- Failed4 lines1 failed1 failed line
failed
Usage
When to use it
- Use
- A run, deploy or eval writes lines the person reads while it works or after it fails.
- Use
- A log can reach thousands of lines and needs filtering by level and text.
- Not for
- The output is one block of code or a command. Use Code block.
- Not for
- The output is structured data. Use JSON view.
- Not for
- The steps are a handful with durations. Use Timeline.
Rules
8 rules
- Must
- Give every line a stable id that never changes or repeats; do not use the array index when lines are removed or reordered. Because rows are windowed and measured by id, so a reused id shows the wrong height and the wrong text after a filter.
- Must
- Set level to debug, info, warn or fail; leave it out for info. Because only warn and fail take color, through the row wash and the level word, and the level cells count by these four.
- Must
- Pass streaming while lines still arrive and drop it when the run ends. Because it shows "Streaming" with a running arc and says "Waiting for the first line" instead of "No output" while empty.
- Must
- Pass label as a noun phrase that names the log: "Deploy log for api@v314". Because it is the header title and the accessible name of the log region, and the default "Logs" cannot tell two logs apart.
- Should
- Set a fixed height that fits its place; the log scrolls inside it. Because rows are windowed, so the box needs a fixed height to know how many to render.
- Should
- Pass kind for the thing the log belongs to: run for an eval, agent for an agent. Because the hue names what the log is about without coloring the lines.
- Never
- Send lines with a live key, token or customer card number. Because every line is searchable, copyable and kept in the page, and Copy lines puts the whole log on the clipboard.
- Never
- Underline resource IDs inside lines; the viewer turns that off on purpose. Because in a log the most repeated ID would get the loudest mark, which is noise.
State order
2 states, highest first
- 1
- streaming
- 2
- failed
Accessibility
6 checks
- The body is role="log" with aria-live="off" and one tab stop, named by label, so a streaming log does not read every line.
- A polite status region announces the number of failed lines when it changes.
- Level is a word on every row, so color is never the only signal; fail and warn add a wash and a colored word.
- The level cells are toggle buttons with aria-pressed; the wrap toggle is named "Wrap lines".
- Next failure is named with its count; the jump button names how many lines are new and how many failed.
- The log stays left to right inside a right-to-left page.
Keyboard
3 keys
- Tab
- Moves through filter, levels, wrap, then the log body as one stop.
- Escape in the filter
- Clears the filter text.
- Arrow keys, Page Up, Page Down
- Scroll the focused log body.
Edge cases
10 edge cases
- No lines, streaming
- Says "Waiting for the first line."
- No lines, finished
- Says "No output."
- Filter matches nothing
- Says "No lines match" with the text in a code tag, or "No lines at these levels."
- Scrolled up while lines arrive
- Following stops; a button counts the new lines and the failed ones, "38 new, 2 fail".
- 100,000 lines
- Only the rows on screen render; each is measured as it appears.
- Failure 40,000 lines up
- Next failure walks the fail lines in order and centers each.
- Hand selection
- Copies one line per row, with the time, level and source joined by spaces.
- Narrow box
- The filter takes its own row under 448px, level counts show from 576px and the time column hides below 640px.
- Offscreen while streaming
- The running arc pauses when the frame leaves the viewport.
- Zoom 200%
- Rows re-measure and grow with the text.
API
10 props
linesLogLine[]defaultrequiredstreamingbooleandefaultfalsefollowbooleandefaulttruelabelstringdefault'Logs'heightnumberdefault360headerbooleandefaulttruetoolbarbooleandefaultfalsetimestampsbooleandefaulttruewrapbooleandefaulttruekind'agent' | 'key' | 'run' | 'deploy' | 'model'
Tokens
16 tokens
--log-level- 5ch
--code-text- var(--ink)
--code-comment- oklch(var(--ink-c) / var(--code-comment-alpha))
--accent-wash- var(--surface-selected)
--fail-text- oklch(51% 0.180 26)
--warn-text- oklch(49% 0.100 68)
--surface-page- var(--paper)
--surface-hover- oklch(var(--ink-c) / 0.05)
--surface-pressed- oklch(var(--ink-c) / 0.08)
--surface-inverse- var(--ink)
--text-inverse- var(--paper)
--line-frame- oklch(var(--ink-c) / var(--line-frame-alpha))
--line-row- oklch(var(--ink-c) / 0.08)
--elev-overlay- 0 0 0 1px var(--line-frame), 0 12px 24px -12px oklch(var(--text-on-field-c) / var(--shadow-alpha))
--type-code- 400 13px/20px var(--font-mono)
--type-label-sm- 400 12px/16px var(--font-sans)