use super::*;
#[derive(PartialEq)]
pub enum IterExecResult {
Success,
Skip,
}
pub trait Dumper {
fn dump_model(
&self,
ctx: &CommonFieldContext,
model: &model::Model,
output: &mut dyn Write,
round: &mut usize,
comma_flag: bool,
) -> Result<IterExecResult>;
}
pub fn dump_timeseries(
mut advance: Advance,
time_begin: SystemTime,
time_end: SystemTime,
dumper: &dyn Dumper,
output: &mut dyn Write,
output_format: Option<OutputFormat>,
br: Option<String>,
errs: Receiver<Error>,
) -> Result<()> {
let mut model = match advance.jump_sample_to(time_begin) {
Some(m) => m,
None => bail!(
"No initial sample could be found!\n\
You may have provided a time in the future or no data was recorded during the provided time. \
Please check your input and timezone.\n\
If you are using remote, please make sure the below service on target host is running."
),
};
cliutil::check_initial_sample_time_in_time_range(model.timestamp, time_begin, time_end)?;
let json = output_format == Some(OutputFormat::Json);
let csv = output_format == Some(OutputFormat::Csv);
let openmetrics = output_format == Some(OutputFormat::OpenMetrics);
let mut round = 0;
if json {
write!(output, "[")?;
}
loop {
if let Ok(e) = errs.try_recv() {
bail!(e);
}
let ctx = CommonFieldContext {
timestamp: model
.timestamp
.duration_since(SystemTime::UNIX_EPOCH)?
.as_secs() as i64,
hostname: model.system.hostname.clone(),
};
let comma_flag = round != 0;
let res = match dumper.dump_model(&ctx, &model, output, &mut round, comma_flag) {
Ok(res) => res,
Err(e) => {
if e.downcast_ref::<std::io::Error>()
.map_or(false, |e| e.kind() == std::io::ErrorKind::BrokenPipe)
{
return Ok(());
} else {
return Err(e);
}
}
};
if advance.get_next_ts() > time_end {
break;
}
model = match advance.advance(Direction::Forward) {
Some(m) => m,
None => break,
};
if res == IterExecResult::Skip {
continue;
}
if json {
writeln!(output)?;
} else if br.is_some() && !csv {
writeln!(output, "{}", br.as_ref().unwrap())?;
}
}
if json {
write!(output, "]")?;
} else if openmetrics {
writeln!(output, "# EOF")?;
}
cliutil::check_final_sample_time_with_requested_time(model.timestamp, time_end);
Ok(())
}