use std::{path::PathBuf, str::FromStr};
use clap::Parser;
use wasmer_wasix::journal::{
copy_journal, FilteredJournalBuilder, LogFileJournal, PrintingJournal,
};
use crate::commands::CliCommand;
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
pub enum FilterOut {
Memory,
Threads,
FileSystem,
Core,
Snapshots,
Networking,
}
impl FromStr for FilterOut {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s.to_lowercase().as_str() {
"mem" | "memory" => Self::Memory,
"thread" | "threads" => Self::Threads,
"fs" | "file" | "filesystem" | "file-system" => Self::FileSystem,
"core" => Self::Core,
"snap" | "snapshot" | "snapshots" => Self::Snapshots,
"net" | "network" | "networking" => Self::Networking,
t => return Err(format!("unknown filter type - {}", t)),
})
}
}
#[derive(Debug, Parser)]
pub struct CmdJournalFilter {
#[clap(index = 1)]
source_path: PathBuf,
#[clap(index = 2)]
target_path: PathBuf,
#[clap(short, long = "filter")]
filters: Vec<FilterOut>,
}
impl CliCommand for CmdJournalFilter {
type Output = ();
fn run(self) -> Result<(), anyhow::Error> {
let mut temp_filename = self
.target_path
.file_name()
.ok_or_else(|| {
anyhow::format_err!(
"The path is not a valid filename - {}",
self.target_path.to_string_lossy()
)
})?
.to_string_lossy()
.to_string();
temp_filename.insert_str(0, ".staging.");
let temp_path = self.target_path.with_file_name(&temp_filename);
std::fs::remove_file(&temp_path).ok();
let source = LogFileJournal::new(self.source_path)?;
let target = LogFileJournal::new(temp_path.clone())?;
let mut builder = FilteredJournalBuilder::new();
for filter in self.filters {
builder = match filter {
FilterOut::Memory => builder.with_ignore_memory(true),
FilterOut::Threads => builder.with_ignore_threads(true),
FilterOut::FileSystem => builder.with_ignore_fs(true),
FilterOut::Core => builder.with_ignore_core(true),
FilterOut::Snapshots => builder.with_ignore_snapshots(true),
FilterOut::Networking => builder.with_ignore_networking(true),
}
}
let target = builder.build(target);
copy_journal(&source, &target)?;
drop(target);
std::fs::rename(temp_path, self.target_path.clone())?;
let journal = LogFileJournal::new(&self.target_path)?;
let printer = PrintingJournal::default();
copy_journal(&journal, &printer)?;
Ok(())
}
}