From 82e2ef986fd2991d6633c873e943a27986e77908 Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Thu, 25 Sep 2025 04:33:44 +0300 Subject: [PATCH] feat: update dependencies to include tracing and improve logging throughout the application --- Cargo.lock | 81 +++++++++++++- crates/analytics/Cargo.toml | 1 + crates/analytics/src/cmd/serve.rs | 4 +- crates/analytics/src/core.rs | 121 +++++++-------------- crates/analytics/src/handlers/albums.rs | 4 + crates/analytics/src/handlers/artists.rs | 2 + crates/analytics/src/handlers/scrobbles.rs | 2 + crates/analytics/src/handlers/stats.rs | 8 ++ crates/analytics/src/handlers/tracks.rs | 3 + crates/analytics/src/subscriber/mod.rs | 14 +-- crates/dropbox/Cargo.toml | 1 + crates/googledrive/Cargo.toml | 1 + crates/jetstream/Cargo.toml | 1 + crates/playlists/Cargo.toml | 1 + crates/rockskyd/Cargo.toml | 4 + crates/rockskyd/src/main.rs | 12 ++ crates/scrobbler/Cargo.toml | 1 + crates/spotify/Cargo.toml | 1 + crates/storage/Cargo.toml | 1 + crates/tracklist/Cargo.toml | 1 + crates/webscrobbler/Cargo.toml | 1 + 21 files changed, 168 insertions(+), 97 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e3a5af0..e77930a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3064,9 +3064,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "lru-slab" @@ -3227,6 +3227,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "nu-ansi-term" +version = "0.50.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "nuid" version = "0.5.0" @@ -3402,9 +3411,9 @@ dependencies = [ [[package]] name = "owo-colors" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" +checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" dependencies = [ "supports-color 2.1.0", "supports-color 3.0.2", @@ -4837,6 +4846,7 @@ dependencies = [ "sqlx", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -4888,6 +4898,7 @@ dependencies = [ "tempfile", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -4919,6 +4930,7 @@ dependencies = [ "tempfile", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -4941,6 +4953,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-tungstenite", + "tracing", "tungstenite", "url", ] @@ -4968,6 +4981,7 @@ dependencies = [ "sqlx", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -4995,6 +5009,7 @@ dependencies = [ "sqlx", "tokio", "tokio-stream", + "tracing", "uuid", ] @@ -5018,6 +5033,7 @@ dependencies = [ "sqlx", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -5034,6 +5050,7 @@ dependencies = [ "sqlx", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -5053,6 +5070,7 @@ dependencies = [ "serde_json", "tokio", "tokio-stream", + "tracing", "uuid", ] @@ -5080,6 +5098,7 @@ dependencies = [ "sqlx", "tokio", "tokio-stream", + "tracing", ] [[package]] @@ -5089,6 +5108,7 @@ dependencies = [ "anyhow", "clap", "dotenv", + "owo-colors", "rocksky-analytics", "rocksky-dropbox", "rocksky-googledrive", @@ -5099,6 +5119,9 @@ dependencies = [ "rocksky-tracklist", "rocksky-webscrobbler", "tokio", + "tracing", + "tracing-log", + "tracing-subscriber", ] [[package]] @@ -5630,6 +5653,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "1.3.0" @@ -6440,6 +6472,15 @@ dependencies = [ "syn 2.0.101", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "time" version = "0.3.44" @@ -6780,6 +6821,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", ] [[package]] @@ -6958,6 +7025,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/crates/analytics/Cargo.toml b/crates/analytics/Cargo.toml index b014274..a81d143 100644 --- a/crates/analytics/Cargo.toml +++ b/crates/analytics/Cargo.toml @@ -28,3 +28,4 @@ polars = "0.46.0" clap = "4.5.31" actix-web = "4.9.0" tokio-stream = { version = "0.1.17", features = ["full"] } +tracing = "0.1.41" diff --git a/crates/analytics/src/cmd/serve.rs b/crates/analytics/src/cmd/serve.rs index c04a185..d4be314 100644 --- a/crates/analytics/src/cmd/serve.rs +++ b/crates/analytics/src/cmd/serve.rs @@ -29,7 +29,7 @@ async fn call_method( req: HttpRequest, ) -> Result { let method = req.match_info().get("method").unwrap_or("unknown"); - println!("Method: {}", method.bright_green()); + tracing::info!(method = %method.bright_green(), "API call"); let conn = data.get_ref().clone(); handle(method, &mut payload, &req, conn) @@ -45,7 +45,7 @@ pub async fn serve(conn: Arc>) -> Result<(), Error> { let addr = format!("{}:{}", host, port); let url = format!("http://{}", addr); - println!("Listening on {}", url.bright_green()); + tracing::info!(url = %url.bright_green(), "Listening on"); let conn = conn.clone(); HttpServer::new(move || { diff --git a/crates/analytics/src/core.rs b/crates/analytics/src/core.rs index 4f67b56..a3f6d6a 100644 --- a/crates/analytics/src/core.rs +++ b/crates/analytics/src/core.rs @@ -194,12 +194,7 @@ pub async fn load_tracks(conn: Arc>, pool: &Pool) -> .await?; for (i, track) in tracks.clone().into_iter().enumerate() { - println!( - "track {} - {} - {}", - i, - track.title.bright_green(), - track.artist - ); + tracing::info!(track = i, title = %track.title.bright_green(), artist = %track.artist); match conn.execute( "INSERT INTO tracks ( id, @@ -255,11 +250,11 @@ pub async fn load_tracks(conn: Arc>, pool: &Pool) -> ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting track"), } } - println!("tracks: {:?}", tracks.len()); + tracing::info!(tracks = tracks.len(), "Loaded tracks"); Ok(()) } @@ -277,7 +272,7 @@ pub async fn load_artists( .await?; for (i, artist) in artists.clone().into_iter().enumerate() { - println!("artist {} - {}", i, artist.name.bright_green()); + tracing::info!(artist = i, name = %artist.name.bright_green()); match conn.execute( "INSERT INTO artists ( id, @@ -323,11 +318,11 @@ pub async fn load_artists( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting artist"), } } - println!("artists: {:?}", artists.len()); + tracing::info!(artists = artists.len(), "Loaded artists"); Ok(()) } @@ -342,7 +337,7 @@ pub async fn load_albums(conn: Arc>, pool: &Pool) -> .await?; for (i, album) in albums.clone().into_iter().enumerate() { - println!("album {} - {}", i, album.title.bright_green()); + tracing::info!(album = i, title = %album.title.bright_green(), artist = %album.artist); match conn.execute( "INSERT INTO albums ( id, @@ -388,11 +383,11 @@ pub async fn load_albums(conn: Arc>, pool: &Pool) -> ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting album"), } } - println!("albums: {:?}", albums.len()); + tracing::info!(albums = albums.len(), "Loaded albums"); Ok(()) } @@ -407,7 +402,7 @@ pub async fn load_users(conn: Arc>, pool: &Pool) -> .await?; for (i, user) in users.clone().into_iter().enumerate() { - println!("user {} - {}", i, user.display_name.bright_green()); + tracing::info!(user = i, name = %user.display_name.bright_green()); match conn.execute( "INSERT INTO users ( id, @@ -429,11 +424,11 @@ pub async fn load_users(conn: Arc>, pool: &Pool) -> ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting user"), } } - println!("users: {:?}", users.len()); + tracing::info!(users = users.len(), "Loaded users"); Ok(()) } @@ -451,15 +446,7 @@ pub async fn load_scrobbles( .await?; for (i, scrobble) in scrobbles.clone().into_iter().enumerate() { - println!( - "scrobble {} - {}", - i, - match scrobble.uri.clone() { - Some(uri) => uri.to_string(), - None => "None".to_string(), - } - .bright_green() - ); + tracing::info!(scrobble = i, uri = %scrobble.uri.clone().unwrap_or_else(|| "None".to_string()).bright_green()); match conn.execute( "INSERT INTO scrobbles ( id, @@ -489,11 +476,11 @@ pub async fn load_scrobbles( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting scrobble"), } } - println!("scrobbles: {:?}", scrobbles.len()); + tracing::info!(scrobbles = scrobbles.len(), "Loaded scrobbles"); Ok(()) } @@ -511,12 +498,7 @@ pub async fn load_album_tracks( .await?; for (i, album_track) in album_tracks.clone().into_iter().enumerate() { - println!( - "album_track {} - {} - {}", - i, - album_track.album_id.bright_green(), - album_track.track_id - ); + tracing::info!(album_track = i, album_id = %album_track.album_id.bright_green(), track_id = %album_track.track_id); match conn.execute( "INSERT INTO album_tracks ( id, @@ -532,10 +514,11 @@ pub async fn load_album_tracks( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting album_track"), } } - println!("album_tracks: {:?}", album_tracks.len()); + + tracing::info!(album_tracks = album_tracks.len(), "Loaded album_tracks"); Ok(()) } @@ -553,12 +536,7 @@ pub async fn load_loved_tracks( .await?; for (i, loved_track) in loved_tracks.clone().into_iter().enumerate() { - println!( - "loved_track {} - {} - {}", - i, - loved_track.user_id.bright_green(), - loved_track.track_id - ); + tracing::info!(loved_track = i, user_id = %loved_track.user_id.bright_green(), track_id = %loved_track.track_id); match conn.execute( "INSERT INTO loved_tracks ( id, @@ -577,11 +555,11 @@ pub async fn load_loved_tracks( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting loved_track"), } } - println!("loved_tracks: {:?}", loved_tracks.len()); + tracing::info!(loved_tracks = loved_tracks.len(), "Loaded loved_tracks"); Ok(()) } @@ -599,12 +577,7 @@ pub async fn load_artist_tracks( .await?; for (i, artist_track) in artist_tracks.clone().into_iter().enumerate() { - println!( - "artist_track {} - {} - {}", - i, - artist_track.artist_id.bright_green(), - artist_track.track_id - ); + tracing::info!(artist_track = i, artist_id = %artist_track.artist_id.bright_green(), track_id = %artist_track.track_id); match conn.execute( "INSERT INTO artist_tracks (id, artist_id, track_id, created_at) VALUES (?, ?, ?, ?)", params![ @@ -615,11 +588,11 @@ pub async fn load_artist_tracks( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting artist_track"), } } - println!("artist_tracks: {:?}", artist_tracks.len()); + tracing::info!(artist_tracks = artist_tracks.len(), "Loaded artist_tracks"); Ok(()) } @@ -637,12 +610,7 @@ pub async fn load_artist_albums( .await?; for (i, artist_album) in artist_albums.clone().into_iter().enumerate() { - println!( - "artist_albums {} - {} - {}", - i, - artist_album.artist_id.bright_green(), - artist_album.album_id - ); + tracing::info!(artist_album = i, artist_id = %artist_album.artist_id.bright_green(), album_id = %artist_album.album_id); match conn.execute( "INSERT INTO artist_albums (id, artist_id, album_id, created_at) VALUES (?, ?, ?, ?)", params![ @@ -653,11 +621,11 @@ pub async fn load_artist_albums( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting artist_album"), } } - println!("artist_albums: {:?}", artist_albums.len()); + tracing::info!(artist_albums = artist_albums.len(), "Loaded artist_albums"); Ok(()) } @@ -675,12 +643,7 @@ pub async fn load_user_albums( .await?; for (i, user_album) in user_albums.clone().into_iter().enumerate() { - println!( - "user_album {} - {} - {}", - i, - user_album.user_id.bright_green(), - user_album.album_id - ); + tracing::info!(user_album = i, user_id = %user_album.user_id.bright_green(), album_id = %user_album.album_id); match conn.execute( "INSERT INTO user_albums (id, user_id, album_id, created_at) VALUES (?, ?, ?, ?)", params![ @@ -691,11 +654,11 @@ pub async fn load_user_albums( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting user_album"), } } - println!("user_albums: {:?}", user_albums.len()); + tracing::info!(user_albums = user_albums.len(), "Loaded user_albums"); Ok(()) } @@ -713,12 +676,7 @@ pub async fn load_user_artists( .await?; for (i, user_artist) in user_artists.clone().into_iter().enumerate() { - println!( - "user_artist {} - {} - {}", - i, - user_artist.user_id.bright_green(), - user_artist.artist_id - ); + tracing::info!(user_artist = i, user_id = %user_artist.user_id.bright_green(), artist_id = %user_artist.artist_id); match conn.execute( "INSERT INTO user_artists (id, user_id, artist_id, created_at) VALUES (?, ?, ?, ?)", params![ @@ -729,11 +687,11 @@ pub async fn load_user_artists( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting user_artist"), } } - println!("user_artists: {:?}", user_artists.len()); + tracing::info!(user_artists = user_artists.len(), "Loaded user_artists"); Ok(()) } @@ -751,12 +709,7 @@ pub async fn load_user_tracks( .await?; for (i, user_track) in user_tracks.clone().into_iter().enumerate() { - println!( - "user_track {} - {} - {}", - i, - user_track.user_id.bright_green(), - user_track.track_id - ); + tracing::info!(user_track = i, user_id = %user_track.user_id.bright_green(), track_id = %user_track.track_id); match conn.execute( "INSERT INTO user_tracks (id, user_id, track_id, created_at) VALUES (?, ?, ?, ?)", params![ @@ -767,10 +720,10 @@ pub async fn load_user_tracks( ], ) { Ok(_) => (), - Err(e) => println!("error: {}", e), + Err(e) => tracing::error!(error = %e, "Error inserting user_track"), } } - println!("user_tracks: {:?}", user_tracks.len()); + tracing::info!(user_tracks = user_tracks.len(), "Loaded user_tracks"); Ok(()) } diff --git a/crates/analytics/src/handlers/albums.rs b/crates/analytics/src/handlers/albums.rs index 6a71b9c..3976ce3 100644 --- a/crates/analytics/src/handlers/albums.rs +++ b/crates/analytics/src/handlers/albums.rs @@ -22,6 +22,7 @@ pub async fn get_albums( let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(20); let did = params.user_did; + tracing::info!(limit, offset, user_did = ?did, "Get albums"); let conn = conn.lock().unwrap(); let mut stmt = match did { @@ -118,6 +119,7 @@ pub async fn get_top_albums( let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(20); let did = params.user_did; + tracing::info!(limit, offset, user_did = ?did, "Get top albums"); let conn = conn.lock().unwrap(); let mut stmt = match did { @@ -237,6 +239,8 @@ pub async fn get_album_tracks( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let conn = conn.lock().unwrap(); + tracing::info!(album_id = %params.album_id, "Get album tracks"); + let mut stmt = conn.prepare(r#" SELECT t.id, diff --git a/crates/analytics/src/handlers/artists.rs b/crates/analytics/src/handlers/artists.rs index c6138b7..0be4954 100644 --- a/crates/analytics/src/handlers/artists.rs +++ b/crates/analytics/src/handlers/artists.rs @@ -318,6 +318,7 @@ pub async fn get_artist_albums( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let conn = conn.lock().unwrap(); + tracing::info!(artist_id = %params.artist_id, "Get artist albums"); let mut stmt = conn.prepare(r#" SELECT @@ -376,6 +377,7 @@ pub async fn get_artist_listeners( let pagination = params.pagination.unwrap_or_default(); let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(10); + tracing::info!(artist_id = %params.artist_id, limit, offset, "Get artist listeners"); let conn = conn.lock().unwrap(); let mut stmt = diff --git a/crates/analytics/src/handlers/scrobbles.rs b/crates/analytics/src/handlers/scrobbles.rs index b752dd1..ce4e9fe 100644 --- a/crates/analytics/src/handlers/scrobbles.rs +++ b/crates/analytics/src/handlers/scrobbles.rs @@ -19,6 +19,7 @@ pub async fn get_scrobbles( let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(20); let did = params.user_did; + tracing::info!(limit, offset, user_did = ?did, "Get scrobbles"); let conn = conn.lock().unwrap(); let mut stmt = match did { @@ -139,6 +140,7 @@ pub async fn get_distinct_scrobbles( let pagination = params.pagination.unwrap_or_default(); let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(10); + tracing::info!(limit, offset, user_did = ?params.user_did, "Get distinct scrobbles"); let conn = conn.lock().unwrap(); let mut stmt = conn.prepare( diff --git a/crates/analytics/src/handlers/stats.rs b/crates/analytics/src/handlers/stats.rs index 18c4153..a2b2f76 100644 --- a/crates/analytics/src/handlers/stats.rs +++ b/crates/analytics/src/handlers/stats.rs @@ -23,6 +23,7 @@ pub async fn get_stats( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; + tracing::info!(user_did = ?params.user_did, "Get stats"); let conn = conn.lock().unwrap(); let mut stmt = conn.prepare("SELECT COUNT(*) FROM scrobbles s LEFT JOIN users u ON s.user_id = u.id WHERE u.did = ? OR u.handle = ?")?; @@ -118,6 +119,7 @@ pub async fn get_scrobbles_per_day( .end .unwrap_or(GetScrobblesPerDayParams::default().end.unwrap()); let did = params.user_did; + tracing::info!(start = %start, end = %end, user_did = ?did, "Get scrobbles per day"); let conn = conn.lock().unwrap(); match did { @@ -190,6 +192,7 @@ pub async fn get_scrobbles_per_month( .end .unwrap_or(GetScrobblesPerDayParams::default().end.unwrap()); let did = params.user_did; + tracing::info!(start = %start, end = %end, user_did = ?did, "Get scrobbles per month"); let conn = conn.lock().unwrap(); match did { @@ -266,6 +269,7 @@ pub async fn get_scrobbles_per_year( .end .unwrap_or(GetScrobblesPerDayParams::default().end.unwrap()); let did = params.user_did; + tracing::info!(start = %start, end = %end, user_did = ?did, "Get scrobbles per year"); let conn = conn.lock().unwrap(); match did { @@ -338,6 +342,8 @@ pub async fn get_album_scrobbles( .end .unwrap_or(GetAlbumScrobblesParams::default().end.unwrap()); let conn = conn.lock().unwrap(); + tracing::info!(album_id = %params.album_id, start = %start, end = %end, "Get album scrobbles"); + let mut stmt = conn.prepare( r#" SELECT @@ -379,6 +385,7 @@ pub async fn get_artist_scrobbles( .end .unwrap_or(GetArtistScrobblesParams::default().end.unwrap()); let conn = conn.lock().unwrap(); + tracing::info!(artist_id = %params.artist_id, start = %start, end = %end, "Get artist scrobbles"); let mut stmt = conn.prepare( r#" @@ -426,6 +433,7 @@ pub async fn get_track_scrobbles( .end .unwrap_or(GetTrackScrobblesParams::default().end.unwrap()); let conn = conn.lock().unwrap(); + tracing::info!(track_id = %params.track_id, start = %start, end = %end, "Get track scrobbles"); let mut stmt = conn.prepare( r#" diff --git a/crates/analytics/src/handlers/tracks.rs b/crates/analytics/src/handlers/tracks.rs index 761dbc8..9859152 100644 --- a/crates/analytics/src/handlers/tracks.rs +++ b/crates/analytics/src/handlers/tracks.rs @@ -19,6 +19,7 @@ pub async fn get_tracks( let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(20); let did = params.user_did; + tracing::info!(limit, offset, user_did = ?did, "Get tracks"); let conn = conn.lock().unwrap(); match did { @@ -178,6 +179,7 @@ pub async fn get_loved_tracks( let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(20); let did = params.user_did; + tracing::info!(limit, offset, user_did = ?did, "Get loved tracks"); let conn = conn.lock().unwrap(); let mut stmt = conn.prepare( @@ -261,6 +263,7 @@ pub async fn get_top_tracks( let offset = pagination.skip.unwrap_or(0); let limit = pagination.take.unwrap_or(20); let did = params.user_did; + tracing::info!(limit, offset, user_did = ?did, "Get top tracks"); let conn = conn.lock().unwrap(); match did { diff --git a/crates/analytics/src/subscriber/mod.rs b/crates/analytics/src/subscriber/mod.rs index 5f80333..abe7d6e 100644 --- a/crates/analytics/src/subscriber/mod.rs +++ b/crates/analytics/src/subscriber/mod.rs @@ -16,7 +16,7 @@ pub async fn subscribe(conn: Arc>) -> Result<(), Error> { let addr = env::var("NATS_URL").unwrap_or_else(|_| "nats://localhost:4222".to_string()); let conn = conn.clone(); let nc = connect(&addr).await?; - println!("Connected to NATS server at {}", addr.bright_green()); + tracing::info!(server = %addr.bright_green(), "Connected to NATS"); let nc = Arc::new(Mutex::new(nc)); on_scrobble(nc.clone(), conn.clone()); @@ -652,7 +652,7 @@ pub async fn save_track( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[artist_albums] error: {}", e); + tracing::error!("[artist_albums] error: {}", e); return Err(e.into()); } } @@ -684,7 +684,7 @@ pub async fn like(conn: Arc>, payload: LikePayload) -> Result< Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[likes] error: {}", e); + tracing::error!("[likes] error: {}", e); return Err(e.into()); } } @@ -700,7 +700,7 @@ pub async fn unlike(conn: Arc>, payload: UnlikePayload) -> Res ) { Ok(_) => (), Err(e) => { - println!("[unlikes] error: {}", e); + tracing::error!("[unlikes] error: {}", e); return Err(e.into()); } } @@ -740,7 +740,7 @@ pub async fn save_user(conn: Arc>, payload: UserPayload) -> Re Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[users] error: {}", e); + tracing::error!("[users] error: {}", e); return Err(e.into()); } } @@ -921,8 +921,8 @@ mod tests { match serde_json::from_str::(data) { Err(e) => { - eprintln!("Error parsing payload: {}", e); - println!("{}", data); + tracing::error!("Error parsing payload: {}", e); + tracing::error!("{}", data); } Ok(_) => {} } diff --git a/crates/dropbox/Cargo.toml b/crates/dropbox/Cargo.toml index ceddae8..30c688f 100644 --- a/crates/dropbox/Cargo.toml +++ b/crates/dropbox/Cargo.toml @@ -43,3 +43,4 @@ symphonia = { version = "0.5.4", features = ["all"] } tempfile = "3.19.1" tokio = { version = "1.43.0", features = ["full"] } tokio-stream = { version = "0.1.17", features = ["full"] } +tracing = "0.1.41" diff --git a/crates/googledrive/Cargo.toml b/crates/googledrive/Cargo.toml index 464f26b..845e545 100644 --- a/crates/googledrive/Cargo.toml +++ b/crates/googledrive/Cargo.toml @@ -44,3 +44,4 @@ symphonia = { version = "0.5.4", features = ["all"] } tempfile = "3.19.1" tokio = { version = "1.43.0", features = ["full"] } tokio-stream = { version = "0.1.17", features = ["full"] } +tracing = "0.1.41" diff --git a/crates/jetstream/Cargo.toml b/crates/jetstream/Cargo.toml index 3b54511..2c8216f 100644 --- a/crates/jetstream/Cargo.toml +++ b/crates/jetstream/Cargo.toml @@ -38,3 +38,4 @@ reqwest = { version = "0.12.12", features = [ sha256 = "1.6.0" time = { version = "0.3.44", features = ["formatting", "macros"] } redis = { version = "0.29.0", features = ["aio", "tokio-comp"] } +tracing = "0.1.41" diff --git a/crates/playlists/Cargo.toml b/crates/playlists/Cargo.toml index b2f5aac..a64a241 100644 --- a/crates/playlists/Cargo.toml +++ b/crates/playlists/Cargo.toml @@ -37,3 +37,4 @@ reqwest = { version = "0.12.12", features = [ hex = "0.4.3" jsonwebtoken = "9.3.1" sha2 = "0.10.8" +tracing = "0.1.41" diff --git a/crates/rockskyd/Cargo.toml b/crates/rockskyd/Cargo.toml index 66eb638..a4071da 100644 --- a/crates/rockskyd/Cargo.toml +++ b/crates/rockskyd/Cargo.toml @@ -20,3 +20,7 @@ rocksky-scrobbler = { path = "../scrobbler" } rocksky-spotify = { path = "../spotify" } rocksky-tracklist = { path = "../tracklist" } rocksky-webscrobbler = { path = "../webscrobbler" } +tracing = "0.1.41" +tracing-subscriber = "0.3.20" +tracing-log = "0.2.0" +owo-colors = "4.2.2" diff --git a/crates/rockskyd/src/main.rs b/crates/rockskyd/src/main.rs index ef07ac1..20b6310 100644 --- a/crates/rockskyd/src/main.rs +++ b/crates/rockskyd/src/main.rs @@ -1,5 +1,6 @@ use clap::Command; use dotenv::dotenv; +use tracing_subscriber::fmt::format::Format; pub mod cmd; @@ -35,6 +36,17 @@ fn cli() -> Command { #[tokio::main] async fn main() -> Result<(), Box> { + let format = Format::default() + .with_level(true) + .with_target(true) + .with_ansi(true) + .compact(); + + tracing_subscriber::fmt() + .event_format(format) + .with_max_level(tracing::Level::INFO) + .init(); + dotenv().ok(); let args = cli().get_matches(); diff --git a/crates/scrobbler/Cargo.toml b/crates/scrobbler/Cargo.toml index dc5da3a..6b6978a 100644 --- a/crates/scrobbler/Cargo.toml +++ b/crates/scrobbler/Cargo.toml @@ -44,3 +44,4 @@ uuid = { version = "1.17.0", features = ["v4"] } actix-limitation = "0.5.1" actix-session = "0.10.1" tokio-stream = { version = "0.1.17", features = ["full"] } +tracing = "0.1.41" diff --git a/crates/spotify/Cargo.toml b/crates/spotify/Cargo.toml index 6f778df..4aab6a8 100644 --- a/crates/spotify/Cargo.toml +++ b/crates/spotify/Cargo.toml @@ -38,3 +38,4 @@ sqlx = { version = "0.8.3", features = [ ] } tokio = { version = "1.43.0", features = ["full"] } tokio-stream = { version = "0.1.17", features = ["full"] } +tracing = "0.1.41" diff --git a/crates/storage/Cargo.toml b/crates/storage/Cargo.toml index 44c01e5..fb96cff 100644 --- a/crates/storage/Cargo.toml +++ b/crates/storage/Cargo.toml @@ -26,3 +26,4 @@ sqlx = { version = "0.8.3", features = [ ] } actix-web = "4.9.0" tokio-stream = { version = "0.1.17", features = ["full"] } +tracing = "0.1.41" diff --git a/crates/tracklist/Cargo.toml b/crates/tracklist/Cargo.toml index 4ff6d2c..3a5c168 100644 --- a/crates/tracklist/Cargo.toml +++ b/crates/tracklist/Cargo.toml @@ -22,3 +22,4 @@ polars = "0.46.0" clap = "4.5.31" rand = "0.9.2" uuid = { version = "1.18.0", features = ["v4"] } +tracing = "0.1.41" diff --git a/crates/webscrobbler/Cargo.toml b/crates/webscrobbler/Cargo.toml index d7a0c5a..fc7ba16 100644 --- a/crates/webscrobbler/Cargo.toml +++ b/crates/webscrobbler/Cargo.toml @@ -42,3 +42,4 @@ rand = "0.9.0" tokio-stream = { version = "0.1.17", features = ["full"] } actix-session = "0.10.1" actix-limitation = "0.5.1" +tracing = "0.1.41" -- 2.43.0 From d363372f190fe0419970731c70aca807caf7c06d Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Thu, 25 Sep 2025 21:17:02 +0300 Subject: [PATCH] Refactor logging to use `tracing` instead of `println` and `eprintln` - Replaced all instances of `println!` and `eprintln!` with `tracing::info!`, `tracing::warn!`, and `tracing::error!` for better structured logging. - Updated log messages to include relevant context and structured fields for improved traceability. - Ensured consistent logging practices across the `jetstream`, `scrobbler`, and `webscrobbler` crates. --- crates/analytics/src/subscriber/mod.rs | 86 +++++------ crates/dropbox/src/cmd/serve.rs | 4 +- crates/dropbox/src/handlers/files.rs | 8 ++ crates/dropbox/src/scan.rs | 134 ++++++++---------- crates/googledrive/src/cmd/serve.rs | 4 +- .../googledrive/src/repo/google_drive_path.rs | 7 +- crates/googledrive/src/scan.rs | 106 ++++---------- crates/jetstream/src/repo.rs | 106 +++++--------- crates/jetstream/src/subscriber.rs | 15 +- crates/jetstream/src/webhook/discord/mod.rs | 4 +- crates/jetstream/src/webhook_worker.rs | 4 +- crates/scrobbler/src/auth.rs | 2 +- .../scrobbler/src/handlers/v1/nowplaying.rs | 2 +- .../scrobbler/src/handlers/v1/submission.rs | 2 +- crates/scrobbler/src/lib.rs | 5 +- .../scrobbler/src/listenbrainz/core/submit.rs | 10 +- .../src/listenbrainz/core/validate_token.rs | 2 +- crates/scrobbler/src/listenbrainz/handlers.rs | 25 ++-- crates/scrobbler/src/main.rs | 6 +- crates/scrobbler/src/rocksky.rs | 7 +- crates/scrobbler/src/scrobbler.rs | 72 +++------- crates/scrobbler/src/spotify/client.rs | 12 +- crates/webscrobbler/src/handlers.rs | 21 +-- crates/webscrobbler/src/lib.rs | 5 +- crates/webscrobbler/src/rocksky.rs | 12 +- crates/webscrobbler/src/scrobbler.rs | 13 +- crates/webscrobbler/src/spotify/client.rs | 12 +- 27 files changed, 260 insertions(+), 426 deletions(-) diff --git a/crates/analytics/src/subscriber/mod.rs b/crates/analytics/src/subscriber/mod.rs index abe7d6e..a64fe50 100644 --- a/crates/analytics/src/subscriber/mod.rs +++ b/crates/analytics/src/subscriber/mod.rs @@ -42,15 +42,15 @@ pub fn on_scrobble(nc: Arc>, conn: Arc>) { let data = String::from_utf8(msg.payload.to_vec()).unwrap(); match serde_json::from_str::(&data) { Ok(payload) => match save_scrobble(conn.clone(), payload.clone()).await { - Ok(_) => println!( - "Scrobble saved successfully for {}", - payload.scrobble.uri.cyan() + Ok(_) => tracing::info!( + uri = %payload.scrobble.uri.cyan(), + "Scrobble saved successfully", ), - Err(e) => eprintln!("Error saving scrobble: {}", e), + Err(e) => tracing::error!("Error saving scrobble: {}", e), }, Err(e) => { - eprintln!("Error parsing payload: {}", e); - println!("{}", data); + tracing::error!("Error parsing payload: {}", e); + tracing::debug!("{}", data); } } } @@ -77,13 +77,16 @@ pub fn on_new_track(nc: Arc>, conn: Arc>) { match serde_json::from_str::(&data) { Ok(payload) => match save_track(conn.clone(), payload.clone()).await { Ok(_) => { - println!("Song saved successfully for {}", payload.track.title.cyan()) + tracing::info!( + title = %payload.track.title.cyan(), + "Track saved successfully", + ) } - Err(e) => eprintln!("Error saving song: {}", e), + Err(e) => tracing::error!("Error saving track: {}", e), }, Err(e) => { - eprintln!("Error parsing payload: {}", e); - println!("{}", data); + tracing::error!("Error parsing payload: {}", e); + tracing::debug!("{}", data); } } } @@ -109,15 +112,15 @@ pub fn on_like(nc: Arc>, conn: Arc>) { let data = String::from_utf8(msg.payload.to_vec()).unwrap(); match serde_json::from_str::(&data) { Ok(payload) => match like(conn.clone(), payload.clone()).await { - Ok(_) => println!( - "Like saved successfully for {}", - payload.track_id.xata_id.cyan() + Ok(_) => tracing::info!( + track_id = %payload.track_id.xata_id.cyan(), + "Like saved successfully", ), - Err(e) => eprintln!("Error saving like: {}", e), + Err(e) => tracing::error!("Error saving like: {}", e), }, Err(e) => { - eprintln!("Error parsing payload: {}", e); - println!("{}", data); + tracing::error!("Error parsing payload: {}", e); + tracing::debug!("{}", data); } } } @@ -143,15 +146,15 @@ pub fn on_unlike(nc: Arc>, conn: Arc>) { let data = String::from_utf8(msg.payload.to_vec()).unwrap(); match serde_json::from_str::(&data) { Ok(payload) => match unlike(conn.clone(), payload.clone()).await { - Ok(_) => println!( - "Unlike saved successfully for {}", - payload.track_id.xata_id.cyan() + Ok(_) => tracing::info!( + track_id = %payload.track_id.xata_id.cyan(), + "Unlike saved successfully", ), - Err(e) => eprintln!("Error saving unlike: {}", e), + Err(e) => tracing::error!("Error saving unlike: {}", e), }, Err(e) => { - eprintln!("Error parsing payload: {}", e); - println!("{}", data); + tracing::error!("Error parsing payload: {}", e); + tracing::debug!("{}", data); } } } @@ -177,16 +180,15 @@ pub fn on_new_user(nc: Arc>, conn: Arc>) { let data = String::from_utf8(msg.payload.to_vec()).unwrap(); match serde_json::from_str::(&data) { Ok(payload) => match save_user(conn.clone(), payload.clone()).await { - Ok(_) => println!( - "User saved successfully for {}{}", - "@".cyan(), - payload.handle.cyan() + Ok(_) => tracing::info!( + handle = %payload.handle.cyan(), + "User saved successfully", ), - Err(e) => eprintln!("Error saving user: {}", e), + Err(e) => tracing::error!("Error saving user: {}", e), }, Err(e) => { - eprintln!("Error parsing payload: {}", e); - println!("{}", data); + tracing::error!("Error parsing payload: {}", e); + tracing::debug!("{}", data); } } } @@ -253,7 +255,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[artists] error: {}", e); + tracing::error!("[artists] error: {}", e); return Err(e.into()); } } @@ -308,7 +310,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[albums] error: {}", e); + tracing::error!("[albums] error: {}", e); return Err(e.into()); } } @@ -371,7 +373,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[tracks] error: {}", e); + tracing::error!("[tracks] error: {}", e); return Err(e.into()); } } @@ -394,7 +396,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[album_tracks] error: {}", e); + tracing::error!("[album_tracks] error: {}", e); return Err(e.into()); } } @@ -412,7 +414,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[artist_tracks] error: {}", e); + tracing::error!("[artist_tracks] error: {}", e); return Err(e.into()); } } @@ -430,7 +432,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[artist_albums] error: {}", e); + tracing::error!("[artist_albums] error: {}", e); return Err(e.into()); } } @@ -448,7 +450,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[user_albums] error: {}", e); + tracing::error!("[user_albums] error: {}", e); return Err(e.into()); } } @@ -466,7 +468,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[user_artists] error: {}", e); + tracing::error!("[user_artists] error: {}", e); return Err(e.into()); } } @@ -484,7 +486,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[user_tracks] error: {}", e); + tracing::error!("[user_tracks] error: {}", e); return Err(e.into()); } } @@ -521,7 +523,7 @@ pub async fn save_scrobble( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[scrobbles] error: {}", e); + tracing::error!("[scrobbles] error: {}", e); return Err(e.into()); } } @@ -593,7 +595,7 @@ pub async fn save_track( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[tracks] error: {}", e); + tracing::error!("[tracks] error: {}", e); return Err(e.into()); } } @@ -616,7 +618,7 @@ pub async fn save_track( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[album_tracks] error: {}", e); + tracing::error!("[album_tracks] error: {}", e); return Err(e.into()); } } @@ -634,7 +636,7 @@ pub async fn save_track( Ok(_) => (), Err(e) => { if !e.to_string().contains("violates primary key constraint") { - println!("[artist_tracks] error: {}", e); + tracing::error!("[artist_tracks] error: {}", e); return Err(e.into()); } } diff --git a/crates/dropbox/src/cmd/serve.rs b/crates/dropbox/src/cmd/serve.rs index 9053f43..43e4b3f 100644 --- a/crates/dropbox/src/cmd/serve.rs +++ b/crates/dropbox/src/cmd/serve.rs @@ -27,7 +27,7 @@ async fn call_method( req: HttpRequest, ) -> Result { let method = req.match_info().get("method").unwrap_or("unknown"); - println!("Method: {}", method.bright_green()); + tracing::info!(method = %method.bright_green(), "API call"); let conn = data.get_ref().clone(); handle(method, &mut payload, &req, conn) @@ -41,7 +41,7 @@ pub async fn serve() -> Result<(), Error> { let addr = format!("{}:{}", host, port); let url = format!("http://{}", addr); - println!("Listening on {}", url.bright_green()); + tracing::info!(url = %url.bright_green(), "Listening on"); let pool = PgPoolOptions::new() .max_connections(5) diff --git a/crates/dropbox/src/handlers/files.rs b/crates/dropbox/src/handlers/files.rs index 9878de7..95b10c6 100644 --- a/crates/dropbox/src/handlers/files.rs +++ b/crates/dropbox/src/handlers/files.rs @@ -2,6 +2,7 @@ use std::{env, sync::Arc, thread}; use actix_web::{web, HttpRequest, HttpResponse}; use anyhow::Error; +use owo_colors::OwoColorize; use sqlx::{Pool, Postgres}; use tokio_stream::StreamExt; @@ -24,6 +25,7 @@ pub async fn get_files( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let refresh_token = find_dropbox_refresh_token(&pool.clone(), ¶ms.did).await?; + tracing::info!(did = %params.did.bright_green(), "dropbox.getFiles"); if refresh_token.is_none() { return Ok(HttpResponse::Unauthorized().finish()); @@ -48,6 +50,7 @@ pub async fn create_music_folder( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let refresh_token = find_dropbox_refresh_token(&pool.clone(), ¶ms.did).await?; + tracing::info!(did = %params.did.bright_green(), "dropbox.createMusicFolder"); if refresh_token.is_none() { return Ok(HttpResponse::Unauthorized().finish()); @@ -72,6 +75,7 @@ pub async fn get_files_at( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let refresh_token = find_dropbox_refresh_token(&pool.clone(), ¶ms.did).await?; + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.getFilesAt"); if refresh_token.is_none() { return Ok(HttpResponse::Unauthorized().finish()); @@ -96,6 +100,7 @@ pub async fn download_file( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let refresh_token = find_dropbox_refresh_token(&pool.clone(), ¶ms.did).await?; + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.downloadFile"); if refresh_token.is_none() { return Ok(HttpResponse::Unauthorized().finish()); @@ -118,6 +123,7 @@ pub async fn get_temporary_link( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let refresh_token = find_dropbox_refresh_token(&pool.clone(), ¶ms.did).await?; + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.getTemporaryLink"); if refresh_token.is_none() { return Ok(HttpResponse::Unauthorized().finish()); @@ -142,6 +148,7 @@ pub async fn get_metadata( let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; let refresh_token = find_dropbox_refresh_token(&pool.clone(), ¶ms.did).await?; + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.getMetadata"); if refresh_token.is_none() { return Ok(HttpResponse::Unauthorized().finish()); @@ -165,6 +172,7 @@ pub async fn scan_folder( ) -> Result { let body = read_payload!(payload); let params = serde_json::from_slice::(&body)?; + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.scanFolder"); let pool = pool.clone(); thread::spawn(move || { diff --git a/crates/dropbox/src/scan.rs b/crates/dropbox/src/scan.rs index 9395c27..62fecdc 100644 --- a/crates/dropbox/src/scan.rs +++ b/crates/dropbox/src/scan.rs @@ -91,14 +91,14 @@ pub fn scan_audio_files( .await?; if res.status().as_u16() == 400 || res.status().as_u16() == 409 { - println!("Path not found: {}", path.bright_red()); + tracing::error!(path = %path.bright_red(), "Path not found"); return Ok(()); } let entry = res.json::().await?; if entry.tag.clone().unwrap().as_str() == "folder" { - println!("Scanning folder: {}", path.bright_green()); + tracing::info!(path = %path.bright_green(), "Scanning folder"); let parent_path = Path::new(&path) .parent() @@ -160,7 +160,7 @@ pub fn scan_audio_files( let client = Client::new(); - println!("Downloading file: {}", path.bright_green()); + tracing::info!(path = %path.bright_green(), "Downloading file"); let res = client .post(&format!("{}/files/download", CONTENT_URL)) @@ -176,15 +176,12 @@ pub fn scan_audio_files( let mut tmpfile = File::create(&tmppath)?; tmpfile.write_all(&bytes)?; - println!( - "Reading file: {}", - &tmppath.clone().display().to_string().bright_green() - ); + tracing::info!(path = %tmppath.clone().display().to_string().bright_green(), "Reading file"); let tagged_file = match Probe::open(&tmppath)?.read() { Ok(tagged_file) => tagged_file, Err(e) => { - println!("Error opening file: {}", e); + tracing::error!(path = %tmppath.clone().display().to_string().bright_red(), "Error reading file: {}", e); return Ok(()); } }; @@ -193,71 +190,57 @@ pub fn scan_audio_files( let tag = match primary_tag { Some(tag) => tag, None => { - println!("No tag found in file"); + tracing::error!(path = %tmppath.clone().display().to_string().bright_red(), "No tag found in file"); return Ok(()); } }; let pictures = tag.pictures(); - println!( - "Title: {}", - tag.get_string(&lofty::tag::ItemKey::TrackTitle) - .unwrap_or_default() - .bright_green() - ); - println!( - "Artist: {}", - tag.get_string(&lofty::tag::ItemKey::TrackArtist) - .unwrap_or_default() - .bright_green() + tracing::info!( + title = %tag + .get_string(&lofty::tag::ItemKey::TrackTitle) + .unwrap_or_default(), ); - println!( - "Album Artist: {}", - tag.get_string(&lofty::tag::ItemKey::AlbumArtist) - .unwrap_or_default() - .bright_green() + tracing::info!( + artist = %tag + .get_string(&lofty::tag::ItemKey::TrackArtist) + .unwrap_or_default(), ); - println!( - "Album: {}", - tag.get_string(&lofty::tag::ItemKey::AlbumTitle) - .unwrap_or_default() - .bright_green() + tracing::info!( + album = %tag + .get_string(&lofty::tag::ItemKey::AlbumTitle) + .unwrap_or_default(), ); - println!( - "Lyrics: {}", - tag.get_string(&lofty::tag::ItemKey::Lyrics) - .unwrap_or_default() - .bright_green() + tracing::info!( + album_artist = %tag + .get_string(&lofty::tag::ItemKey::AlbumArtist) + .unwrap_or_default(), ); - println!("Year: {}", tag.year().unwrap_or_default().bright_green()); - println!( - "Track Number: {}", - tag.track().unwrap_or_default().bright_green() + tracing::info!( + lyrics = %tag + .get_string(&lofty::tag::ItemKey::Lyrics) + .unwrap_or_default(), ); - println!( - "Track Total: {}", - tag.track_total().unwrap_or_default().bright_green() + tracing::info!(year = %tag.year().unwrap_or_default()); + tracing::info!(track_number = %tag.track().unwrap_or_default()); + tracing::info!(track_total = %tag.track_total().unwrap_or_default()); + tracing::info!( + release_date = %tag + .get_string(&lofty::tag::ItemKey::OriginalReleaseDate) + .unwrap_or_default(), ); - println!( - "Release Date: {:?}", - tag.get_string(&lofty::tag::ItemKey::OriginalReleaseDate) - .unwrap_or_default() - .bright_green() + tracing::info!( + recording_date = %tag + .get_string(&lofty::tag::ItemKey::RecordingDate) + .unwrap_or_default(), ); - println!( - "Recording Date: {:?}", - tag.get_string(&lofty::tag::ItemKey::RecordingDate) - .unwrap_or_default() - .bright_green() + tracing::info!( + copyright_message = %tag + .get_string(&lofty::tag::ItemKey::CopyrightMessage) + .unwrap_or_default(), ); - println!( - "Copyright Message: {}", - tag.get_string(&lofty::tag::ItemKey::CopyrightMessage) - .unwrap_or_default() - .bright_green() - ); - println!("Pictures: {:?}", pictures); + tracing::info!(pictures = ?pictures); let title = tag .get_string(&lofty::tag::ItemKey::TrackTitle) @@ -290,18 +273,18 @@ pub fn scan_audio_files( match track { Some(track) => { - println!("Track exists: {}", title.bright_green()); + tracing::info!(title = %title.bright_green(), "Track exists"); let parent_path = Path::new(&path) .parent() .map(|p| p.to_string_lossy().to_string()); let status = create_dropbox_path(&pool, &entry, &track, &dropbox_id, parent_path).await; - println!("status: {:?}", status); + tracing::info!(status = ?status); // TODO: publish file metadata to nats } None => { - println!("Creating track: {}", title.bright_green()); + tracing::info!(title = %title.bright_green(), "Creating track"); let album_art = upload_album_cover(albumart_id.into(), pictures, &access_token).await?; let client = Client::new(); @@ -338,7 +321,7 @@ pub fn scan_audio_files( })) .send() .await?; - println!("Track Saved: {} {}", title, response.status()); + tracing::info!(title = title, status = %response.status(), "Track saved"); tokio::time::sleep(std::time::Duration::from_secs(3)).await; let track = get_track_by_hash(&pool, &hash).await?; @@ -353,7 +336,7 @@ pub fn scan_audio_files( return Ok(()); } - println!("Failed to create track: {}", title.bright_green()); + tracing::error!(title = %title.bright_red(), "Failed to create track"); } } @@ -413,7 +396,7 @@ pub async fn upload_album_cover( .send() .await?; - println!("Cover uploaded: {}", response.status()); + tracing::info!(status = %response.status(), "Cover uploaded"); Ok(Some(name)) } @@ -433,15 +416,18 @@ pub async fn get_track_duration(path: &Path) -> Result { let meta_opts = MetadataOptions::default(); let format_opts = FormatOptions::default(); - let probed = - match symphonia::default::get_probe().format(&hint, media_source, &format_opts, &meta_opts) - { - Ok(probed) => probed, - Err(_) => { - println!("Error probing file"); - return Ok(duration); - } - }; + let probed = match symphonia::default::get_probe().format( + &hint, + media_source, + &format_opts, + &meta_opts, + ) { + Ok(probed) => probed, + Err(e) => { + tracing::error!(path = %path.display().to_string().bright_red(), "Error probing file: {}", e); + return Ok(duration); + } + }; if let Some(track) = probed.format.tracks().first() { if let Some(duration) = track.codec_params.n_frames { diff --git a/crates/googledrive/src/cmd/serve.rs b/crates/googledrive/src/cmd/serve.rs index 8ead9b5..c64588d 100644 --- a/crates/googledrive/src/cmd/serve.rs +++ b/crates/googledrive/src/cmd/serve.rs @@ -27,7 +27,7 @@ async fn call_method( req: HttpRequest, ) -> Result { let method = req.match_info().get("method").unwrap_or("unknown"); - println!("Method: {}", method.bright_green()); + tracing::info!(method = %method.bright_green(), "API call"); let conn = data.get_ref().clone(); handle(method, &mut payload, &req, conn) @@ -41,7 +41,7 @@ pub async fn serve() -> Result<(), Error> { let addr = format!("{}:{}", host, port); let url = format!("http://{}", addr); - println!("Listening on {}", url.bright_green()); + tracing::info!(url = %url.bright_green(), "Listening on"); let pool = PgPoolOptions::new() .max_connections(5) diff --git a/crates/googledrive/src/repo/google_drive_path.rs b/crates/googledrive/src/repo/google_drive_path.rs index 2088b14..e23bff2 100644 --- a/crates/googledrive/src/repo/google_drive_path.rs +++ b/crates/googledrive/src/repo/google_drive_path.rs @@ -1,3 +1,4 @@ +use owo_colors::OwoColorize; use sqlx::{Pool, Postgres}; use crate::{ @@ -47,7 +48,11 @@ pub async fn create_google_drive_path( .execute(pool) .await?; - println!("{:?}", result); + tracing::info!( + file_id = %file.id.bright_green(), + rows_affected = %result.rows_affected(), + "Google Drive path created" + ); sqlx::query( r#" diff --git a/crates/googledrive/src/scan.rs b/crates/googledrive/src/scan.rs index 0dd81a3..3221309 100644 --- a/crates/googledrive/src/scan.rs +++ b/crates/googledrive/src/scan.rs @@ -104,7 +104,7 @@ pub fn scan_audio_files( let file = res.json::().await?; if file.mime_type == "application/vnd.google-apps.folder" { - println!("Scanning folder: {}", file.name.bright_green()); + tracing::info!(folder = %file.name.bright_green(), "Scanning folder"); create_google_drive_directory( &pool, @@ -172,7 +172,7 @@ pub fn scan_audio_files( return Ok(()); } - println!("Downloading file: {}", file.name.bright_green()); + tracing::info!(file = %file.name.bright_green(), "Downloading file"); let client = Client::new(); @@ -191,15 +191,12 @@ pub fn scan_audio_files( let mut tmpfile = std::fs::File::create(&tmppath)?; tmpfile.write_all(&bytes)?; - println!( - "Reading file: {}", - &tmppath.clone().display().to_string().bright_green() - ); + tracing::info!(path = %tmppath.display(), "Reading file"); let tagged_file = match Probe::open(&tmppath)?.read() { Ok(tagged_file) => tagged_file, Err(e) => { - println!("Error opening file: {}", e); + tracing::warn!(file = %file.name.bright_green(), error = %e, "Failed to open file with lofty"); return Ok(()); } }; @@ -208,71 +205,25 @@ pub fn scan_audio_files( let tag = match primary_tag { Some(tag) => tag, None => { - println!("No tag found in file"); + tracing::warn!(file = %file.name.bright_green(), "No tag found in file"); return Ok(()); } }; let pictures = tag.pictures(); - println!( - "Title: {}", - tag.get_string(&lofty::tag::ItemKey::TrackTitle) - .unwrap_or_default() - .bright_green() - ); - println!( - "Artist: {}", - tag.get_string(&lofty::tag::ItemKey::TrackArtist) - .unwrap_or_default() - .bright_green() - ); - println!( - "Album Artist: {}", - tag.get_string(&lofty::tag::ItemKey::AlbumArtist) - .unwrap_or_default() - .bright_green() - ); - println!( - "Album: {}", - tag.get_string(&lofty::tag::ItemKey::AlbumTitle) - .unwrap_or_default() - .bright_green() - ); - println!( - "Lyrics: {}", - tag.get_string(&lofty::tag::ItemKey::Lyrics) - .unwrap_or_default() - .bright_green() - ); - println!("Year: {}", tag.year().unwrap_or_default().bright_green()); - println!( - "Track Number: {}", - tag.track().unwrap_or_default().bright_green() - ); - println!( - "Track Total: {}", - tag.track_total().unwrap_or_default().bright_green() - ); - println!( - "Release Date: {:?}", - tag.get_string(&lofty::tag::ItemKey::OriginalReleaseDate) - .unwrap_or_default() - .bright_green() - ); - println!( - "Recording Date: {:?}", - tag.get_string(&lofty::tag::ItemKey::RecordingDate) - .unwrap_or_default() - .bright_green() - ); - println!( - "Copyright Message: {}", - tag.get_string(&lofty::tag::ItemKey::CopyrightMessage) - .unwrap_or_default() - .bright_green() - ); - println!("Pictures: {:?}", pictures); + tracing::info!(title = %tag.get_string(&lofty::tag::ItemKey::TrackTitle).unwrap_or_default(), "Title"); + tracing::info!(artist = %tag.get_string(&lofty::tag::ItemKey::TrackArtist).unwrap_or_default(), "Artist"); + tracing::info!(album_artist = %tag.get_string(&lofty::tag::ItemKey::AlbumArtist).unwrap_or_default(), "Album artist"); + tracing::info!(album = %tag.get_string(&lofty::tag::ItemKey::AlbumTitle).unwrap_or_default(), "Album"); + tracing::info!(lyrics = %tag.get_string(&lofty::tag::ItemKey::Lyrics).unwrap_or_default(), "Lyrics"); + tracing::info!(year = %tag.year().unwrap_or_default(), "Year"); + tracing::info!(track_number = %tag.track().unwrap_or_default(), "Track number"); + tracing::info!(track_total = %tag.track_total().unwrap_or_default(), "Track total"); + tracing::info!(release_date = %tag.get_string(&lofty::tag::ItemKey::OriginalReleaseDate).unwrap_or_default(), "Release date"); + tracing::info!(recording_date = %tag.get_string(&lofty::tag::ItemKey::RecordingDate).unwrap_or_default(), "Recording date"); + tracing::info!(copyright = %tag.get_string(&lofty::tag::ItemKey::CopyrightMessage).unwrap_or_default(), "Copyright message"); + tracing::info!(pictures = %pictures.len(), "Pictures found"); let title = tag .get_string(&lofty::tag::ItemKey::TrackTitle) @@ -304,9 +255,9 @@ pub fn scan_audio_files( match track { Some(track) => { - println!("Track exists: {}", title.bright_green()); + tracing::info!(title = %title.bright_green(), "Track exists"); let parent_drive_id = parent_drive_file_id.as_deref(); - let status = create_google_drive_path( + create_google_drive_path( &pool, &file, &track, @@ -315,11 +266,10 @@ pub fn scan_audio_files( ) .await?; - println!("status: {:?}", status); // TODO: publish file metadata to nats } None => { - println!("Creating track: {}", title.bright_green()); + tracing::info!(title = %title.bright_green(), "Creating track"); let albumart = upload_album_cover(albumart_id.into(), pictures, &access_token).await?; @@ -358,22 +308,20 @@ pub fn scan_audio_files( })) .send() .await?; - println!("Track Saved: {} {}", title, response.status()); + tracing::info!(status = %response.status(), "Track saved"); tokio::time::sleep(std::time::Duration::from_secs(3)).await; let track = get_track_by_hash(&pool, &hash).await?; if let Some(track) = track { let parent_drive_id = parent_drive_file_id.as_deref(); - let status = create_google_drive_path( + create_google_drive_path( &pool, &file, &track, &google_drive_id, parent_drive_id.unwrap_or(""), ) - .await; - - println!("status: {:?}", status); + .await?; // TODO: publish file metadata to nats @@ -382,7 +330,7 @@ pub fn scan_audio_files( return Ok(()); } - println!("Failed to create track: {}", title.bright_green()); + tracing::warn!(title = %title.bright_green(), "Failed to create track"); } } @@ -442,7 +390,7 @@ pub async fn upload_album_cover( .send() .await?; - println!("Cover uploaded: {}", response.status()); + tracing::info!(status = %response.status(), "Cover uploaded"); Ok(Some(name)) } @@ -466,8 +414,8 @@ pub async fn get_track_duration(path: &Path) -> Result { match symphonia::default::get_probe().format(&hint, media_source, &format_opts, &meta_opts) { Ok(probed) => probed, - Err(_) => { - println!("Error probing file"); + Err(e) => { + tracing::warn!(path = %path.display(), error = %e, "Failed to probe media"); return Ok(duration); } }; diff --git a/crates/jetstream/src/repo.rs b/crates/jetstream/src/repo.rs index e872529..470249b 100644 --- a/crates/jetstream/src/repo.rs +++ b/crates/jetstream/src/repo.rs @@ -16,9 +16,16 @@ use crate::{ }, webhook_worker::{push_to_queue, AppState}, xata::{ - album::Album, album_track::AlbumTrack, artist::Artist, artist_album::ArtistAlbum, - artist_track::ArtistTrack, track::Track, user::User, user_album::UserAlbum, - user_artist::UserArtist, user_track::UserTrack, + album::Album, + album_track::AlbumTrack, + artist::Artist, + artist_album::ArtistAlbum, + artist_track::ArtistTrack, + track::Track, + user::{self, User}, + user_album::UserAlbum, + user_artist::UserArtist, + user_track::UserTrack, }, }; @@ -56,14 +63,7 @@ pub async fn save_scrobble( let user_id = save_user(&mut tx, did).await?; - println!( - "Saving scrobble: {} ", - format!( - "{} - {} - {}", - scrobble_record.title, scrobble_record.artist, scrobble_record.album - ) - .magenta() - ); + tracing::info!(title = %scrobble_record.title.magenta(), artist = %scrobble_record.artist.magenta(), album = %scrobble_record.album.magenta(), "Saving scrobble"); sqlx::query( r#" @@ -144,7 +144,7 @@ pub async fn save_scrobble( { Ok(_) => {} Err(e) => { - eprintln!("Failed to push to webhook queue: {}", e); + tracing::error!(error = %e, "Failed to push to webhook queue"); } } } @@ -188,7 +188,7 @@ pub async fn save_scrobble( } } _ => { - println!("Unsupported operation: {}", commit.operation); + tracing::warn!(operation = %commit.operation, "Unsupported operation"); } } Ok(()) @@ -341,11 +341,11 @@ pub async fn save_album( .await?; if !albums.is_empty() { - println!("Album already exists: {}", albums[0].title.magenta()); + tracing::info!(name = %albums[0].title.magenta(), "Album already exists"); return Ok(albums[0].xata_id.clone()); } - println!("Saving album: {}", scrobble_record.album.magenta()); + tracing::info!(name = %scrobble_record.album, "Saving new album"); let uri: Option = None; let artist_uri: Option = None; @@ -402,11 +402,11 @@ pub async fn save_artist( .await?; if !artists.is_empty() { - println!("Artist already exists: {}", artists[0].name.magenta()); + tracing::info!(name = %scrobble_record.album_artist, "Artist already exists"); return Ok(artists[0].xata_id.clone()); } - println!("Saving artist: {}", scrobble_record.album_artist.magenta()); + tracing::info!(name = %scrobble_record.album_artist, "Saving new artist"); let uri: Option = None; let picture = ""; @@ -450,17 +450,11 @@ pub async fn save_album_track( .await?; if !album_tracks.is_empty() { - println!( - "Album track already exists: {}", - format!("{} - {}", album_id, track_id).magenta() - ); + tracing::info!(album_id = %album_id, track_id = %track_id, "Album track already exists"); return Ok(()); } - println!( - "Saving album track: {}", - format!("{} - {}", album_id, track_id).magenta() - ); + tracing::info!(album_id = %album_id, track_id = %track_id, "Saving album track"); sqlx::query( r#" @@ -492,17 +486,11 @@ pub async fn save_artist_track( .await?; if !artist_tracks.is_empty() { - println!( - "Artist track already exists: {}", - format!("{} - {}", artist_id, track_id).magenta() - ); + tracing::info!(artist_id = %artist_id, track_id = %track_id, "Artist track already exists"); return Ok(()); } - println!( - "Saving artist track: {}", - format!("{} - {}", artist_id, track_id).magenta() - ); + tracing::info!(artist_id = %artist_id, track_id = %track_id, "Saving artist track"); sqlx::query( r#" @@ -534,17 +522,11 @@ pub async fn save_artist_album( .await?; if !artist_albums.is_empty() { - println!( - "Artist album already exists: {}", - format!("{} - {}", artist_id, album_id).magenta() - ); + tracing::info!(artist_id = %artist_id, album_id = %album_id, "Artist album already exists"); return Ok(()); } - println!( - "Saving artist album: {}", - format!("{} - {}", artist_id, album_id).magenta() - ); + tracing::info!(artist_id = %artist_id, album_id = %album_id, "Saving artist album"); sqlx::query( r#" @@ -585,7 +567,7 @@ pub async fn save_user_artist( match artists.is_empty() { true => { - println!("Saving artist: {}", record.name.magenta()); + tracing::info!(name = %record.name, "Artist not found in database, inserting new artist"); let did = users[0].did.clone(); sqlx::query( r#" @@ -632,10 +614,7 @@ pub async fn save_user_artist( .await?; if !user_artists.is_empty() { - println!( - "User artist already exists: {}", - format!("{} - {}", user_id, artist_id).magenta() - ); + tracing::info!(user_id = %user_id, artist_id = %artist_id, "Updating user artist"); sqlx::query( r#" UPDATE user_artists @@ -652,10 +631,7 @@ pub async fn save_user_artist( return Ok(()); } - println!( - "Saving user artist: {}", - format!("{} - {}", user_id, artist_id).magenta() - ); + tracing::info!(user_id = %user_id, artist_id = %artist_id, "Inserting user artist"); sqlx::query( r#" @@ -699,7 +675,7 @@ pub async fn save_user_album( match albums.is_empty() { true => { - println!("Saving album: {}", record.title.magenta()); + tracing::info!(title = %record.title, artist = %record.artist, "Album not found in database, inserting new album"); let did = users[0].did.clone(); sqlx::query( r#" @@ -752,10 +728,7 @@ pub async fn save_user_album( .await?; if !user_albums.is_empty() { - println!( - "User album already exists: {}", - format!("{} - {}", user_id, album_id).magenta() - ); + tracing::info!(user_id = %user_id, album_id = %album_id, "Updating user album"); sqlx::query( r#" UPDATE user_albums @@ -772,10 +745,7 @@ pub async fn save_user_album( return Ok(()); } - println!( - "Saving user album: {}", - format!("{} - {}", user_id, album_id).magenta() - ); + tracing::info!(user_id = %user_id, album_id = %album_id, "Inserting user album"); sqlx::query( r#" @@ -822,7 +792,7 @@ pub async fn save_user_track( match tracks.is_empty() { true => { - println!("Saving track: {}", record.title.magenta()); + tracing::info!(title = %record.title, artist = %record.artist, album = %record.album, "Track not found in database, inserting new track"); let did = users[0].did.clone(); sqlx::query( r#" @@ -894,10 +864,7 @@ pub async fn save_user_track( .await?; if !user_tracks.is_empty() { - println!( - "User track already exists: {}", - format!("{} - {}", user_id, track_id).magenta() - ); + tracing::info!(user_id = %user_id, track_id = %track_id, "Updating user track"); sqlx::query( r#" UPDATE user_tracks @@ -914,10 +881,7 @@ pub async fn save_user_track( return Ok(()); } - println!( - "Saving user track: {}", - format!("{} - {}", user_id, track_id).magenta() - ); + tracing::info!(user_id = %user_id, track_id = %track_id, "Inserting user track"); sqlx::query( r#" @@ -954,7 +918,7 @@ pub async fn update_artist_uri( .await?; if artists.is_empty() { - println!("Artist not found: {}", record.name.magenta()); + tracing::warn!(name = %record.name, "Artist not found in database"); return Ok(()); } @@ -1023,7 +987,7 @@ pub async fn update_album_uri( .fetch_all(&mut **tx) .await?; if albums.is_empty() { - println!("Album not found: {}", record.title.magenta()); + tracing::warn!(title = %record.title, "Album not found in database"); return Ok(()); } let album_id = &albums[0].xata_id; @@ -1082,7 +1046,7 @@ pub async fn update_track_uri( .await?; if tracks.is_empty() { - println!("Track not found: {}", record.title.magenta()); + tracing::warn!(title = %record.title, "Track not found in database"); return Ok(()); } diff --git a/crates/jetstream/src/subscriber.rs b/crates/jetstream/src/subscriber.rs index 4250c49..83237e9 100644 --- a/crates/jetstream/src/subscriber.rs +++ b/crates/jetstream/src/subscriber.rs @@ -40,20 +40,17 @@ impl ScrobbleSubscriber { let pool = Arc::new(Mutex::new(pool)); let (mut ws_stream, _) = connect_async(&self.service_url).await?; - println!( - "Connected to jetstream at {}", - self.service_url.bright_green() - ); + tracing::info!(url = %self.service_url.bright_green(), "Connected to jetstream at"); while let Some(msg) = ws_stream.next().await { match msg { Ok(msg) => { if let Err(e) = handle_message(state.clone(), pool.clone(), msg).await { - eprintln!("Error handling message: {}", e); + tracing::error!(error = %e, "Error handling message"); } } Err(e) => { - eprintln!("WebSocket error: {}", e); + tracing::error!(error = %e, "WebSocket error"); break; } } @@ -76,14 +73,14 @@ async fn handle_message( return Ok::<(), Error>(()); } - println!("Received message: {:#?}", message); + tracing::info!(message = %text.bright_green(), "Received message"); if let Some(commit) = message.commit { match save_scrobble(state, pool, &message.did, commit).await { Ok(_) => { - println!("Scrobble saved successfully"); + tracing::info!(user_id = %message.did.bright_green(), "Scrobble saved successfully"); } Err(e) => { - eprintln!("Error saving scrobble: {}", e); + tracing::error!(error = %e, "Error saving scrobble"); } } } diff --git a/crates/jetstream/src/webhook/discord/mod.rs b/crates/jetstream/src/webhook/discord/mod.rs index c06b367..f1d22a4 100644 --- a/crates/jetstream/src/webhook/discord/mod.rs +++ b/crates/jetstream/src/webhook/discord/mod.rs @@ -37,7 +37,7 @@ pub async fn post_embeds( embeds: Vec, ) -> reqwest::Result<()> { if discord_webhook_url.is_empty() { - println!("DISCORD_WEBHOOK_URL is not set, skipping webhook post"); + tracing::warn!("DISCORD_WEBHOOK_URL is not set, skipping webhook post"); return Ok(()); } @@ -48,7 +48,7 @@ pub async fn post_embeds( let res = http.post(discord_webhook_url).json(&body).send().await?; if !res.status().is_success() { let text = res.text().await.unwrap_or_default(); - eprintln!("Failed to post to Discord webhook: {}", text); + tracing::error!(error = %text, "Failed to post to Discord webhook"); } Ok(()) } diff --git a/crates/jetstream/src/webhook_worker.rs b/crates/jetstream/src/webhook_worker.rs index 0c072b0..4235871 100644 --- a/crates/jetstream/src/webhook_worker.rs +++ b/crates/jetstream/src/webhook_worker.rs @@ -79,7 +79,7 @@ async fn run_worker( } Ok(None) => break, Err(e) => { - eprintln!("Failed to pop from Redis: {}", e); + tracing::error!(error = %e, "Failed to pop from Redis"); break; } } @@ -93,7 +93,7 @@ async fn run_worker( tokens -= 1; if let Err(e) = discord::post_embeds(&http, &discord_webhook_url, embeds).await { - eprintln!("Failed to post to Discord webhook: {}", e); + tracing::error!(error = %e, "Failed to post to Discord webhook"); } } } diff --git a/crates/scrobbler/src/auth.rs b/crates/scrobbler/src/auth.rs index a7171db..831c7bc 100644 --- a/crates/scrobbler/src/auth.rs +++ b/crates/scrobbler/src/auth.rs @@ -37,7 +37,7 @@ pub async fn authenticate_v1( let expected_password = md5::compute(expected_password); let expected_password = format!("{:x}", expected_password); if expected_password != password_md5 { - println!("{} != {}", expected_password, password_md5); + tracing::error!(expected = %expected_password, provided = %password_md5, "Invalid password"); return Err(Error::msg("Invalid password")); } Ok(()) diff --git a/crates/scrobbler/src/handlers/v1/nowplaying.rs b/crates/scrobbler/src/handlers/v1/nowplaying.rs index 27533ac..ac019d3 100644 --- a/crates/scrobbler/src/handlers/v1/nowplaying.rs +++ b/crates/scrobbler/src/handlers/v1/nowplaying.rs @@ -18,7 +18,7 @@ pub fn nowplaying( let a = form.get("a").unwrap().to_string(); let t = form.get("t").unwrap().to_string(); - println!("Now playing: {} - {} {}", a, t, s.cyan()); + tracing::info!(artist = %a, track = %t, user = %s.cyan(), "Now playing"); let user_id = verify_session_id(cache, &s); if let Err(e) = user_id { diff --git a/crates/scrobbler/src/handlers/v1/submission.rs b/crates/scrobbler/src/handlers/v1/submission.rs index 73a997a..88edc1c 100644 --- a/crates/scrobbler/src/handlers/v1/submission.rs +++ b/crates/scrobbler/src/handlers/v1/submission.rs @@ -29,7 +29,7 @@ pub async fn submission( } let user_id = user_id.unwrap(); - println!("Submission: {} - {} {} {} {}", a, t, i, user_id, s.cyan()); + tracing::info!(artist = %a, track = %t, timestamp = %i, user_id = %user_id, "Submission"); match scrobble_v1(pool, cache, &form).await { Ok(_) => Ok(HttpResponse::Ok().body("OK\n")), diff --git a/crates/scrobbler/src/lib.rs b/crates/scrobbler/src/lib.rs index e615d46..1b23032 100644 --- a/crates/scrobbler/src/lib.rs +++ b/crates/scrobbler/src/lib.rs @@ -56,10 +56,7 @@ pub async fn run() -> Result<(), Error> { .parse::() .unwrap_or(7882); - println!( - "Starting Scrobble server @ {}", - format!("{}:{}", host, port).green() - ); + tracing::info!(url = %format!("http://{}:{}", host, port).bright_green(), "Starting Scrobble server @"); let limiter = web::Data::new( Limiter::builder("redis://127.0.0.1") diff --git a/crates/scrobbler/src/listenbrainz/core/submit.rs b/crates/scrobbler/src/listenbrainz/core/submit.rs index a642aaf..7e0dd59 100644 --- a/crates/scrobbler/src/listenbrainz/core/submit.rs +++ b/crates/scrobbler/src/listenbrainz/core/submit.rs @@ -17,7 +17,7 @@ pub async fn submit_listens( token: &str, ) -> Result { if payload.listen_type != "playing_now" { - println!("skipping listen type: {}", payload.listen_type.cyan()); + tracing::info!(listen_type = %payload.listen_type.cyan(), "Skipping listen type"); return Ok(HttpResponse::Ok().json(json!({ "status": "ok", "payload": { @@ -62,13 +62,7 @@ pub async fn submit_listens( cache.del(&format!("listenbrainz:cache:{}:{}:{}", artist, track, did))?; - println!( - "Retryable error on attempt {}/{}: {}", - attempt, - RETRIES, - e.to_string().yellow() - ); - println!("{:#?}", payload); + tracing::error!(error = %e, attempt = attempt, "Retryable error submitting listens for {} - {} (attempt {}/{})", artist, track, attempt, RETRIES); if attempt == RETRIES { return Ok(HttpResponse::BadRequest().json(serde_json::json!({ diff --git a/crates/scrobbler/src/listenbrainz/core/validate_token.rs b/crates/scrobbler/src/listenbrainz/core/validate_token.rs index c8c1293..c6f306e 100644 --- a/crates/scrobbler/src/listenbrainz/core/validate_token.rs +++ b/crates/scrobbler/src/listenbrainz/core/validate_token.rs @@ -12,7 +12,7 @@ pub async fn validate_token(token: &str) -> Result { }, }))), Err(e) => { - println!("Error validating token: {}", e); + tracing::error!(error = %e, "Failed to validate token"); Ok(HttpResponse::BadRequest().json(serde_json::json!({ "error": 4, "message": format!("Failed to validate token: {}", e) diff --git a/crates/scrobbler/src/listenbrainz/handlers.rs b/crates/scrobbler/src/listenbrainz/handlers.rs index 12deb9d..55ec2a7 100644 --- a/crates/scrobbler/src/listenbrainz/handlers.rs +++ b/crates/scrobbler/src/listenbrainz/handlers.rs @@ -58,8 +58,7 @@ pub async fn handle_submit_listens( let body = String::from_utf8_lossy(&payload); let req = serde_json::from_str::(&body) .map_err(|e| { - println!("{}", body); - println!("Error parsing request body: {}", e); + tracing::error!(body = %body, error = %e, "Error parsing request body"); e }) .map_err(actix_web::error::ErrorBadRequest)?; @@ -116,7 +115,7 @@ pub async fn handle_validate_token( })); } Err(e) => { - println!("Error validating token: {}", e); + tracing::error!(error = %e, "Error validating token"); return HttpResponse::InternalServerError().finish(); } } @@ -127,13 +126,13 @@ pub async fn handle_search_users( query: web::Query, data: web::Data>>, ) -> impl Responder { - let pool = data.get_ref(); + let _pool = data.get_ref(); let query = query.into_inner(); match search_users(&query).await { Ok(users) => HttpResponse::Ok().json(users), Err(e) => { - println!("Error searching users: {}", e); + tracing::error!(error = %e, "Error searching users"); HttpResponse::InternalServerError().finish() } } @@ -145,7 +144,7 @@ pub async fn handle_get_listens(user_name: web::Path) -> impl Responder match get_listens(&user_name).await { Ok(listens) => HttpResponse::Ok().json(listens), Err(e) => { - println!("Error getting listens for user {}: {}", user_name, e); + tracing::error!(error = %e, "Error getting listens for user {}", user_name); HttpResponse::InternalServerError().finish() } } @@ -157,7 +156,7 @@ pub async fn handle_get_listen_count(user_name: web::Path) -> impl Respo match get_listen_count(&user_name).await { Ok(count) => HttpResponse::Ok().json(count), Err(e) => { - println!("Error getting listen count for user {}: {}", user_name, e); + tracing::error!(error = %e, "Error getting listen count for user {}", user_name); HttpResponse::InternalServerError().finish() } } @@ -169,7 +168,7 @@ pub async fn handle_get_playing_now(user_name: web::Path) -> impl Respon match get_playing_now(&user_name).await { Ok(playing_now) => HttpResponse::Ok().json(playing_now), Err(e) => { - println!("Error getting playing now for user {}: {}", user_name, e); + tracing::error!(error = %e, "Error getting playing now for user {}", user_name); HttpResponse::InternalServerError().finish() } } @@ -181,7 +180,7 @@ pub async fn handle_get_artists(user_name: web::Path) -> impl Responder match get_top_artists(&user_name).await { Ok(artists) => HttpResponse::Ok().json(artists), Err(e) => { - println!("Error getting top artists: {}", e); + tracing::error!(error = %e, "Error getting top artists"); HttpResponse::InternalServerError().finish() } } @@ -193,7 +192,7 @@ pub async fn handle_get_releases(user_name: web::Path) -> impl Responder match get_top_releases(&user_name).await { Ok(releases) => HttpResponse::Ok().json(releases), Err(e) => { - println!("Error getting top releases: {}", e); + tracing::error!(error = %e, "Error getting top releases"); HttpResponse::InternalServerError().finish() } } @@ -205,7 +204,7 @@ pub async fn handle_get_recordings(user_name: web::Path) -> impl Respond match get_top_recordings(&user_name).await { Ok(recordings) => HttpResponse::Ok().json(recordings), Err(e) => { - println!("Error getting sitewide recordings: {}", e); + tracing::error!(error = %e, "Error getting top recordings"); HttpResponse::InternalServerError().finish() } } @@ -217,7 +216,7 @@ pub async fn handle_get_release_groups(user_name: web::Path) -> impl Res match get_top_release_groups(&user_name).await { Ok(release_groups) => HttpResponse::Ok().json(release_groups), Err(e) => { - println!("Error getting top release groups: {}", e); + tracing::error!(error = %e, "Error getting top release groups"); HttpResponse::InternalServerError().finish() } } @@ -229,7 +228,7 @@ pub async fn handle_get_recording_activity(user_name: web::Path) -> impl match get_top_recordings(&user_name).await { Ok(recordings) => HttpResponse::Ok().json(recordings), Err(e) => { - println!("Error getting top recordings: {}", e); + tracing::error!(error = %e, "Error getting top recordings"); HttpResponse::InternalServerError().finish() } } diff --git a/crates/scrobbler/src/main.rs b/crates/scrobbler/src/main.rs index 65e80e1..61dd9cd 100644 --- a/crates/scrobbler/src/main.rs +++ b/crates/scrobbler/src/main.rs @@ -58,9 +58,9 @@ async fn main() -> Result<(), Error> { .parse::() .unwrap_or(7882); - println!( - "Starting Scrobble server @ {}", - format!("{}:{}", host, port).green() + tracing::info!( + url = %format!("http://{}:{}", host, port).bright_green(), + "Starting Scrobble server @" ); let limiter = web::Data::new( diff --git a/crates/scrobbler/src/rocksky.rs b/crates/scrobbler/src/rocksky.rs index 816b664..8dc2d67 100644 --- a/crates/scrobbler/src/rocksky.rs +++ b/crates/scrobbler/src/rocksky.rs @@ -25,7 +25,7 @@ pub async fn scrobble(cache: &Cache, did: &str, track: Track, timestamp: u64) -> let token = generate_token(did)?; let client = Client::new(); - println!("Scrobbling track: \n {:#?}", track); + tracing::info!(did = %did, track = ?track, "Scrobbling track"); let response = client .post(&format!("{}/now-playing", ROCKSKY_API)) @@ -35,11 +35,10 @@ pub async fn scrobble(cache: &Cache, did: &str, track: Track, timestamp: u64) -> .await?; let status = response.status(); - println!("Response status: {}", status); + tracing::info!(did = %did, artist = %track.artist, track = %track.title, status = %status, "Scrobble response"); if !status.is_success() { let response_text = response.text().await?; - println!("did: {}", did); - println!("Failed to scrobble track: {}", response_text); + tracing::error!(did = %did, response = %response_text, "Failed to scrobble track"); return Err(Error::msg(format!( "Failed to scrobble track: {}", response_text diff --git a/crates/scrobbler/src/scrobbler.rs b/crates/scrobbler/src/scrobbler.rs index 0950181..a9f0adc 100644 --- a/crates/scrobbler/src/scrobbler.rs +++ b/crates/scrobbler/src/scrobbler.rs @@ -133,7 +133,7 @@ pub async fn scrobble( ); let cached = cache.get(&key)?; if cached.is_some() { - println!("{}", format!("Cached: {}", key).yellow()); + tracing::info!(key = %key, "Cached:"); let track = serde_json::from_str::(&cached.unwrap())?; scrobble.album = Some(track.album.clone()); rocksky::scrobble(cache, &did, track, scrobble.timestamp).await?; @@ -144,7 +144,7 @@ pub async fn scrobble( if let Some(mbid) = &scrobble.mbid { // let result = repo::track::get_track_by_mbid(pool, mbid).await?; let result = mb_client.get_recording(mbid).await?; - println!("{}", "Musicbrainz (mbid)".yellow()); + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (mbid)"); scrobble.album = Some(Track::from(result.clone()).album); rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; tokio::time::sleep(std::time::Duration::from_secs(1)).await; @@ -154,7 +154,7 @@ pub async fn scrobble( let result = repo::track::get_track(pool, &scrobble.track, &scrobble.artist).await?; if let Some(track) = result { - println!("{}", "Xata (track)".yellow()); + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Xata (track)"); scrobble.album = Some(track.album.clone()); let album = repo::album::get_album_by_track_id(pool, &track.xata_id).await?; let artist = repo::artist::get_artist_by_track_id(pool, &track.xata_id).await?; @@ -204,7 +204,7 @@ pub async fn scrobble( .await?; if let Some(track) = result.tracks.items.first() { - println!("{}", "Spotify (track)".yellow()); + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Spotify (track)"); scrobble.album = Some(track.album.name.clone()); let mut track = track.clone(); @@ -232,19 +232,14 @@ pub async fn scrobble( if let Some(recording) = result.recordings.first() { let result = mb_client.get_recording(&recording.id).await?; - println!("{}", "Musicbrainz (recording)".yellow()); + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (recording)"); scrobble.album = Some(Track::from(result.clone()).album); rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; tokio::time::sleep(std::time::Duration::from_secs(1)).await; continue; } - println!( - "{} {} - {}, skipping", - "Track not found: ".yellow(), - scrobble.artist, - scrobble.track - ); + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Track not found, skipping"); scrobble.ignored = Some(true); } @@ -313,7 +308,7 @@ pub async fn scrobble_v1( ); let cached = cache.get(&key)?; if cached.is_some() { - println!("{}", format!("Cached: {}", key).yellow()); + tracing::info!(key = %key, "Cached:"); let track = serde_json::from_str::(&cached.unwrap())?; scrobble.album = Some(track.album.clone()); rocksky::scrobble(cache, &did, track, scrobble.timestamp).await?; @@ -324,7 +319,7 @@ pub async fn scrobble_v1( if let Some(mbid) = &scrobble.mbid { // let result = repo::track::get_track_by_mbid(pool, mbid).await?; let result = mb_client.get_recording(mbid).await?; - println!("{}", "Musicbrainz (mbid)".yellow()); + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (mbid)"); scrobble.album = Some(Track::from(result.clone()).album); rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; tokio::time::sleep(std::time::Duration::from_secs(1)).await; @@ -334,7 +329,7 @@ pub async fn scrobble_v1( let result = repo::track::get_track(pool, &scrobble.track, &scrobble.artist).await?; if let Some(track) = result { - println!("{}", "Xata (track)".yellow()); + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Xata (track)"); scrobble.album = Some(track.album.clone()); let album = repo::album::get_album_by_track_id(pool, &track.xata_id).await?; let artist = repo::artist::get_artist_by_track_id(pool, &track.xata_id).await?; @@ -384,7 +379,7 @@ pub async fn scrobble_v1( .await?; if let Some(track) = result.tracks.items.first() { - println!("{}", "Spotify (track)".yellow()); + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Spotify (track)"); scrobble.album = Some(track.album.name.clone()); let mut track = track.clone(); @@ -412,19 +407,14 @@ pub async fn scrobble_v1( if let Some(recording) = result.recordings.first() { let result = mb_client.get_recording(&recording.id).await?; - println!("{}", "Musicbrainz (recording)".yellow()); + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (recording)"); scrobble.album = Some(Track::from(result.clone()).album); rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; tokio::time::sleep(std::time::Duration::from_secs(1)).await; return Ok(()); } - println!( - "{} {} - {}, skipping", - "Track not found: ".yellow(), - artist, - track - ); + tracing::info!(artist = %artist, track = %track, "Track not found, skipping"); Ok(()) } @@ -435,7 +425,7 @@ pub async fn scrobble_listenbrainz( req: &SubmitListensRequest, token: &str, ) -> Result<(), Error> { - println!("Listenbrainz\n{:#?}", req); + tracing::info!(req = ?req, "Listenbrainz submission"); if req.payload.is_empty() { return Err(Error::msg("No payload found")); @@ -481,12 +471,7 @@ pub async fn scrobble_listenbrainz( .get(&format!("listenbrainz:cache:{}:{}:{}", artist, track, did))? .is_some() { - println!( - "{} {} - {}, recently scrobbled", - "Already scrobbled: ".yellow(), - artist, - track - ); + tracing::info!(artist= %artist, track = %track, "Recently scrobbled, skipping"); return Ok(()); } @@ -496,23 +481,13 @@ pub async fn scrobble_listenbrainz( .get(&format!("{}:current", spotify_user.email))? .is_some() { - println!( - "{} {} - {}, currently scrobbling, skipping", - "Currently scrobbling: ".yellow(), - artist, - track - ); + tracing::info!(artist= %artist, track = %track, "Currently scrobbling, skipping"); return Ok(()); } } if cache.get(&format!("nowplaying:{}", did))?.is_some() { - println!( - "{} {} - {}, currently scrobbling, skipping", - "Currently scrobbling: ".yellow(), - artist, - track - ); + tracing::info!(artist= %artist, track = %track, "Currently scrobbling, skipping"); return Ok(()); } @@ -565,7 +540,7 @@ pub async fn scrobble_listenbrainz( ); let cached = cache.get(&key)?; if cached.is_some() { - println!("{}", format!("Cached: {}", key).yellow()); + tracing::info!(key = %key, "Cached"); let track = serde_json::from_str::(&cached.unwrap())?; scrobble.album = Some(track.album.clone()); rocksky::scrobble(cache, &did, track, scrobble.timestamp).await?; @@ -576,7 +551,7 @@ pub async fn scrobble_listenbrainz( if let Some(mbid) = &scrobble.mbid { // let result = repo::track::get_track_by_mbid(pool, mbid).await?; let result = mb_client.get_recording(mbid).await?; - println!("{}", "Musicbrainz (mbid)".yellow()); + tracing::info!("Musicbrainz (mbid)"); scrobble.album = Some(Track::from(result.clone()).album); rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; tokio::time::sleep(std::time::Duration::from_secs(1)).await; @@ -586,7 +561,7 @@ pub async fn scrobble_listenbrainz( let result = repo::track::get_track(pool, &scrobble.track, &scrobble.artist).await?; if let Some(track) = result { - println!("{}", "Xata (track)".yellow()); + tracing::info!("Xata (track)"); scrobble.album = Some(track.album.clone()); let album = repo::album::get_album_by_track_id(pool, &track.xata_id).await?; let artist = repo::artist::get_artist_by_track_id(pool, &track.xata_id).await?; @@ -636,7 +611,7 @@ pub async fn scrobble_listenbrainz( .await?; if let Some(track) = result.tracks.items.first() { - println!("{}", "Spotify (track)".yellow()); + tracing::info!("Spotify (track)"); scrobble.album = Some(track.album.name.clone()); let mut track = track.clone(); @@ -676,12 +651,7 @@ pub async fn scrobble_listenbrainz( } */ - println!( - "{} {} - {}, skipping", - "Track not found: ".yellow(), - artist, - track - ); + tracing::warn!(artist = %artist, track = %track, "Track not found, skipping"); Ok(()) } diff --git a/crates/scrobbler/src/spotify/client.rs b/crates/scrobbler/src/spotify/client.rs index 70788ea..e036e48 100644 --- a/crates/scrobbler/src/spotify/client.rs +++ b/crates/scrobbler/src/spotify/client.rs @@ -36,11 +36,7 @@ impl SpotifyClient { let data = response.text().await?; if data == "Too many requests" { - println!( - "> retry-after {}", - headers.get("retry-after").unwrap().to_str().unwrap() - ); - println!("> {} [get_album]", data); + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_album"); return Ok(None); } @@ -56,11 +52,7 @@ impl SpotifyClient { let data = response.text().await?; if data == "Too many requests" { - println!( - "> retry-after {}", - headers.get("retry-after").unwrap().to_str().unwrap() - ); - println!("> {} [get_artist]", data); + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_artist"); return Ok(None); } diff --git a/crates/webscrobbler/src/handlers.rs b/crates/webscrobbler/src/handlers.rs index ee548fa..0620e98 100644 --- a/crates/webscrobbler/src/handlers.rs +++ b/crates/webscrobbler/src/handlers.rs @@ -32,7 +32,7 @@ async fn handle_scrobble( req: HttpRequest, ) -> Result { let id = req.match_info().get("id").unwrap(); - println!("Received scrobble for ID: {}", id.cyan()); + tracing::info!(id = %id.bright_green(), "Received scrobble"); let pool = data.get_ref().clone(); @@ -50,15 +50,14 @@ async fn handle_scrobble( let body = read_payload!(payload); let params = serde_json::from_slice::(&body).map_err(|err| { let body = String::from_utf8_lossy(&body); - println!("Failed to parse JSON: {}", body); - println!("Failed to parse JSON: {}", err); + tracing::error!(body = %body, error = %err, "Failed to parse JSON"); actix_web::error::ErrorBadRequest(format!("Failed to parse JSON: {}", err)) })?; - println!("Parsed scrobble request: {:#?}", params); + tracing::info!(params = ?params, "Parsed scrobble request"); if params.event_name != "scrobble" { - println!("Skipping non-scrobble event: {}", params.event_name.green()); + tracing::info!(event_name = %params.event_name.cyan(), "Skipping non-scrobble event"); return Ok(HttpResponse::Ok().body("Skipping non-scrobble event")); } @@ -75,7 +74,7 @@ async fn handle_scrobble( })?; if spotify_token.is_some() { - println!("User has a Spotify token, skipping scrobble"); + tracing::info!("User has a Spotify token, skipping scrobble"); return Ok(HttpResponse::Ok().body("User has a Spotify token, skipping scrobble")); } } @@ -91,18 +90,12 @@ async fn handle_scrobble( )); if cached.is_err() { - println!( - "Failed to check cache for Emby scrobble: {}", - cached.unwrap_err() - ); + tracing::error!(artist = %artist, track = %track, error = %cached.unwrap_err(), "Failed to check cache for Emby scrobble"); return Ok(HttpResponse::Ok().body("Failed to check cache for Emby scrobble")); } if cached.unwrap().is_some() { - println!( - "Skipping duplicate scrobble for Emby: {} - {}", - artist, track - ); + tracing::warn!(artist = %artist, track = %track, "Skipping duplicate scrobble for Emby"); return Ok(HttpResponse::Ok().body("Skipping duplicate scrobble for Emby")); } } diff --git a/crates/webscrobbler/src/lib.rs b/crates/webscrobbler/src/lib.rs index 43f9cc3..4127290 100644 --- a/crates/webscrobbler/src/lib.rs +++ b/crates/webscrobbler/src/lib.rs @@ -44,10 +44,7 @@ pub async fn start_server() -> Result<(), Error> { .parse::() .unwrap_or(7883); - println!( - "Starting WebScrobbler Webhook @ {}", - format!("{}:{}", host, port).green() - ); + tracing::info!(url = %format!("http://{}:{}", host, port).bright_green(), "Starting WebScrobbler server @"); let limiter = web::Data::new( Limiter::builder("redis://127.0.0.1") diff --git a/crates/webscrobbler/src/rocksky.rs b/crates/webscrobbler/src/rocksky.rs index 1889ee8..8ba8e4f 100644 --- a/crates/webscrobbler/src/rocksky.rs +++ b/crates/webscrobbler/src/rocksky.rs @@ -1,5 +1,4 @@ use anyhow::Error; -use owo_colors::OwoColorize; use reqwest::Client; use crate::{auth::generate_token, cache::Cache, types::Track}; @@ -26,7 +25,7 @@ pub async fn scrobble(cache: &Cache, did: &str, track: Track, timestamp: u64) -> let token = generate_token(did)?; let client = Client::new(); - println!("Scrobbling track: \n {:#?}", track); + tracing::info!(did = %did, track = ?track, "Scrobbling track"); let response = client .post(&format!("{}/now-playing", ROCKSKY_API)) @@ -36,16 +35,13 @@ pub async fn scrobble(cache: &Cache, did: &str, track: Track, timestamp: u64) -> .await?; if !response.status().is_success() { - println!( - "Failed to scrobble track: {}", - response.status().to_string() - ); + tracing::error!(did = %did, artist = %track.artist, track = %track.title, status = %response.status(), "Failed to scrobble track"); let text = response.text().await?; - println!("Response: {}", text); + tracing::error!(did = %did, response = %text, "Response"); return Err(Error::msg(format!("Failed to scrobble track: {}", text))); } - println!("Scrobbled track: {}", track.title.green()); + tracing::info!(did = %did, artist = %track.artist, track = %track.title, "Scrobbled track"); Ok(()) } diff --git a/crates/webscrobbler/src/scrobbler.rs b/crates/webscrobbler/src/scrobbler.rs index b332d4d..700309f 100644 --- a/crates/webscrobbler/src/scrobbler.rs +++ b/crates/webscrobbler/src/scrobbler.rs @@ -34,7 +34,7 @@ pub async fn scrobble( let cached = cache.get(&key)?; if cached.is_some() { - println!("{}", format!("Cached: {}", key).yellow()); + tracing::info!(artist = %scrobble.data.song.parsed.artist, track = %scrobble.data.song.parsed.track, "Using cached track"); let track = serde_json::from_str::(&cached.unwrap())?; rocksky::scrobble(cache, &did, track, scrobble.time).await?; tokio::time::sleep(std::time::Duration::from_secs(1)).await; @@ -127,7 +127,7 @@ pub async fn scrobble( let result = spotify_client.search(&query).await?; if let Some(track) = result.tracks.items.first() { - println!("{}", "Spotify (track)".yellow()); + tracing::info!("Spotify (track)"); let mut track = track.clone(); if let Some(album) = spotify_client.get_album(&track.album.id).await? { @@ -154,18 +154,13 @@ pub async fn scrobble( if let Some(recording) = result.recordings.first() { let result = mb_client.get_recording(&recording.id).await?; - println!("{}", "Musicbrainz (recording)".yellow()); + tracing::info!("Musicbrainz (recording)"); rocksky::scrobble(cache, &did, result.into(), scrobble.time).await?; tokio::time::sleep(std::time::Duration::from_secs(1)).await; return Ok(()); } - println!( - "{} {} - {}, skipping", - "Track not found: ".yellow(), - scrobble.data.song.parsed.artist, - scrobble.data.song.parsed.track - ); + tracing::warn!(artist = %scrobble.data.song.parsed.artist, track = %scrobble.data.song.parsed.track, "Track not found, skipping"); Ok(()) } diff --git a/crates/webscrobbler/src/spotify/client.rs b/crates/webscrobbler/src/spotify/client.rs index 70788ea..e036e48 100644 --- a/crates/webscrobbler/src/spotify/client.rs +++ b/crates/webscrobbler/src/spotify/client.rs @@ -36,11 +36,7 @@ impl SpotifyClient { let data = response.text().await?; if data == "Too many requests" { - println!( - "> retry-after {}", - headers.get("retry-after").unwrap().to_str().unwrap() - ); - println!("> {} [get_album]", data); + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_album"); return Ok(None); } @@ -56,11 +52,7 @@ impl SpotifyClient { let data = response.text().await?; if data == "Too many requests" { - println!( - "> retry-after {}", - headers.get("retry-after").unwrap().to_str().unwrap() - ); - println!("> {} [get_artist]", data); + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_artist"); return Ok(None); } -- 2.43.0 From 17d6e85cd66c0b094a4b0d99528c626d0fb961ce Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Thu, 25 Sep 2025 21:19:01 +0300 Subject: [PATCH] feat: remove unused crate main files for analytics, dropbox, googledrive, jetstream, playlists, scrobbler, and webscrobbler --- crates/analytics/src/main.rs | 50 --------------- crates/dropbox/src/main.rs | 37 ----------- crates/googledrive/src/main.rs | 37 ----------- crates/jetstream/src/main.rs | 37 ----------- crates/playlists/src/main.rs | 65 -------------------- crates/scrobbler/src/main.rs | 105 -------------------------------- crates/webscrobbler/src/main.rs | 12 ---- 7 files changed, 343 deletions(-) delete mode 100644 crates/analytics/src/main.rs delete mode 100644 crates/dropbox/src/main.rs delete mode 100644 crates/googledrive/src/main.rs delete mode 100644 crates/jetstream/src/main.rs delete mode 100644 crates/playlists/src/main.rs delete mode 100644 crates/scrobbler/src/main.rs delete mode 100644 crates/webscrobbler/src/main.rs diff --git a/crates/analytics/src/main.rs b/crates/analytics/src/main.rs deleted file mode 100644 index 61af8c5..0000000 --- a/crates/analytics/src/main.rs +++ /dev/null @@ -1,50 +0,0 @@ -use core::create_tables; -use std::{ - env, - sync::{Arc, Mutex}, -}; - -use clap::Command; -use cmd::{serve::serve, sync::sync}; -use dotenv::dotenv; -use duckdb::Connection; -use sqlx::postgres::PgPoolOptions; - -pub mod cmd; -pub mod core; -pub mod handlers; -pub mod subscriber; -pub mod types; -pub mod xata; - -fn cli() -> Command { - Command::new("analytics") - .version(env!("CARGO_PKG_VERSION")) - .about("Rocksky Analytics CLI built with Rust and DuckDB") - .subcommand(Command::new("sync").about("Sync data from Xata to DuckDB")) - .subcommand(Command::new("serve").about("Serve the Rocksky Analytics API")) -} - -#[tokio::main] -async fn main() -> Result<(), Box> { - dotenv().ok(); - - let pool = PgPoolOptions::new() - .max_connections(5) - .connect(&env::var("XATA_POSTGRES_URL")?) - .await?; - let conn = Connection::open("./rocksky-analytics.ddb")?; - - create_tables(&conn).await?; - - let args = cli().get_matches(); - let conn = Arc::new(Mutex::new(conn)); - - match args.subcommand() { - Some(("sync", _)) => sync(conn, &pool).await?, - Some(("serve", _)) => serve(conn).await?, - _ => serve(conn).await?, - } - - Ok(()) -} diff --git a/crates/dropbox/src/main.rs b/crates/dropbox/src/main.rs deleted file mode 100644 index 7f9d0fd..0000000 --- a/crates/dropbox/src/main.rs +++ /dev/null @@ -1,37 +0,0 @@ -use clap::Command; -use cmd::{scan::scan, serve::serve}; -use dotenv::dotenv; - -pub mod client; -pub mod cmd; -pub mod consts; -pub mod crypto; -pub mod handlers; -pub mod repo; -pub mod scan; -pub mod token; -pub mod types; -pub mod xata; - -fn cli() -> Command { - Command::new("dropbox") - .version(env!("CARGO_PKG_VERSION")) - .about("Rocksky Dropbox Service") - .subcommand(Command::new("scan").about("Scan Dropbox Music Folder")) - .subcommand(Command::new("serve").about("Serve Rocksky Dropbox API")) -} - -#[tokio::main] -async fn main() -> Result<(), Box> { - dotenv().ok(); - - let args = cli().get_matches(); - - match args.subcommand() { - Some(("scan", _)) => scan().await?, - Some(("serve", _)) => serve().await?, - _ => serve().await?, - } - - Ok(()) -} diff --git a/crates/googledrive/src/main.rs b/crates/googledrive/src/main.rs deleted file mode 100644 index bd6ceb2..0000000 --- a/crates/googledrive/src/main.rs +++ /dev/null @@ -1,37 +0,0 @@ -use clap::Command; -use cmd::{scan::scan, serve::serve}; -use dotenv::dotenv; - -pub mod client; -pub mod cmd; -pub mod consts; -pub mod crypto; -pub mod handlers; -pub mod repo; -pub mod scan; -pub mod token; -pub mod types; -pub mod xata; - -fn cli() -> Command { - Command::new("googledrive") - .version(env!("CARGO_PKG_VERSION")) - .about("Rocksky Google Drive Service") - .subcommand(Command::new("scan").about("Scan Google Drive Music Folder")) - .subcommand(Command::new("serve").about("Serve Rocksky Google Drive API")) -} - -#[tokio::main] -async fn main() -> Result<(), Box> { - dotenv().ok(); - - let args = cli().get_matches(); - - match args.subcommand() { - Some(("scan", _)) => scan().await?, - Some(("serve", _)) => serve().await?, - _ => serve().await?, - } - - Ok(()) -} diff --git a/crates/jetstream/src/main.rs b/crates/jetstream/src/main.rs deleted file mode 100644 index d4c5aee..0000000 --- a/crates/jetstream/src/main.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::{env, sync::Arc}; - -use dotenv::dotenv; -use subscriber::ScrobbleSubscriber; -use tokio::sync::Mutex; - -use crate::webhook_worker::AppState; - -pub mod profile; -pub mod repo; -pub mod subscriber; -pub mod types; -pub mod webhook; -pub mod webhook_worker; -pub mod xata; - -#[tokio::main] -async fn main() -> Result<(), anyhow::Error> { - dotenv()?; - let jetstream_server = env::var("JETSTREAM_SERVER") - .unwrap_or_else(|_| "wss://jetstream2.us-west.bsky.network".to_string()); - let url = format!( - "{}/subscribe?wantedCollections=app.rocksky.*", - jetstream_server - ); - let subscriber = ScrobbleSubscriber::new(&url); - - let redis_url = env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string()); - let redis = redis::Client::open(redis_url)?; - let queue_key = - env::var("WEBHOOK_QUEUE_KEY").unwrap_or_else(|_| "rocksky:webhook_queue".to_string()); - - let state = Arc::new(Mutex::new(AppState { redis, queue_key })); - - subscriber.run(state).await?; - Ok(()) -} diff --git a/crates/playlists/src/main.rs b/crates/playlists/src/main.rs deleted file mode 100644 index 5b845cd..0000000 --- a/crates/playlists/src/main.rs +++ /dev/null @@ -1,65 +0,0 @@ -use core::{create_tables, find_spotify_users, load_users, save_playlists}; -use std::{ - env, - sync::{Arc, Mutex}, -}; - -use anyhow::Error; -use async_nats::connect; -use dotenv::dotenv; -use duckdb::Connection; -use owo_colors::OwoColorize; -use rocksky_playlists::subscriber::subscribe; -use spotify::get_user_playlists; -use sqlx::postgres::PgPoolOptions; - -pub mod core; -pub mod crypto; -pub mod spotify; -pub mod types; -pub mod xata; - -#[tokio::main] -async fn main() -> Result<(), Error> { - dotenv().ok(); - - let conn = Connection::open("./rocksky-playlists.ddb")?; - let conn = Arc::new(Mutex::new(conn)); - create_tables(conn.clone())?; - - subscribe(conn.clone()).await?; - - let pool = PgPoolOptions::new() - .max_connections(5) - .connect(&env::var("XATA_POSTGRES_URL")?) - .await?; - let users = find_spotify_users(&pool, 0, 100).await?; - - load_users(conn.clone(), &pool).await?; - - sqlx::query(r#" - CREATE UNIQUE INDEX IF NOT EXISTS user_playlists_unique_index ON user_playlists (user_id, playlist_id) - "#) - .execute(&pool) - .await?; - let conn = conn.clone(); - - let addr = env::var("NATS_URL").unwrap_or_else(|_| "nats://localhost:4222".to_string()); - let nc = connect(&addr).await?; - let nc = Arc::new(Mutex::new(nc)); - println!("Connected to NATS server at {}", addr.bright_green()); - - for user in users { - let token = user.1.clone(); - let did = user.2.clone(); - let user_id = user.3.clone(); - let playlists = get_user_playlists(token).await?; - save_playlists(&pool, conn.clone(), nc.clone(), playlists, &user_id, &did).await?; - } - - println!("Done!"); - - loop { - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; - } -} diff --git a/crates/scrobbler/src/main.rs b/crates/scrobbler/src/main.rs deleted file mode 100644 index 61dd9cd..0000000 --- a/crates/scrobbler/src/main.rs +++ /dev/null @@ -1,105 +0,0 @@ -pub mod auth; -pub mod cache; -pub mod crypto; -pub mod handlers; -pub mod listenbrainz; -pub mod musicbrainz; -pub mod params; -pub mod repo; -pub mod response; -pub mod rocksky; -pub mod scrobbler; -pub mod signature; -pub mod spotify; -pub mod types; -pub mod xata; - -use actix_limitation::{Limiter, RateLimiter}; -use actix_session::SessionExt as _; -use actix_web::{ - dev::ServiceRequest, - web::{self, Data}, - App, HttpServer, -}; -use anyhow::Error; -use cache::Cache; -use dotenv::dotenv; -use owo_colors::OwoColorize; -use sqlx::postgres::PgPoolOptions; -use std::{env, sync::Arc, time::Duration}; - -pub const BANNER: &str = r#" - ___ ___ _____ __ __ __ - / | __ ______/ (_)___ / ___/______________ / /_ / /_ / /__ _____ - / /| |/ / / / __ / / __ \ \__ \/ ___/ ___/ __ \/ __ \/ __ \/ / _ \/ ___/ - / ___ / /_/ / /_/ / / /_/ / ___/ / /__/ / / /_/ / /_/ / /_/ / / __/ / -/_/ |_\__,_/\__,_/_/\____/ /____/\___/_/ \____/_.___/_.___/_/\___/_/ - - This is the Rocksky Scrobbler API compatible with Last.fm AudioScrobbler API -"#; - -#[tokio::main] -async fn main() -> Result<(), Error> { - dotenv().ok(); - - println!("{}", BANNER.magenta()); - - let cache = Cache::new()?; - - let pool = PgPoolOptions::new() - .max_connections(5) - .connect(&env::var("XATA_POSTGRES_URL")?) - .await?; - let conn = Arc::new(pool); - - let host = env::var("SCROBBLE_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()); - let port = env::var("SCROBBLE_PORT") - .unwrap_or_else(|_| "7882".to_string()) - .parse::() - .unwrap_or(7882); - - tracing::info!( - url = %format!("http://{}:{}", host, port).bright_green(), - "Starting Scrobble server @" - ); - - let limiter = web::Data::new( - Limiter::builder("redis://127.0.0.1") - .key_by(|req: &ServiceRequest| { - req.get_session() - .get(&"session-id") - .unwrap_or_else(|_| req.cookie(&"rate-api-id").map(|c| c.to_string())) - }) - .limit(100) - .period(Duration::from_secs(60)) // 60 minutes - .build() - .unwrap(), - ); - - HttpServer::new(move || { - App::new() - .wrap(RateLimiter::default()) - .app_data(limiter.clone()) - .app_data(Data::new(conn.clone())) - .app_data(Data::new(cache.clone())) - .service(handlers::handle_methods) - .service(handlers::handle_nowplaying) - .service(handlers::handle_submission) - .service(listenbrainz::handlers::handle_submit_listens) - .service(listenbrainz::handlers::handle_validate_token) - .service(listenbrainz::handlers::handle_search_users) - .service(listenbrainz::handlers::handle_get_playing_now) - .service(listenbrainz::handlers::handle_get_listens) - .service(listenbrainz::handlers::handle_get_listen_count) - .service(listenbrainz::handlers::handle_get_artists) - .service(listenbrainz::handlers::handle_get_recordings) - .service(listenbrainz::handlers::handle_get_release_groups) - .service(handlers::index) - .service(handlers::handle_get) - }) - .bind((host, port))? - .run() - .await?; - - Ok(()) -} diff --git a/crates/webscrobbler/src/main.rs b/crates/webscrobbler/src/main.rs deleted file mode 100644 index 7c0f3f1..0000000 --- a/crates/webscrobbler/src/main.rs +++ /dev/null @@ -1,12 +0,0 @@ -use anyhow::Error; -use dotenv::dotenv; -use rocksky_webscrobbler::start_server; - -#[tokio::main] -async fn main() -> Result<(), Error> { - dotenv().ok(); - - start_server().await?; - - Ok(()) -} -- 2.43.0 From 1c78d6db34546db416d17e0135a85d975a67e6e7 Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Thu, 25 Sep 2025 21:23:28 +0300 Subject: [PATCH] feat: remove unused binary entries for scrobbler and webscrobbler --- crates/jetstream/src/repo.rs | 13 +++---------- crates/scrobbler/Cargo.toml | 4 ---- crates/webscrobbler/Cargo.toml | 4 ---- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/crates/jetstream/src/repo.rs b/crates/jetstream/src/repo.rs index 470249b..1352909 100644 --- a/crates/jetstream/src/repo.rs +++ b/crates/jetstream/src/repo.rs @@ -16,16 +16,9 @@ use crate::{ }, webhook_worker::{push_to_queue, AppState}, xata::{ - album::Album, - album_track::AlbumTrack, - artist::Artist, - artist_album::ArtistAlbum, - artist_track::ArtistTrack, - track::Track, - user::{self, User}, - user_album::UserAlbum, - user_artist::UserArtist, - user_track::UserTrack, + album::Album, album_track::AlbumTrack, artist::Artist, artist_album::ArtistAlbum, + artist_track::ArtistTrack, track::Track, user::User, user_album::UserAlbum, + user_artist::UserArtist, user_track::UserTrack, }, }; diff --git a/crates/scrobbler/Cargo.toml b/crates/scrobbler/Cargo.toml index 6b6978a..15f4f8c 100644 --- a/crates/scrobbler/Cargo.toml +++ b/crates/scrobbler/Cargo.toml @@ -6,10 +6,6 @@ edition.workspace = true license.workspace = true repository.workspace = true -[[bin]] -name = "scrobbler" -path = "src/main.rs" - [dependencies] serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.139" diff --git a/crates/webscrobbler/Cargo.toml b/crates/webscrobbler/Cargo.toml index fc7ba16..9610b13 100644 --- a/crates/webscrobbler/Cargo.toml +++ b/crates/webscrobbler/Cargo.toml @@ -6,10 +6,6 @@ edition.workspace = true license.workspace = true repository.workspace = true -[[bin]] -name = "webscrobbler" -path = "src/main.rs" - [dependencies] serde = { version = "1.0.217", features = ["derive"] } serde_json = "1.0.139" -- 2.43.0 From e75b5242b4457e7beb94124df6cca1d6888c3b3c Mon Sep 17 00:00:00 2001 From: Tsiry Sandratraina Date: Thu, 25 Sep 2025 21:27:08 +0300 Subject: [PATCH] feat: remove unused owo_colors dependency from submission and scrobbler modules --- crates/scrobbler/src/handlers/v1/submission.rs | 1 - crates/scrobbler/src/scrobbler.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/crates/scrobbler/src/handlers/v1/submission.rs b/crates/scrobbler/src/handlers/v1/submission.rs index 88edc1c..dd0a87e 100644 --- a/crates/scrobbler/src/handlers/v1/submission.rs +++ b/crates/scrobbler/src/handlers/v1/submission.rs @@ -1,6 +1,5 @@ use actix_web::HttpResponse; use anyhow::Error; -use owo_colors::OwoColorize; use serde_json::json; use std::{collections::BTreeMap, sync::Arc}; diff --git a/crates/scrobbler/src/scrobbler.rs b/crates/scrobbler/src/scrobbler.rs index a9f0adc..ab63a17 100644 --- a/crates/scrobbler/src/scrobbler.rs +++ b/crates/scrobbler/src/scrobbler.rs @@ -1,7 +1,6 @@ use std::{collections::BTreeMap, env}; use anyhow::Error; -use owo_colors::OwoColorize; use rand::Rng; use sqlx::{Pool, Postgres}; -- 2.43.0