diff --git a/src/bin/migrate_exif.rs b/src/bin/migrate_exif.rs index c405e52..5f5af9d 100644 --- a/src/bin/migrate_exif.rs +++ b/src/bin/migrate_exif.rs @@ -3,6 +3,7 @@ use std::sync::{Arc, Mutex}; use chrono::Utc; use clap::Parser; +use opentelemetry; use rayon::prelude::*; use walkdir::WalkDir; @@ -63,6 +64,9 @@ fn main() -> anyhow::Result<()> { let results: Vec<_> = image_files .par_iter() .map(|path| { + // Create context for this processing iteration + let context = opentelemetry::Context::new(); + let relative_path = match path.strip_prefix(&base) { Ok(p) => p.to_str().unwrap().to_string(), Err(_) => { @@ -76,7 +80,7 @@ fn main() -> anyhow::Result<()> { // Check if EXIF data already exists let existing = if let Ok(mut dao_lock) = dao.lock() { - dao_lock.get_exif(&relative_path).ok().flatten() + dao_lock.get_exif(&context, &relative_path).ok().flatten() } else { eprintln!("✗ {} - Failed to acquire database lock", relative_path); return Err(anyhow::anyhow!("Lock error")); @@ -117,10 +121,12 @@ fn main() -> anyhow::Result<()> { if let Ok(mut dao_lock) = dao.lock() { let result = if existing.is_some() { // Update existing record - dao_lock.update_exif(insert_exif).map(|_| "update") + dao_lock + .update_exif(&context, insert_exif) + .map(|_| "update") } else { // Insert new record - dao_lock.store_exif(insert_exif).map(|_| "insert") + dao_lock.store_exif(&context, insert_exif).map(|_| "insert") }; match result { diff --git a/src/cleanup/database_updater.rs b/src/cleanup/database_updater.rs index 9eb287e..052d7ba 100644 --- a/src/cleanup/database_updater.rs +++ b/src/cleanup/database_updater.rs @@ -50,7 +50,7 @@ impl DatabaseUpdater { // Update image_exif table if let Ok(mut dao) = self.exif_dao.lock() { - match dao.update_file_path(old_path, new_path) { + match dao.update_file_path(&context, old_path, new_path) { Ok(_) => { info!("Updated image_exif: {} -> {}", old_path, new_path); success_count += 1; @@ -120,7 +120,7 @@ impl DatabaseUpdater { // Get from image_exif if let Ok(mut dao) = self.exif_dao.lock() { - match dao.get_all_file_paths() { + match dao.get_all_file_paths(&context) { Ok(paths) => { info!("Found {} paths in image_exif", paths.len()); all_paths.extend(paths); diff --git a/src/database/mod.rs b/src/database/mod.rs index d9fc780..f71d885 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -7,6 +7,7 @@ use std::sync::{Arc, Mutex}; use crate::database::models::{ Favorite, ImageExif, InsertFavorite, InsertImageExif, InsertUser, User, }; +use crate::otel::trace_db_call; pub mod models; pub mod schema; @@ -221,18 +222,42 @@ impl FavoriteDao for SqliteFavoriteDao { } pub trait ExifDao: Sync + Send { - fn store_exif(&mut self, exif_data: InsertImageExif) -> Result; - fn get_exif(&mut self, file_path: &str) -> Result, DbError>; - fn update_exif(&mut self, exif_data: InsertImageExif) -> Result; - fn delete_exif(&mut self, file_path: &str) -> Result<(), DbError>; - fn get_all_with_date_taken(&mut self) -> Result, DbError>; + fn store_exif( + &mut self, + context: &opentelemetry::Context, + exif_data: InsertImageExif, + ) -> Result; + fn get_exif( + &mut self, + context: &opentelemetry::Context, + file_path: &str, + ) -> Result, DbError>; + fn update_exif( + &mut self, + context: &opentelemetry::Context, + exif_data: InsertImageExif, + ) -> Result; + fn delete_exif( + &mut self, + context: &opentelemetry::Context, + file_path: &str, + ) -> Result<(), DbError>; + fn get_all_with_date_taken( + &mut self, + context: &opentelemetry::Context, + ) -> Result, DbError>; /// Batch load EXIF data for multiple file paths (single query) - fn get_exif_batch(&mut self, file_paths: &[String]) -> Result, DbError>; + fn get_exif_batch( + &mut self, + context: &opentelemetry::Context, + file_paths: &[String], + ) -> Result, DbError>; /// Query files by EXIF criteria with optional filters fn query_by_exif( &mut self, + context: &opentelemetry::Context, camera_make: Option<&str>, camera_model: Option<&str>, lens_model: Option<&str>, @@ -242,13 +267,24 @@ pub trait ExifDao: Sync + Send { ) -> Result, DbError>; /// Get distinct camera makes with counts - fn get_camera_makes(&mut self) -> Result, DbError>; + fn get_camera_makes( + &mut self, + context: &opentelemetry::Context, + ) -> Result, DbError>; /// Update file path in EXIF database - fn update_file_path(&mut self, old_path: &str, new_path: &str) -> Result<(), DbError>; + fn update_file_path( + &mut self, + context: &opentelemetry::Context, + old_path: &str, + new_path: &str, + ) -> Result<(), DbError>; /// Get all file paths from EXIF database - fn get_all_file_paths(&mut self) -> Result, DbError>; + fn get_all_file_paths( + &mut self, + context: &opentelemetry::Context, + ) -> Result, DbError>; } pub struct SqliteExifDao { @@ -270,113 +306,151 @@ impl SqliteExifDao { } impl ExifDao for SqliteExifDao { - fn store_exif(&mut self, exif_data: InsertImageExif) -> Result { - use schema::image_exif::dsl::*; + fn store_exif( + &mut self, + context: &opentelemetry::Context, + exif_data: InsertImageExif, + ) -> Result { + trace_db_call(context, "insert", "store_exif", |_span| { + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - diesel::insert_into(image_exif) - .values(&exif_data) - .execute(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::InsertError))?; + diesel::insert_into(image_exif) + .values(&exif_data) + .execute(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Insert error"))?; - image_exif - .filter(file_path.eq(&exif_data.file_path)) - .first::(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + image_exif + .filter(file_path.eq(&exif_data.file_path)) + .first::(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Query error")) + }) + .map_err(|_| DbError::new(DbErrorKind::InsertError)) } - fn get_exif(&mut self, path: &str) -> Result, DbError> { - use schema::image_exif::dsl::*; + fn get_exif( + &mut self, + context: &opentelemetry::Context, + path: &str, + ) -> Result, DbError> { + trace_db_call(context, "query", "get_exif", |_span| { + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - match image_exif - .filter(file_path.eq(path)) - .first::(connection.deref_mut()) - { - Ok(exif) => Ok(Some(exif)), - Err(diesel::result::Error::NotFound) => Ok(None), - Err(_) => Err(DbError::new(DbErrorKind::QueryError)), - } + match image_exif + .filter(file_path.eq(path)) + .first::(connection.deref_mut()) + { + Ok(exif) => Ok(Some(exif)), + Err(diesel::result::Error::NotFound) => Ok(None), + Err(_) => Err(anyhow::anyhow!("Query error")), + } + }) + .map_err(|_| DbError::new(DbErrorKind::QueryError)) } - fn update_exif(&mut self, exif_data: InsertImageExif) -> Result { - use schema::image_exif::dsl::*; + fn update_exif( + &mut self, + context: &opentelemetry::Context, + exif_data: InsertImageExif, + ) -> Result { + trace_db_call(context, "update", "update_exif", |_span| { + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - diesel::update(image_exif.filter(file_path.eq(&exif_data.file_path))) - .set(( - camera_make.eq(&exif_data.camera_make), - camera_model.eq(&exif_data.camera_model), - lens_model.eq(&exif_data.lens_model), - width.eq(&exif_data.width), - height.eq(&exif_data.height), - orientation.eq(&exif_data.orientation), - gps_latitude.eq(&exif_data.gps_latitude), - gps_longitude.eq(&exif_data.gps_longitude), - gps_altitude.eq(&exif_data.gps_altitude), - focal_length.eq(&exif_data.focal_length), - aperture.eq(&exif_data.aperture), - shutter_speed.eq(&exif_data.shutter_speed), - iso.eq(&exif_data.iso), - date_taken.eq(&exif_data.date_taken), - last_modified.eq(&exif_data.last_modified), - )) - .execute(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::InsertError))?; + diesel::update(image_exif.filter(file_path.eq(&exif_data.file_path))) + .set(( + camera_make.eq(&exif_data.camera_make), + camera_model.eq(&exif_data.camera_model), + lens_model.eq(&exif_data.lens_model), + width.eq(&exif_data.width), + height.eq(&exif_data.height), + orientation.eq(&exif_data.orientation), + gps_latitude.eq(&exif_data.gps_latitude), + gps_longitude.eq(&exif_data.gps_longitude), + gps_altitude.eq(&exif_data.gps_altitude), + focal_length.eq(&exif_data.focal_length), + aperture.eq(&exif_data.aperture), + shutter_speed.eq(&exif_data.shutter_speed), + iso.eq(&exif_data.iso), + date_taken.eq(&exif_data.date_taken), + last_modified.eq(&exif_data.last_modified), + )) + .execute(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Update error"))?; - image_exif - .filter(file_path.eq(&exif_data.file_path)) - .first::(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + image_exif + .filter(file_path.eq(&exif_data.file_path)) + .first::(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Query error")) + }) + .map_err(|_| DbError::new(DbErrorKind::UpdateError)) } - fn delete_exif(&mut self, path: &str) -> Result<(), DbError> { - use schema::image_exif::dsl::*; + fn delete_exif(&mut self, context: &opentelemetry::Context, path: &str) -> Result<(), DbError> { + trace_db_call(context, "delete", "delete_exif", |_span| { + use schema::image_exif::dsl::*; - diesel::delete(image_exif.filter(file_path.eq(path))) - .execute(self.connection.lock().unwrap().deref_mut()) - .map(|_| ()) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + diesel::delete(image_exif.filter(file_path.eq(path))) + .execute(self.connection.lock().unwrap().deref_mut()) + .map(|_| ()) + .map_err(|_| anyhow::anyhow!("Delete error")) + }) + .map_err(|_| DbError::new(DbErrorKind::QueryError)) } - fn get_all_with_date_taken(&mut self) -> Result, DbError> { - use schema::image_exif::dsl::*; + fn get_all_with_date_taken( + &mut self, + context: &opentelemetry::Context, + ) -> Result, DbError> { + trace_db_call(context, "query", "get_all_with_date_taken", |_span| { + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - image_exif - .select((file_path, date_taken)) - .filter(date_taken.is_not_null()) - .load::<(String, Option)>(connection.deref_mut()) - .map(|records| { - records - .into_iter() - .filter_map(|(path, dt)| dt.map(|ts| (path, ts))) - .collect() - }) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + image_exif + .select((file_path, date_taken)) + .filter(date_taken.is_not_null()) + .load::<(String, Option)>(connection.deref_mut()) + .map(|records| { + records + .into_iter() + .filter_map(|(path, dt)| dt.map(|ts| (path, ts))) + .collect() + }) + .map_err(|_| anyhow::anyhow!("Query error")) + }) + .map_err(|_| DbError::new(DbErrorKind::QueryError)) } - fn get_exif_batch(&mut self, file_paths: &[String]) -> Result, DbError> { - use schema::image_exif::dsl::*; + fn get_exif_batch( + &mut self, + context: &opentelemetry::Context, + file_paths: &[String], + ) -> Result, DbError> { + trace_db_call(context, "query", "get_exif_batch", |_span| { + use schema::image_exif::dsl::*; - if file_paths.is_empty() { - return Ok(Vec::new()); - } + if file_paths.is_empty() { + return Ok(Vec::new()); + } - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - image_exif - .filter(file_path.eq_any(file_paths)) - .load::(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + image_exif + .filter(file_path.eq_any(file_paths)) + .load::(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Query error")) + }) + .map_err(|_| DbError::new(DbErrorKind::QueryError)) } fn query_by_exif( &mut self, + context: &opentelemetry::Context, camera_make_filter: Option<&str>, camera_model_filter: Option<&str>, lens_model_filter: Option<&str>, @@ -384,88 +458,111 @@ impl ExifDao for SqliteExifDao { date_from: Option, date_to: Option, ) -> Result, DbError> { - use schema::image_exif::dsl::*; + trace_db_call(context, "query", "query_by_exif", |_span| { + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - let mut query = image_exif.into_boxed(); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut query = image_exif.into_boxed(); - // Camera filters (case-insensitive partial match) - if let Some(make) = camera_make_filter { - query = query.filter(camera_make.like(format!("%{}%", make))); - } - if let Some(model) = camera_model_filter { - query = query.filter(camera_model.like(format!("%{}%", model))); - } - if let Some(lens) = lens_model_filter { - query = query.filter(lens_model.like(format!("%{}%", lens))); - } + // Camera filters (case-insensitive partial match) + if let Some(make) = camera_make_filter { + query = query.filter(camera_make.like(format!("%{}%", make))); + } + if let Some(model) = camera_model_filter { + query = query.filter(camera_model.like(format!("%{}%", model))); + } + if let Some(lens) = lens_model_filter { + query = query.filter(lens_model.like(format!("%{}%", lens))); + } - // GPS bounding box - if let Some((min_lat, max_lat, min_lon, max_lon)) = gps_bounds { - query = query - .filter(gps_latitude.between(min_lat, max_lat)) - .filter(gps_longitude.between(min_lon, max_lon)) - .filter(gps_latitude.is_not_null()) - .filter(gps_longitude.is_not_null()); - } + // GPS bounding box + if let Some((min_lat, max_lat, min_lon, max_lon)) = gps_bounds { + query = query + .filter(gps_latitude.between(min_lat, max_lat)) + .filter(gps_longitude.between(min_lon, max_lon)) + .filter(gps_latitude.is_not_null()) + .filter(gps_longitude.is_not_null()); + } - // Date range - if let Some(from) = date_from { - query = query.filter(date_taken.ge(from)); - } - if let Some(to) = date_to { - query = query.filter(date_taken.le(to)); - } - if date_from.is_some() || date_to.is_some() { - query = query.filter(date_taken.is_not_null()); - } + // Date range + if let Some(from) = date_from { + query = query.filter(date_taken.ge(from)); + } + if let Some(to) = date_to { + query = query.filter(date_taken.le(to)); + } + if date_from.is_some() || date_to.is_some() { + query = query.filter(date_taken.is_not_null()); + } - query - .load::(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + query + .load::(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Query error")) + }) + .map_err(|_| DbError::new(DbErrorKind::QueryError)) } - fn get_camera_makes(&mut self) -> Result, DbError> { - use diesel::dsl::count; - use schema::image_exif::dsl::*; + fn get_camera_makes( + &mut self, + context: &opentelemetry::Context, + ) -> Result, DbError> { + trace_db_call(context, "query", "get_camera_makes", |_span| { + use diesel::dsl::count; + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - image_exif - .filter(camera_make.is_not_null()) - .group_by(camera_make) - .select((camera_make, count(id))) - .order(count(id).desc()) - .load::<(Option, i64)>(connection.deref_mut()) - .map(|records| { - records - .into_iter() - .filter_map(|(make, cnt)| make.map(|m| (m, cnt))) - .collect() - }) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + image_exif + .filter(camera_make.is_not_null()) + .group_by(camera_make) + .select((camera_make, count(id))) + .order(count(id).desc()) + .load::<(Option, i64)>(connection.deref_mut()) + .map(|records| { + records + .into_iter() + .filter_map(|(make, cnt)| make.map(|m| (m, cnt))) + .collect() + }) + .map_err(|_| anyhow::anyhow!("Query error")) + }) + .map_err(|_| DbError::new(DbErrorKind::QueryError)) } - fn update_file_path(&mut self, old_path: &str, new_path: &str) -> Result<(), DbError> { - use schema::image_exif::dsl::*; + fn update_file_path( + &mut self, + context: &opentelemetry::Context, + old_path: &str, + new_path: &str, + ) -> Result<(), DbError> { + trace_db_call(context, "update", "update_file_path", |_span| { + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - diesel::update(image_exif.filter(file_path.eq(old_path))) - .set(file_path.eq(new_path)) - .execute(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::UpdateError))?; - Ok(()) + diesel::update(image_exif.filter(file_path.eq(old_path))) + .set(file_path.eq(new_path)) + .execute(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Update error"))?; + Ok(()) + }) + .map_err(|_| DbError::new(DbErrorKind::UpdateError)) } - fn get_all_file_paths(&mut self) -> Result, DbError> { - use schema::image_exif::dsl::*; + fn get_all_file_paths( + &mut self, + context: &opentelemetry::Context, + ) -> Result, DbError> { + trace_db_call(context, "query", "get_all_file_paths", |_span| { + use schema::image_exif::dsl::*; - let mut connection = self.connection.lock().expect("Unable to get ExifDao"); + let mut connection = self.connection.lock().expect("Unable to get ExifDao"); - image_exif - .select(file_path) - .load(connection.deref_mut()) - .map_err(|_| DbError::new(DbErrorKind::QueryError)) + image_exif + .select(file_path) + .load(connection.deref_mut()) + .map_err(|_| anyhow::anyhow!("Query error")) + }) + .map_err(|_| DbError::new(DbErrorKind::QueryError)) } } diff --git a/src/files.rs b/src/files.rs index 15250c4..bf0260a 100644 --- a/src/files.rs +++ b/src/files.rs @@ -143,6 +143,7 @@ pub async fn list_photos( let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao"); let exif_results = exif_dao_guard .query_by_exif( + &span_context, req.camera_make.as_deref(), req.camera_model.as_deref(), req.lens_model.as_deref(), @@ -276,7 +277,7 @@ pub async fn list_photos( // Batch fetch EXIF data let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao"); let exif_map: std::collections::HashMap = exif_dao_guard - .get_exif_batch(&file_paths) + .get_exif_batch(&span_context, &file_paths) .unwrap_or_default() .into_iter() .filter_map(|exif| exif.date_taken.map(|dt| (exif.file_path, dt))) @@ -451,7 +452,7 @@ pub async fn list_photos( // Batch fetch EXIF data let mut exif_dao_guard = exif_dao.lock().expect("Unable to get ExifDao"); let exif_map: std::collections::HashMap = exif_dao_guard - .get_exif_batch(&file_paths) + .get_exif_batch(&span_context, &file_paths) .unwrap_or_default() .into_iter() .filter_map(|exif| exif.date_taken.map(|dt| (exif.file_path, dt))) @@ -896,6 +897,7 @@ mod tests { impl crate::database::ExifDao for MockExifDao { fn store_exif( &mut self, + _context: &opentelemetry::Context, data: crate::database::models::InsertImageExif, ) -> Result { // Return a dummy ImageExif for tests @@ -923,6 +925,7 @@ mod tests { fn get_exif( &mut self, + _context: &opentelemetry::Context, _: &str, ) -> Result, crate::database::DbError> { Ok(None) @@ -930,6 +933,7 @@ mod tests { fn update_exif( &mut self, + _context: &opentelemetry::Context, data: crate::database::models::InsertImageExif, ) -> Result { // Return a dummy ImageExif for tests @@ -955,18 +959,24 @@ mod tests { }) } - fn delete_exif(&mut self, _: &str) -> Result<(), crate::database::DbError> { + fn delete_exif( + &mut self, + _context: &opentelemetry::Context, + _: &str, + ) -> Result<(), crate::database::DbError> { Ok(()) } fn get_all_with_date_taken( &mut self, + _context: &opentelemetry::Context, ) -> Result, crate::database::DbError> { Ok(Vec::new()) } fn get_exif_batch( &mut self, + _context: &opentelemetry::Context, _: &[String], ) -> Result, crate::database::DbError> { Ok(Vec::new()) @@ -974,6 +984,7 @@ mod tests { fn query_by_exif( &mut self, + _context: &opentelemetry::Context, _: Option<&str>, _: Option<&str>, _: Option<&str>, @@ -984,15 +995,26 @@ mod tests { Ok(Vec::new()) } - fn get_camera_makes(&mut self) -> Result, crate::database::DbError> { + fn get_camera_makes( + &mut self, + _context: &opentelemetry::Context, + ) -> Result, crate::database::DbError> { Ok(Vec::new()) } - fn update_file_path(&mut self, old_path: &str, new_path: &str) -> Result<(), DbError> { + fn update_file_path( + &mut self, + _context: &opentelemetry::Context, + _old_path: &str, + _new_path: &str, + ) -> Result<(), DbError> { Ok(()) } - fn get_all_file_paths(&mut self) -> Result, DbError> { + fn get_all_file_paths( + &mut self, + _context: &opentelemetry::Context, + ) -> Result, DbError> { Ok(Vec::new()) } } diff --git a/src/main.rs b/src/main.rs index 3187bea..b459f39 100644 --- a/src/main.rs +++ b/src/main.rs @@ -158,6 +158,7 @@ async fn get_file_metadata( let tracer = global_tracer(); let context = extract_context_from_request(&request); let mut span = tracer.start_with_context("get_file_metadata", &context); + let span_context = opentelemetry::Context::current(); let full_path = is_valid_full_path(&app_state.base_path, &path.path, false); @@ -171,7 +172,7 @@ async fn get_file_metadata( // Query EXIF data if available if let Ok(mut dao) = exif_dao.lock() - && let Ok(Some(exif)) = dao.get_exif(&path.path) + && let Ok(Some(exif)) = dao.get_exif(&span_context, &path.path) { response.exif = Some(exif.into()); } @@ -205,6 +206,7 @@ async fn upload_image( let tracer = global_tracer(); let context = extract_context_from_request(&request); let mut span = tracer.start_with_context("upload_image", &context); + let span_context = opentelemetry::Context::current(); let mut file_content: BytesMut = BytesMut::new(); let mut file_name: Option = None; @@ -305,7 +307,7 @@ async fn upload_image( }; if let Ok(mut dao) = exif_dao.lock() { - if let Err(e) = dao.store_exif(insert_exif) { + if let Err(e) = dao.store_exif(&span_context, insert_exif) { error!("Failed to store EXIF data for {}: {:?}", relative_path, e); } else { debug!("EXIF data stored for {}", relative_path); @@ -877,6 +879,7 @@ fn process_new_files( exif_dao: Arc>>, modified_since: Option, ) { + let context = opentelemetry::Context::new(); let thumbs = dotenv::var("THUMBNAILS").expect("THUMBNAILS not defined"); let thumbnail_directory = Path::new(&thumbs); @@ -922,7 +925,7 @@ fn process_new_files( let existing_exif_paths: HashMap = { let mut dao = exif_dao.lock().expect("Unable to lock ExifDao"); - match dao.get_exif_batch(&file_paths) { + match dao.get_exif_batch(&context, &file_paths) { Ok(exif_records) => exif_records .into_iter() .map(|record| (record.file_path, true)) @@ -995,7 +998,7 @@ fn process_new_files( }; let mut dao = exif_dao.lock().expect("Unable to lock ExifDao"); - if let Err(e) = dao.store_exif(insert_exif) { + if let Err(e) = dao.store_exif(&context, insert_exif) { error!("Failed to store EXIF data for {}: {:?}", relative_path, e); } else { debug!("EXIF data stored for {}", relative_path); diff --git a/src/memories.rs b/src/memories.rs index d941cd2..a65f9df 100644 --- a/src/memories.rs +++ b/src/memories.rs @@ -335,6 +335,7 @@ pub fn extract_date_from_filename(filename: &str) -> Option>>, + context: &opentelemetry::Context, base_path: &str, now: NaiveDate, span_mode: MemoriesSpan, @@ -344,7 +345,7 @@ fn collect_exif_memories( ) -> Vec<(MemoryItem, NaiveDate)> { // Query database for all files with date_taken let exif_records = match exif_dao.lock() { - Ok(mut dao) => match dao.get_all_with_date_taken() { + Ok(mut dao) => match dao.get_all_with_date_taken(context) { Ok(records) => records, Err(e) => { warn!("Failed to query EXIF database: {:?}", e); @@ -471,8 +472,9 @@ pub async fn list_memories( exif_dao: Data>>, ) -> impl Responder { let tracer = global_tracer(); - let context = extract_context_from_request(&request); - let mut span = tracer.start_with_context("list_memories", &context); + let parent_context = extract_context_from_request(&request); + let mut span = tracer.start_with_context("list_memories", &parent_context); + let span_context = opentelemetry::Context::current(); let span_mode = q.span.unwrap_or(MemoriesSpan::Day); let years_back: u32 = 15; @@ -506,6 +508,7 @@ pub async fn list_memories( // Phase 1: Query EXIF database let exif_memories = collect_exif_memories( &exif_dao, + &span_context, &app_state.base_path, now, span_mode, diff --git a/src/tags.rs b/src/tags.rs index 0e9d75f..a98a73e 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -113,7 +113,7 @@ async fn get_all_tags( let camera_makes = exif_dao .lock() .expect("Unable to get ExifDao") - .get_camera_makes() + .get_camera_makes(&span_context) .unwrap_or_else(|e| { log::warn!("Failed to get camera makes: {:?}", e); Vec::new() @@ -591,7 +591,7 @@ impl TagDao for SqliteTagDao { &mut self, old_name: &str, new_name: &str, - context: &opentelemetry::Context, + _context: &opentelemetry::Context, ) -> anyhow::Result<()> { use crate::database::schema::tagged_photo::dsl::*; @@ -603,7 +603,7 @@ impl TagDao for SqliteTagDao { fn get_all_photo_names( &mut self, - context: &opentelemetry::Context, + _context: &opentelemetry::Context, ) -> anyhow::Result> { use crate::database::schema::tagged_photo::dsl::*;