tracing
tracing fornece logging estruturado e contextual para Rust assíncrono. Spans seguem requisições entre tarefas; campos são tipados e filtráveis em tempo de execução.
Receita
[dependencies]
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }use tracing::{info, instrument};
#[instrument]
async fn fetch_user(user_id: u64) -> String {
info!(%user_id, "buscando usuário");
format!("user-{user_id}")
}
#[tokio::main]
async fn main() {
tracing_subscriber::fmt()
.with_env_filter("info")
.init();
fetch_user(42).await;
}Quando usar isso:
- Serviços de produção que precisam de IDs de requisição e campos de latência
- Código assíncrono onde
println!perde a ordenação - Exportação OpenTelemetry via
tracing-opentelemetry
Exemplo em Funcionamento
use tracing::{info_span, Instrument};
async fn work() {
let span = info_span!("job", job_id = 7);
async {
tracing::info!("iniciado");
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
tracing::info!("concluído");
}
.instrument(span)
.await;
}O que isso demonstra:
- Spans aninham e anexam metadados
.instrument(span)propaga o contexto através de.await- Subscribers formatam a saída (texto ou JSON)
Mergulho Profundo
Camadas
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
tracing_subscriber::registry()
.with(tracing_subscriber::fmt::layer())
.with(tracing_subscriber::EnvFilter::from_default_env())
.init();Defina RUST_LOG=info,my_crate=debug em produção para verbosidade direcionada.
Link Cruzado
Veja tracing no Tokio e Observabilidade para métricas e OTLP.
Armadilhas
- Inicializando o subscriber duas vezes - causa pânico em testes. Correção:
OnceLockoutracing_subscriber::try_init(). - Campos de span enormes - logar payloads completos é caro. Correção: logar IDs e tamanhos.
.instrumentfaltando em tarefas spawnadas - links pai quebrados. Correção: instrumentar antes detokio::spawn.println!em bibliotecas - ignora filtros. Correção: apenas macrostracing.- Debug em loops intensos - proteja com
tracing::enabled!ou verificações de nível.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
log facade | Suportar crates mais antigos | Greenfield sem ponte |
env_logger | CLIs minúsculas | Serviços assíncronos multi-thread |
slog | Código legado | Novas pilhas Tokio |
FAQs
tracing vs crate log?
tracing é um superconjunto com spans. Muitos crates usam log; adicione a ponte tracing-log.
Logs JSON para Loki/Datadog?
Use tracing_subscriber::fmt::layer().json() ou uma camada JSON dedicada.
Como rastrear requisições Axum?
tower-http TraceLayer mais tracing em handlers. Veja a skill de serviço Axum.
Custo de performance?
Spans desabilitados são baratos. Logging estruturado habilitado custa IO - amostre em caminhos extremos.
Relacionados
Versões da Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.