# План реалізації: Типізований журнал подій (100k) з локалізацією та фільтрацією

## Огляд
Згідно з результатами [дослідження](../research.md), буде реалізовано високоефективний журнал подій (log viewer) на основі структури `VecDeque<LogEntry>`, що здатний тримати до 100 000 записів для кожного хоста з мінімальними витратами пам'яті (~2.5 МБ на хост). 

Функціональність охоплює:
- Запис Pings, Timeouts, Statistics, Route Updates та Incidents.
- Вікно перегляду `egui` з можливістю включення/виключення певних типів записів у реальному часі.
- Локалізацію (i18n): всі рядки формуватимуться мовою інтерфейсу (`tr!`).
- Запис до файлу (додавання) із заданим у налаштуваннях шляхом (за замовчуванням `~/назва_хоста.log`).

## Зміни в архітектурі
1. **Залежності**: Додати `chrono` (для роботи з часом) та `dirs` (для знаходження домашньої директорії) в `Cargo.toml`. У майбутньому `std::time::SystemTime` може бути використано, але `chrono` зручніше для форматування.
2. **`src/model/status.rs`**: 
   - Створення `enum LogEntry` для різних типів подій.
   - Метод `LogEntry::format` (або `to_string`), що використовує макроси `tr!` для локалізованого виводу.
   - Розширення `HostStatus` полями:
     - `events: VecDeque<LogEntry>` 
     - `prev_alive: Option<bool>` 
     - `incident_start: Option<u64>` (за допомогою timestamp)
     - `log_pings_since_stats: u32`
   - Розширення `HostInfo` полями `log_to_file: bool` та `log_file_path: String`.
3. **`src/app.rs`**: 
   - Модифікація `EguiPinger` для зберігання поточних обраних фільтрів журналу та адреси відкритого вікна (`viewing_log`).
   - Додавання UI-кнопки 📋 біля хопу/хоста для перегляду логу.
   - Використання `ScrollArea::stick_to_bottom` (бажано спільно з `show_rows` для 100k записів).
4. **`src/logic/pinger.rs`**: 
   - Підтримка додавання `LogEntry` при: кожній відповіді (або таймауті), обривах/відновленнях, змінах маршруту та при відправці кожного 300-го пінгу (статистика).
   - Відокремлений асинхронний чи синхронний запис у файл `OpenOptions::new().create(true).append(true)` у `pinger_task`, якщо увімкнено логування для хосту.

## Етапи реалізації

- [x] **Крок 1: Оновлення Cargo.toml**
  - Додати `chrono = "0.4"` та `dirs = "5.0"` (або `"6.0"` за сумісністю).

- [x] **Крок 2: Розширення моделі `src/model/status.rs`**
  - Створити `enum LogEntry`. Врахувати параметри, наведені у `research.md` (timeout = `rtt: None`).
  - Додати методи для отримання `LogEntry` як форматованого рядку з підтримкою `tr!`.
  - Додати поля `events`, `prev_alive`, `incident_start`, `log_pings_since_stats` у `HostStatus`.
  - Забезпечити обмеження розміру `events` у 100_000 елементів (видалення `pop_front` при перевищенні).
  - У `HostInfo` додати `log_to_file` і `log_file_path`.

- [x] **Крок 3: Інтеграція генерації подій в `src/logic/pinger.rs`**
  - У циклі отримання відповіді (або timeout) додавати `LogEntry::Ping` в `events`.
  - Перевіряти `alive` vs `prev_alive`:
    - Впало: генерувати `LogEntry::Incident` (Connectivity lost), запам'ятовувати `incident_start`.
    - Піднялося: генерувати `LogEntry::Incident` (Connectivity restored), рахувати downtime.
  - Інкрементувати лічильник та генерувати `LogEntry::Statistics` щожні 300 результатів.
  - При оновленні траси(`should_update` == true) додати `LogEntry::RouteUpdate`.
  - *Важливо:* Синхронізувати запис у файл. Після додавання запису до черги перевірити і записати форматований рядок (через `LogEntry::format()`), якщо `log_to_file` активували. Опрацювати маркери `=== Початок журналу ... ===` при зміні параметру в UI (можливо, потребує відстежування стану логування).

- [x] **Крок 4: Розширення графічного інтерфейсу `src/app.rs`**
  - Додати іконку "📋" до елементів у `ui_layout`.
  - При кліку на "📋" встановлювати `viewing_log = Some(address)`. При ініціалізації встановлювати для нового хоста дефолтний `log_file_path` через крейт `dirs::home_dir()`.
  - Реалізувати вікно `egui::Window::new` для візуального перегляду логу:
    - Розділ керування записом у файл: чекбокс `log_to_file`, поле шляху.
    - Розділ фільтрів: 4 чекбокси (Пінги, Таймаути, Статистика/Траса, Інциденти).
    - Обрізання подій за допомогою фільтрів.
    - Використовувати `ScrollArea::vertical().stick_to_bottom(true)` з викликом `show_rows` для віртуалізації відображення, щоб UI не зависав на 100 000 елементах. (Оскільки ширина та висота тексту моноширинного шрифту фіксована, `show_rows` працюватиме ідеально).

- [x] **Крок 5: Обробка перекладів (I18n)**
  - Перевірити всі використання макросів `tr!` у нових файлах.
  - Запустити скрипти / макроси (наприклад, `xtr` або `cargo build` з увімкненою фічею) для генерування нових `msgids` у POT-файл, оновити PO.

- [x] **Крок 6: Тестування**
  - Запустити тести. Переконатися що старі тести у `status_tests.rs` і `pinger_tests.rs` не поламалися через нові поля.
  - Додати нові модульні тести на ліміт `VecDeque` у 100 000 (заповнити буфер повністю і перевірити розмір).
  - Ручне тестування вікна логу: дочекатися таймаутів, увімкнути запис у файл, перевірити чи використовуються правильно мови (українська/англійська) та фільтри.

## Критерії успіху
- Пам'ять для `egui_pinger` зросла не більше ніж на кілька мегабайт (навмисно заповнити буфер до 100к).
- Scrolling (прокручування) вікна до самого низу працює миттєво.
- Перемикання чекбоксів фільтрації у вікні перегляду миттєво приховує/показує вказані рядки.
- Запис логу до вказаного файлу дописує (`append`) форматований текст мовою, вибраною в інтерфейсі програми без блокування UI-потоку (хоча I/O через OS page cache відбувається дуже швидко).
- На екрані чітко видно записи про обрив (loss) і відновлення (restore), а також статистику кожні 300 пінгів.
