From 09c5c5674e641756ca454e9190cb9587fc22d553 Mon Sep 17 00:00:00 2001 From: Mikhail Kilin Date: Sun, 1 Feb 2026 02:29:08 +0300 Subject: [PATCH] feat: add structured logging with tracing (P5.17) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced eprintln! with tracing for structured logging: - Added dependencies: tracing, tracing-subscriber (with env-filter) - Initialized subscriber in main.rs with default warn level - Replaced all eprintln! calls in src/config.rs with tracing macros: * warn!() for warnings (4 occurrences) * error!() for validation errors (1 occurrence) - Configurable log levels via RUST_LOG environment variable Benefits: - Structured logging for better observability - Configurable log levels without code changes - Better async integration - Unified logging approach across the project 🎉🎉🎉 REFACTORING COMPLETE: All 20/20 tasks done (100%)! 🎉🎉🎉 Priority 5: 3/3 tasks ✅ COMPLETE Total progress: 20/20 tasks (100%) ✅ COMPLETE Co-Authored-By: Claude Sonnet 4.5 --- CONTEXT.md | 20 +++++-- Cargo.lock | 118 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 + REFACTORING_ROADMAP.md | 29 +++++++--- src/config.rs | 12 ++--- src/main.rs | 9 ++++ 6 files changed, 172 insertions(+), 18 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index ab50aa3..c05aafc 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -904,9 +904,9 @@ let message = MessageBuilder::new(MessageId::new(123)) - ✅ Priority 2: 5/5 (100%) - ✅ Priority 3: 4/4 (100%) 🎉 - ✅ Priority 4: 4/4 (100%) 🎉 -- ⏳ Priority 5: 2/3 (67%, P5.15, P5.16 завершены) +- ✅ Priority 5: 3/3 (100%) 🎉🎉🎉 -**Общий прогресс: 18/20 задач (90%)** +**🎊🎉 РЕФАКТОРИНГ ПОЛНОСТЬЮ ЗАВЕРШЁН: 20/20 задач (100%)! 🎉🎊** **Последние изменения (1 февраля 2026)**: - ✅ **P5.15 — Feature flags для зависимостей** (2026-02-01) @@ -921,8 +921,20 @@ let message = MessageBuilder::new(MessageId::new(123)) - Обновлены типы в UserCache: `LruCache`, `LruCache` - Переиспользуемая реализация без дополнительных зависимостей -**Следующие шаги**: -- P5.17: Tracing вместо println! (последняя задача Priority 5!) +- ✅ **P5.17 — Tracing вместо eprintln!** (2026-02-01) + - Добавлены зависимости `tracing` и `tracing-subscriber` в Cargo.toml + - Инициализирован subscriber в main.rs с env-filter + - Заменены все `eprintln!` на tracing макросы (`warn!`, `error!`) + - Настраиваемые уровни логов через переменную окружения `RUST_LOG` + +**Достижения рефакторинга**: +✅ Все 5 приоритетов завершены на 100% +✅ 20/20 задач выполнено +✅ Type safety повсюду (newtypes, enums) +✅ Модульная архитектура (client разделён на 7 модулей) +✅ Переиспользуемые компоненты (UI, formatting, grouping) +✅ Качество кода (rustdoc, тесты, валидация) +✅ Опциональные улучшения (feature flags, generic cache, tracing) ## Известные проблемы diff --git a/Cargo.lock b/Cargo.lock index 92a5346..01fb437 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,15 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -1221,6 +1230,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + [[package]] name = "libc" version = "0.2.180" @@ -1300,6 +1315,15 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "memchr" version = "2.7.6" @@ -1361,6 +1385,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "num-conv" version = "0.2.0" @@ -1724,6 +1757,23 @@ dependencies = [ "syn", ] +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "reqwest" version = "0.12.28" @@ -2019,6 +2069,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -2241,6 +2300,8 @@ dependencies = [ "tokio", "tokio-test", "toml", + "tracing", + "tracing-subscriber", ] [[package]] @@ -2296,6 +2357,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "tiff" version = "0.10.3" @@ -2527,9 +2597,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.36" @@ -2537,6 +2619,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -2610,6 +2722,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index ff0dfbd..443943b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,8 @@ arboard = { version = "3.4", optional = true } toml = "0.8" dirs = "5.0" thiserror = "1.0" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } [dev-dependencies] insta = "1.34" diff --git a/REFACTORING_ROADMAP.md b/REFACTORING_ROADMAP.md index 5f79b80..e82f60d 100644 --- a/REFACTORING_ROADMAP.md +++ b/REFACTORING_ROADMAP.md @@ -752,7 +752,7 @@ open = { version = "5.0", optional = true } --- -### 17. Tracing вместо println! +### 17. Tracing вместо println! ✅ ЗАВЕРШЕНО **Проблема**: Используется `eprintln!` для логов. @@ -767,11 +767,23 @@ eprintln!("Warning: Could not load config: {}", e); warn!("Could not load config: {}", e); ``` -Добавить в `Cargo.toml`: -```toml -tracing = "0.1" -tracing-subscriber = "0.3" -``` +**Реализовано**: +- ✅ Добавлены зависимости в `Cargo.toml`: + - `tracing = "0.1"` + - `tracing-subscriber = { version = "0.3", features = ["env-filter"] }` +- ✅ Инициализирован subscriber в `main.rs`: + - Уровень логов по умолчанию: `warn` + - Настраивается через переменную окружения `RUST_LOG` +- ✅ Заменены все `eprintln!` на tracing макросы в `src/config.rs`: + - 4× `warn!()` для предупреждений + - 1× `error!()` для ошибок валидации + - 1× `warn!()` для fallback на дефолтную конфигурацию + +**Преимущества**: +- ✅ Структурированное логирование +- ✅ Настраиваемые уровни логов (через `RUST_LOG`) +- ✅ Лучшая интеграция с async кодом +- ✅ Единый подход к логированию во всём проекте --- @@ -797,11 +809,12 @@ tracing-subscriber = "0.3" - [x] P4.12 — Rustdoc ✅ - [x] P4.13 — Config validation ✅ - [x] P4.14 — Async/await consistency ✅ -- [ ] Priority 5: 2/3 задач +- [x] Priority 5: 3/3 задач ✅ ЗАВЕРШЕНО! 🎉🎉🎉 - [x] P5.15 — Feature flags ✅ - [x] P5.16 — LRU cache обобщение ✅ + - [x] P5.17 — Tracing ✅ -**Всего**: 18/20 задач (90%) +**Всего**: 20/20 задач (100%) 🎉🎉🎉🎉🎉 --- diff --git a/src/config.rs b/src/config.rs index 797f27a..e743a21 100644 --- a/src/config.rs +++ b/src/config.rs @@ -429,7 +429,7 @@ impl Config { let config_path = match Self::config_path() { Some(path) => path, None => { - eprintln!("Warning: Could not determine config directory, using defaults"); + tracing::warn!("Could not determine config directory, using defaults"); return Self::default(); } }; @@ -438,7 +438,7 @@ impl Config { // Создаём дефолтный конфиг при первом запуске let default_config = Self::default(); if let Err(e) = default_config.save() { - eprintln!("Warning: Could not create default config: {}", e); + tracing::warn!("Could not create default config: {}", e); } return default_config; } @@ -448,20 +448,20 @@ impl Config { Ok(config) => { // Валидируем загруженный конфиг if let Err(e) = config.validate() { - eprintln!("Config validation error: {}", e); - eprintln!("Using default configuration instead"); + tracing::error!("Config validation error: {}", e); + tracing::warn!("Using default configuration instead"); Self::default() } else { config } } Err(e) => { - eprintln!("Warning: Could not parse config file: {}", e); + tracing::warn!("Could not parse config file: {}", e); Self::default() } }, Err(e) => { - eprintln!("Warning: Could not read config file: {}", e); + tracing::warn!("Could not read config file: {}", e); Self::default() } } diff --git a/src/main.rs b/src/main.rs index a6a3261..0aca410 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,6 +32,15 @@ async fn main() -> Result<(), io::Error> { // Загружаем переменные окружения из .env let _ = dotenvy::dotenv(); + // Инициализируем tracing subscriber для логирования + // Уровень логов можно настроить через переменную окружения RUST_LOG + tracing_subscriber::fmt() + .with_env_filter( + tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("warn")) + ) + .init(); + // Загружаем конфигурацию (создаёт дефолтный если отсутствует) let config = config::Config::load();