mongodb 2.8.2

The official MongoDB driver for Rust
Documentation
use bson::oid::ObjectId;

use crate::{
    event::cmap::{
        CmapEventHandler,
        ConnectionCheckedInEvent,
        ConnectionCheckedOutEvent,
        ConnectionCheckoutFailedEvent,
        ConnectionCheckoutFailedReason,
        ConnectionCheckoutStartedEvent,
        ConnectionClosedEvent,
        ConnectionClosedReason,
        ConnectionCreatedEvent,
        ConnectionReadyEvent,
        PoolClearedEvent,
        PoolClosedEvent,
        PoolCreatedEvent,
        PoolReadyEvent,
    },
    trace::{TracingRepresentation, CONNECTION_TRACING_EVENT_TARGET},
};

#[derive(Clone)]
pub(crate) struct ConnectionTracingEventEmitter {
    topology_id: ObjectId,
}

impl ConnectionTracingEventEmitter {
    pub(crate) fn new(topology_id: ObjectId) -> ConnectionTracingEventEmitter {
        Self { topology_id }
    }
}

impl CmapEventHandler for ConnectionTracingEventEmitter {
    fn handle_pool_created_event(&self, event: PoolCreatedEvent) {
        let options_ref = event.options.as_ref();
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            maxIdleTimeMS = options_ref.and_then(|o| o.max_idle_time.map(|m| m.as_millis())),
            maxPoolSize = options_ref.and_then(|o| o.max_pool_size),
            minPoolSize = options_ref.and_then(|o| o.min_pool_size),
            "Connection pool created",
        );
    }

    fn handle_pool_ready_event(&self, event: PoolReadyEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            "Connection pool ready",
        );
    }

    fn handle_pool_cleared_event(&self, event: PoolClearedEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            serviceId = event.service_id.map(|id| id.tracing_representation()),
            "Connection pool cleared",
        );
    }

    fn handle_pool_closed_event(&self, event: PoolClosedEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            "Connection pool closed",
        );
    }

    fn handle_connection_created_event(&self, event: ConnectionCreatedEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            driverConnectionId = event.connection_id,
            "Connection created",
        );
    }

    fn handle_connection_ready_event(&self, event: ConnectionReadyEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            driverConnectionId = event.connection_id,
            durationMS = event.duration.as_millis(),
            "Connection ready",
        );
    }

    fn handle_connection_closed_event(&self, event: ConnectionClosedEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            driverConnectionId = event.connection_id,
            reason = event.reason.tracing_representation(),
            error = event.error.map(|e| e.tracing_representation()),
            "Connection closed",
        );
    }

    fn handle_connection_checkout_started_event(&self, event: ConnectionCheckoutStartedEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            "Connection checkout started",
        );
    }

    fn handle_connection_checkout_failed_event(&self, event: ConnectionCheckoutFailedEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            reason = event.reason.tracing_representation(),
            error = event.error.map(|e| e.tracing_representation()),
            durationMS = event.duration.as_millis(),
            "Connection checkout failed",
        );
    }

    fn handle_connection_checked_out_event(&self, event: ConnectionCheckedOutEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            driverConnectionId = event.connection_id,
            durationMS = event.duration.as_millis(),
            "Connection checked out",
        );
    }

    fn handle_connection_checked_in_event(&self, event: ConnectionCheckedInEvent) {
        tracing::debug!(
            target: CONNECTION_TRACING_EVENT_TARGET,
            topologyId = self.topology_id.tracing_representation(),
            serverHost = event.address.host().as_ref(),
            serverPort = event.address.port_tracing_representation(),
            driverConnectionId = event.connection_id,
            "Connection checked in",
        );
    }
}

impl TracingRepresentation for ConnectionClosedReason {
    type Representation = &'static str;

    fn tracing_representation(&self) -> &'static str {
        match self {
            ConnectionClosedReason::Stale => "Connection became stale because the pool was cleared",
            ConnectionClosedReason::Idle => {
                "Connection has been available but unused for longer than the configured max idle \
                 time"
            }
            ConnectionClosedReason::Error => "An error occurred while using the connection",
            ConnectionClosedReason::Dropped => "Connection was dropped during an operation",
            ConnectionClosedReason::PoolClosed => "Connection pool was closed",
        }
    }
}

impl TracingRepresentation for ConnectionCheckoutFailedReason {
    type Representation = &'static str;

    fn tracing_representation(&self) -> &'static str {
        match self {
            ConnectionCheckoutFailedReason::Timeout => {
                "Failed to establish a new connection within connectTimeoutMS"
            }
            ConnectionCheckoutFailedReason::ConnectionError => {
                "An error occurred while trying to establish a new connection"
            }
        }
    }
}