Skip to content

Commit 5eda5fd

Browse files
committed
Define a Drain::flush method
This is simpler than the API in #332 , but requires more work by slog_async to implement it.
1 parent 69e7310 commit 5eda5fd

File tree

1 file changed

+126
-0
lines changed

1 file changed

+126
-0
lines changed

src/lib.rs

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,17 @@ where
10721072
let _ = self.drain.log(record, &self.list);
10731073
}
10741074

1075+
/// Flush all pending log records,
1076+
/// blocking until competion.
1077+
///
1078+
/// Will call [`std::io::Write::flush`] if applicable.
1079+
///
1080+
/// Returns [`FlushError::NotSupported`] if the underlying drain does not support [`Drain::flush`].
1081+
#[inline]
1082+
pub fn flush(&self) -> result::Result<(), FlushError> {
1083+
self.drain.flush()
1084+
}
1085+
10751086
/// Get list of key-value pairs assigned to this `Logger`
10761087
pub fn list(&self) -> &OwnedKVList {
10771088
&self.list
@@ -1152,6 +1163,53 @@ where
11521163
fn is_enabled(&self, level: Level) -> bool {
11531164
self.drain.is_enabled(level)
11541165
}
1166+
1167+
#[inline]
1168+
fn flush(&self) -> result::Result<(), FlushError> {
1169+
self.drain.flush()
1170+
}
1171+
}
1172+
1173+
/// An error that occurs when calling [`Drain::flush`].
1174+
#[non_exhaustive]
1175+
#[derive(Debug)]
1176+
pub enum FlushError {
1177+
/// An error that occurs doing IO.
1178+
///
1179+
/// Often triggered by [`std::io::]
1180+
#[cfg(feature = "std")]
1181+
Io(std::io::Error),
1182+
/// Indicates this drain does not support flushing.
1183+
NotSupported,
1184+
}
1185+
#[cfg(feature = "std")]
1186+
impl From<std::io::Error> for FlushError {
1187+
fn from(value: std::io::Error) -> Self {
1188+
FlushError::Io(value)
1189+
}
1190+
}
1191+
#[cfg(has_std_error)]
1192+
impl StdError for FlushError {
1193+
fn source(&self) -> Option<&(dyn StdError + 'static)> {
1194+
match self {
1195+
#[cfg(feature = "std")]
1196+
FlushError::Io(cause) => Some(cause),
1197+
FlushError::NotSupported => None,
1198+
}
1199+
}
1200+
}
1201+
impl fmt::Display for FlushError {
1202+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1203+
match self {
1204+
#[cfg(feature = "std")]
1205+
FlushError::Io(_) => {
1206+
f.write_str("Encountered IO error during flushing")
1207+
}
1208+
FlushError::NotSupported => {
1209+
f.write_str("Drain does not support flushing")
1210+
}
1211+
}
1212+
}
11551213
}
11561214

11571215
// {{{ Drain
@@ -1196,6 +1254,15 @@ pub trait Drain {
11961254
values: &OwnedKVList,
11971255
) -> result::Result<Self::Ok, Self::Err>;
11981256

1257+
/// Flush all pending log records, blocking until competion.
1258+
///
1259+
/// Should call [`std::io::Write::flush`] if applicable.
1260+
///
1261+
/// Returns [`FlushError::NotSupported`] if the drain has not implemented this method.
1262+
fn flush(&self) -> result::Result<(), FlushError> {
1263+
Err(FlushError::NotSupported)
1264+
}
1265+
11991266
/// **Avoid**: Check if messages at the specified log level are **maybe**
12001267
/// enabled for this logger.
12011268
///
@@ -1358,6 +1425,10 @@ impl<'a, D: Drain + 'a> Drain for &'a D {
13581425
fn is_enabled(&self, level: Level) -> bool {
13591426
(**self).is_enabled(level)
13601427
}
1428+
#[inline]
1429+
fn flush(&self) -> result::Result<(), FlushError> {
1430+
(**self).flush()
1431+
}
13611432
}
13621433

13631434
impl<'a, D: Drain + 'a> Drain for &'a mut D {
@@ -1375,6 +1446,10 @@ impl<'a, D: Drain + 'a> Drain for &'a mut D {
13751446
fn is_enabled(&self, level: Level) -> bool {
13761447
(**self).is_enabled(level)
13771448
}
1449+
#[inline]
1450+
fn flush(&self) -> result::Result<(), FlushError> {
1451+
(**self).flush()
1452+
}
13781453
}
13791454

13801455
/// Internal utility module used to "maybe" bound traits
@@ -1536,6 +1611,10 @@ impl<D: Drain + ?Sized> Drain for Box<D> {
15361611
fn is_enabled(&self, level: Level) -> bool {
15371612
(**self).is_enabled(level)
15381613
}
1614+
#[inline]
1615+
fn flush(&self) -> result::Result<(), FlushError> {
1616+
(**self).flush()
1617+
}
15391618
}
15401619

15411620
impl<D: Drain + ?Sized> Drain for Arc<D> {
@@ -1552,6 +1631,10 @@ impl<D: Drain + ?Sized> Drain for Arc<D> {
15521631
fn is_enabled(&self, level: Level) -> bool {
15531632
(**self).is_enabled(level)
15541633
}
1634+
#[inline]
1635+
fn flush(&self) -> result::Result<(), FlushError> {
1636+
(**self).flush()
1637+
}
15551638
}
15561639

15571640
/// `Drain` discarding everything
@@ -1575,6 +1658,10 @@ impl Drain for Discard {
15751658
fn is_enabled(&self, _level: Level) -> bool {
15761659
false
15771660
}
1661+
#[inline]
1662+
fn flush(&self) -> result::Result<(), FlushError> {
1663+
Ok(())
1664+
}
15781665
}
15791666

15801667
/// `Drain` filtering records
@@ -1623,6 +1710,10 @@ where
16231710
*/
16241711
self.0.is_enabled(level)
16251712
}
1713+
#[inline]
1714+
fn flush(&self) -> result::Result<(), FlushError> {
1715+
self.0.flush()
1716+
}
16261717
}
16271718

16281719
/// `Drain` filtering records by `Record` logging level
@@ -1663,6 +1754,10 @@ impl<D: Drain> Drain for LevelFilter<D> {
16631754
fn is_enabled(&self, level: Level) -> bool {
16641755
level.is_at_least(self.1) && self.0.is_enabled(level)
16651756
}
1757+
#[inline]
1758+
fn flush(&self) -> result::Result<(), FlushError> {
1759+
self.0.flush()
1760+
}
16661761
}
16671762

16681763
/// `Drain` mapping error returned by another `Drain`
@@ -1704,6 +1799,10 @@ impl<D: Drain, E> Drain for MapError<D, E> {
17041799
fn is_enabled(&self, level: Level) -> bool {
17051800
self.drain.is_enabled(level)
17061801
}
1802+
#[inline]
1803+
fn flush(&self) -> result::Result<(), FlushError> {
1804+
self.drain.flush()
1805+
}
17071806
}
17081807

17091808
/// `Drain` duplicating records into two other `Drain`s
@@ -1743,6 +1842,17 @@ impl<D1: Drain, D2: Drain> Drain for Duplicate<D1, D2> {
17431842
fn is_enabled(&self, level: Level) -> bool {
17441843
self.0.is_enabled(level) || self.1.is_enabled(level)
17451844
}
1845+
/// Flush both drains.
1846+
///
1847+
/// Will return [`FlushError::NotSupported`] if either drain does not support flushing.
1848+
/// If one drain supports flushing and the other does not,
1849+
/// it is unspecified whether or not anything will be flushed at all.
1850+
#[inline]
1851+
fn flush(&self) -> result::Result<(), FlushError> {
1852+
self.0.flush()?;
1853+
self.1.flush()?;
1854+
Ok(())
1855+
}
17461856
}
17471857

17481858
/// `Drain` panicking on error
@@ -1789,6 +1899,10 @@ where
17891899
fn is_enabled(&self, level: Level) -> bool {
17901900
self.0.is_enabled(level)
17911901
}
1902+
#[inline]
1903+
fn flush(&self) -> result::Result<(), FlushError> {
1904+
self.0.flush()
1905+
}
17921906
}
17931907

17941908
/// `Drain` ignoring result
@@ -1825,6 +1939,11 @@ impl<D: Drain> Drain for IgnoreResult<D> {
18251939
fn is_enabled(&self, level: Level) -> bool {
18261940
self.drain.is_enabled(level)
18271941
}
1942+
1943+
#[inline]
1944+
fn flush(&self) -> result::Result<(), FlushError> {
1945+
self.drain.flush()
1946+
}
18281947
}
18291948

18301949
/// Error returned by `Mutex<D : Drain>`
@@ -1920,6 +2039,13 @@ impl<D: Drain> Drain for std::sync::Mutex<D> {
19202039
fn is_enabled(&self, level: Level) -> bool {
19212040
self.lock().ok().map_or(true, |lock| lock.is_enabled(level))
19222041
}
2042+
#[inline]
2043+
fn flush(&self) -> result::Result<(), FlushError> {
2044+
let guard = self.lock().map_err(|_poison| {
2045+
std::io::Error::new(std::io::ErrorKind::Other, "Mutex is poisoned")
2046+
})?;
2047+
guard.flush()
2048+
}
19232049
}
19242050
// }}}
19252051

0 commit comments

Comments
 (0)