diff --git a/proxmox-syslog-api/src/api_types.rs b/proxmox-syslog-api/src/api_types.rs index 1a5702d6..01341241 100644 --- a/proxmox-syslog-api/src/api_types.rs +++ b/proxmox-syslog-api/src/api_types.rs @@ -38,7 +38,7 @@ use proxmox_schema::api_types::SYSTEMD_DATETIME_FORMAT; }, )] #[derive(Clone, PartialEq, Serialize, Deserialize)] -/// Syslog filtering options. +/// Syslog API filtering options. pub struct SyslogFilter { pub start: Option, pub limit: Option, @@ -56,3 +56,45 @@ pub struct SyslogLine { /// Line text. pub t: String, } + +#[api( + properties: { + since: { + type: Integer, + optional: true, + description: "Display all log since this UNIX epoch. Conflicts with 'startcursor'.", + minimum: 0, + }, + until: { + type: Integer, + optional: true, + description: "Display all log until this UNIX epoch. Conflicts with 'endcursor'.", + minimum: 0, + }, + lastentries: { + type: Integer, + optional: true, + description: "Limit to the last X lines. Conflicts with a range.", + minimum: 0, + }, + startcursor: { + type: String, + description: "Start after the given Cursor. Conflicts with 'since'.", + optional: true, + }, + endcursor: { + type: String, + description: "End before the given Cursor. Conflicts with 'until'", + optional: true, + }, + } +)] +#[derive(Clone, PartialEq, Serialize, Deserialize)] +/// Journal API filtering options. +pub struct JournalFilter { + pub since: Option, + pub until: Option, + pub lastentries: Option, + pub startcursor: Option, + pub endcursor: Option, +} diff --git a/proxmox-syslog-api/src/journal.rs b/proxmox-syslog-api/src/journal.rs index 73b5c96d..d7c6ef9c 100644 --- a/proxmox-syslog-api/src/journal.rs +++ b/proxmox-syslog-api/src/journal.rs @@ -1,10 +1,18 @@ +use std::io::{BufRead, BufReader}; use std::process::{Command, Stdio}; use anyhow::Error; -use super::{SyslogFilter, SyslogLine}; +use super::{JournalFilter, SyslogFilter, SyslogLine}; -pub fn dump_journal(filter: SyslogFilter) -> Result<(u64, Vec), Error> { +/// Syslog API implementation +/// +/// The syslog api uses `journalctl' to get the log entries, and +/// uses paging to limit the amount of data returned (start, limit). +/// +/// Note: Please use [dump_journal] for live view, because that is more performant +/// for that case. +pub fn dump_syslog(filter: SyslogFilter) -> Result<(u64, Vec), Error> { let mut args = vec!["-o", "short", "--no-pager"]; if let Some(service) = &filter.service { @@ -71,3 +79,65 @@ pub fn dump_journal(filter: SyslogFilter) -> Result<(u64, Vec), Erro Ok((count, lines)) } + +/// Journal API implementation +/// +/// The journal api uses `mini-journalreader' binary to get the log entries. +/// The cursor based api allows to implement live view efficiently. +pub fn dump_journal(filter: JournalFilter) -> Result, Error> { + let mut args = vec![]; + + if let Some(lastentries) = filter.lastentries { + args.push(String::from("-n")); + args.push(format!("{}", lastentries)); + } + + if let Some(since) = filter.since { + args.push(String::from("-b")); + args.push(since.to_string()); + } + + if let Some(until) = filter.until { + args.push(String::from("-e")); + args.push(until.to_string()); + } + + if let Some(startcursor) = &filter.startcursor { + args.push(String::from("-f")); + args.push(startcursor.to_string()); + } + + if let Some(endcursor) = &filter.endcursor { + args.push(String::from("-t")); + args.push(endcursor.to_string()); + } + + let mut lines: Vec = vec![]; + + let mut child = Command::new("mini-journalreader") + .args(&args) + .stdout(Stdio::piped()) + .spawn()?; + + if let Some(ref mut stdout) = child.stdout { + for line in BufReader::new(stdout).lines() { + match line { + Ok(line) => { + lines.push(line); + } + Err(err) => { + log::error!("reading journal failed: {}", err); + let _ = child.kill(); + break; + } + } + } + } + + let status = child.wait().unwrap(); + if !status.success() { + log::error!("journalctl failed with {}", status); + } + + Ok(lines) +} diff --git a/proxmox-syslog-api/src/lib.rs b/proxmox-syslog-api/src/lib.rs index 4dd5565a..cf40489b 100644 --- a/proxmox-syslog-api/src/lib.rs +++ b/proxmox-syslog-api/src/lib.rs @@ -6,4 +6,4 @@ pub use api_types::*; #[cfg(feature = "impl")] mod journal; #[cfg(feature = "impl")] -pub use journal::dump_journal; +pub use journal::{dump_journal, dump_syslog};