docs [AI]

This commit is contained in:
2026-06-30 18:51:09 +07:00
parent 18cad76e38
commit f7a76353ea
67 changed files with 2104 additions and 1417 deletions
+21 -2
View File
@@ -1,20 +1,37 @@
// tools/log/src/error.rs
//! Типизированная ошибка приложения и реестр кодов ошибок.
//!
//! [`AppError`] несёт стабильный машинный `code` (из реестра `ERR_*` ниже),
//! раздельные сообщения для пользователя и для логов, произвольные метаданные и
//! опциональную причину-источник. Коды используются в логах и метриках как
//! устойчивые идентификаторы классов ошибок.
use std::collections::HashMap;
use std::fmt;
// Реестр кодов ошибок (Error Codes Registry)
// ── Реестр кодов ошибок (стабильные машинные идентификаторы) ──
/// Таймаут инфраструктуры (сеть/DNS/соединение).
pub const ERR_INFRA_TIMEOUT: &str = "INFRA_TIMEOUT";
/// Провал аутентификации (неверный auth-тег/payload).
pub const ERR_AUTH_FAILED: &str = "AUTH_FAILED";
/// Пакет отброшен из-за MTU в туннеле.
pub const ERR_NET_MTU_DROP: &str = "NET_TUNNEL_MTU_DROP";
/// Нарушение маскировки/целостности TLS (tampering, провал AEAD).
pub const ERR_NET_TLS_TAMPER: &str = "NET_TLS_TAMPER";
/// Необработанная паника (перехватывается логгером).
pub const ERR_SYS_PANIC: &str = "SYS_UNHANDLED_PANIC";
/// Ошибка приложения с машинным кодом, раздельными сообщениями и контекстом.
#[derive(Debug)]
pub struct AppError {
/// Стабильный код класса ошибки (один из `ERR_*`).
pub code: &'static str,
/// Сообщение для пользователя (может показываться в UI).
pub user_msg: String,
/// Техническое сообщение для логов/отладки.
pub internal_msg: String,
/// Произвольные пары ключ-значение с контекстом.
pub metadata: HashMap<String, String>,
/// Опциональная причина-источник (для цепочки ошибок).
pub cause: Option<Box<dyn std::error::Error + Send + Sync>>,
}
@@ -33,11 +50,13 @@ impl AppError {
}
}
/// Добавляет пару ключ-значение в метаданные (builder-стиль).
pub fn with_context(mut self, key: &str, value: &str) -> Self {
self.metadata.insert(key.to_string(), value.to_string());
self
}
/// Прикрепляет причину-источник ошибки (builder-стиль).
pub fn with_cause(mut self, err: impl std::error::Error + Send + Sync + 'static) -> Self {
self.cause = Some(Box::new(err));
self
+23
View File
@@ -1,3 +1,18 @@
//! # netrunner-logger — единый логгер и реестр ошибок проекта
//!
//! Тонкая обёртка над `tracing`/`tracing-subscriber`, дающая всем крейтам общий
//! стиль логирования и типизированные ошибки ([`error`]). Особенности:
//!
//! - **Один глобальный [`Logger`]** (`OnceLock` + `Once`): инициализируется раз,
//! уровень переключается на лету через reloadable-фильтр ([`set_level`](Logger::set_level)).
//! - **Два режима**: production (JSON в файл с суточной ротацией + перехват паник)
//! и debug (цветной вывод в консоль; на Android — `tracing_android`).
//! - **PII-редактор** ([`PiiRedactorLayer`]) — слой-заготовка для маскировки IP и
//! прочих чувствительных данных перед записью.
//!
//! Макросы `info!`/`error!`/… ре-экспортируются, чтобы во всех крейтах писать
//! `netrunner_logger::info!` без прямой зависимости на `tracing`.
pub mod error;
use regex::Regex;
@@ -21,6 +36,8 @@ pub use error::{
type ReloadableFilter = Handle<EnvFilter, Registry>;
/// Глобальный логгер: ручка перезагружаемого фильтра уровня + guard файлового
/// аппендера (держит фоновый writer живым, пока жив логгер).
pub struct Logger {
filter_handle: ReloadableFilter,
_guard: Option<WorkerGuard>,
@@ -29,6 +46,7 @@ pub struct Logger {
static INIT: Once = Once::new();
static LOGGER: OnceLock<Logger> = OnceLock::new();
/// Слой маскировки PII (сейчас — заготовка; regex для IP готов к использованию).
#[allow(dead_code)]
struct PiiRedactorLayer {
ip_regex: Regex,
@@ -50,6 +68,9 @@ impl<S: tracing::Subscriber> Layer<S> for PiiRedactorLayer {
}
impl Logger {
/// Инициализирует глобальный логгер (идемпотентно — только первый вызов
/// действует). `is_production` выбирает JSON-в-файл + перехват паник против
/// цветного вывода в консоль; `log_dir` — куда писать файлы в прод-режиме.
pub fn init(log_dir: Option<&str>, is_production: bool) {
INIT.call_once(|| {
// 1. Настройка динамического фильтра
@@ -130,6 +151,7 @@ impl Logger {
});
}
/// Меняет уровень логирования на лету (например `"debug"`, `"info,foo=warn"`).
pub fn set_level(&self, level: &str) {
if let Ok(new_filter) = EnvFilter::try_new(level) {
let _ = self.filter_handle.reload(new_filter);
@@ -137,6 +159,7 @@ impl Logger {
}
}
/// Доступ к глобальному логгеру (паникует, если [`init`](Logger::init) не звали).
pub fn global() -> &'static Logger {
LOGGER.get().expect("Logger not initialized!")
}