Skip to content

Commit fb98190

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 79b5770 commit fb98190

File tree

1 file changed

+125
-0
lines changed

1 file changed

+125
-0
lines changed

src/lib.rs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,16 @@ where
10791079
let _ = self.drain.log(record, &self.list);
10801080
}
10811081

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

11641221
// {{{ Drain
@@ -1203,6 +1260,15 @@ pub trait Drain {
12031260
values: &OwnedKVList,
12041261
) -> result::Result<Self::Ok, Self::Err>;
12051262

1263+
/// Flush all pending log records, blocking until completion.
1264+
///
1265+
/// Should call [`std::io::Write::flush`] if applicable.
1266+
///
1267+
/// Returns [`FlushError::NotSupported`] if the drain has not implemented this method.
1268+
fn flush(&self) -> result::Result<(), FlushError> {
1269+
Err(FlushError::NotSupported)
1270+
}
1271+
12061272
/// **Avoid**: Check if messages at the specified log level are **maybe**
12071273
/// enabled for this logger.
12081274
///
@@ -1365,6 +1431,10 @@ impl<'a, D: Drain + 'a> Drain for &'a D {
13651431
fn is_enabled(&self, level: Level) -> bool {
13661432
(**self).is_enabled(level)
13671433
}
1434+
#[inline]
1435+
fn flush(&self) -> result::Result<(), FlushError> {
1436+
(**self).flush()
1437+
}
13681438
}
13691439

13701440
impl<'a, D: Drain + 'a> Drain for &'a mut D {
@@ -1382,6 +1452,10 @@ impl<'a, D: Drain + 'a> Drain for &'a mut D {
13821452
fn is_enabled(&self, level: Level) -> bool {
13831453
(**self).is_enabled(level)
13841454
}
1455+
#[inline]
1456+
fn flush(&self) -> result::Result<(), FlushError> {
1457+
(**self).flush()
1458+
}
13851459
}
13861460

13871461
/// Internal utility module used to "maybe" bound traits
@@ -1543,6 +1617,10 @@ impl<D: Drain + ?Sized> Drain for Box<D> {
15431617
fn is_enabled(&self, level: Level) -> bool {
15441618
(**self).is_enabled(level)
15451619
}
1620+
#[inline]
1621+
fn flush(&self) -> result::Result<(), FlushError> {
1622+
(**self).flush()
1623+
}
15461624
}
15471625

15481626
impl<D: Drain + ?Sized> Drain for Arc<D> {
@@ -1559,6 +1637,10 @@ impl<D: Drain + ?Sized> Drain for Arc<D> {
15591637
fn is_enabled(&self, level: Level) -> bool {
15601638
(**self).is_enabled(level)
15611639
}
1640+
#[inline]
1641+
fn flush(&self) -> result::Result<(), FlushError> {
1642+
(**self).flush()
1643+
}
15621644
}
15631645

15641646
/// `Drain` discarding everything
@@ -1582,6 +1664,10 @@ impl Drain for Discard {
15821664
fn is_enabled(&self, _level: Level) -> bool {
15831665
false
15841666
}
1667+
#[inline]
1668+
fn flush(&self) -> result::Result<(), FlushError> {
1669+
Ok(())
1670+
}
15851671
}
15861672

15871673
/// `Drain` filtering records
@@ -1630,6 +1716,10 @@ where
16301716
*/
16311717
self.0.is_enabled(level)
16321718
}
1719+
#[inline]
1720+
fn flush(&self) -> result::Result<(), FlushError> {
1721+
self.0.flush()
1722+
}
16331723
}
16341724

16351725
/// `Drain` filtering records by `Record` logging level
@@ -1670,6 +1760,10 @@ impl<D: Drain> Drain for LevelFilter<D> {
16701760
fn is_enabled(&self, level: Level) -> bool {
16711761
level.is_at_least(self.1) && self.0.is_enabled(level)
16721762
}
1763+
#[inline]
1764+
fn flush(&self) -> result::Result<(), FlushError> {
1765+
self.0.flush()
1766+
}
16731767
}
16741768

16751769
/// `Drain` mapping error returned by another `Drain`
@@ -1711,6 +1805,10 @@ impl<D: Drain, E> Drain for MapError<D, E> {
17111805
fn is_enabled(&self, level: Level) -> bool {
17121806
self.drain.is_enabled(level)
17131807
}
1808+
#[inline]
1809+
fn flush(&self) -> result::Result<(), FlushError> {
1810+
self.drain.flush()
1811+
}
17141812
}
17151813

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

17551864
/// `Drain` panicking on error
@@ -1796,6 +1905,10 @@ where
17961905
fn is_enabled(&self, level: Level) -> bool {
17971906
self.0.is_enabled(level)
17981907
}
1908+
#[inline]
1909+
fn flush(&self) -> result::Result<(), FlushError> {
1910+
self.0.flush()
1911+
}
17991912
}
18001913

18011914
/// `Drain` ignoring result
@@ -1832,6 +1945,11 @@ impl<D: Drain> Drain for IgnoreResult<D> {
18321945
fn is_enabled(&self, level: Level) -> bool {
18331946
self.drain.is_enabled(level)
18341947
}
1948+
1949+
#[inline]
1950+
fn flush(&self) -> result::Result<(), FlushError> {
1951+
self.drain.flush()
1952+
}
18351953
}
18361954

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

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

0 commit comments

Comments
 (0)