Skip to content

Commit 97599b5

Browse files
committed
Define a Drain::flush method
This is simpler than the API in slog-rs#332 , but requires more work by slog_async to implement it.
1 parent 79b5770 commit 97599b5

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
@@ -1079,6 +1079,17 @@ where
10791079
let _ = self.drain.log(record, &self.list);
10801080
}
10811081

1082+
/// Flush all pending log records,
1083+
/// blocking until completion.
1084+
///
1085+
/// Will call [`std::io::Write::flush`] if applicable.
1086+
///
1087+
/// Returns [`FlushError::NotSupported`] if the underlying drain does not support [`Drain::flush`].
1088+
#[inline]
1089+
pub fn flush(&self) -> result::Result<(), FlushError> {
1090+
self.drain.flush()
1091+
}
1092+
10821093
/// Get list of key-value pairs assigned to this `Logger`
10831094
pub fn list(&self) -> &OwnedKVList {
10841095
&self.list
@@ -1159,6 +1170,53 @@ where
11591170
fn is_enabled(&self, level: Level) -> bool {
11601171
self.drain.is_enabled(level)
11611172
}
1173+
1174+
#[inline]
1175+
fn flush(&self) -> result::Result<(), FlushError> {
1176+
self.drain.flush()
1177+
}
1178+
}
1179+
1180+
/// An error that occurs when calling [`Drain::flush`].
1181+
#[non_exhaustive]
1182+
#[derive(Debug)]
1183+
pub enum FlushError {
1184+
/// An error that occurs doing IO.
1185+
///
1186+
/// Often triggered by [`std::io::]
1187+
#[cfg(feature = "std")]
1188+
Io(std::io::Error),
1189+
/// Indicates this drain does not support flushing.
1190+
NotSupported,
1191+
}
1192+
#[cfg(feature = "std")]
1193+
impl From<std::io::Error> for FlushError {
1194+
fn from(value: std::io::Error) -> Self {
1195+
FlushError::Io(value)
1196+
}
1197+
}
1198+
#[cfg(has_std_error)]
1199+
impl StdError for FlushError {
1200+
fn source(&self) -> Option<&(dyn StdError + 'static)> {
1201+
match self {
1202+
#[cfg(feature = "std")]
1203+
FlushError::Io(cause) => Some(cause),
1204+
FlushError::NotSupported => None,
1205+
}
1206+
}
1207+
}
1208+
impl fmt::Display for FlushError {
1209+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1210+
match self {
1211+
#[cfg(feature = "std")]
1212+
FlushError::Io(_) => {
1213+
f.write_str("Encountered IO error during flushing")
1214+
}
1215+
FlushError::NotSupported => {
1216+
f.write_str("Drain does not support flushing")
1217+
}
1218+
}
1219+
}
11621220
}
11631221

11641222
// {{{ Drain
@@ -1203,6 +1261,15 @@ pub trait Drain {
12031261
values: &OwnedKVList,
12041262
) -> result::Result<Self::Ok, Self::Err>;
12051263

1264+
/// Flush all pending log records, blocking until completion.
1265+
///
1266+
/// Should call [`std::io::Write::flush`] if applicable.
1267+
///
1268+
/// Returns [`FlushError::NotSupported`] if the drain has not implemented this method.
1269+
fn flush(&self) -> result::Result<(), FlushError> {
1270+
Err(FlushError::NotSupported)
1271+
}
1272+
12061273
/// **Avoid**: Check if messages at the specified log level are **maybe**
12071274
/// enabled for this logger.
12081275
///
@@ -1365,6 +1432,10 @@ impl<'a, D: Drain + 'a> Drain for &'a D {
13651432
fn is_enabled(&self, level: Level) -> bool {
13661433
(**self).is_enabled(level)
13671434
}
1435+
#[inline]
1436+
fn flush(&self) -> result::Result<(), FlushError> {
1437+
(**self).flush()
1438+
}
13681439
}
13691440

13701441
impl<'a, D: Drain + 'a> Drain for &'a mut D {
@@ -1382,6 +1453,10 @@ impl<'a, D: Drain + 'a> Drain for &'a mut D {
13821453
fn is_enabled(&self, level: Level) -> bool {
13831454
(**self).is_enabled(level)
13841455
}
1456+
#[inline]
1457+
fn flush(&self) -> result::Result<(), FlushError> {
1458+
(**self).flush()
1459+
}
13851460
}
13861461

13871462
/// Internal utility module used to "maybe" bound traits
@@ -1543,6 +1618,10 @@ impl<D: Drain + ?Sized> Drain for Box<D> {
15431618
fn is_enabled(&self, level: Level) -> bool {
15441619
(**self).is_enabled(level)
15451620
}
1621+
#[inline]
1622+
fn flush(&self) -> result::Result<(), FlushError> {
1623+
(**self).flush()
1624+
}
15461625
}
15471626

15481627
impl<D: Drain + ?Sized> Drain for Arc<D> {
@@ -1559,6 +1638,10 @@ impl<D: Drain + ?Sized> Drain for Arc<D> {
15591638
fn is_enabled(&self, level: Level) -> bool {
15601639
(**self).is_enabled(level)
15611640
}
1641+
#[inline]
1642+
fn flush(&self) -> result::Result<(), FlushError> {
1643+
(**self).flush()
1644+
}
15621645
}
15631646

15641647
/// `Drain` discarding everything
@@ -1582,6 +1665,10 @@ impl Drain for Discard {
15821665
fn is_enabled(&self, _level: Level) -> bool {
15831666
false
15841667
}
1668+
#[inline]
1669+
fn flush(&self) -> result::Result<(), FlushError> {
1670+
Ok(())
1671+
}
15851672
}
15861673

15871674
/// `Drain` filtering records
@@ -1630,6 +1717,10 @@ where
16301717
*/
16311718
self.0.is_enabled(level)
16321719
}
1720+
#[inline]
1721+
fn flush(&self) -> result::Result<(), FlushError> {
1722+
self.0.flush()
1723+
}
16331724
}
16341725

16351726
/// `Drain` filtering records by `Record` logging level
@@ -1670,6 +1761,10 @@ impl<D: Drain> Drain for LevelFilter<D> {
16701761
fn is_enabled(&self, level: Level) -> bool {
16711762
level.is_at_least(self.1) && self.0.is_enabled(level)
16721763
}
1764+
#[inline]
1765+
fn flush(&self) -> result::Result<(), FlushError> {
1766+
self.0.flush()
1767+
}
16731768
}
16741769

16751770
/// `Drain` mapping error returned by another `Drain`
@@ -1711,6 +1806,10 @@ impl<D: Drain, E> Drain for MapError<D, E> {
17111806
fn is_enabled(&self, level: Level) -> bool {
17121807
self.drain.is_enabled(level)
17131808
}
1809+
#[inline]
1810+
fn flush(&self) -> result::Result<(), FlushError> {
1811+
self.drain.flush()
1812+
}
17141813
}
17151814

17161815
/// `Drain` duplicating records into two other `Drain`s
@@ -1750,6 +1849,17 @@ impl<D1: Drain, D2: Drain> Drain for Duplicate<D1, D2> {
17501849
fn is_enabled(&self, level: Level) -> bool {
17511850
self.0.is_enabled(level) || self.1.is_enabled(level)
17521851
}
1852+
/// Flush both drains.
1853+
///
1854+
/// Will return [`FlushError::NotSupported`] if either drain does not support flushing.
1855+
/// If one drain supports flushing and the other does not,
1856+
/// it is unspecified whether or not anything will be flushed at all.
1857+
#[inline]
1858+
fn flush(&self) -> result::Result<(), FlushError> {
1859+
self.0.flush()?;
1860+
self.1.flush()?;
1861+
Ok(())
1862+
}
17531863
}
17541864

17551865
/// `Drain` panicking on error
@@ -1796,6 +1906,10 @@ where
17961906
fn is_enabled(&self, level: Level) -> bool {
17971907
self.0.is_enabled(level)
17981908
}
1909+
#[inline]
1910+
fn flush(&self) -> result::Result<(), FlushError> {
1911+
self.0.flush()
1912+
}
17991913
}
18001914

18011915
/// `Drain` ignoring result
@@ -1832,6 +1946,11 @@ impl<D: Drain> Drain for IgnoreResult<D> {
18321946
fn is_enabled(&self, level: Level) -> bool {
18331947
self.drain.is_enabled(level)
18341948
}
1949+
1950+
#[inline]
1951+
fn flush(&self) -> result::Result<(), FlushError> {
1952+
self.drain.flush()
1953+
}
18351954
}
18361955

18371956
/// Error returned by `Mutex<D : Drain>`
@@ -1927,6 +2046,13 @@ impl<D: Drain> Drain for std::sync::Mutex<D> {
19272046
fn is_enabled(&self, level: Level) -> bool {
19282047
self.lock().ok().map_or(true, |lock| lock.is_enabled(level))
19292048
}
2049+
#[inline]
2050+
fn flush(&self) -> result::Result<(), FlushError> {
2051+
let guard = self.lock().map_err(|_poison| {
2052+
std::io::Error::new(std::io::ErrorKind::Other, "Mutex is poisoned")
2053+
})?;
2054+
guard.flush()
2055+
}
19302056
}
19312057

19322058
#[cfg(feature = "parking_lot_0_12")]

0 commit comments

Comments
 (0)