Skip to content

Commit 6164660

Browse files
authored
RUST-580 Add tracing integration and command tracing events (#757)
1 parent 74c2895 commit 6164660

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+5644
-158
lines changed

.evergreen/compile-only.sh

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/bin/bash
22

33
set -o errexit
4+
set -o xtrace
45

56
source ./.evergreen/configure-rust.sh
67
rustup update $RUST_VERSION
@@ -10,21 +11,9 @@ if [ "$MSRV" = "true" ]; then
1011
cp .evergreen/MSRV-Cargo.lock Cargo.lock
1112
fi
1213

13-
if [ "$ASYNC_RUNTIME" = "tokio" ]; then
14-
FEATURE_FLAGS=snappy-compression,zlib-compression
14+
source ./.evergreen/feature-combinations.sh
1515

16-
# Zstd requires Rust version 1.54
17-
if [[ $RUST_VERSION == "nightly" ]]; then
18-
FEATURE_FLAGS=$FEATURE_FLAGS,zstd-compression
19-
fi
20-
21-
rustup run $RUST_VERSION cargo build --features $FEATURE_FLAGS
22-
rustup run $RUST_VERSION cargo build --features tokio-sync,$FEATURE_FLAGS
23-
24-
elif [ "$ASYNC_RUNTIME" = "async-std" ]; then
25-
rustup run $RUST_VERSION cargo build --no-default-features --features async-std-runtime
26-
rustup run $RUST_VERSION cargo build --no-default-features --features sync
27-
else
28-
echo "invalid async runtime: ${ASYNC_RUNTIME}" >&2
29-
exit 1
30-
fi
16+
# build with all available features to ensure all optional dependencies are brought in too.
17+
for ((i = 0; i < ${#FEATURE_COMBINATIONS[@]}; i++)); do
18+
rustup run $RUST_VERSION cargo build ${FEATURE_COMBINATIONS[$i]}
19+
done

.evergreen/config.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ functions:
548548
working_dir: "src"
549549
script: |
550550
${PREPARE_SHELL}
551-
ASYNC_RUNTIME=${ASYNC_RUNTIME} RUST_VERSION=${RUST_VERSION} MSRV=${MSRV} .evergreen/compile-only.sh
551+
RUST_VERSION=${RUST_VERSION} MSRV=${MSRV} .evergreen/compile-only.sh
552552
553553
"check cargo deny":
554554
- command: shell.exec
@@ -1858,9 +1858,8 @@ buildvariants:
18581858
matrix_spec:
18591859
os:
18601860
- ubuntu-18.04
1861-
async-runtime: "*"
18621861
extra-rust-versions: "*"
1863-
display_name: "! Compile on Rust ${extra-rust-versions} with ${async-runtime}"
1862+
display_name: "! Compile on Rust ${extra-rust-versions}"
18641863
tasks:
18651864
- "compile-only"
18661865

.evergreen/feature-combinations.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
export FEATURE_COMBINATIONS=(
77
'' # default features
88
'--no-default-features --features async-std-runtime,sync' # features that conflict w/ default features
9-
'--features tokio-sync,zstd-compression,snappy-compression,zlib-compression,openssl-tls,aws-auth,csfle' # additive features
9+
'--features tokio-sync,zstd-compression,snappy-compression,zlib-compression,openssl-tls,aws-auth,tracing-unstable,csfle' # additive features
1010
)

.evergreen/run-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ if [ "$SINGLE_THREAD" = true ]; then
1010
OPTIONS="$OPTIONS --test-threads=1"
1111
fi
1212

13-
FEATURE_FLAGS="zstd-compression,snappy-compression,zlib-compression,${TLS_FEATURE}"
13+
FEATURE_FLAGS="zstd-compression,snappy-compression,zlib-compression,tracing-unstable,${TLS_FEATURE}"
1414

1515
if [ "$ASYNC_RUNTIME" = "tokio" ]; then
1616
ASYNC_FEATURE_FLAGS=${FEATURE_FLAGS}

Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ snappy-compression = ["snap"]
7070
# DO NOT USE; see https://jira.mongodb.org/browse/RUST-569 for the status of CSFLE support in the Rust driver.
7171
csfle = ["mongocrypt", "rayon", "num_cpus"]
7272

73+
# DO NOT USE; see https://jira.mongodb.org/browse/RUST-580 for the status of tracing/logging support in the Rust driver.
74+
# Enables support for emitting tracing events.
75+
# TODO: pending https://github.com/tokio-rs/tracing/issues/2036 stop depending directly on log.
76+
tracing-unstable = ["tracing", "log"]
77+
7378
[dependencies]
7479
async-trait = "0.1.42"
7580
base64 = "0.13.0"
@@ -85,6 +90,7 @@ futures-executor = "0.3.14"
8590
hex = "0.4.0"
8691
hmac = "0.12.1"
8792
lazy_static = "1.4.0"
93+
log = { version = "0.4.17", optional = true }
8894
md-5 = "0.10.1"
8995
mongocrypt = { git = "https://github.com/mongodb/libmongocrypt-rust.git", branch = "main", optional = true }
9096
num_cpus = { version = "1.13.1", optional = true }
@@ -105,6 +111,7 @@ strsim = "0.10.0"
105111
take_mut = "0.2.2"
106112
thiserror = "1.0.24"
107113
tokio-openssl = { version = "0.6.3", optional = true }
114+
tracing = { version = "0.1.36", optional = true }
108115
trust-dns-proto = "0.21.2"
109116
trust-dns-resolver = "0.21.2"
110117
typed-builder = "0.10.0"
@@ -172,6 +179,7 @@ serde = { version = "*", features = ["rc"] }
172179
serde_json = "1.0.64"
173180
semver = "1.0.0"
174181
time = "0.3.9"
182+
tracing-subscriber = "0.3.16"
175183
regex = "1.6.0"
176184

177185
[package.metadata.docs.rs]

src/client/executor.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,12 @@ use crate::{
3434
TRANSIENT_TRANSACTION_ERROR,
3535
UNKNOWN_TRANSACTION_COMMIT_RESULT,
3636
},
37-
event::command::{CommandFailedEvent, CommandStartedEvent, CommandSucceededEvent},
37+
event::command::{
38+
CommandEvent,
39+
CommandFailedEvent,
40+
CommandStartedEvent,
41+
CommandSucceededEvent,
42+
},
3843
hello::LEGACY_HELLO_COMMAND_NAME_LOWERCASE,
3944
operation::{
4045
AbortTransaction,
@@ -624,23 +629,21 @@ impl Client {
624629
bytes: serialized,
625630
};
626631

627-
self.emit_command_event(|handler| {
632+
self.emit_command_event(|| {
628633
let command_body = if should_redact {
629634
Document::new()
630635
} else {
631636
Document::from_reader(raw_cmd.bytes.as_slice())
632637
.unwrap_or_else(|e| doc! { "serialization error": e.to_string() })
633638
};
634-
let command_started_event = CommandStartedEvent {
639+
CommandEvent::Started(CommandStartedEvent {
635640
command: command_body,
636641
db: raw_cmd.target_db.clone(),
637642
command_name: raw_cmd.name.clone(),
638643
request_id,
639644
connection: connection_info.clone(),
640645
service_id,
641-
};
642-
643-
handler.handle_command_started_event(command_started_event);
646+
})
644647
});
645648

646649
let start_time = Instant::now();
@@ -727,17 +730,20 @@ impl Client {
727730

728731
match command_result {
729732
Err(mut err) => {
730-
self.emit_command_event(|handler| {
731-
let command_failed_event = CommandFailedEvent {
733+
self.emit_command_event(|| {
734+
let mut err = err.clone();
735+
if should_redact {
736+
err.redact();
737+
}
738+
739+
CommandEvent::Failed(CommandFailedEvent {
732740
duration,
733-
command_name: cmd_name,
734-
failure: err.clone(),
741+
command_name: cmd_name.clone(),
742+
failure: err,
735743
request_id,
736-
connection: connection_info,
744+
connection: connection_info.clone(),
737745
service_id,
738-
};
739-
740-
handler.handle_command_failed_event(command_failed_event);
746+
})
741747
});
742748

743749
if let Some(ref mut session) = session {
@@ -750,7 +756,7 @@ impl Client {
750756
op.handle_error(err)
751757
}
752758
Ok(response) => {
753-
self.emit_command_event(|handler| {
759+
self.emit_command_event(|| {
754760
let reply = if should_redact {
755761
Document::new()
756762
} else {
@@ -759,15 +765,14 @@ impl Client {
759765
.unwrap_or_else(|e| doc! { "deserialization error": e.to_string() })
760766
};
761767

762-
let command_succeeded_event = CommandSucceededEvent {
768+
CommandEvent::Succeeded(CommandSucceededEvent {
763769
duration,
764770
reply,
765771
command_name: cmd_name.clone(),
766772
request_id,
767-
connection: connection_info,
773+
connection: connection_info.clone(),
768774
service_id,
769-
};
770-
handler.handle_command_succeeded_event(command_succeeded_event);
775+
})
771776
});
772777

773778
#[cfg(feature = "csfle")]

src/client/mod.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ use derivative::Derivative;
1414

1515
#[cfg(test)]
1616
use crate::options::ServerAddress;
17+
#[cfg(feature = "tracing-unstable")]
18+
use crate::trace::{
19+
command::CommandTracingEventEmitter,
20+
trace_or_log_enabled,
21+
TracingOrLogLevel,
22+
COMMAND_TRACING_EVENT_TARGET,
23+
};
1724
use crate::{
1825
bson::Document,
1926
change_stream::{
@@ -25,7 +32,7 @@ use crate::{
2532
concern::{ReadConcern, WriteConcern},
2633
db::Database,
2734
error::{ErrorKind, Result},
28-
event::command::CommandEventHandler,
35+
event::command::{handle_command_event, CommandEvent},
2936
operation::{AggregateTarget, ListDatabases},
3037
options::{
3138
ClientOptions,
@@ -39,6 +46,7 @@ use crate::{
3946
sdam::{server_selection, SelectedServer, SessionSupportStatus, Topology},
4047
ClientSession,
4148
};
49+
4250
pub(crate) use executor::{HELLO_COMMAND_NAMES, REDACTED_COMMANDS};
4351
pub(crate) use session::{ClusterTime, SESSIONS_UNSUPPORTED_COMMANDS};
4452

@@ -145,9 +153,42 @@ impl Client {
145153
Ok(client)
146154
}
147155

148-
pub(crate) fn emit_command_event(&self, emit: impl FnOnce(&Arc<dyn CommandEventHandler>)) {
156+
#[cfg(not(feature = "tracing-unstable"))]
157+
pub(crate) fn emit_command_event(&self, generate_event: impl FnOnce() -> CommandEvent) {
149158
if let Some(ref handler) = self.inner.options.command_event_handler {
150-
emit(handler);
159+
let event = generate_event();
160+
handle_command_event(handler.as_ref(), event);
161+
}
162+
}
163+
164+
#[cfg(feature = "tracing-unstable")]
165+
pub(crate) fn emit_command_event(&self, generate_event: impl FnOnce() -> CommandEvent) {
166+
let tracing_emitter = if trace_or_log_enabled!(
167+
target: COMMAND_TRACING_EVENT_TARGET,
168+
TracingOrLogLevel::Debug
169+
) {
170+
Some(CommandTracingEventEmitter::new(
171+
self.inner.options.tracing_max_document_length_bytes,
172+
self.inner.topology.id,
173+
))
174+
} else {
175+
None
176+
};
177+
let apm_event_handler = self.inner.options.command_event_handler.as_ref();
178+
if !(tracing_emitter.is_some() || apm_event_handler.is_some()) {
179+
return;
180+
}
181+
182+
let event = generate_event();
183+
if let (Some(event_handler), Some(ref tracing_emitter)) =
184+
(apm_event_handler, &tracing_emitter)
185+
{
186+
handle_command_event(event_handler.as_ref(), event.clone());
187+
handle_command_event(tracing_emitter, event);
188+
} else if let Some(event_handler) = apm_event_handler {
189+
handle_command_event(event_handler.as_ref(), event);
190+
} else if let Some(ref tracing_emitter) = tracing_emitter {
191+
handle_command_event(tracing_emitter, event);
151192
}
152193
}
153194

src/client/options/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,20 @@ pub struct ClientOptions {
530530
#[builder(default)]
531531
pub tls: Option<Tls>,
532532

533+
/// The maximum number of bytes that the driver should include in a tracing event
534+
/// or log message's extended JSON string representation of a BSON document, e.g. a
535+
/// command or reply from the server.
536+
/// If truncation of a document at the exact specified length would occur in the middle
537+
/// of a Unicode codepoint, the document will be truncated at the closest larger length
538+
/// which falls on a boundary between codepoints.
539+
/// Note that in cases where truncation occurs the output will not be valid JSON.
540+
///
541+
/// The default value is 1000.
542+
#[cfg(any(feature = "tracing-unstable", docsrs))]
543+
#[cfg_attr(docsrs, doc(cfg(feature = "tracing-unstable")))]
544+
#[builder(default)]
545+
pub tracing_max_document_length_bytes: Option<usize>,
546+
533547
/// Specifies the default write concern for operations performed on the Client. See the
534548
/// WriteConcern type documentation for more details.
535549
#[builder(default)]
@@ -1259,6 +1273,8 @@ impl ClientOptions {
12591273
sdam_event_handler: None,
12601274
#[cfg(test)]
12611275
test_options: None,
1276+
#[cfg(feature = "tracing-unstable")]
1277+
tracing_max_document_length_bytes: None,
12621278
}
12631279
}
12641280

src/client/session/test/causal_consistency.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ use crate::{
66
client::options::SessionOptions,
77
coll::options::CollectionOptions,
88
error::Result,
9+
event::command::CommandEvent,
910
options::ReadConcern,
10-
test::{log_uncaptured, CommandEvent, EventClient, LOCK},
11+
test::{log_uncaptured, EventClient, LOCK},
1112
ClientSession,
1213
Collection,
1314
};

0 commit comments

Comments
 (0)