Наблюдаемость
masterror рассматривает телеметрию как часть жизненного цикла ошибки. Каждый
AppError отслеживает флаг изменения; телеметрия испускается один раз на
каждое изменение состояния — при конструировании, после мутации или когда
ошибка пересекает транспортную границу (IntoResponse в Axum,
error_response() в Actix, конверсия в Status для tonic). Вручную почти
ничего вызывать не нужно.
Флаги функций
| Флаг | Что добавляет |
|---|---|
tracing | Структурированное событие tracing на каждую ошибку, trace_id через log-mdc |
metrics | Счётчик error_total{code,category} через крейт metrics |
backtrace | Ленивый захват std::backtrace::Backtrace, управляемый RUST_BACKTRACE |
colored | ANSI-раскраска терминального вывода с детекцией TTY |
[dependencies]
masterror = { version = "0.28", features = ["tracing", "metrics", "backtrace"] }
Tracing
С включённым tracing каждая ошибка испускает одно событие уровня ERROR с
target masterror::error:
| Поле | Содержимое |
|---|---|
code | Строка AppCode, например NOT_FOUND |
category | Метка AppErrorKind, например Database |
message | Публичное сообщение, если есть |
retry_seconds | Рекомендация о повторе, если задана |
redactable | Редактируется ли сообщение на транспортных границах |
metadata_len | Количество присоединённых полей метаданных |
www_authenticate | Вызов аутентификации, если задан |
trace_id | Берётся из ключа trace_id контекста log-mdc, если присутствует |
Испускание учитывает подписчика: если ни один подписчик не заинтересован в событиях уровня ERROR для этого target, событие остаётся в ожидании и повторяется при следующем сбросе, так что ничего не теряется при поздней установке подписчика.
Чтобы соотносить ошибки с запросами, сохраните trace ID в MDC в middleware запроса:
log_mdc::insert("trace_id", request_id);
Каждая ошибка, сконструированная пока ключ установлен, несёт его в событии.
Метрики
С включённым metrics каждая свежеизменённая ошибка инкрементирует:
error_total{code="NOT_FOUND", category="NotFound"}
Обе метки — стабильные строки (AppCode::as_str() и метка AppErrorKind),
поэтому дашборды и алерты переживают рефакторинг ваших доменных типов.
Подключайте любой recorder metrics (Prometheus, StatsD, …) как обычно;
masterror использует только metrics::counter!.
Бэктрейсы
С включённым backtrace снимок Backtrace захватывается лениво в момент
сброса телеметрии, а не при каждом конструировании. Захват управляется
RUST_BACKTRACE: не задано, пустое, 0, off и false отключают его; любое
другое значение включает. Настройка читается один раз и кэшируется на процесс.
#[cfg(feature = "backtrace")] {
use masterror::AppError;
let err = AppError::internal("db down");
if let Some(bt) = err.backtrace() {
eprintln!("{bt}");
}
}
Можно также присоединить заранее захваченный трейс через
AppError::with_backtrace(backtrace) — он имеет приоритет над ленивым
захватом.
Ручной сброс через .log()
Конструкторы и конверсии испускают телеметрию автоматически. После мутации ошибки (добавление полей, изменение рекомендации о повторе) можно принудительно испустить её заново:
use masterror::{AppError, field};
let err = AppError::service("upstream degraded")
.with_field(field::str("upstream", "billing"));
err.log();
log() идемпотентен в рамках состояния: если с последнего испускания ничего
не изменилось, он ничего не делает. HTTP/gRPC-адаптеры делают такой же сброс
на границе, поэтому ошибка, которая сконструирована, обогащена и затем
возвращена из обработчика Axum, испускается один раз на состояние — один раз
при конструировании и один раз на границе для обогащённого состояния — и
никогда дважды для одного состояния.
Инспекция цепочки
Независимо от флагов, AppError предоставляет инструменты, нужные конвейерам
логирования:
#[cfg(feature = "std")] {
use std::io::Error as IoError;
use masterror::AppError;
let err = AppError::internal("db down").with_context(IoError::other("disk offline"));
assert_eq!(err.chain().count(), 2);
let _root = err.root_cause();
assert!(err.metadata().is_empty());
}
metadata().iter_with_redaction() выдаёт тройки (key, value, policy), чтобы
слой логирования мог соблюдать редактирование полей — см.
Контекст и метаданные.
Цветной терминальный вывод
Флаг colored добавляет masterror::colored::style для CLI-инструментов.
Цвета применяются только когда stderr — это TTY, NO_COLOR не задан, TERM
не равен dumb и терминал поддерживает ANSI; иначе текст проходит без
изменений. Результат детекции кэшируется на процесс.
| Функция | Стиль | Для чего |
|---|---|---|
error_kind_critical | красный | критические виды сбоев |
error_kind_warning | жёлтый | восстановимые виды/предупреждения |
error_code | голубой | машинные коды |
error_message | ярко-белый | основное сообщение |
source_context | приглушённый | вторичная информация об источнике |
metadata_key | зелёный | имена структурированных полей |
#[cfg(feature = "colored")] {
use masterror::colored::style;
eprintln!(
"{}: {}",
style::error_code("ERR_DB_001"),
style::error_message("Database connection failed")
);
}
Запускаемое демо:
examples/colored_cli.rs.
См. также: Флаги возможностей · Контекст и метаданные · Веб-фреймворки · Лучшие практики