Streaming de logs em Rust com Tokio
O que você ganha
Você ganha um tailer de logs pequeno e focado que pode ser adicionado a qualquer serviço:
- baixa latência: eventos são enviados assim que chegam
- memória limitada: backpressure via leituras em streaming
- JSON estruturado pronto para qualquer pipeline de logs
Enviar logs linha por linha mantém a latência baixa e a memória estável. Este trecho mostra um tailer assíncrono mínimo que emite JSON.
O streamer
use tokio::{fs::File, io::{AsyncBufReadExt, BufReader}};
use serde::Serialize;
#[derive(Serialize)]
struct LogLine<'a> {
line: &'a str,
source: &'a str,
}
async fn stream_file(path: &str, source: &str) -> anyhow::Result<()> {
let file = File::open(path).await?;
let reader = BufReader::new(file);
let mut lines = reader.lines();
while let Some(line) = lines.next_line().await? {
let payload = LogLine { line: &line, source };
let json = serde_json::to_string(&payload)?;
// Replace with your sink: TCP, HTTP, Kafka, etc.
println!("{}", json);
}
Ok(())
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Run with: cargo run -- path/to/app.log
let path = std::env::args().nth(1).expect("missing log path");
stream_file(&path, "app").await
}
Observações
BufReadermantém a memória limitada;lines()produz valores de forma lazy.- Substitua
println!pelo cliente do sink de sua preferência. - Use
tokio::select!para combinar múltiplos arquivos ou sinais de encerramento. - Emita JSON estruturado para que consumidores downstream possam parsear de forma confiável.