1use std::time::{Duration, Instant};
2
3use sofie_core::Result;
4use tracing::field::Empty;
5use tracing::{Instrument, Span};
6
7const SLOW_STATEMENT: Duration = Duration::from_millis(250);
8
9pub async fn traced_statement<T>(
11 sql: &str,
12 run: impl Future<Output = Result<T>>,
13 rows: impl FnOnce(&T) -> Option<u64>,
14) -> Result<T> {
15 let span = if Span::current().is_disabled() {
16 Span::none()
17 } else {
18 tracing::info_span!("statement", db.query.text = sql, db.rows = Empty)
19 };
20 let started = Instant::now();
21 let result = run.instrument(span.clone()).await;
22 if let Some(count) = result.as_ref().ok().and_then(rows) {
23 span.record("db.rows", count);
24 }
25 let elapsed = started.elapsed();
26 #[cfg(feature = "metrics")]
27 crate::metrics::statement(sql, elapsed);
28 if elapsed > SLOW_STATEMENT {
29 let duration_ms = u64::try_from(elapsed.as_millis()).unwrap_or(u64::MAX);
30 span.in_scope(|| tracing::warn!(db.query.text = sql, duration_ms, "slow statement"));
31 }
32 result
33}