use crate::Uuid;
use std::time::Instant;
#[derive(Debug, Clone)]
pub struct QueryContext {
start_time: Instant,
query_id: Uuid,
query: String,
arguments: Vec<String>,
last_insert_id: Option<i64>,
rows_affected: Option<u64>,
success: bool,
}
impl QueryContext {
#[inline]
pub fn new() -> Self {
Self {
start_time: Instant::now(),
query_id: Uuid::now_v7(),
query: String::new(),
arguments: Vec::new(),
last_insert_id: None,
rows_affected: None,
success: false,
}
}
#[inline]
pub fn set_query(&mut self, query: impl ToString) {
self.query = query.to_string();
}
#[inline]
pub fn add_argument(&mut self, value: impl ToString) {
self.arguments.push(value.to_string());
}
#[inline]
pub fn append_arguments(&mut self, arguments: &mut Vec<String>) {
self.arguments.append(arguments);
}
#[inline]
pub fn set_last_insert_id(&mut self, last_insert_id: i64) {
self.last_insert_id = Some(last_insert_id);
}
#[inline]
pub fn set_query_result(&mut self, rows_affected: Option<u64>, success: bool) {
self.rows_affected = rows_affected;
self.success = success;
}
#[inline]
pub fn start_time(&self) -> Instant {
self.start_time
}
#[inline]
pub fn query_id(&self) -> Uuid {
self.query_id
}
#[inline]
pub fn query(&self) -> &str {
&self.query
}
#[inline]
pub fn arguments(&self) -> &[String] {
&self.arguments
}
#[inline]
pub fn last_insert_id(&self) -> Option<i64> {
self.last_insert_id
}
#[inline]
pub fn rows_affected(&self) -> Option<u64> {
self.rows_affected
}
#[inline]
pub fn is_success(&self) -> bool {
self.success
}
#[inline]
pub fn format_arguments(&self) -> String {
self.arguments().join(", ")
}
#[inline]
pub fn record_error(&self, message: impl AsRef<str>) {
let query_id = self.query_id().to_string();
let query = self.query();
let arguments = self.format_arguments();
tracing::error!(query_id, query, arguments, message = message.as_ref());
}
#[cfg(feature = "metrics")]
#[inline]
pub fn emit_metrics(&self, action: impl Into<crate::SharedString>) {
metrics::histogram!(
"zino_model_query_duration_seconds",
self.start_time().elapsed().as_secs_f64(),
"action" => action.into(),
);
}
}
impl Default for QueryContext {
#[inline]
fn default() -> Self {
Self::new()
}
}