use super::EventWriterConfig;
use crate::{
error::{Error, Result},
event::EventMeta,
protobuf::{
summary::{Audio, Image},
Event, Summary, TensorProto,
},
protobuf_ext::{IntoHistogram, IntoImageList},
record_writer::RecordAsyncWriter,
};
use async_std::{fs::File, io::BufWriter, path::Path};
use futures::io::AsyncWrite;
use std::{borrow::Cow, convert::TryInto, string::ToString};
#[derive(Debug, Clone, PartialEq)]
pub struct EventAsyncWriter<W> {
auto_flush: bool,
events_writer: RecordAsyncWriter<Event, W>,
}
impl EventAsyncWriter<BufWriter<File>> {
pub async fn create<P>(path: P, config: EventWriterConfig) -> Result<Self>
where
P: AsRef<Path>,
{
let writer = BufWriter::new(File::create(path).await?);
Self::from_writer(writer, config)
}
pub async fn from_prefix<'a, 'b, P, S>(
prefix: P,
file_name_suffix: S,
config: EventWriterConfig,
) -> Result<Self>
where
P: Into<Cow<'a, str>>,
S: Into<Cow<'b, str>>,
{
let (dir_prefix, file_name) = super::create_tf_style_path(prefix, file_name_suffix)?;
async_std::fs::create_dir_all(&dir_prefix).await?;
let path = dir_prefix.join(file_name);
Self::create(path, config).await
}
}
impl<W> EventAsyncWriter<W>
where
W: AsyncWrite + Unpin,
{
pub fn from_writer(writer: W, config: EventWriterConfig) -> Result<Self> {
let EventWriterConfig { auto_flush } = config;
Ok(Self {
auto_flush,
events_writer: RecordAsyncWriter::from_writer(writer)?,
})
}
pub async fn write_scalar(
&mut self,
tag: impl ToString,
event_meta: impl Into<EventMeta>,
value: f32,
) -> Result<()> {
let summary = Summary::from_scalar(tag, value)?;
let event = event_meta.into().build_with_summary(summary);
self.events_writer.send(event).await?;
if self.auto_flush {
self.events_writer.flush().await?;
}
Ok(())
}
pub async fn write_histogram(
&mut self,
tag: impl ToString,
event_meta: impl Into<EventMeta>,
histogram: impl IntoHistogram,
) -> Result<()> {
let summary = Summary::from_histogram(tag, histogram)?;
let event = event_meta.into().build_with_summary(summary);
self.events_writer.send(event).await?;
if self.auto_flush {
self.events_writer.flush().await?;
}
Ok(())
}
pub async fn write_tensor(
&mut self,
tag: impl ToString,
event_meta: impl Into<EventMeta>,
tensor: impl TryInto<TensorProto, Error = impl Into<Error>>,
) -> Result<()> {
let summary = Summary::from_tensor(tag, tensor)?;
let event = event_meta.into().build_with_summary(summary);
self.events_writer.send(event).await?;
if self.auto_flush {
self.events_writer.flush().await?;
}
Ok(())
}
pub async fn write_image(
&mut self,
tag: impl ToString,
event_meta: impl Into<EventMeta>,
image: impl TryInto<Image, Error = impl Into<Error>>,
) -> Result<()> {
let summary = Summary::from_image(tag, image)?;
let event = event_meta.into().build_with_summary(summary);
self.events_writer.send(event).await?;
if self.auto_flush {
self.events_writer.flush().await?;
}
Ok(())
}
pub async fn write_image_list(
&mut self,
tag: impl ToString,
event_meta: impl Into<EventMeta>,
images: impl IntoImageList,
) -> Result<()> {
let summary = Summary::from_image_list(tag, images)?;
let event = event_meta.into().build_with_summary(summary);
self.events_writer.send(event).await?;
if self.auto_flush {
self.events_writer.flush().await?;
}
Ok(())
}
pub async fn write_audio(
&mut self,
tag: impl ToString,
event_meta: impl Into<EventMeta>,
audio: impl TryInto<Audio, Error = impl Into<Error>>,
) -> Result<()> {
let summary = Summary::from_audio(tag, audio)?;
let event = event_meta.into().build_with_summary(summary);
self.events_writer.send(event).await?;
if self.auto_flush {
self.events_writer.flush().await?;
}
Ok(())
}
pub async fn write_event(&mut self, event: Event) -> Result<()> {
self.events_writer.send(event).await?;
if self.auto_flush {
self.events_writer.flush().await?;
}
Ok(())
}
pub async fn flush(&mut self) -> Result<()> {
self.events_writer.flush().await?;
Ok(())
}
}