https://github.com/wunamesst/tailr
A blazing-fast log tail & search server. Single binary, web UI, real-time streaming.
https://github.com/wunamesst/tailr
devops log-search log-tail log-viewer monitoring rust vue3 websocket
Last synced: 11 days ago
JSON representation
A blazing-fast log tail & search server. Single binary, web UI, real-time streaming.
- Host: GitHub
- URL: https://github.com/wunamesst/tailr
- Owner: wunamesst
- License: mit
- Created: 2026-05-25T05:57:38.000Z (26 days ago)
- Default Branch: main
- Last Pushed: 2026-06-08T12:40:47.000Z (12 days ago)
- Last Synced: 2026-06-08T13:24:00.487Z (12 days ago)
- Topics: devops, log-search, log-tail, log-viewer, monitoring, rust, vue3, websocket
- Language: Rust
- Homepage: https://tailr.flolib.com/
- Size: 843 KB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
tailr
A blazing-fast log tail & search server. Single binary, web UI, real-time streaming.
Quick Start •
Features •
Installation •
API •
License
---
## Features
- **Real-time tail** — WebSocket-based live log streaming
- **Multi-keyword filter** — AND logic, like `grep kw1 | grep kw2`
- **Fast search** — mmap-based grep with regex support
- **Log level detection** — Auto-detects ALERT/ERROR/WARN/INFO/DEBUG/TRACE
- **Single binary** — No dependencies, no runtime, just run
- **Web UI** — Built-in Vue 3 SPA, no separate frontend deployment
- **Log rotation aware** — Detects inode changes, handles logrotate
- **Self-upgrade** — One command to update to the latest version
- **Multi-language UI** — English (default) and Chinese, with easy extensibility
- **Cross-platform** — Linux (x86_64/ARM64), macOS
## Quickstart
```bash
# Run with specific log directories
tailr --log /var/log/app /var/log/nginx
# Run with a single file
tailr --log /var/log/syslog
# Custom bind address
tailr --log /var/log -b 127.0.0.1:8080
```
Open `http://localhost:7700` in your browser.
## Installation
### Download binary
Download the latest binary from [GitHub Releases](https://github.com/wunamesst/tailr/releases).
### Build from source
```bash
# Clone
git clone https://github.com/wunamesst/tailr.git
cd tailr
# Build frontend + Rust binary
make build
# Or just run in dev mode
make dev
```
### Cross-compile for Linux (from macOS)
```bash
make build-linux # x86_64
make build-linux-arm # aarch64
make release # both + frontend
```
Uses Docker with musl for static binaries (no glibc dependency).
## CLI
```
tailr [OPTIONS] # Start server (default)
tailr upgrade [--check] # Check/perform self-upgrade
Options:
-l, --log ... Log directories or files to serve (can specify multiple)
-b, --bind Bind address [default: 0.0.0.0:7700]
-d, --daemon Run as daemon in background
--stop Stop running daemon
--status Show daemon status
--systemd Print systemd service file and exit
--launchd Print launchd plist file and exit (macOS)
--pid-file Custom PID file path
--log-file Custom log file path for daemon mode
-h, --help Print help
-V, --version Print version
Subcommands:
upgrade Check for updates and upgrade tailr to the latest version
-c, --check Only check for updates without installing
```
**Priority:** CLI args > `TAILR_LOG_DIR` env var > `/logs`
### Daemon Mode
Run tailr as a background daemon instead of using `nohup`:
```bash
# Start in daemon mode
tailr --daemon --log /var/log/app /var/log/nginx
# Check status
tailr --status
# Stop daemon
tailr --stop
```
**PID/Log files** are stored in `~/.local/share/tailr/` by default. Customize with:
```bash
tailr --daemon --log /var/log/app \
--pid-file /run/tailr.pid \
--log-file /var/log/tailr.log
```
### System Service
#### systemd (Linux)
```bash
# Generate and install service file
tailr --systemd --log /var/log/app | sudo tee /etc/systemd/system/tailr.service
# Enable and start
sudo systemctl enable --now tailr
# Check status
sudo systemctl status tailr
```
#### launchd (macOS)
```bash
# Generate and install plist
tailr --launchd --log /var/log/app > ~/Library/LaunchAgents/com.tailr.plist
# Load and start
launchctl load ~/Library/LaunchAgents/com.tailr.plist
# Check status
launchctl list | grep tailr
```
### Self-Upgrade
```bash
# Check for updates
tailr upgrade --check
# Upgrade to latest version
tailr upgrade
```
**Note:** The upgrade replaces the binary atomically. If tailr is running as a service, you'll need to restart it after upgrading.
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `TAILR_LOG_DIR` | `/logs` | Comma-separated log directories (fallback if no CLI args) |
| `TAILR_BIND` | `0.0.0.0:7700` | Listen address |
| `RUST_LOG` | — | Tracing filter (e.g. `tailr=debug`) |
## API
| Route | Method | Description |
|-------|--------|-------------|
| `/api/files` | GET | List log files (filtered: text files only) |
| `/api/file/content` | GET | Paginated file content (`?path=&offset=&limit=`) |
| `/api/file/tail` | GET | Last N lines (`?path=&lines=`) |
| `/api/file/info` | GET | File metadata + line count |
| `/api/search` | GET | Grep search (`?path=&q=®ex=&levels=&context=&limit=`) |
| `/api/health` | GET | Status + uptime |
| `/ws` | WS | Real-time log streaming |
### WebSocket Protocol
```json
// Subscribe to a file
{"type": "subscribe", "path": "/var/log/app.log"}
// Receive new entries
{"type": "append", "path": "/var/log/app.log", "seq": 42, "entries": [...]}
// Catchup on reconnect
{"type": "catchup", "path": "/var/log/app.log", "entries": [...], "lastSeq": 100}
```
## Development
```bash
# Terminal 1: Rust backend
cargo run
# Terminal 2: Vite dev server (with proxy)
cd frontend && npm run dev
```
Vite proxies `/api` and `/ws` to `http://localhost:7700`.
### Testing
```bash
make test # Run all checks (clippy + vue-tsc)
make test-backend # cargo test + cargo clippy
make test-frontend # vue-tsc --noEmit
```
### Internationalization (i18n)
The web UI supports multiple languages:
- **English (en-US)** — Default
- **Chinese (zh-CN)** — 简体中文
**Adding a new language:**
1. Create a new locale file in `frontend/src/locales/` (e.g., `ja-JP.json`)
2. Copy the structure from `en-US.json` and translate all strings
3. Update `frontend/src/locales/index.ts` to include the new locale in the type definition
4. Add the locale option to the language switcher in `SettingsPanel.vue`
The language preference is persisted in localStorage and auto-detected from the browser on first visit.
## Architecture
```
src/main.rs # CLI (clap), env vars, starts axum server
crates/
protocol/ # Shared types: LogEntry, WSMessage, LogLevel
tail-engine/ # File watching (notify), LineIndex (mmap)
search-engine/ # Grep-based search (grep-regex/grep-searcher)
server/ # Axum app: REST API, WebSocket, static files
frontend/ # Vue 3 + TypeScript + Vite SPA
```
## License
[MIT](LICENSE)