Menu
Public repository / 23447341749e267e6dbb85b2c02caa6b9d729c52
AkurAI-Monitor / src/pibun_push.rs
Latest change 0dc722fc5be3c8872e2688a51720c1882acdfd3c - Monitor: push error/warn logs to pi-bun #errors in real time by Ólafur Búi Ólafsson
// Fire-and-forget push of error/warn logs to pi-bun's #errors channel.
// Called from every log ingestion path (ingest API, journald) so errors
// appear in the Workbench instantly — no polling, no timer.
use crate::config;
/// Push a log line to pi-bun's /api/ingest-error if its level is error or warn.
/// Spawns a detached task — never blocks the caller or propagates failures.
pub fn push_error(source: &str, line: &str, level: Option<&str>) {
let level = level.unwrap_or("info");
if level != "error" && level != "warn" && level != "warning" {
return;
}
let cfg = config::get();
if cfg.pibun_ingest_token.is_empty() {
return; // not configured
}
let url = cfg.pibun_ingest_url.clone();
let token = cfg.pibun_ingest_token.clone();
let channel = cfg.pibun_ingest_channel.clone();
let source = source.to_string();
let line = line.to_string();
let level = level.to_string();
tokio::spawn(async move {
let body = serde_json::json!({
"channel": channel,
"level": level,
"source": source,
"body": line,
});
let result = reqwest::Client::new()
.post(&url)
.header("Authorization", format!("Bearer {token}"))
.json(&body)
.timeout(std::time::Duration::from_secs(5))
.send()
.await;
match result {
Ok(resp) if resp.status().is_success() => {}
Ok(resp) => {
tracing::warn!(status = %resp.status(), "pi-bun error push rejected");
}
Err(e) => {
tracing::warn!(error = %e, "pi-bun error push failed");
}
}
});
}