1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
//! ErrorLog trait and default implementations
//!
use std::fmt;
use std::net::SocketAddr;
use std::marker::PhantomData;

use config::{NewErrorLog};

/// A reason connection pool being shut down
///
/// This value is passed to ``ErrorLog::pool_shutting_down`` method.
#[derive(Debug)]
pub enum ShutdownReason {
    /// Request stream is shutting down
    ///
    /// This usually means that all clones of ``queue::Pool`` object are
    /// destroyed
    RequestStreamClosed,
    /// Address stream is closed
    ///
    /// Shutting down address stream is commonly used to force shut down
    /// connection pool, even if there are users. Users will get an error
    /// on the next `start_send`.
    AddressStreamClosed,
    #[doc(hidden)]
    __Nonexhaustive,
}


/// The thrait that has appropriate hooks for logging different events
///
/// There is a default ``WarnLogger``, but the idea is that you may give
/// connection pool a name, change logging levels, and do other interesting
/// stuff in your own error log handler.
pub trait ErrorLog {
    /// Connection error type that is returned by connect/hanshake function
    type ConnectionError;
    /// Error when sending request returned by Sink
    type SinkError;
    /// Error when establishing a new connection
    fn connection_error(&self, _addr: SocketAddr, _e: Self::ConnectionError) {}
    /// Error when sending a request
    ///
    /// This also means connection is closed
    fn sink_error(&self, _addr: SocketAddr, _e: Self::SinkError) {}
    /// Pool is started to shut down for the specified reason
    fn pool_shutting_down(&self, _reason: ShutdownReason) {}
    /// Pool is fully closed at this moment
    fn pool_closed(&self) {}
}


/// A constructor for a default error logger
pub struct WarnLogger;

/// An instance of default error logger
pub struct WarnLoggerInstance<C, S>(PhantomData<* const (C, S)>);

impl<C, S> Clone for WarnLoggerInstance<C, S> {
    fn clone(&self) -> Self {
        WarnLoggerInstance(PhantomData)
    }
}

impl<C: fmt::Display, S: fmt::Display> NewErrorLog<C, S> for WarnLogger {
    type ErrorLog = WarnLoggerInstance<C, S>;
    fn construct(self) -> Self::ErrorLog {
        WarnLoggerInstance(PhantomData)
    }
}

impl<C, S> ErrorLog for WarnLoggerInstance<C, S>
    where C: fmt::Display,
          S: fmt::Display,
{
    type ConnectionError = C;
    type SinkError = S;
    fn connection_error(&self, addr: SocketAddr, e: Self::ConnectionError) {
        warn!("Connecting to {} failed: {}", addr, e);
    }
    fn sink_error(&self, addr: SocketAddr, e: Self::SinkError) {
        warn!("Connection to {} errored: {}", addr, e);
    }
    /// Starting to shut down pool
    fn pool_shutting_down(&self, reason: ShutdownReason) {
        warn!("Shutting down connection pool: {}", reason);
    }
    /// This is triggered when pool done all the work and shut down entirely
    fn pool_closed(&self) {
    }
}

impl fmt::Display for ShutdownReason {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ShutdownReason::*;
        f.write_str(match *self {
            RequestStreamClosed => "request stream closed",
            AddressStreamClosed => "address stream closed",
            __Nonexhaustive => unreachable!(),
        })
    }
}