llv
Rails has ~"beautiful"~ trashy noisy unreadable garbage logs that it vomits uselessly into your terminal. We can do better.
Local log viewer for Rails development.log. Tails the file, groups lines by request (or background job), and shows them in a master/detail view — browser by default, or a TUI.
This is vide-coded because solving this years-old frustration now only takes 30mins between other work. Feel free to enhance it.
Setup
In your Rails app, enable tagged-logging with the request id so HTTP lines can be grouped reliably. Edit config/environments/development.rb:
config. = [:request_id]
ActiveJob lines already carry their own tags, no change needed for those.
Install llv globally — it's a standalone CLI, not something you bundle into your app. Once published to RubyGems:
gem install llv
In the meantime, from a clone of this repo:
bundle install && rake install
Run
Browser UI (default):
llv path/to/development.log
# opens http://127.0.0.1:9292
Terminal UI:
llv --tui path/to/development.log
Useful flags:
--tail— only show lines appended after launch. By defaultllvreplays the whole file first so you see existing requests too.--limit N— keep at most N items in memory (default 500).--port,--host— change the web server bind.--no-open— don't auto-launch the browser.
TUI keys
I don't use many terminal apps so please contribute enhancements to make it behave more as you'd expect.
The TUI is a two-pane master/detail with one focused pane at a time. Cursor keys and the vi-style hjkl both work.
| key | when focus is LIST (left) | when focus is DETAIL (right) |
|---|---|---|
↑ / k |
previous request | scroll one line up |
↓ / j |
next request | scroll one line down |
→ / l / enter |
move focus to DETAIL | — |
← / h / esc |
— | move focus back to LIST |
tab |
swap focus | swap focus |
PgUp / PgDn / space |
page through the list | page through detail |
Ctrl-U / Ctrl-D |
— | half-page up / down |
g / Home |
first item | scroll to top |
G / End |
last item | scroll to bottom |
s |
toggle SQL ↳ source lines |
toggle SQL ↳ source lines |
H / J / C |
toggle http / jobs / cable | toggle http / jobs / cable |
q / Ctrl-C |
quit | quit |
The header shows which pane has focus ([LIST] or [DETAIL]) and the divider thickens (│ → ┃) when the detail pane is active.
What you see
- Left pane — newest-first list of items. Each item is one HTTP request (with method, path, status, duration), one ActiveJob run, or one ActionCable (
/cable) connection. - Right pane — the log lines that belong to the selected item, with the ANSI colours Rails already emits (bold cyan for SQL labels, bold blue for the SQL itself, etc.). SQL source
↳lines are revealed alongside their query.
Filtering noise
ActionCable (/cable) requests are very chatty in development and are usually not what you're trying to debug. Each kind (http, jobs, cable) has its own independent toggle:
- Browser: three buttons in the header — click one to toggle its requests on/off. They're independent, so "HTTP + Jobs but not Cable" is one click on the Cable button.
- TUI:
Htoggles HTTP,Jtoggles Jobs,Ctoggles Cable. The header shows the current state and the total reflects items visible / items captured.
Layout
lib/llv/
ansi.rb # SGR <-> HTML span
parser.rb # line classifier, stateful for untagged-HTTP grouping
group_store.rb # thread-safe ring buffer, pub/sub
tailer.rb # listen-based file follower, rotation-aware
web.rb # Sinatra + SSE
tui.rb # bubbletea Model + lipgloss layout
public/ # vanilla HTML/JS/CSS
Tests
bundle exec rake test
# or:
bundle exec ruby -Ilib -Itest test/parser_test.rb
Releasing to RubyGems
For maintainers. The Rakefile pulls in bundler/gem_tasks, which gives you rake build and rake release.
One-time setup — sign in to RubyGems so credentials land in ~/.gem/credentials:
gem signin
Cutting a new release:
- Bump
Llv::VERSIONinlib/llv/version.rb(llv.gemspecreads from there, so it's the single source of truth). - Commit and push the version bump.
bundle exec rake release— this buildspkg/llv-<version>.gem, tagsv<version>in git, pushes the tag, then pushes the gem to rubygems.org.
If you want to do it by hand instead:
bundle exec rake build # writes pkg/llv-<version>.gem
gem push pkg/llv-<version>.gem