Skip to content

Commit 0fd5853

Browse files
committed
Don't emit INFO spans for administrative queries
This prevents internal queries like `SELECT @@max_allowed_packet` from showing up in user tracing unless tracing level TRACE is allowed.
1 parent 0e8d22e commit 0fd5853

File tree

3 files changed

+49
-14
lines changed

3 files changed

+49
-14
lines changed

src/conn/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ impl Conn {
887887
/// Do nothing if socket address is already in [`Opts`] or if `prefer_socket` is `false`.
888888
async fn read_socket(&mut self) -> Result<()> {
889889
if self.inner.opts.prefer_socket() && self.inner.socket.is_none() {
890-
let row_opt = self.query_first("SELECT @@socket").await?;
890+
let row_opt = self.query_internal("SELECT @@socket").await?;
891891
self.inner.socket = row_opt.unwrap_or((None,)).0;
892892
}
893893
Ok(())
@@ -898,7 +898,7 @@ impl Conn {
898898
let max_allowed_packet = if let Some(value) = self.opts().max_allowed_packet() {
899899
Some(value)
900900
} else {
901-
self.query_first("SELECT @@max_allowed_packet").await?
901+
self.query_internal("SELECT @@max_allowed_packet").await?
902902
};
903903
if let Some(stream) = self.inner.stream.as_mut() {
904904
stream.set_max_allowed_packet(max_allowed_packet.unwrap_or(DEFAULT_MAX_ALLOWED_PACKET));
@@ -911,7 +911,7 @@ impl Conn {
911911
let wait_timeout = if let Some(value) = self.opts().wait_timeout() {
912912
Some(value)
913913
} else {
914-
self.query_first("SELECT @@wait_timeout").await?
914+
self.query_internal("SELECT @@wait_timeout").await?
915915
};
916916
self.inner.wait_timeout = Duration::from_secs(wait_timeout.unwrap_or(28800) as u64);
917917
Ok(())

src/conn/routines/query.rs

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use futures_core::future::BoxFuture;
22
use futures_util::FutureExt;
33
use mysql_common::constants::Command;
44
#[cfg(feature = "tracing")]
5-
use tracing::{field, info_span, Instrument, Level};
5+
use tracing::{field, info_span, span_enabled, trace_span, Instrument, Level};
66

77
use crate::{Conn, TextProtocol};
88

@@ -12,24 +12,35 @@ use super::Routine;
1212
#[derive(Debug, Copy, Clone)]
1313
pub struct QueryRoutine<'a> {
1414
data: &'a [u8],
15+
#[cfg_attr(not(feature = "tracing"), allow(dead_code))]
16+
internal: bool,
1517
}
1618

1719
impl<'a> QueryRoutine<'a> {
18-
pub fn new(data: &'a [u8]) -> Self {
19-
Self { data }
20+
pub fn new(data: &'a [u8], internal: bool) -> Self {
21+
Self { data, internal }
2022
}
2123
}
2224

2325
impl Routine<()> for QueryRoutine<'_> {
2426
fn call<'a>(&'a mut self, conn: &'a mut Conn) -> BoxFuture<'a, crate::Result<()>> {
2527
#[cfg(feature = "tracing")]
26-
let span = info_span!(
27-
"mysql_async::query",
28-
mysql_async.connection.id = conn.id(),
29-
mysql_async.query.sql = field::Empty
30-
);
28+
let span = if self.internal {
29+
trace_span!(
30+
"mysql_async::query",
31+
mysql_async.connection.id = conn.id(),
32+
mysql_async.query.sql = field::Empty
33+
)
34+
} else {
35+
info_span!(
36+
"mysql_async::query",
37+
mysql_async.connection.id = conn.id(),
38+
mysql_async.query.sql = field::Empty
39+
)
40+
};
41+
3142
#[cfg(feature = "tracing")]
32-
if tracing::span_enabled!(Level::DEBUG) {
43+
if span_enabled!(Level::DEBUG) {
3344
// The statement may contain sensitive data. Restrict to DEBUG.
3445
span.record(
3546
"mysql_async.query.sql",

src/queryable/mod.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,33 @@ impl Conn {
106106
where
107107
Q: AsQuery + 'a,
108108
{
109-
self.routine(QueryRoutine::new(query.as_query().as_ref()))
109+
self.routine(QueryRoutine::new(query.as_query().as_ref(), false))
110110
.await
111111
}
112+
113+
/// Used for internal querying of connection settings,
114+
/// bypassing instrumentation meant for user queries.
115+
// This is a merge of `Queryable::query_first` and `Conn::query_iter`.
116+
// TODO: find a cleaner way without duplicating code.
117+
pub(crate) fn query_internal<'a, T, Q>(&'a mut self, query: Q) -> BoxFuture<'a, Option<T>>
118+
where
119+
Q: AsQuery + 'a,
120+
T: FromRow + Send + 'static,
121+
{
122+
async move {
123+
self.routine(QueryRoutine::new(query.as_query().as_ref(), true))
124+
.await?;
125+
let mut result: QueryResult<'a, 'static, TextProtocol> = QueryResult::new(self);
126+
let output = if result.is_empty() {
127+
None
128+
} else {
129+
result.next().await?.map(crate::from_row)
130+
};
131+
result.drop_result().await?;
132+
Ok(output)
133+
}
134+
.boxed()
135+
}
112136
}
113137

114138
/// Methods of this trait are used to execute database queries.
@@ -456,7 +480,7 @@ impl Queryable for Conn {
456480
Q: AsQuery + 'a,
457481
{
458482
async move {
459-
self.routine(QueryRoutine::new(query.as_query().as_ref()))
483+
self.routine(QueryRoutine::new(query.as_query().as_ref(), false))
460484
.await?;
461485
Ok(QueryResult::new(self))
462486
}

0 commit comments

Comments
 (0)