From 86116b8157fe19ec67425973dadf4d4cd7540d65 Mon Sep 17 00:00:00 2001 From: MythEclipse Date: Thu, 31 Jul 2025 16:51:08 +0700 Subject: [PATCH] feat: add logging for SurrealDB queries across multiple repositories --- .../src/v1/landing/events/events_repository.rs | 9 +++++++++ .../testimonials/testimonials_repository.rs | 17 +++++++++++++++++ .../src/v1/mentors/mentors_repository.rs | 9 ++++++++- .../v1/gacha_claims/gacha_claims_repository.rs | 8 +++++++- .../gacha_credits/gacha_credits_repository.rs | 6 +++++- .../v1/gacha_items/gacha_items_repository.rs | 14 ++++++++++++++ .../v1/gacha_rolls/gacha_rolls_repository.rs | 6 ++++++ imphnen-iam/src/v1/auth/auth_repository.rs | 16 ++++++++++++++++ .../v1/permissions/permissions_repository.rs | 8 ++++++++ 9 files changed, 90 insertions(+), 3 deletions(-) diff --git a/imphnen-cms/src/v1/landing/events/events_repository.rs b/imphnen-cms/src/v1/landing/events/events_repository.rs index c4ed1f2..cb2c6e3 100644 --- a/imphnen-cms/src/v1/landing/events/events_repository.rs +++ b/imphnen-cms/src/v1/landing/events/events_repository.rs @@ -4,6 +4,7 @@ use imphnen_libs::{AppState, MetaRequestDto, ResourceEnum, ResponseListSuccessDt use imphnen_utils::{DetailQueryBuilder, ListQueryBuilder, get_id, get_iso_date}; use std::time::Instant; use tracing::instrument; +use tracing::info; pub struct EventsRepository<'a> { state: &'a AppState, @@ -25,6 +26,7 @@ impl<'a> EventsRepository<'a> { .with_pagination(meta.page, Some(10)) .with_sorting(meta.sort_by.as_deref(), meta.order.as_deref()) .build(); + info!(query = %query, "Executing SurrealDB query"); let res: Vec = self.state.surrealdb_ws.query(query).await?.take(0)?; let elapsed = now.elapsed(); @@ -48,6 +50,7 @@ impl<'a> EventsRepository<'a> { .with_id(&id) .with_select_fields(vec!["*"]); let sql = builder.build(); + info!(query = %sql, "Executing SurrealDB query"); let result: Option = builder.apply_bindings(db.query(sql)).await?.take(0)?; let elapsed = now.elapsed(); @@ -72,6 +75,8 @@ impl<'a> EventsRepository<'a> { pub async fn query_create_event(&self, data: EventsSchema) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + let query_str = format!("CREATE {} CONTENT ...", ResourceEnum::Events.to_string()); + info!(query = %query_str, "Executing SurrealDB query"); let record: Option = db .create(ResourceEnum::Events.to_string()) .content(data) @@ -106,6 +111,8 @@ impl<'a> EventsRepository<'a> { }; let record_key = get_id(&merged.id)?; + let query_str = format!("UPDATE {:?} MERGE ...", record_key); + info!(query = %query_str, "Executing SurrealDB query"); let record: Option = db.update(record_key).merge(merged).await?; let elapsed = now.elapsed(); if std::env::var("RUST_ENV").unwrap_or_else(|_| "development".to_string()) @@ -130,6 +137,8 @@ impl<'a> EventsRepository<'a> { } let record_key = get_id(&event.id)?; + let query_str = format!("UPDATE {:?} MERGE {{ is_deleted: true }}", record_key); + info!(query = %query_str, "Executing SurrealDB query"); let record: Option = db .update(record_key) .merge(serde_json::json!({ "is_deleted": true })) diff --git a/imphnen-cms/src/v1/landing/testimonials/testimonials_repository.rs b/imphnen-cms/src/v1/landing/testimonials/testimonials_repository.rs index cdb81ac..484fb9b 100644 --- a/imphnen-cms/src/v1/landing/testimonials/testimonials_repository.rs +++ b/imphnen-cms/src/v1/landing/testimonials/testimonials_repository.rs @@ -7,6 +7,7 @@ use imphnen_utils::{DetailQueryBuilder, ListQueryBuilder, get_id, get_iso_date}; use serde_json; use std::time::Instant; use tracing::instrument; +use tracing::info; pub struct TestimonialsRepository<'a> { state: &'a AppState, @@ -28,6 +29,7 @@ impl<'a> TestimonialsRepository<'a> { .with_pagination(meta.page, Some(10)) .with_sorting(meta.sort_by.as_deref(), meta.order.as_deref()) .build(); + info!(query = %query, "Executing SurrealDB query"); let res: Vec = self.state.surrealdb_ws.query(query).await?.take(0)?; let elapsed = now.elapsed(); @@ -55,6 +57,7 @@ impl<'a> TestimonialsRepository<'a> { .with_condition("is_deleted = false") .with_select_fields(vec!["*", "user.* as user"]); let sql = builder.build(); + info!(query = %sql, "Executing SurrealDB query"); let result: Option = builder.apply_bindings(db.query(sql)).await?.take(0)?; let elapsed = now.elapsed(); @@ -82,6 +85,11 @@ impl<'a> TestimonialsRepository<'a> { ) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + info!( + resource = %ResourceEnum::Testimonials.to_string(), + payload = ?data, + "Executing SurrealDB create" + ); let record: Option = db .create(ResourceEnum::Testimonials.to_string()) .content(data) @@ -120,6 +128,11 @@ impl<'a> TestimonialsRepository<'a> { }; let record_key = get_id(&merged.id)?; + info!( + record_key = ?record_key, + payload = ?merged, + "Executing SurrealDB update" + ); let record: Option = db.update(record_key).merge(merged).await?; let elapsed = now.elapsed(); @@ -145,6 +158,10 @@ impl<'a> TestimonialsRepository<'a> { } let record_key = get_id(&testimonial.id)?; + info!( + record_key = ?record_key, + "Executing SurrealDB soft delete" + ); let record: Option = db .update(record_key) .merge(serde_json::json!({ "is_deleted": true })) diff --git a/imphnen-dimentorin/src/v1/mentors/mentors_repository.rs b/imphnen-dimentorin/src/v1/mentors/mentors_repository.rs index fbe673e..50cbac3 100644 --- a/imphnen-dimentorin/src/v1/mentors/mentors_repository.rs +++ b/imphnen-dimentorin/src/v1/mentors/mentors_repository.rs @@ -8,6 +8,7 @@ use imphnen_utils::{DetailQueryBuilder, QueryListBuilder, get_iso_date}; use serde_json::{Map, Value}; use std::time::Instant; use tracing::instrument; +use tracing::info; pub struct MentorsRepository<'a> { pub state: &'a AppState, @@ -114,6 +115,7 @@ impl<'a> MentorsRepository<'a> { } let sql = builder.build(); + info!(query = %sql, "Executing SurrealDB query in query_mentor_by_email"); let mentor_opt: Option = builder.apply_bindings(db.query(sql)).await?.take(0)?; let elapsed = now.elapsed(); @@ -172,6 +174,7 @@ impl<'a> MentorsRepository<'a> { } let sql = builder.build(); + info!(query = %sql, "Executing SurrealDB query in query_mentor_by_id"); let mentor_opt: Option = builder.apply_bindings(db.query(sql)).await?.take(0)?; let elapsed = now.elapsed(); @@ -194,8 +197,10 @@ impl<'a> MentorsRepository<'a> { let now = Instant::now(); let db = &self.state.surrealdb_ws; let dto: MentorInsertDto = data.into(); + let resource = ResourceEnum::Mentors.to_string(); + info!(query = %resource, "Executing SurrealDB create in query_create_mentor"); let record: Option = db - .create(ResourceEnum::Mentors.to_string()) + .create(resource) .content(dto.clone()) .await?; let elapsed = now.elapsed(); @@ -237,6 +242,7 @@ impl<'a> MentorsRepository<'a> { merged_data_json.insert("updated_at".to_string(), Value::String(get_iso_date())); + info!(query = ?record_key, "Executing SurrealDB update in query_update_mentor"); let record: Option = db.update(record_key).merge(merged_data_json).await?; let elapsed = now.elapsed(); @@ -282,6 +288,7 @@ impl<'a> MentorsRepository<'a> { patch.insert("is_deleted".to_string(), Value::Bool(true)); patch.insert("updated_at".to_string(), Value::String(get_iso_date())); + info!(query = ?record_key, "Executing SurrealDB soft delete in query_delete_mentor"); let record: Option = db.update(record_key).merge(patch).await?; let elapsed = now.elapsed(); if std::env::var("RUST_ENV").unwrap_or_else(|_| "development".to_string()) diff --git a/imphnen-gacha/src/v1/gacha_claims/gacha_claims_repository.rs b/imphnen-gacha/src/v1/gacha_claims/gacha_claims_repository.rs index 6016bd3..b8975b2 100644 --- a/imphnen-gacha/src/v1/gacha_claims/gacha_claims_repository.rs +++ b/imphnen-gacha/src/v1/gacha_claims/gacha_claims_repository.rs @@ -3,7 +3,7 @@ use crate::{AppState, ResourceEnum}; use anyhow::{Result, bail}; use imphnen_iam::DetailQueryBuilder; use std::time::Instant; -use tracing::instrument; +use tracing::{instrument, info}; pub struct GachaClaimRepository<'a> { state: &'a AppState, @@ -27,6 +27,7 @@ impl<'a> GachaClaimRepository<'a> { .with_fetch("item") .with_fetch("user"); let sql = builder.build(); + info!(query = %sql, "Executing SurrealDB query"); let result: Option = builder.apply_bindings(db.query(sql)).await?.take(0)?; let elapsed = now.elapsed(); @@ -48,6 +49,11 @@ impl<'a> GachaClaimRepository<'a> { ) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + info!( + resource = %ResourceEnum::GachaClaims.to_string(), + content = ?data, + "Executing SurrealDB create query" + ); let record: Option = db .create(ResourceEnum::GachaClaims.to_string()) .content(data) diff --git a/imphnen-gacha/src/v1/gacha_credits/gacha_credits_repository.rs b/imphnen-gacha/src/v1/gacha_credits/gacha_credits_repository.rs index 21962bb..7719af6 100644 --- a/imphnen-gacha/src/v1/gacha_credits/gacha_credits_repository.rs +++ b/imphnen-gacha/src/v1/gacha_credits/gacha_credits_repository.rs @@ -4,7 +4,7 @@ use anyhow::{Result, bail}; use imphnen_iam::make_thing; use std::time::Instant; use surrealdb::Uuid; -use tracing::instrument; +use tracing::{instrument, info}; pub struct GachaCreditRepository<'a> { state: &'a AppState, @@ -27,6 +27,7 @@ impl<'a> GachaCreditRepository<'a> { ResourceEnum::GachaCredits, ResourceEnum::Users ); + info!(query = %sql, "Executing SurrealDB query"); let result: Vec = db.query(sql).bind(("user_id", user_id)).await?.take(0)?; let elapsed = now.elapsed(); @@ -66,6 +67,7 @@ impl<'a> GachaCreditRepository<'a> { bail!("No extra roll credits remaining"); } credit.available_rolls -= 1; + info!(operation = "update", table = %ResourceEnum::GachaCredits.to_string(), id = %credit.id.id.to_raw(), "Executing SurrealDB update for consume_credit"); let _: Option = db .update(( &ResourceEnum::GachaCredits.to_string(), @@ -91,6 +93,7 @@ impl<'a> GachaCreditRepository<'a> { let db = &self.state.surrealdb_ws; if let Some(mut credit) = self.query_by_user_id(payload.user_id.clone()).await? { credit.available_rolls += payload.amount; + info!(operation = "update", table = %ResourceEnum::GachaCredits.to_string(), id = %credit.id.id.to_raw(), "Executing SurrealDB update for add_credit"); let _: Option = db .update(( &ResourceEnum::GachaCredits.to_string(), @@ -108,6 +111,7 @@ impl<'a> GachaCreditRepository<'a> { available_rolls: payload.amount, ..Default::default() }; + info!(operation = "create", table = %ResourceEnum::GachaCredits.to_string(), "Executing SurrealDB create for add_credit"); let _: Option = db .create(ResourceEnum::GachaCredits.to_string()) .content(data) diff --git a/imphnen-gacha/src/v1/gacha_items/gacha_items_repository.rs b/imphnen-gacha/src/v1/gacha_items/gacha_items_repository.rs index 73fbee8..a4d188b 100644 --- a/imphnen-gacha/src/v1/gacha_items/gacha_items_repository.rs +++ b/imphnen-gacha/src/v1/gacha_items/gacha_items_repository.rs @@ -9,6 +9,7 @@ use imphnen_utils::get_iso_date; use serde_json::{Map, Value}; use std::time::Instant; use tracing::instrument; +use tracing::info; pub struct GachaItemRepository<'a> { state: &'a AppState, @@ -25,6 +26,11 @@ impl<'a> GachaItemRepository<'a> { meta: MetaRequestDto, ) -> Result>> { let now = Instant::now(); + let surreal_query = format!( + "SELECT * FROM {} WHERE is_deleted = false AND name LIKE ?", + ResourceEnum::GachaItems.to_string() + ); + info!(query = %surreal_query, "Executing SurrealDB query"); let raw_result: ResponseListSuccessDto> = QueryListBuilder::new( &self.state.surrealdb_ws, @@ -57,6 +63,8 @@ impl<'a> GachaItemRepository<'a> { pub async fn query_gacha_item_by_id(&self, id: String) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + let surreal_query = format!("SELECT * FROM {} WHERE id = '{}'", ResourceEnum::GachaItems.to_string(), id); + info!(query = %surreal_query, "Executing SurrealDB query"); let result: Option = db .select((ResourceEnum::GachaItems.to_string(), id.clone())) .await?; @@ -79,6 +87,8 @@ impl<'a> GachaItemRepository<'a> { ) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + let surreal_query = format!("CREATE {} CONTENT ...", ResourceEnum::GachaItems.to_string()); + info!(query = %surreal_query, "Executing SurrealDB query"); let record: Option = db .create(ResourceEnum::GachaItems.to_string()) .content(data) @@ -111,6 +121,8 @@ impl<'a> GachaItemRepository<'a> { created_at: existing.created_at, ..data.clone() }; + let surreal_query = format!("UPDATE {:?} MERGE ...", record_key); + info!(query = %surreal_query, "Executing SurrealDB query"); let record: Option = db.update(record_key).merge(merged).await?; let elapsed = now.elapsed(); @@ -139,6 +151,8 @@ impl<'a> GachaItemRepository<'a> { patch.insert("is_deleted".to_string(), Value::Bool(true)); patch.insert("updated_at".to_string(), Value::String(get_iso_date())); + let surreal_query = format!("UPDATE {:?} MERGE ...", record_key); + info!(query = %surreal_query, "Executing SurrealDB query"); let record: Option = db.update(record_key).merge(patch).await?; let elapsed = now.elapsed(); if std::env::var("RUST_ENV").unwrap_or_else(|_| "development".to_string()) diff --git a/imphnen-gacha/src/v1/gacha_rolls/gacha_rolls_repository.rs b/imphnen-gacha/src/v1/gacha_rolls/gacha_rolls_repository.rs index abec2aa..4e8d238 100644 --- a/imphnen-gacha/src/v1/gacha_rolls/gacha_rolls_repository.rs +++ b/imphnen-gacha/src/v1/gacha_rolls/gacha_rolls_repository.rs @@ -10,6 +10,7 @@ use rand_distr::weighted::WeightedIndex; use serde_json::{Map, Value}; use std::time::Instant; use tracing::instrument; +use tracing::info; pub struct GachaRollRepository<'a> { state: &'a AppState, @@ -33,6 +34,7 @@ impl<'a> GachaRollRepository<'a> { .with_select_fields(vec!["*"]) .with_fetch("item"); let sql = builder.build(); + info!(query = %sql, "Executing SurrealDB query"); let result: Option = builder.apply_bindings(db.query(sql)).await?.take(0)?; let elapsed = now.elapsed(); @@ -54,6 +56,7 @@ impl<'a> GachaRollRepository<'a> { ) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + info!(query = "CREATE", "Executing SurrealDB create operation for GachaRolls"); let record: Option = db .create(ResourceEnum::GachaRolls.to_string()) .content(data) @@ -77,6 +80,7 @@ impl<'a> GachaRollRepository<'a> { let table_name = ResourceEnum::GachaRolls.to_string(); let sql = format!("SELECT * FROM {table_name} WHERE is_deleted = false FETCH item"); + info!(query = %sql, "Executing SurrealDB query"); let result: Vec = db.query(sql).await?.take(0)?; let elapsed = now.elapsed(); if std::env::var("RUST_ENV").unwrap_or_else(|_| "development".to_string()) @@ -87,6 +91,7 @@ impl<'a> GachaRollRepository<'a> { Ok(result) } + #[instrument] pub fn roll_once(rolls: &[GachaRollQueryDto]) -> Option { let filtered: Vec<_> = rolls .iter() @@ -120,6 +125,7 @@ impl<'a> GachaRollRepository<'a> { patch.insert("is_deleted".to_string(), Value::Bool(true)); patch.insert("updated_at".to_string(), Value::String(get_iso_date())); + info!(query = "UPDATE", record_key = ?record_key, "Executing SurrealDB update operation for GachaRolls"); let record: Option = db.update(record_key).merge(patch).await?; let elapsed = now.elapsed(); if std::env::var("RUST_ENV").unwrap_or_else(|_| "development".to_string()) diff --git a/imphnen-iam/src/v1/auth/auth_repository.rs b/imphnen-iam/src/v1/auth/auth_repository.rs index 79d9722..34c6a08 100644 --- a/imphnen-iam/src/v1/auth/auth_repository.rs +++ b/imphnen-iam/src/v1/auth/auth_repository.rs @@ -7,6 +7,8 @@ use crate::{ use anyhow::{Result, anyhow, bail}; use chrono::{Duration, Utc}; use surrealdb::sql::Thing; +use tracing::instrument; +use tracing::info; pub struct AuthRepository<'a> { pub state: &'a AppState, @@ -17,6 +19,7 @@ impl<'a> AuthRepository<'a> { Self { state } } + #[instrument(skip(self, user), err)] pub async fn query_store_user(&self, user: UsersDetailQueryDto) -> Result { if user.email.trim().is_empty() { bail!("Email is required"); @@ -30,12 +33,14 @@ impl<'a> AuthRepository<'a> { permissions, }; + info!(query = %format!("DELETE FROM {} WHERE id = '{}'", table, user_id), "Executing SurrealDB query"); let _record: Option = self .state .surrealdb_mem .delete::>((table.clone(), user_id.clone())) .await?; + info!(query = %format!("CREATE {}:{}", table, user_id), "Executing SurrealDB query"); let record: Option = self .state .surrealdb_mem @@ -49,10 +54,12 @@ impl<'a> AuthRepository<'a> { } } + #[instrument(skip(self, email), err)] pub async fn query_get_stored_user( &self, email: String, ) -> Result { + info!(query = %format!("SELECT FROM {} WHERE id = '{}'", ResourceEnum::UsersCache.to_string(), email), "Executing SurrealDB query"); let user_cache: Option = self .state .surrealdb_mem @@ -105,7 +112,9 @@ impl<'a> AuthRepository<'a> { } } + #[instrument(skip(self, email), err)] pub async fn query_delete_stored_user(&self, email: String) -> Result { + info!(query = %format!("DELETE FROM {} WHERE id = '{}'", ResourceEnum::UsersCache.to_string(), email), "Executing SurrealDB query"); let record: Option = self .state .surrealdb_mem @@ -117,13 +126,16 @@ impl<'a> AuthRepository<'a> { } } + #[instrument(skip(self, email), err)] pub async fn query_get_stored_otp(&self, email: String) -> Result { let table = ResourceEnum::OtpCache.to_string(); let key = (table.as_str(), email.as_str()); + info!(query = %format!("SELECT FROM {} WHERE id = '{}'", table, email), "Executing SurrealDB query"); let result: Option = self.state.surrealdb_mem.select(key).await?; match result { Some(data) => match Utc::now() > data.expires_at { true => { + info!(query = %format!("DELETE FROM {} WHERE id = '{}'", table, email), "Executing SurrealDB query"); let _ = self .state .surrealdb_mem @@ -137,9 +149,11 @@ impl<'a> AuthRepository<'a> { } } + #[instrument(skip(self, email, otp), err)] pub async fn query_store_otp(&self, email: String, otp: u32) -> Result { let expires_at = Utc::now() + Duration::seconds(300); let table: String = ResourceEnum::OtpCache.to_string(); + info!(query = %format!("CREATE {}:{}", table, email), "Executing SurrealDB query"); let record: Option = self .state .surrealdb_mem @@ -152,7 +166,9 @@ impl<'a> AuthRepository<'a> { } } + #[instrument(skip(self, email), err)] pub async fn query_delete_stored_otp(&self, email: String) -> Result { + info!(query = %format!("DELETE FROM {} WHERE id = '{}'", ResourceEnum::OtpCache.to_string(), email), "Executing SurrealDB query"); let record: Option = self .state .surrealdb_mem diff --git a/imphnen-iam/src/v1/permissions/permissions_repository.rs b/imphnen-iam/src/v1/permissions/permissions_repository.rs index 0f77ad2..634e02a 100644 --- a/imphnen-iam/src/v1/permissions/permissions_repository.rs +++ b/imphnen-iam/src/v1/permissions/permissions_repository.rs @@ -7,6 +7,7 @@ use imphnen_utils::{DetailQueryBuilder, QueryListBuilder, extract_id}; use serde_json; use std::time::Instant; use tracing::instrument; +use tracing::info; pub struct PermissionsRepository<'a> { state: &'a AppState, @@ -23,6 +24,7 @@ impl<'a> PermissionsRepository<'a> { meta: MetaRequestDto, ) -> Result>> { let now = Instant::now(); + info!("Executing SurrealDB query: QueryListBuilder for Permissions with meta: {:?}", meta); let raw_result: ResponseListSuccessDto> = QueryListBuilder::new( &self.state.surrealdb_ws, @@ -61,6 +63,7 @@ impl<'a> PermissionsRepository<'a> { ) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + info!(id = %id, "Executing SurrealDB select for Permissions"); let result: Option = db .select((ResourceEnum::Permissions.to_string(), id.clone())) .await?; @@ -82,6 +85,7 @@ impl<'a> PermissionsRepository<'a> { id: String, ) -> Result { let now = Instant::now(); + info!(id = %id, "Executing transformed_query_permission_by_id (delegates to query_permission_by_id)"); let raw_result = self.query_permission_by_id(id.clone()).await?; let elapsed = now.elapsed(); if std::env::var("RUST_ENV").unwrap_or_else(|_| "development".to_string()) @@ -109,6 +113,7 @@ impl<'a> PermissionsRepository<'a> { .with_where("name", Some(name.clone())) .with_select_fields(vec!["*"]); let sql = builder.build(); + info!(query = %sql, "Executing SurrealDB query"); let result: Option = builder.apply_bindings(db.query(sql)).await?.take(0)?; let elapsed = now.elapsed(); @@ -130,6 +135,7 @@ impl<'a> PermissionsRepository<'a> { ) -> Result { let now = Instant::now(); let db = &self.state.surrealdb_ws; + info!("Executing SurrealDB create for Permissions with data: {:?}", data); let record: Option = db .create(ResourceEnum::Permissions.to_string()) .content(data) @@ -162,6 +168,7 @@ impl<'a> PermissionsRepository<'a> { created_at: existing.created_at, ..data.clone() }; + info!(record_key = ?record_key, "Executing SurrealDB update for Permissions"); let record: Option = db.update(record_key).merge(merged).await?; let elapsed = now.elapsed(); @@ -188,6 +195,7 @@ impl<'a> PermissionsRepository<'a> { bail!("Permission already deleted"); } let record_key = get_id(&permission.id)?; + info!(record_key = ?record_key, "Executing SurrealDB soft delete for Permissions"); let record: Option = db .update(record_key) .merge(serde_json::json!({ "is_deleted": true }))