mongodb/trace/
server_selection.rs

1use super::{
2    trace_or_log_enabled,
3    TracingOrLogLevel,
4    TracingRepresentation,
5    SERVER_SELECTION_TRACING_EVENT_TARGET,
6};
7use crate::{
8    error::Error,
9    sdam::{SelectedServer, TopologyDescription},
10    selection_criteria::SelectionCriteria,
11};
12use bson::oid::ObjectId;
13use std::time::{Duration, Instant};
14
15impl TracingRepresentation for SelectionCriteria {
16    type Representation = String;
17
18    fn tracing_representation(&self) -> Self::Representation {
19        self.to_string()
20    }
21}
22
23impl TracingRepresentation for TopologyDescription {
24    type Representation = String;
25
26    fn tracing_representation(&self) -> Self::Representation {
27        self.to_string()
28    }
29}
30
31/// Type responsible for emitting server selection tracing events.
32pub(crate) struct ServerSelectionTracingEventEmitter<'a> {
33    topology_id: ObjectId,
34    criteria: &'a SelectionCriteria,
35    operation_name: &'a str,
36    start_time: Instant,
37    timeout: Duration,
38}
39
40impl ServerSelectionTracingEventEmitter<'_> {
41    pub(crate) fn new<'a>(
42        topology_id: ObjectId,
43        criteria: &'a SelectionCriteria,
44        operation_name: &'a str,
45        start_time: Instant,
46        timeout: Duration,
47    ) -> ServerSelectionTracingEventEmitter<'a> {
48        ServerSelectionTracingEventEmitter::<'a> {
49            topology_id,
50            criteria,
51            operation_name,
52            start_time,
53            timeout,
54        }
55    }
56
57    pub(crate) fn emit_started_event(&self, topology_description: TopologyDescription) {
58        if trace_or_log_enabled!(
59            target: SERVER_SELECTION_TRACING_EVENT_TARGET,
60            TracingOrLogLevel::Debug
61        ) {
62            tracing::debug!(
63                target: SERVER_SELECTION_TRACING_EVENT_TARGET,
64                topologyId = self.topology_id.tracing_representation(),
65                operation = self.operation_name,
66                selector = self.criteria.tracing_representation(),
67                topologyDescription = topology_description.tracing_representation(),
68                "Server selection started"
69            );
70        }
71    }
72
73    pub(crate) fn emit_failed_event(
74        &self,
75        topology_description: &TopologyDescription,
76        error: &Error,
77    ) {
78        if trace_or_log_enabled!(
79            target: SERVER_SELECTION_TRACING_EVENT_TARGET,
80            TracingOrLogLevel::Debug
81        ) {
82            tracing::debug!(
83                target: SERVER_SELECTION_TRACING_EVENT_TARGET,
84                topologyId = self.topology_id.tracing_representation(),
85                operation = self.operation_name,
86                selector = self.criteria.tracing_representation(),
87                topologyDescription = topology_description.tracing_representation(),
88                failure = error.tracing_representation(),
89                "Server selection failed"
90            );
91        }
92    }
93
94    pub(crate) fn emit_succeeded_event(
95        &self,
96        topology_description: &TopologyDescription,
97        server: &SelectedServer,
98    ) {
99        if trace_or_log_enabled!(
100            target: SERVER_SELECTION_TRACING_EVENT_TARGET,
101            TracingOrLogLevel::Debug
102        ) {
103            tracing::debug!(
104                target: SERVER_SELECTION_TRACING_EVENT_TARGET,
105                topologyId = self.topology_id.tracing_representation(),
106                operation = self.operation_name,
107                selector = self.criteria.tracing_representation(),
108                topologyDescription = topology_description.tracing_representation(),
109                serverHost = server.address().host().as_ref(),
110                serverPort = server.address().port_tracing_representation(),
111                "Server selection succeeded"
112            );
113        }
114    }
115
116    pub(crate) fn emit_waiting_event(&self, topology_description: &TopologyDescription) {
117        if trace_or_log_enabled!(
118            target: SERVER_SELECTION_TRACING_EVENT_TARGET,
119            TracingOrLogLevel::Info
120        ) {
121            let remaining_time = self
122                .timeout
123                .checked_sub(self.start_time.elapsed())
124                .unwrap_or(Duration::ZERO);
125            tracing::info!(
126                target: SERVER_SELECTION_TRACING_EVENT_TARGET,
127                topologyId = self.topology_id.tracing_representation(),
128                operation = self.operation_name,
129                selector = self.criteria.tracing_representation(),
130                topologyDescription = topology_description.tracing_representation(),
131                remainingTimeMS = remaining_time.as_millis(),
132                "Waiting for suitable server to become available",
133            );
134        }
135    }
136}