Skip to content

Commit 6da2bc5

Browse files
chore: initial commit
0 parents  commit 6da2bc5

17 files changed

Lines changed: 3980 additions & 0 deletions

File tree

.gitignore

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Binaries
2+
logt
3+
logt.exe
4+
*.exe
5+
6+
# IDE
7+
.idea/
8+
.vscode/
9+
*.swp
10+
*.swo
11+
12+
# OS
13+
.DS_Store
14+
Thumbs.db
15+
16+
# Go
17+
go.work
18+
go.work.sum
19+
20+
# Test
21+
*.log
22+
test_*.txt
23+
24+
# Temporary
25+
tmp/
26+
temp/

README.md

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
1+
# LogT — Современный Explorer логов (TUI)
2+
3+
> **Легковесная альтернатива lnav** с упором на UX, авто-парсинг JSON и мгновенную фильтрацию.
4+
5+
![Go](https://img.shields.io/badge/Go-1.21+-00ADD8?style=for-the-badge)
6+
![License](https://img.shields.io/badge/License-MIT-green?style=for-the-badge)
7+
[![Tests](https://img.shields.io/badge/Tests-36%20passing-44b526?style=for-the-badge)]()
8+
9+
## 🚀 Возможности
10+
11+
### Основные
12+
- **Мульти-source tailing** — Слежение за несколькими файлами по шаблону (`./logs/*.log`)
13+
- **Ring Buffer** — Хранит последние 5000 строк в памяти (настраивается)
14+
- **Stdin Support**`cat app.log | logt`
15+
- **Log Forwarding** — Экспорт отфильтрованных логов в файл (`--forward`) или stdout (`--forward -`)
16+
17+
### Просмотр
18+
- **Live Tail** — Автопрокрутка при поступлении новых строк
19+
- **Подсветка синтаксиса** — Цветовая кодировка уровней (INFO=синий, WARN=желтый, ERROR=красный)
20+
- **JSON Expand** — Нажмите Enter на JSON строке для разворачивания в полноэкранное дерево
21+
22+
### Интерактивность
23+
- **Fuzzy Filter** — Нажмите `/` для мгновенной фильтрации
24+
- **Regex Filter** — Нажмите `r` для режима регулярных выражений
25+
- **Pause/Resume** — Нажмите `Space` для паузы автопрокрутки
26+
- **Source Toggle** — Нажмите `Tab` для показа/скрытия панели источников
27+
- **JSON Explorer** — Нажмите `Enter` на JSON строке для просмотра ключей
28+
29+
## 🚀 Тесты производительности
30+
31+
Протестировано на **Intel Core i3-10100 @ 3.6 GHz**:
32+
33+
| Операция | Скорость | Примечания |
34+
|-----------|-------|-------|
35+
| RingBuffer Add | **~27M ops/sec** | Потокобезопасный, блокировка-free чтение |
36+
| JSON Парсинг | **~314K строк/sec** | Авто-детект + парсинг |
37+
| Fuzzy Фильтр | **~3.7M совпадений/sec** | Без учёта регистра |
38+
| Определение уровня | **~394K строк/sec** | На основе регулярных выражений |
39+
| IsValidJSON | **~1.3M проверок/sec** | Быстрая валидация |
40+
41+
**Память**: Ring buffer ограничен ~2MB для 5000 строк (настраивается)
42+
43+
*LogT разработан для высоконагруженных окружений с минимальным потреблением CPU/RAM.*
44+
45+
## 📦 Установка
46+
47+
### Из исходников
48+
```bash
49+
# Клонировать репозиторий
50+
git clone https://github.com/turkprogrammer/logt.git
51+
cd logt
52+
53+
# Собрать бинарник
54+
go build -o logt ./cmd/logt
55+
56+
# Или установить в GOPATH
57+
go install ./cmd/logt
58+
```
59+
60+
### Предсобранные бинарники
61+
Скачать с [Releases](https://github.com/turkprogrammer/logt/releases)
62+
63+
> **Примечание:** Если репозиторий ещё не опубликован, используйте локальную разработку:
64+
> ```bash
65+
> go build -o logt ./cmd/logt
66+
> ```
67+
68+
## 🛠️ Использование
69+
70+
### Базовое
71+
```bash
72+
# Следить за одним файлом
73+
logt ./app.log
74+
75+
# Следить за несколькими файлами по шаблону
76+
logt ./logs/*.log
77+
78+
# Фильтр по уровню
79+
logt --level error ./app.log
80+
81+
# Stdin pipe
82+
cat app.log | logt
83+
```
84+
85+
### Тестовые логи
86+
87+
#### Windows (PowerShell)
88+
```powershell
89+
# Простой JSON (с кавычками)
90+
echo '{"level":"info","msg":"Server started"}' | Out-File -FilePath app.log -Encoding utf8
91+
92+
# JSON с доп. полями
93+
echo '{"level":"error","msg":"Connection failed","host":"db1","port":5432}' | Out-File app.log -Encoding utf8
94+
95+
# Несколько строк
96+
@'
97+
{"level":"info","msg":"Starting"}
98+
{"level":"warn","msg":"Low memory"}
99+
{"level":"error","msg":"OOM killed"}
100+
{"level":"debug","msg":"GC done"}
101+
'@ | Out-File app.log -Encoding utf8
102+
103+
# Запуск
104+
.\logt.exe app.log
105+
106+
# Pipe
107+
Get-Content app.log | .\logt.exe
108+
```
109+
110+
#### Windows (CMD)
111+
```cmd
112+
# Простой JSON
113+
echo {"level":"info","msg":"Server started"} > app.log
114+
115+
# JSON с доп. полями - используем printf для кавычек
116+
printf "{\"level\":\"error\",\"msg\":\"Connection failed\",\"host\":\"db1\",\"port\":5432}\n" > app.log
117+
118+
# Несколько строк (CMD)
119+
(
120+
echo {"level":"info","msg":"Starting"}
121+
echo {"level":"warn","msg":"Low memory"}
122+
echo {"level":"error","msg":"OOM killed"}
123+
echo {"level":"debug","msg":"GC done"}
124+
) > app.log
125+
126+
# Запуск
127+
logt.exe app.log
128+
129+
# Pipe
130+
type app.log | logt.exe
131+
```
132+
133+
#### Linux / macOS
134+
```bash
135+
# Простой JSON
136+
echo '{"level":"info","msg":"Server started"}' > app.log
137+
138+
# JSON с доп. полями
139+
echo '{"level":"error","msg":"Connection failed","host":"db1","port":5432}' > app.log
140+
141+
# Logfmt
142+
echo 'level=info msg="Server started"' > app.log
143+
echo 'level=error msg="Connection failed" host=db1 port=5432' > app.log
144+
145+
# Plain text с уровнем
146+
echo '2024-01-15 10:30:00 INFO Server started' > app.log
147+
echo '2024-01-15 10:30:01 ERROR Connection failed' > app.log
148+
149+
# Несколько строк
150+
cat > app.log << 'EOF'
151+
{"level":"info","msg":"Starting application"}
152+
{"level":"info","msg":"Loading config from /etc/app.conf"}
153+
{"level":"warn","msg":"Config key 'debug' not found, using default"}
154+
{"level":"debug","msg":"Initializing database connection pool"}
155+
{"level":"info","msg":"Connected to postgres://localhost:5432/db"}
156+
{"level":"error","msg":"Query failed: relation 'users' does not exist"}
157+
{"level":"info","msg":"Running migrations..."}
158+
{"level":"info","msg":"Migration v001_create_users completed"}
159+
{"level":"info","msg":"Server listening on :8080"}
160+
{"level":"error","msg":"Unhandled panic: index out of range"}
161+
{"level":"warn","msg":"Retry attempt 1/3 for external API"}
162+
{"level":"error","msg":"External API still unavailable after 3 retries"}
163+
EOF
164+
165+
# Запуск
166+
./logt app.log
167+
168+
# Pipe
169+
cat app.log | ./logt
170+
171+
# С другими командами
172+
kubectl logs deployment/myapp | ./logt
173+
journalctl -f | ./logt
174+
docker logs -f mycontainer | ./logt
175+
```
176+
177+
#### Мульти-формат (mixed sources)
178+
```bash
179+
# Создаём разные файлы
180+
echo '{"level":"info","msg":"API log"}' > api.log
181+
echo 'level=warn msg="Auth warning"' > auth.log
182+
echo '2024-01-15 ERROR Database connection lost' > db.log
183+
184+
# Следим за всеми сразу
185+
logt api.log auth.log db.log
186+
# или
187+
logt ./*.log
188+
```
189+
190+
### Примеры
191+
```bash
192+
# Следить за всеми логами сервисов
193+
logt /var/log/services/*.log
194+
195+
# Найти только ошибки
196+
logt --level error ./app.log
197+
198+
# С настроенным буфером
199+
logt --buffer 10000 --max-buffer 20000 ./app.log
200+
201+
# Экспорт отфильтрованных логов в файл
202+
logt --forward filtered.log ./app.log
203+
204+
# Экспорт в stdout (pipe)
205+
logt --forward - ./app.log | grep ERROR
206+
207+
# С источниками из конфига
208+
logt
209+
210+
# Stdin от другой команды
211+
kubectl logs deployment/app | logt
212+
```
213+
214+
## ⌨️ Горячие клавиши
215+
216+
| Клавиша | Действие |
217+
|-----|--------|
218+
| `Space` | Пауза/Продолжить автопрокрутку |
219+
| `/` | Открыть Fuzzy фильтр |
220+
| `r` | Переключить Fuzzy/Regex фильтр |
221+
| `Enter` | Применить фильтр / Открыть JSON |
222+
| `Backspace` | Удалить символ из фильтра |
223+
| `Esc` | Очистить фильтр / Закрыть JSON просмотр |
224+
| `↑ / ↓` | Прокрутка вверх/вниз |
225+
| `PgUp / PgDn` | Прокрутка по страницам |
226+
| `Home / End` | Перейти в начало/конец |
227+
| `g` | Перейти в начало (less-style) |
228+
| `G` | Перейти в конец (less-style) |
229+
| `n` | Следующее совпадение |
230+
| `N` | Предыдущее совпадение |
231+
| `Tab` | Переключить панель источников |
232+
| `q` | Выход |
233+
234+
## 🏗️ Архитектура
235+
236+
```
237+
logt/
238+
├── cmd/logt/main.go # Точка входа, CLI
239+
├── internal/
240+
│ ├── config/config.go # Загрузка конфигурации (yaml, env)
241+
│ ├── domain/domain.go # Модели, Парсеры, RingBuffer
242+
│ ├── provider/provider.go # Провайдеры файлов и stdin
243+
│ └── ui/
244+
│ ├── model.go # Состояние Bubble Tea
245+
│ ├── update.go # Обработчики сообщений
246+
│ └── view.go # Рендеринг через Lip Gloss
247+
├── config.example.yaml # Пример конфигурации
248+
└── README.md
249+
```
250+
251+
### Проектные решения
252+
253+
1. **Гексагональная архитектура** — Домен-ориентированный дизайн с чёткими границами
254+
2. **Channel-based Concurrency** — Безопасные обновления UI через Go каналы
255+
3. **Throttling** — UI обновляется максимум 20 раз/сек для предотвращения CPU spike
256+
4. **Без внешней tail библиотеки** — Собственная реализация через polling
257+
258+
## 🧪 Тестирование
259+
260+
```bash
261+
# Запустить все тесты
262+
go test ./...
263+
264+
# С бенчмарками
265+
go test -bench=. ./...
266+
267+
# Конкретный тест
268+
go test -v -run TestRingBuffer ./...
269+
```
270+
271+
### Покрытие тестами
272+
- RingBuffer overflow (100k → 5k limit)
273+
- Конкурентный доступ (thread-safety)
274+
- JSON/Logfmt/Plain парсеры с fallback
275+
- Fuzzy filter matching
276+
- Определение уровня (case-insensitive)
277+
- Конфигурация (yaml, env, flags)
278+
279+
## 📊 Сравнение
280+
281+
| Возможность | LogT | lnav |
282+
|---------|------|------|
283+
| Размер бинарника | ~6MB | ~15MB |
284+
| Время старта | <100ms | ~200ms |
285+
| JSON поддержка | Нативная | Ограниченная |
286+
| Fuzzy Filter |||
287+
| Regex Filter |||
288+
| YAML конфиг |||
289+
| Требует конфиг |||
290+
291+
## 🔧 Конфигурация
292+
293+
LogT работает **без конфига** из коробки. Для кастомизации создайте файл:
294+
295+
```yaml
296+
# ~/.config/logt/config.yaml или ./logt.yaml
297+
buffer-size: 5000 # Размер буфера
298+
buffer-max: 10000 # Максимальный размер
299+
theme: dark # Тема (dark)
300+
forward: filtered.log # Файл для экспорта
301+
sources: # Источники по умолчанию
302+
- /var/log/*.log
303+
```
304+
305+
### Переменные окружения
306+
```bash
307+
LOGT_BUFFER_SIZE=10000
308+
LOGT_LEVEL=error
309+
LOGT_FORWARD=filtered.log
310+
LOGT_THEME=dark
311+
```
312+
313+
### Флаги командной строки
314+
```
315+
-p, --path string Пути к файлам или шаблоны
316+
-l, --level string Фильтр по уровню
317+
-b, --buffer int Размер буфера (по умолчанию: 5000)
318+
-m, --max-buffer int Максимальный размер буфера
319+
-f, --forward string Экспорт логов (файл или stdout)
320+
-t, --theme string Тема (dark)
321+
-v, --version Версия
322+
-h, --help Помощь
323+
```
324+
325+
## 📝 Поддерживаемые форматы логов
326+
327+
### Авто-определение
328+
- **JSON**`{"level": "error", "message": "..."}`
329+
- **Logfmt**`level=error msg="..."`
330+
- **Plain**`2024-01-01 10:00:00 ERROR message`
331+
332+
### Определение уровня
333+
Без учёта регистра:
334+
- `FATAL`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`
335+
336+
## 🐛 Известные ограничения
337+
338+
- Windows-only file watching (polling, не inotify)
339+
- Нет удалённой поддержки логов (в планах: HTTP forwarding)
340+
- TUI only (без headless режима)
341+
342+
## 🤝 Вклад
343+
344+
1. Fork
345+
2. Создайте feature branch
346+
3. Запустите тесты: `go test ./...`
347+
4. Отправьте PR
348+
349+
## 📄 Лицензия
350+
351+
MIT License - см. [LICENSE](LICENSE)

0 commit comments

Comments
 (0)