use crate::core::condition::SqlValue;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub struct QueryEvent {
pub sql: String,
pub params: Vec<SqlValue>,
pub duration_ms: u64,
pub rows_affected: u64,
pub table: String,
}
pub type QueryLogger = Arc<dyn Fn(&QueryEvent) + Send + Sync>;
static SLOW_QUERY_THRESHOLD_MS: AtomicU64 = AtomicU64::new(200);
pub fn set_slow_threshold(ms: u64) {
SLOW_QUERY_THRESHOLD_MS.store(ms, Ordering::Relaxed);
}
pub fn slow_threshold() -> u64 {
SLOW_QUERY_THRESHOLD_MS.load(Ordering::Relaxed)
}
static SLOW_LOGGER: once_cell::sync::Lazy<std::sync::Mutex<Option<QueryLogger>>> =
once_cell::sync::Lazy::new(|| std::sync::Mutex::new(None));
static ON_QUERY_LOGGER: once_cell::sync::Lazy<std::sync::Mutex<Option<QueryLogger>>> =
once_cell::sync::Lazy::new(|| std::sync::Mutex::new(None));
pub fn set_logger(logger: QueryLogger) {
if let Ok(mut l) = SLOW_LOGGER.lock() {
*l = Some(logger);
}
}
pub fn set_on_query(logger: QueryLogger) {
if let Ok(mut l) = ON_QUERY_LOGGER.lock() {
*l = Some(logger);
}
}
pub fn clear_on_query() {
if let Ok(mut l) = ON_QUERY_LOGGER.lock() {
*l = None;
}
}
pub(crate) fn log_query(
sql: &str,
params: &[SqlValue],
duration_ms: u64,
rows_affected: u64,
table: &str,
) {
let event = QueryEvent {
sql: sql.to_string(),
params: params.to_vec(),
duration_ms,
rows_affected,
table: table.to_string(),
};
#[cfg(feature = "tracing")]
{
tracing::trace!(
target: "rok_fluent::query",
sql = %event.sql,
table = %event.table,
duration_ms = event.duration_ms,
rows_affected = event.rows_affected,
"query executed"
);
}
if let Ok(l) = ON_QUERY_LOGGER.lock() {
if let Some(ref cb) = *l {
cb(&event);
}
}
if duration_ms >= slow_threshold() {
if let Ok(l) = SLOW_LOGGER.lock() {
if let Some(ref logger) = *l {
logger(&event);
}
}
}
}