Skip to content

Commit 9a01e11

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 9a01e11

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
@@ -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,52 @@ 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+
FlushError::Io(_) => {
1205+
f.write_str("Encountered IO error during flushing")
1206+
}
1207+
FlushError::NotSupported => {
1208+
f.write_str("Drain does not support flushing")
1209+
}
1210+
}
1211+
}
11551212
}
11561213

11571214
// {{{ Drain
@@ -1196,6 +1253,15 @@ pub trait Drain {
11961253
values: &OwnedKVList,
11971254
) -> result::Result<Self::Ok, Self::Err>;
11981255

1256+
/// Flush all pending log records, blocking until competion.
1257+
///
1258+
/// Should call [`std::io::Write::flush`] if applicable.
1259+
///
1260+
/// Returns [`FlushError::NotSupported`] if the drain has not implemented this method.
1261+
fn flush(&self) -> result::Result<(), FlushError> {
1262+
Err(FlushError::NotSupported)
1263+
}
1264+
11991265
/// **Avoid**: Check if messages at the specified log level are **maybe**
12001266
/// enabled for this logger.
12011267
///
@@ -1358,6 +1424,10 @@ impl<'a, D: Drain + 'a> Drain for &'a D {
13581424
fn is_enabled(&self, level: Level) -> bool {
13591425
(**self).is_enabled(level)
13601426
}
1427+
#[inline]
1428+
fn flush(&self) -> result::Result<(), FlushError> {
1429+
(**self).flush()
1430+
}
13611431
}
13621432

13631433
impl<'a, D: Drain + 'a> Drain for &'a mut D {
@@ -1375,6 +1445,10 @@ impl<'a, D: Drain + 'a> Drain for &'a mut D {
13751445
fn is_enabled(&self, level: Level) -> bool {
13761446
(**self).is_enabled(level)
13771447
}
1448+
#[inline]
1449+
fn flush(&self) -> result::Result<(), FlushError> {
1450+
(**self).flush()
1451+
}
13781452
}
13791453

13801454
/// Internal utility module used to "maybe" bound traits
@@ -1536,6 +1610,10 @@ impl<D: Drain + ?Sized> Drain for Box<D> {
15361610
fn is_enabled(&self, level: Level) -> bool {
15371611
(**self).is_enabled(level)
15381612
}
1613+
#[inline]
1614+
fn flush(&self) -> result::Result<(), FlushError> {
1615+
(**self).flush()
1616+
}
15391617
}
15401618

15411619
impl<D: Drain + ?Sized> Drain for Arc<D> {
@@ -1552,6 +1630,10 @@ impl<D: Drain + ?Sized> Drain for Arc<D> {
15521630
fn is_enabled(&self, level: Level) -> bool {
15531631
(**self).is_enabled(level)
15541632
}
1633+
#[inline]
1634+
fn flush(&self) -> result::Result<(), FlushError> {
1635+
(**self).flush()
1636+
}
15551637
}
15561638

15571639
/// `Drain` discarding everything
@@ -1575,6 +1657,10 @@ impl Drain for Discard {
15751657
fn is_enabled(&self, _level: Level) -> bool {
15761658
false
15771659
}
1660+
#[inline]
1661+
fn flush(&self) -> result::Result<(), FlushError> {
1662+
Ok(())
1663+
}
15781664
}
15791665

15801666
/// `Drain` filtering records
@@ -1623,6 +1709,10 @@ where
16231709
*/
16241710
self.0.is_enabled(level)
16251711
}
1712+
#[inline]
1713+
fn flush(&self) -> result::Result<(), FlushError> {
1714+
self.0.flush()
1715+
}
16261716
}
16271717

16281718
/// `Drain` filtering records by `Record` logging level
@@ -1663,6 +1753,10 @@ impl<D: Drain> Drain for LevelFilter<D> {
16631753
fn is_enabled(&self, level: Level) -> bool {
16641754
level.is_at_least(self.1) && self.0.is_enabled(level)
16651755
}
1756+
#[inline]
1757+
fn flush(&self) -> result::Result<(), FlushError> {
1758+
self.0.flush()
1759+
}
16661760
}
16671761

16681762
/// `Drain` mapping error returned by another `Drain`
@@ -1704,6 +1798,10 @@ impl<D: Drain, E> Drain for MapError<D, E> {
17041798
fn is_enabled(&self, level: Level) -> bool {
17051799
self.drain.is_enabled(level)
17061800
}
1801+
#[inline]
1802+
fn flush(&self) -> result::Result<(), FlushError> {
1803+
self.drain.flush()
1804+
}
17071805
}
17081806

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

17481857
/// `Drain` panicking on error
@@ -1789,6 +1898,10 @@ where
17891898
fn is_enabled(&self, level: Level) -> bool {
17901899
self.0.is_enabled(level)
17911900
}
1901+
#[inline]
1902+
fn flush(&self) -> result::Result<(), FlushError> {
1903+
self.0.flush()
1904+
}
17921905
}
17931906

17941907
/// `Drain` ignoring result
@@ -1825,6 +1938,11 @@ impl<D: Drain> Drain for IgnoreResult<D> {
18251938
fn is_enabled(&self, level: Level) -> bool {
18261939
self.drain.is_enabled(level)
18271940
}
1941+
1942+
#[inline]
1943+
fn flush(&self) -> result::Result<(), FlushError> {
1944+
self.drain.flush()
1945+
}
18281946
}
18291947

18301948
/// Error returned by `Mutex<D : Drain>`
@@ -1920,6 +2038,13 @@ impl<D: Drain> Drain for std::sync::Mutex<D> {
19202038
fn is_enabled(&self, level: Level) -> bool {
19212039
self.lock().ok().map_or(true, |lock| lock.is_enabled(level))
19222040
}
2041+
#[inline]
2042+
fn flush(&self) -> result::Result<(), FlushError> {
2043+
let guard = self.lock().map_err(|_poison| {
2044+
std::io::Error::new(std::io::ErrorKind::Other, "Mutex is poisoned")
2045+
})?;
2046+
guard.flush()
2047+
}
19232048
}
19242049
// }}}
19252050

0 commit comments

Comments
 (0)