Skip to content

Commit 991069a

Browse files
authored
Merge pull request blackbeam#224 from cloneable/issue223-tracing-instrumentation
Add support for tracing
2 parents fa7a5a7 + 0fdecd5 commit 991069a

File tree

9 files changed

+149
-18
lines changed

9 files changed

+149
-18
lines changed

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ socket2 = "0.4.2"
3434
thiserror = "1.0.4"
3535
tokio = { version = "1.0", features = ["io-util", "fs", "net", "time", "rt"] }
3636
tokio-util = { version = "0.7.2", features = ["codec", "io"] }
37+
tracing = { version = "0.1.37", default-features = false, features = ["attributes"], optional = true }
3738
twox-hash = "1"
3839
url = "2.1"
3940

@@ -100,6 +101,7 @@ rustls-tls = [
100101
"webpki-roots",
101102
"rustls-pemfile",
102103
]
104+
tracing = ["dep:tracing"]
103105
nightly = []
104106

105107
[lib]

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ as well as `native-tls`-based TLS support.
8080
[dependencies]
8181
mysql_async = { version = "*", default-features = false, features = ["rustls-tls"] }
8282

83+
* `tracing` – enables instrumentation via `tracing` package.
84+
Primary operations (`query`, `prepare`, `exec`) are instrumented at `INFO` level.
85+
Remaining operations, incl. `get_conn`, are instrumented at `DEBUG` level.
86+
Also at `DEBUG`, the SQL queries and parameters are added to the `query`, `prepare`
87+
and `exec` spans.
88+
89+
**Example:**
90+
91+
```toml
92+
[dependencies]
93+
mysql_async = { version = "*", features = ["tracing"] }
94+
```
95+
8396
[myslqcommonfeatures]: https://github.com/blackbeam/rust_mysql_common#crate-features
8497

8598
## TLS/SSL Support

src/conn/pool/futures/get_conn.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ use std::{
1414
};
1515

1616
use futures_core::ready;
17+
#[cfg(feature = "tracing")]
18+
use {
19+
std::sync::Arc,
20+
tracing::{debug_span, Span},
21+
};
1722

1823
use crate::{
1924
conn::{
@@ -64,6 +69,8 @@ pub struct GetConn {
6469
pub(crate) queue_id: Option<QueueId>,
6570
pub(crate) pool: Option<Pool>,
6671
pub(crate) inner: GetConnInner,
72+
#[cfg(feature = "tracing")]
73+
span: Arc<Span>,
6774
}
6875

6976
impl GetConn {
@@ -72,6 +79,8 @@ impl GetConn {
7279
queue_id: None,
7380
pool: Some(pool.clone()),
7481
inner: GetConnInner::New,
82+
#[cfg(feature = "tracing")]
83+
span: Arc::new(debug_span!("mysql_async::get_conn")),
7584
}
7685
}
7786

@@ -94,6 +103,10 @@ impl Future for GetConn {
94103
type Output = Result<Conn>;
95104

96105
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
106+
#[cfg(feature = "tracing")]
107+
let span = self.span.clone();
108+
#[cfg(feature = "tracing")]
109+
let _span_guard = span.enter();
97110
loop {
98111
match self.inner {
99112
GetConnInner::New => {

src/conn/routines/exec.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::mem;
33
use futures_core::future::BoxFuture;
44
use futures_util::FutureExt;
55
use mysql_common::{packets::ComStmtExecuteRequestBuilder, params::Params};
6+
#[cfg(feature = "tracing")]
7+
use tracing::{field, info_span, Instrument, Level, Span};
68

79
use crate::{BinaryProtocol, Conn, DriverError, Statement};
810

@@ -23,10 +25,33 @@ impl<'a> ExecRoutine<'a> {
2325

2426
impl Routine<()> for ExecRoutine<'_> {
2527
fn call<'a>(&'a mut self, conn: &'a mut Conn) -> BoxFuture<'a, crate::Result<()>> {
26-
async move {
28+
#[cfg(feature = "tracing")]
29+
let span = info_span!(
30+
"mysql_async::exec",
31+
mysql_async.connection.id = conn.id(),
32+
mysql_async.statement.id = self.stmt.id(),
33+
mysql_async.query.params = field::Empty,
34+
);
35+
36+
let fut = async move {
2737
loop {
2838
match self.params {
2939
Params::Positional(ref params) => {
40+
#[cfg(feature = "tracing")]
41+
if tracing::span_enabled!(Level::DEBUG) {
42+
// The params may contain sensitive data. Restrict to DEBUG.
43+
// TODO: make more efficient
44+
// TODO: use intersperse() once stable
45+
let sep = std::iter::repeat(", ");
46+
let ps = params
47+
.iter()
48+
.map(|p| p.as_sql(true))
49+
.zip(sep)
50+
.map(|(val, sep)| val + sep)
51+
.collect::<String>();
52+
Span::current().record("mysql_async.query.params", ps);
53+
}
54+
3055
if self.stmt.num_params() as usize != params.len() {
3156
Err(DriverError::StmtParamsMismatch {
3257
required: self.stmt.num_params(),
@@ -76,7 +101,11 @@ impl Routine<()> for ExecRoutine<'_> {
76101
}
77102
}
78103
Ok(())
79-
}
80-
.boxed()
104+
};
105+
106+
#[cfg(feature = "tracing")]
107+
let fut = fut.instrument(span);
108+
109+
fut.boxed()
81110
}
82111
}

src/conn/routines/next_set.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use std::marker::PhantomData;
22

33
use futures_core::future::BoxFuture;
44
use futures_util::FutureExt;
5+
#[cfg(feature = "tracing")]
6+
use tracing::{debug_span, Instrument};
57

68
use crate::{queryable::Protocol, Conn};
79

@@ -22,11 +24,20 @@ where
2224
P: Protocol,
2325
{
2426
fn call<'a>(&'a mut self, conn: &'a mut Conn) -> BoxFuture<'a, crate::Result<()>> {
27+
#[cfg(feature = "tracing")]
28+
let span = debug_span!(
29+
"mysql_async::next_set",
30+
mysql_async.connection.id = conn.id()
31+
);
2532
conn.sync_seq_id();
26-
async move {
33+
let fut = async move {
2734
conn.read_result_set::<P>(false).await?;
2835
Ok(())
29-
}
30-
.boxed()
36+
};
37+
38+
#[cfg(feature = "tracing")]
39+
let fut = fut.instrument(span);
40+
41+
fut.boxed()
3142
}
3243
}

src/conn/routines/ping.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use futures_core::future::BoxFuture;
22
use futures_util::FutureExt;
33
use mysql_common::constants::Command;
4+
#[cfg(feature = "tracing")]
5+
use tracing::{debug_span, Instrument};
46

57
use crate::Conn;
68

@@ -12,11 +14,18 @@ pub struct PingRoutine;
1214

1315
impl Routine<()> for PingRoutine {
1416
fn call<'a>(&'a mut self, conn: &'a mut Conn) -> BoxFuture<'a, crate::Result<()>> {
15-
async move {
17+
#[cfg(feature = "tracing")]
18+
let span = debug_span!("mysql_async::ping", mysql_async.connection.id = conn.id());
19+
20+
let fut = async move {
1621
conn.write_command_data(Command::COM_PING, &[]).await?;
1722
conn.read_packet().await?;
1823
Ok(())
19-
}
20-
.boxed()
24+
};
25+
26+
#[cfg(feature = "tracing")]
27+
let fut = fut.instrument(span);
28+
29+
fut.boxed()
2130
}
2231
}

src/conn/routines/prepare.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::{borrow::Cow, sync::Arc};
33
use futures_core::future::BoxFuture;
44
use futures_util::FutureExt;
55
use mysql_common::constants::Command;
6+
#[cfg(feature = "tracing")]
7+
use tracing::{field, info_span, Instrument, Level, Span};
68

79
use crate::{queryable::stmt::StmtInner, Conn};
810

@@ -24,12 +26,30 @@ impl PrepareRoutine {
2426

2527
impl Routine<Arc<StmtInner>> for PrepareRoutine {
2628
fn call<'a>(&'a mut self, conn: &'a mut Conn) -> BoxFuture<'a, crate::Result<Arc<StmtInner>>> {
27-
async move {
29+
#[cfg(feature = "tracing")]
30+
let span = info_span!(
31+
"mysql_async::prepare",
32+
mysql_async.connection.id = conn.id(),
33+
mysql_async.statement.id = field::Empty,
34+
mysql_async.query.sql = field::Empty,
35+
);
36+
#[cfg(feature = "tracing")]
37+
if tracing::span_enabled!(Level::DEBUG) {
38+
// The statement may contain sensitive data. Restrict to DEBUG.
39+
span.record(
40+
"mysql_async.query.sql",
41+
String::from_utf8_lossy(&*self.query).as_ref(),
42+
);
43+
}
44+
45+
let fut = async move {
2846
conn.write_command_data(Command::COM_STMT_PREPARE, &self.query)
2947
.await?;
3048

3149
let packet = conn.read_packet().await?;
3250
let mut inner_stmt = StmtInner::from_payload(&*packet, conn.id(), self.query.clone())?;
51+
#[cfg(feature = "tracing")]
52+
Span::current().record("mysql_async.statement.id", inner_stmt.id());
3353

3454
if inner_stmt.num_params() > 0 {
3555
let params = conn.read_column_defs(inner_stmt.num_params()).await?;
@@ -42,7 +62,11 @@ impl Routine<Arc<StmtInner>> for PrepareRoutine {
4262
}
4363

4464
Ok(Arc::new(inner_stmt))
45-
}
46-
.boxed()
65+
};
66+
67+
#[cfg(feature = "tracing")]
68+
let fut = fut.instrument(span);
69+
70+
fut.boxed()
4771
}
4872
}

src/conn/routines/query.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use futures_core::future::BoxFuture;
22
use futures_util::FutureExt;
33
use mysql_common::constants::Command;
4+
#[cfg(feature = "tracing")]
5+
use tracing::{field, info_span, Instrument, Level};
46

57
use crate::{Conn, TextProtocol};
68

@@ -20,12 +22,31 @@ impl<'a> QueryRoutine<'a> {
2022

2123
impl Routine<()> for QueryRoutine<'_> {
2224
fn call<'a>(&'a mut self, conn: &'a mut Conn) -> BoxFuture<'a, crate::Result<()>> {
23-
async move {
25+
#[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+
);
31+
#[cfg(feature = "tracing")]
32+
if tracing::span_enabled!(Level::DEBUG) {
33+
// The statement may contain sensitive data. Restrict to DEBUG.
34+
span.record(
35+
"mysql_async.query.sql",
36+
String::from_utf8_lossy(self.data).as_ref(),
37+
);
38+
}
39+
40+
let fut = async move {
2441
conn.write_command_data(Command::COM_QUERY, self.data)
2542
.await?;
2643
conn.read_result_set::<TextProtocol>(true).await?;
2744
Ok(())
28-
}
29-
.boxed()
45+
};
46+
47+
#[cfg(feature = "tracing")]
48+
let fut = fut.instrument(span);
49+
50+
fut.boxed()
3051
}
3152
}

src/conn/routines/reset.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use futures_core::future::BoxFuture;
22
use futures_util::FutureExt;
33
use mysql_common::constants::Command;
4+
#[cfg(feature = "tracing")]
5+
use tracing::{debug_span, Instrument};
46

57
use crate::Conn;
68

@@ -12,12 +14,19 @@ pub struct ResetRoutine;
1214

1315
impl Routine<()> for ResetRoutine {
1416
fn call<'a>(&'a mut self, conn: &'a mut Conn) -> BoxFuture<'a, crate::Result<()>> {
15-
async move {
17+
#[cfg(feature = "tracing")]
18+
let span = debug_span!("mysql_async::reset", mysql_async.connection.id = conn.id());
19+
20+
let fut = async move {
1621
conn.write_command_data(Command::COM_RESET_CONNECTION, &[])
1722
.await?;
1823
conn.read_packet().await?;
1924
Ok(())
20-
}
21-
.boxed()
25+
};
26+
27+
#[cfg(feature = "tracing")]
28+
let fut = fut.instrument(span);
29+
30+
fut.boxed()
2231
}
2332
}

0 commit comments

Comments
 (0)