Enable logging to cli from stdin

This commit is contained in:
2024-10-25 00:40:53 +02:00
parent 7110a9e8f6
commit fe79d2d91a
2 changed files with 51 additions and 5 deletions

View File

@ -1,3 +1,5 @@
use std::io::{stdin, BufRead};
use chrono::Local; use chrono::Local;
use clap::Parser; use clap::Parser;
use eyre::{eyre, WrapErr}; use eyre::{eyre, WrapErr};
@ -17,9 +19,13 @@ struct Opt {
#[clap(short, long, env = "SNITCH_SEVERITY", default_value = "Error")] #[clap(short, long, env = "SNITCH_SEVERITY", default_value = "Error")]
severity: Severity, severity: Severity,
/// Name of this service /// Treat each line of the message as its own log message.
#[clap(short, long, env = "SNITCH_LINES")]
lines: bool,
/// Log message to snitch. If this is omitted, the message will be read from stdin.
#[clap(env = "SNITCH_MESSAGE")] #[clap(env = "SNITCH_MESSAGE")]
message: String, message: Option<String>,
} }
fn main() { fn main() {
@ -27,15 +33,55 @@ fn main() {
eprintln!("snitch error: {e:?}"); eprintln!("snitch error: {e:?}");
} }
} }
fn run() -> eyre::Result<()> { fn run() -> eyre::Result<()> {
let opt = Opt::parse(); let opt = Opt::parse();
color_eyre::install()?; color_eyre::install()?;
if let Some(message) = &opt.message {
log_from(&opt, message.as_bytes())
} else {
let stdin = stdin();
log_from(&opt, stdin.lock())
}
}
/// Consume a reader and log everything to snitch
fn log_from(opt: &Opt, r: impl BufRead) -> eyre::Result<()> {
if opt.lines {
log_lines(opt, r)
} else {
log_reader(opt, r)
}
}
/// Consume a reader and log everything as a single message to snitch
fn log_reader(opt: &Opt, mut r: impl BufRead) -> eyre::Result<()> {
let mut s = String::new();
r.read_to_string(&mut s)?;
log_message(opt, &s)
}
/// Log each line from a reader to snitch
fn log_lines(opt: &Opt, r: impl BufRead) -> eyre::Result<()> {
for line in r.lines() {
let line = line.wrap_err("Failed to read from stdin")?;
let line = line.trim();
if !line.is_empty() {
log_message(&opt, &line)?;
}
}
Ok(())
}
/// Log a single message to snitch
fn log_message(opt: &Opt, message: &str) -> eyre::Result<()> {
let message = LogMsg { let message = LogMsg {
time: Some(Local::now()), time: Some(Local::now()),
severity: opt.severity, severity: opt.severity,
service: opt.service, service: opt.service.clone(),
message: opt.message, message: message.to_string(),
hostname: probe_hostname(), hostname: probe_hostname(),
file: None, file: None,
line: None, line: None,

View File

@ -4,7 +4,7 @@ use chrono::{DateTime, Local};
use eyre::{eyre, ContextCompat}; use eyre::{eyre, ContextCompat};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub enum Severity { pub enum Severity {
Fatal, Fatal,
Error, Error,