A decentralized music tracking and discovery platform built on AT Protocol 🎵 rocksky.app
spotify atproto lastfm musicbrainz scrobbling listenbrainz

Refactor logging to use tracing #7

merged opened by tsiry-sandratraina.com targeting main from setup-tracing
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:7vdlgi2bflelz7mmuxoqjfcr/sh.tangled.repo.pull/3lzolvk366x22
+556 -972
Diff #0
+77 -4
Cargo.lock
··· 3064 3064 3065 3065 [[package]] 3066 3066 name = "log" 3067 - version = "0.4.27" 3067 + version = "0.4.28" 3068 3068 source = "registry+https://github.com/rust-lang/crates.io-index" 3069 - checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 3069 + checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 3070 3070 3071 3071 [[package]] 3072 3072 name = "lru-slab" ··· 3227 3227 "winapi", 3228 3228 ] 3229 3229 3230 + [[package]] 3231 + name = "nu-ansi-term" 3232 + version = "0.50.1" 3233 + source = "registry+https://github.com/rust-lang/crates.io-index" 3234 + checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" 3235 + dependencies = [ 3236 + "windows-sys 0.52.0", 3237 + ] 3238 + 3230 3239 [[package]] 3231 3240 name = "nuid" 3232 3241 version = "0.5.0" ··· 3402 3411 3403 3412 [[package]] 3404 3413 name = "owo-colors" 3405 - version = "4.2.1" 3414 + version = "4.2.2" 3406 3415 source = "registry+https://github.com/rust-lang/crates.io-index" 3407 - checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" 3416 + checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" 3408 3417 dependencies = [ 3409 3418 "supports-color 2.1.0", 3410 3419 "supports-color 3.0.2", ··· 4837 4846 "sqlx", 4838 4847 "tokio", 4839 4848 "tokio-stream", 4849 + "tracing", 4840 4850 ] 4841 4851 4842 4852 [[package]] ··· 4888 4898 "tempfile", 4889 4899 "tokio", 4890 4900 "tokio-stream", 4901 + "tracing", 4891 4902 ] 4892 4903 4893 4904 [[package]] ··· 4919 4930 "tempfile", 4920 4931 "tokio", 4921 4932 "tokio-stream", 4933 + "tracing", 4922 4934 ] 4923 4935 4924 4936 [[package]] ··· 4941 4953 "tokio", 4942 4954 "tokio-stream", 4943 4955 "tokio-tungstenite", 4956 + "tracing", 4944 4957 "tungstenite", 4945 4958 "url", 4946 4959 ] ··· 4968 4981 "sqlx", 4969 4982 "tokio", 4970 4983 "tokio-stream", 4984 + "tracing", 4971 4985 ] 4972 4986 4973 4987 [[package]] ··· 4995 5009 "sqlx", 4996 5010 "tokio", 4997 5011 "tokio-stream", 5012 + "tracing", 4998 5013 "uuid", 4999 5014 ] 5000 5015 ··· 5018 5033 "sqlx", 5019 5034 "tokio", 5020 5035 "tokio-stream", 5036 + "tracing", 5021 5037 ] 5022 5038 5023 5039 [[package]] ··· 5034 5050 "sqlx", 5035 5051 "tokio", 5036 5052 "tokio-stream", 5053 + "tracing", 5037 5054 ] 5038 5055 5039 5056 [[package]] ··· 5053 5070 "serde_json", 5054 5071 "tokio", 5055 5072 "tokio-stream", 5073 + "tracing", 5056 5074 "uuid", 5057 5075 ] 5058 5076 ··· 5080 5098 "sqlx", 5081 5099 "tokio", 5082 5100 "tokio-stream", 5101 + "tracing", 5083 5102 ] 5084 5103 5085 5104 [[package]] ··· 5089 5108 "anyhow", 5090 5109 "clap", 5091 5110 "dotenv", 5111 + "owo-colors", 5092 5112 "rocksky-analytics", 5093 5113 "rocksky-dropbox", 5094 5114 "rocksky-googledrive", ··· 5099 5119 "rocksky-tracklist", 5100 5120 "rocksky-webscrobbler", 5101 5121 "tokio", 5122 + "tracing", 5123 + "tracing-log", 5124 + "tracing-subscriber", 5102 5125 ] 5103 5126 5104 5127 [[package]] ··· 5630 5653 "tokio", 5631 5654 ] 5632 5655 5656 + [[package]] 5657 + name = "sharded-slab" 5658 + version = "0.1.7" 5659 + source = "registry+https://github.com/rust-lang/crates.io-index" 5660 + checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 5661 + dependencies = [ 5662 + "lazy_static", 5663 + ] 5664 + 5633 5665 [[package]] 5634 5666 name = "shlex" 5635 5667 version = "1.3.0" ··· 6440 6472 "syn 2.0.101", 6441 6473 ] 6442 6474 6475 + [[package]] 6476 + name = "thread_local" 6477 + version = "1.1.9" 6478 + source = "registry+https://github.com/rust-lang/crates.io-index" 6479 + checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" 6480 + dependencies = [ 6481 + "cfg-if", 6482 + ] 6483 + 6443 6484 [[package]] 6444 6485 name = "time" 6445 6486 version = "0.3.44" ··· 6780 6821 checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" 6781 6822 dependencies = [ 6782 6823 "once_cell", 6824 + "valuable", 6825 + ] 6826 + 6827 + [[package]] 6828 + name = "tracing-log" 6829 + version = "0.2.0" 6830 + source = "registry+https://github.com/rust-lang/crates.io-index" 6831 + checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 6832 + dependencies = [ 6833 + "log", 6834 + "once_cell", 6835 + "tracing-core", 6836 + ] 6837 + 6838 + [[package]] 6839 + name = "tracing-subscriber" 6840 + version = "0.3.20" 6841 + source = "registry+https://github.com/rust-lang/crates.io-index" 6842 + checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" 6843 + dependencies = [ 6844 + "nu-ansi-term", 6845 + "sharded-slab", 6846 + "smallvec", 6847 + "thread_local", 6848 + "tracing-core", 6849 + "tracing-log", 6783 6850 ] 6784 6851 6785 6852 [[package]] ··· 6958 7025 "wasm-bindgen", 6959 7026 ] 6960 7027 7028 + [[package]] 7029 + name = "valuable" 7030 + version = "0.1.1" 7031 + source = "registry+https://github.com/rust-lang/crates.io-index" 7032 + checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 7033 + 6961 7034 [[package]] 6962 7035 name = "vcpkg" 6963 7036 version = "0.2.15"
+1
crates/analytics/Cargo.toml
··· 28 28 clap = "4.5.31" 29 29 actix-web = "4.9.0" 30 30 tokio-stream = { version = "0.1.17", features = ["full"] } 31 + tracing = "0.1.41"
+2 -2
crates/analytics/src/cmd/serve.rs
··· 29 29 req: HttpRequest, 30 30 ) -> Result<impl Responder, actix_web::Error> { 31 31 let method = req.match_info().get("method").unwrap_or("unknown"); 32 - println!("Method: {}", method.bright_green()); 32 + tracing::info!(method = %method.bright_green(), "API call"); 33 33 34 34 let conn = data.get_ref().clone(); 35 35 handle(method, &mut payload, &req, conn) ··· 45 45 let addr = format!("{}:{}", host, port); 46 46 47 47 let url = format!("http://{}", addr); 48 - println!("Listening on {}", url.bright_green()); 48 + tracing::info!(url = %url.bright_green(), "Listening on"); 49 49 50 50 let conn = conn.clone(); 51 51 HttpServer::new(move || {
+37 -84
crates/analytics/src/core.rs
··· 194 194 .await?; 195 195 196 196 for (i, track) in tracks.clone().into_iter().enumerate() { 197 - println!( 198 - "track {} - {} - {}", 199 - i, 200 - track.title.bright_green(), 201 - track.artist 202 - ); 197 + tracing::info!(track = i, title = %track.title.bright_green(), artist = %track.artist); 203 198 match conn.execute( 204 199 "INSERT INTO tracks ( 205 200 id, ··· 255 250 ], 256 251 ) { 257 252 Ok(_) => (), 258 - Err(e) => println!("error: {}", e), 253 + Err(e) => tracing::error!(error = %e, "Error inserting track"), 259 254 } 260 255 } 261 256 262 - println!("tracks: {:?}", tracks.len()); 257 + tracing::info!(tracks = tracks.len(), "Loaded tracks"); 263 258 Ok(()) 264 259 } 265 260 ··· 277 272 .await?; 278 273 279 274 for (i, artist) in artists.clone().into_iter().enumerate() { 280 - println!("artist {} - {}", i, artist.name.bright_green()); 275 + tracing::info!(artist = i, name = %artist.name.bright_green()); 281 276 match conn.execute( 282 277 "INSERT INTO artists ( 283 278 id, ··· 323 318 ], 324 319 ) { 325 320 Ok(_) => (), 326 - Err(e) => println!("error: {}", e), 321 + Err(e) => tracing::error!(error = %e, "Error inserting artist"), 327 322 } 328 323 } 329 324 330 - println!("artists: {:?}", artists.len()); 325 + tracing::info!(artists = artists.len(), "Loaded artists"); 331 326 Ok(()) 332 327 } 333 328 ··· 342 337 .await?; 343 338 344 339 for (i, album) in albums.clone().into_iter().enumerate() { 345 - println!("album {} - {}", i, album.title.bright_green()); 340 + tracing::info!(album = i, title = %album.title.bright_green(), artist = %album.artist); 346 341 match conn.execute( 347 342 "INSERT INTO albums ( 348 343 id, ··· 388 383 ], 389 384 ) { 390 385 Ok(_) => (), 391 - Err(e) => println!("error: {}", e), 386 + Err(e) => tracing::error!(error = %e, "Error inserting album"), 392 387 } 393 388 } 394 389 395 - println!("albums: {:?}", albums.len()); 390 + tracing::info!(albums = albums.len(), "Loaded albums"); 396 391 Ok(()) 397 392 } 398 393 ··· 407 402 .await?; 408 403 409 404 for (i, user) in users.clone().into_iter().enumerate() { 410 - println!("user {} - {}", i, user.display_name.bright_green()); 405 + tracing::info!(user = i, name = %user.display_name.bright_green()); 411 406 match conn.execute( 412 407 "INSERT INTO users ( 413 408 id, ··· 429 424 ], 430 425 ) { 431 426 Ok(_) => (), 432 - Err(e) => println!("error: {}", e), 427 + Err(e) => tracing::error!(error = %e, "Error inserting user"), 433 428 } 434 429 } 435 430 436 - println!("users: {:?}", users.len()); 431 + tracing::info!(users = users.len(), "Loaded users"); 437 432 Ok(()) 438 433 } 439 434 ··· 451 446 .await?; 452 447 453 448 for (i, scrobble) in scrobbles.clone().into_iter().enumerate() { 454 - println!( 455 - "scrobble {} - {}", 456 - i, 457 - match scrobble.uri.clone() { 458 - Some(uri) => uri.to_string(), 459 - None => "None".to_string(), 460 - } 461 - .bright_green() 462 - ); 449 + tracing::info!(scrobble = i, uri = %scrobble.uri.clone().unwrap_or_else(|| "None".to_string()).bright_green()); 463 450 match conn.execute( 464 451 "INSERT INTO scrobbles ( 465 452 id, ··· 489 476 ], 490 477 ) { 491 478 Ok(_) => (), 492 - Err(e) => println!("error: {}", e), 479 + Err(e) => tracing::error!(error = %e, "Error inserting scrobble"), 493 480 } 494 481 } 495 482 496 - println!("scrobbles: {:?}", scrobbles.len()); 483 + tracing::info!(scrobbles = scrobbles.len(), "Loaded scrobbles"); 497 484 Ok(()) 498 485 } 499 486 ··· 511 498 .await?; 512 499 513 500 for (i, album_track) in album_tracks.clone().into_iter().enumerate() { 514 - println!( 515 - "album_track {} - {} - {}", 516 - i, 517 - album_track.album_id.bright_green(), 518 - album_track.track_id 519 - ); 501 + tracing::info!(album_track = i, album_id = %album_track.album_id.bright_green(), track_id = %album_track.track_id); 520 502 match conn.execute( 521 503 "INSERT INTO album_tracks ( 522 504 id, ··· 532 514 ], 533 515 ) { 534 516 Ok(_) => (), 535 - Err(e) => println!("error: {}", e), 517 + Err(e) => tracing::error!(error = %e, "Error inserting album_track"), 536 518 } 537 519 } 538 - println!("album_tracks: {:?}", album_tracks.len()); 520 + 521 + tracing::info!(album_tracks = album_tracks.len(), "Loaded album_tracks"); 539 522 Ok(()) 540 523 } 541 524 ··· 553 536 .await?; 554 537 555 538 for (i, loved_track) in loved_tracks.clone().into_iter().enumerate() { 556 - println!( 557 - "loved_track {} - {} - {}", 558 - i, 559 - loved_track.user_id.bright_green(), 560 - loved_track.track_id 561 - ); 539 + tracing::info!(loved_track = i, user_id = %loved_track.user_id.bright_green(), track_id = %loved_track.track_id); 562 540 match conn.execute( 563 541 "INSERT INTO loved_tracks ( 564 542 id, ··· 577 555 ], 578 556 ) { 579 557 Ok(_) => (), 580 - Err(e) => println!("error: {}", e), 558 + Err(e) => tracing::error!(error = %e, "Error inserting loved_track"), 581 559 } 582 560 } 583 561 584 - println!("loved_tracks: {:?}", loved_tracks.len()); 562 + tracing::info!(loved_tracks = loved_tracks.len(), "Loaded loved_tracks"); 585 563 Ok(()) 586 564 } 587 565 ··· 599 577 .await?; 600 578 601 579 for (i, artist_track) in artist_tracks.clone().into_iter().enumerate() { 602 - println!( 603 - "artist_track {} - {} - {}", 604 - i, 605 - artist_track.artist_id.bright_green(), 606 - artist_track.track_id 607 - ); 580 + tracing::info!(artist_track = i, artist_id = %artist_track.artist_id.bright_green(), track_id = %artist_track.track_id); 608 581 match conn.execute( 609 582 "INSERT INTO artist_tracks (id, artist_id, track_id, created_at) VALUES (?, ?, ?, ?)", 610 583 params![ ··· 615 588 ], 616 589 ) { 617 590 Ok(_) => (), 618 - Err(e) => println!("error: {}", e), 591 + Err(e) => tracing::error!(error = %e, "Error inserting artist_track"), 619 592 } 620 593 } 621 594 622 - println!("artist_tracks: {:?}", artist_tracks.len()); 595 + tracing::info!(artist_tracks = artist_tracks.len(), "Loaded artist_tracks"); 623 596 Ok(()) 624 597 } 625 598 ··· 637 610 .await?; 638 611 639 612 for (i, artist_album) in artist_albums.clone().into_iter().enumerate() { 640 - println!( 641 - "artist_albums {} - {} - {}", 642 - i, 643 - artist_album.artist_id.bright_green(), 644 - artist_album.album_id 645 - ); 613 + tracing::info!(artist_album = i, artist_id = %artist_album.artist_id.bright_green(), album_id = %artist_album.album_id); 646 614 match conn.execute( 647 615 "INSERT INTO artist_albums (id, artist_id, album_id, created_at) VALUES (?, ?, ?, ?)", 648 616 params![ ··· 653 621 ], 654 622 ) { 655 623 Ok(_) => (), 656 - Err(e) => println!("error: {}", e), 624 + Err(e) => tracing::error!(error = %e, "Error inserting artist_album"), 657 625 } 658 626 } 659 627 660 - println!("artist_albums: {:?}", artist_albums.len()); 628 + tracing::info!(artist_albums = artist_albums.len(), "Loaded artist_albums"); 661 629 Ok(()) 662 630 } 663 631 ··· 675 643 .await?; 676 644 677 645 for (i, user_album) in user_albums.clone().into_iter().enumerate() { 678 - println!( 679 - "user_album {} - {} - {}", 680 - i, 681 - user_album.user_id.bright_green(), 682 - user_album.album_id 683 - ); 646 + tracing::info!(user_album = i, user_id = %user_album.user_id.bright_green(), album_id = %user_album.album_id); 684 647 match conn.execute( 685 648 "INSERT INTO user_albums (id, user_id, album_id, created_at) VALUES (?, ?, ?, ?)", 686 649 params![ ··· 691 654 ], 692 655 ) { 693 656 Ok(_) => (), 694 - Err(e) => println!("error: {}", e), 657 + Err(e) => tracing::error!(error = %e, "Error inserting user_album"), 695 658 } 696 659 } 697 660 698 - println!("user_albums: {:?}", user_albums.len()); 661 + tracing::info!(user_albums = user_albums.len(), "Loaded user_albums"); 699 662 Ok(()) 700 663 } 701 664 ··· 713 676 .await?; 714 677 715 678 for (i, user_artist) in user_artists.clone().into_iter().enumerate() { 716 - println!( 717 - "user_artist {} - {} - {}", 718 - i, 719 - user_artist.user_id.bright_green(), 720 - user_artist.artist_id 721 - ); 679 + tracing::info!(user_artist = i, user_id = %user_artist.user_id.bright_green(), artist_id = %user_artist.artist_id); 722 680 match conn.execute( 723 681 "INSERT INTO user_artists (id, user_id, artist_id, created_at) VALUES (?, ?, ?, ?)", 724 682 params![ ··· 729 687 ], 730 688 ) { 731 689 Ok(_) => (), 732 - Err(e) => println!("error: {}", e), 690 + Err(e) => tracing::error!(error = %e, "Error inserting user_artist"), 733 691 } 734 692 } 735 693 736 - println!("user_artists: {:?}", user_artists.len()); 694 + tracing::info!(user_artists = user_artists.len(), "Loaded user_artists"); 737 695 Ok(()) 738 696 } 739 697 ··· 751 709 .await?; 752 710 753 711 for (i, user_track) in user_tracks.clone().into_iter().enumerate() { 754 - println!( 755 - "user_track {} - {} - {}", 756 - i, 757 - user_track.user_id.bright_green(), 758 - user_track.track_id 759 - ); 712 + tracing::info!(user_track = i, user_id = %user_track.user_id.bright_green(), track_id = %user_track.track_id); 760 713 match conn.execute( 761 714 "INSERT INTO user_tracks (id, user_id, track_id, created_at) VALUES (?, ?, ?, ?)", 762 715 params![ ··· 767 720 ], 768 721 ) { 769 722 Ok(_) => (), 770 - Err(e) => println!("error: {}", e), 723 + Err(e) => tracing::error!(error = %e, "Error inserting user_track"), 771 724 } 772 725 } 773 726 774 - println!("user_tracks: {:?}", user_tracks.len()); 727 + tracing::info!(user_tracks = user_tracks.len(), "Loaded user_tracks"); 775 728 Ok(()) 776 729 }
+4
crates/analytics/src/handlers/albums.rs
··· 22 22 let offset = pagination.skip.unwrap_or(0); 23 23 let limit = pagination.take.unwrap_or(20); 24 24 let did = params.user_did; 25 + tracing::info!(limit, offset, user_did = ?did, "Get albums"); 25 26 26 27 let conn = conn.lock().unwrap(); 27 28 let mut stmt = match did { ··· 118 119 let offset = pagination.skip.unwrap_or(0); 119 120 let limit = pagination.take.unwrap_or(20); 120 121 let did = params.user_did; 122 + tracing::info!(limit, offset, user_did = ?did, "Get top albums"); 121 123 122 124 let conn = conn.lock().unwrap(); 123 125 let mut stmt = match did { ··· 237 239 let body = read_payload!(payload); 238 240 let params = serde_json::from_slice::<GetAlbumTracksParams>(&body)?; 239 241 let conn = conn.lock().unwrap(); 242 + tracing::info!(album_id = %params.album_id, "Get album tracks"); 243 + 240 244 let mut stmt = conn.prepare(r#" 241 245 SELECT 242 246 t.id,
+2
crates/analytics/src/handlers/artists.rs
··· 318 318 let body = read_payload!(payload); 319 319 let params = serde_json::from_slice::<GetArtistAlbumsParams>(&body)?; 320 320 let conn = conn.lock().unwrap(); 321 + tracing::info!(artist_id = %params.artist_id, "Get artist albums"); 321 322 322 323 let mut stmt = conn.prepare(r#" 323 324 SELECT ··· 376 377 let pagination = params.pagination.unwrap_or_default(); 377 378 let offset = pagination.skip.unwrap_or(0); 378 379 let limit = pagination.take.unwrap_or(10); 380 + tracing::info!(artist_id = %params.artist_id, limit, offset, "Get artist listeners"); 379 381 380 382 let conn = conn.lock().unwrap(); 381 383 let mut stmt =
+2
crates/analytics/src/handlers/scrobbles.rs
··· 19 19 let offset = pagination.skip.unwrap_or(0); 20 20 let limit = pagination.take.unwrap_or(20); 21 21 let did = params.user_did; 22 + tracing::info!(limit, offset, user_did = ?did, "Get scrobbles"); 22 23 23 24 let conn = conn.lock().unwrap(); 24 25 let mut stmt = match did { ··· 139 140 let pagination = params.pagination.unwrap_or_default(); 140 141 let offset = pagination.skip.unwrap_or(0); 141 142 let limit = pagination.take.unwrap_or(10); 143 + tracing::info!(limit, offset, user_did = ?params.user_did, "Get distinct scrobbles"); 142 144 143 145 let conn = conn.lock().unwrap(); 144 146 let mut stmt = conn.prepare(
+8
crates/analytics/src/handlers/stats.rs
··· 23 23 let body = read_payload!(payload); 24 24 25 25 let params = serde_json::from_slice::<GetStatsParams>(&body)?; 26 + tracing::info!(user_did = ?params.user_did, "Get stats"); 26 27 27 28 let conn = conn.lock().unwrap(); 28 29 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 119 .end 119 120 .unwrap_or(GetScrobblesPerDayParams::default().end.unwrap()); 120 121 let did = params.user_did; 122 + tracing::info!(start = %start, end = %end, user_did = ?did, "Get scrobbles per day"); 121 123 122 124 let conn = conn.lock().unwrap(); 123 125 match did { ··· 190 192 .end 191 193 .unwrap_or(GetScrobblesPerDayParams::default().end.unwrap()); 192 194 let did = params.user_did; 195 + tracing::info!(start = %start, end = %end, user_did = ?did, "Get scrobbles per month"); 193 196 194 197 let conn = conn.lock().unwrap(); 195 198 match did { ··· 266 269 .end 267 270 .unwrap_or(GetScrobblesPerDayParams::default().end.unwrap()); 268 271 let did = params.user_did; 272 + tracing::info!(start = %start, end = %end, user_did = ?did, "Get scrobbles per year"); 269 273 270 274 let conn = conn.lock().unwrap(); 271 275 match did { ··· 338 342 .end 339 343 .unwrap_or(GetAlbumScrobblesParams::default().end.unwrap()); 340 344 let conn = conn.lock().unwrap(); 345 + tracing::info!(album_id = %params.album_id, start = %start, end = %end, "Get album scrobbles"); 346 + 341 347 let mut stmt = conn.prepare( 342 348 r#" 343 349 SELECT ··· 379 385 .end 380 386 .unwrap_or(GetArtistScrobblesParams::default().end.unwrap()); 381 387 let conn = conn.lock().unwrap(); 388 + tracing::info!(artist_id = %params.artist_id, start = %start, end = %end, "Get artist scrobbles"); 382 389 383 390 let mut stmt = conn.prepare( 384 391 r#" ··· 426 433 .end 427 434 .unwrap_or(GetTrackScrobblesParams::default().end.unwrap()); 428 435 let conn = conn.lock().unwrap(); 436 + tracing::info!(track_id = %params.track_id, start = %start, end = %end, "Get track scrobbles"); 429 437 430 438 let mut stmt = conn.prepare( 431 439 r#"
+3
crates/analytics/src/handlers/tracks.rs
··· 19 19 let offset = pagination.skip.unwrap_or(0); 20 20 let limit = pagination.take.unwrap_or(20); 21 21 let did = params.user_did; 22 + tracing::info!(limit, offset, user_did = ?did, "Get tracks"); 22 23 23 24 let conn = conn.lock().unwrap(); 24 25 match did { ··· 178 179 let offset = pagination.skip.unwrap_or(0); 179 180 let limit = pagination.take.unwrap_or(20); 180 181 let did = params.user_did; 182 + tracing::info!(limit, offset, user_did = ?did, "Get loved tracks"); 181 183 182 184 let conn = conn.lock().unwrap(); 183 185 let mut stmt = conn.prepare( ··· 261 263 let offset = pagination.skip.unwrap_or(0); 262 264 let limit = pagination.take.unwrap_or(20); 263 265 let did = params.user_did; 266 + tracing::info!(limit, offset, user_did = ?did, "Get top tracks"); 264 267 265 268 let conn = conn.lock().unwrap(); 266 269 match did {
+174 -172
crates/analytics/src/subscriber/mod.rs
··· 16 16 let addr = env::var("NATS_URL").unwrap_or_else(|_| "nats://localhost:4222".to_string()); 17 17 let conn = conn.clone(); 18 18 let nc = connect(&addr).await?; 19 - println!("Connected to NATS server at {}", addr.bright_green()); 19 + tracing::info!(server = %addr.bright_green(), "Connected to NATS"); 20 20 21 21 let nc = Arc::new(Mutex::new(nc)); 22 22 on_scrobble(nc.clone(), conn.clone()); ··· 39 39 40 40 41 41 42 + let data = String::from_utf8(msg.payload.to_vec()).unwrap(); 43 + match serde_json::from_str::<ScrobblePayload>(&data) { 44 + Ok(payload) => match save_scrobble(conn.clone(), payload.clone()).await { 45 + Ok(_) => tracing::info!( 46 + uri = %payload.scrobble.uri.cyan(), 47 + "Scrobble saved successfully", 48 + ), 49 + Err(e) => tracing::error!("Error saving scrobble: {}", e), 50 + }, 51 + Err(e) => { 52 + tracing::error!("Error parsing payload: {}", e); 53 + tracing::debug!("{}", data); 54 + } 55 + } 56 + } 42 57 43 58 44 59 ··· 59 74 60 75 61 76 77 + match serde_json::from_str::<NewTrackPayload>(&data) { 78 + Ok(payload) => match save_track(conn.clone(), payload.clone()).await { 79 + Ok(_) => { 80 + tracing::info!( 81 + title = %payload.track.title.cyan(), 82 + "Track saved successfully", 83 + ) 84 + } 85 + Err(e) => tracing::error!("Error saving track: {}", e), 86 + }, 87 + Err(e) => { 88 + tracing::error!("Error parsing payload: {}", e); 89 + tracing::debug!("{}", data); 90 + } 91 + } 92 + } 62 93 63 94 64 95 ··· 78 109 79 110 80 111 112 + let data = String::from_utf8(msg.payload.to_vec()).unwrap(); 113 + match serde_json::from_str::<LikePayload>(&data) { 114 + Ok(payload) => match like(conn.clone(), payload.clone()).await { 115 + Ok(_) => tracing::info!( 116 + track_id = %payload.track_id.xata_id.cyan(), 117 + "Like saved successfully", 118 + ), 119 + Err(e) => tracing::error!("Error saving like: {}", e), 120 + }, 121 + Err(e) => { 122 + tracing::error!("Error parsing payload: {}", e); 123 + tracing::debug!("{}", data); 124 + } 125 + } 126 + } 81 127 82 128 83 129 ··· 97 143 98 144 99 145 146 + let data = String::from_utf8(msg.payload.to_vec()).unwrap(); 147 + match serde_json::from_str::<UnlikePayload>(&data) { 148 + Ok(payload) => match unlike(conn.clone(), payload.clone()).await { 149 + Ok(_) => tracing::info!( 150 + track_id = %payload.track_id.xata_id.cyan(), 151 + "Unlike saved successfully", 152 + ), 153 + Err(e) => tracing::error!("Error saving unlike: {}", e), 154 + }, 155 + Err(e) => { 156 + tracing::error!("Error parsing payload: {}", e); 157 + tracing::debug!("{}", data); 158 + } 159 + } 160 + } 100 161 101 162 102 163 ··· 116 177 117 178 118 179 180 + let data = String::from_utf8(msg.payload.to_vec()).unwrap(); 181 + match serde_json::from_str::<UserPayload>(&data) { 182 + Ok(payload) => match save_user(conn.clone(), payload.clone()).await { 183 + Ok(_) => tracing::info!( 184 + handle = %payload.handle.cyan(), 185 + "User saved successfully", 186 + ), 187 + Err(e) => tracing::error!("Error saving user: {}", e), 188 + }, 189 + Err(e) => { 190 + tracing::error!("Error parsing payload: {}", e); 191 + tracing::debug!("{}", data); 192 + } 193 + } 194 + } 119 195 120 196 121 197 ··· 176 252 177 253 178 254 255 + Ok(_) => (), 256 + Err(e) => { 257 + if !e.to_string().contains("violates primary key constraint") { 258 + tracing::error!("[artists] error: {}", e); 259 + return Err(e.into()); 260 + } 261 + } 179 262 180 263 181 264 ··· 224 307 225 308 226 309 310 + Ok(_) => (), 311 + Err(e) => { 312 + if !e.to_string().contains("violates primary key constraint") { 313 + tracing::error!("[albums] error: {}", e); 314 + return Err(e.into()); 315 + } 316 + } 227 317 228 318 229 319 ··· 280 370 281 371 282 372 373 + Ok(_) => (), 374 + Err(e) => { 375 + if !e.to_string().contains("violates primary key constraint") { 376 + tracing::error!("[tracks] error: {}", e); 377 + return Err(e.into()); 378 + } 379 + } 283 380 284 381 285 382 ··· 296 393 297 394 298 395 396 + Ok(_) => (), 397 + Err(e) => { 398 + if !e.to_string().contains("violates primary key constraint") { 399 + tracing::error!("[album_tracks] error: {}", e); 400 + return Err(e.into()); 401 + } 402 + } 299 403 300 404 301 405 ··· 307 411 308 412 309 413 414 + Ok(_) => (), 415 + Err(e) => { 416 + if !e.to_string().contains("violates primary key constraint") { 417 + tracing::error!("[artist_tracks] error: {}", e); 418 + return Err(e.into()); 419 + } 420 + } 310 421 311 422 312 423 ··· 318 429 319 430 320 431 432 + Ok(_) => (), 433 + Err(e) => { 434 + if !e.to_string().contains("violates primary key constraint") { 435 + tracing::error!("[artist_albums] error: {}", e); 436 + return Err(e.into()); 437 + } 438 + } 321 439 322 440 323 441 ··· 329 447 330 448 331 449 450 + Ok(_) => (), 451 + Err(e) => { 452 + if !e.to_string().contains("violates primary key constraint") { 453 + tracing::error!("[user_albums] error: {}", e); 454 + return Err(e.into()); 455 + } 456 + } 332 457 333 458 334 459 ··· 340 465 341 466 342 467 468 + Ok(_) => (), 469 + Err(e) => { 470 + if !e.to_string().contains("violates primary key constraint") { 471 + tracing::error!("[user_artists] error: {}", e); 472 + return Err(e.into()); 473 + } 474 + } 343 475 344 476 345 477 ··· 351 483 352 484 353 485 486 + Ok(_) => (), 487 + Err(e) => { 488 + if !e.to_string().contains("violates primary key constraint") { 489 + tracing::error!("[user_tracks] error: {}", e); 490 + return Err(e.into()); 491 + } 492 + } 354 493 355 494 356 495 ··· 381 520 382 521 383 522 523 + Ok(_) => (), 524 + Err(e) => { 525 + if !e.to_string().contains("violates primary key constraint") { 526 + tracing::error!("[scrobbles] error: {}", e); 527 + return Err(e.into()); 528 + } 529 + } 384 530 385 531 386 532 ··· 446 592 447 593 448 594 595 + Ok(_) => (), 596 + Err(e) => { 597 + if !e.to_string().contains("violates primary key constraint") { 598 + tracing::error!("[tracks] error: {}", e); 599 + return Err(e.into()); 600 + } 601 + } 449 602 450 603 451 604 ··· 462 615 463 616 464 617 618 + Ok(_) => (), 619 + Err(e) => { 620 + if !e.to_string().contains("violates primary key constraint") { 621 + tracing::error!("[album_tracks] error: {}", e); 622 + return Err(e.into()); 623 + } 624 + } 465 625 466 626 467 627 ··· 473 633 474 634 475 635 636 + Ok(_) => (), 637 + Err(e) => { 638 + if !e.to_string().contains("violates primary key constraint") { 639 + tracing::error!("[artist_tracks] error: {}", e); 640 + return Err(e.into()); 641 + } 642 + } 476 643 477 644 478 645 ··· 484 651 485 652 486 653 487 - 488 - 489 - 490 - 491 - 492 - 493 - 494 - 495 - 496 - 497 - 498 - 499 - 500 - 501 - 502 - 503 - 504 - 505 - 506 - 507 - 508 - 509 - 510 - 511 - 512 - 513 - 514 - 515 - 516 - 517 - 518 - 519 - 520 - 521 - 522 - 523 - 524 - 525 - 526 - 527 - 528 - 529 - 530 - 531 - 532 - 533 - 534 - 535 - 536 - 537 - 538 - 539 - 540 - 541 - 542 - 543 - 544 - 545 - 546 - 547 - 548 - 549 - 550 - 551 - 552 - 553 - 554 - 555 - 556 - 557 - 558 - 559 - 560 - 561 - 562 - 563 - 564 - 565 - 566 - 567 - 568 - 569 - 570 - 571 - 572 - 573 - 574 - 575 - 576 - 577 - 578 - 579 - 580 - 581 - 582 - 583 - 584 - 585 - 586 - 587 - 588 - 589 - 590 - 591 - 592 - 593 - 594 - 595 - 596 - 597 - 598 - 599 - 600 - 601 - 602 - 603 - 604 - 605 - 606 - 607 - 608 - 609 - 610 - 611 - 612 - 613 - 614 - 615 - 616 - 617 - 618 - 619 - 620 - 621 - 622 - 623 - 624 - 625 - 626 - 627 - 628 - 629 - 630 - 631 - 632 - 633 - 634 - 635 - 636 - 637 - 638 - 639 - 640 - 641 - 642 - 643 - 644 - 645 - 646 - 647 - 648 - 649 - 650 - 651 - 652 654 Ok(_) => (), 653 655 Err(e) => { 654 656 if !e.to_string().contains("violates primary key constraint") { 655 - println!("[artist_albums] error: {}", e); 657 + tracing::error!("[artist_albums] error: {}", e); 656 658 return Err(e.into()); 657 659 } 658 660 } ··· 684 686 Ok(_) => (), 685 687 Err(e) => { 686 688 if !e.to_string().contains("violates primary key constraint") { 687 - println!("[likes] error: {}", e); 689 + tracing::error!("[likes] error: {}", e); 688 690 return Err(e.into()); 689 691 } 690 692 } ··· 700 702 ) { 701 703 Ok(_) => (), 702 704 Err(e) => { 703 - println!("[unlikes] error: {}", e); 705 + tracing::error!("[unlikes] error: {}", e); 704 706 return Err(e.into()); 705 707 } 706 708 } ··· 740 742 Ok(_) => (), 741 743 Err(e) => { 742 744 if !e.to_string().contains("violates primary key constraint") { 743 - println!("[users] error: {}", e); 745 + tracing::error!("[users] error: {}", e); 744 746 return Err(e.into()); 745 747 } 746 748 } ··· 921 923 922 924 match serde_json::from_str::<types::ScrobblePayload>(data) { 923 925 Err(e) => { 924 - eprintln!("Error parsing payload: {}", e); 925 - println!("{}", data); 926 + tracing::error!("Error parsing payload: {}", e); 927 + tracing::error!("{}", data); 926 928 } 927 929 Ok(_) => {} 928 930 }
+1
crates/dropbox/Cargo.toml
··· 43 43 tempfile = "3.19.1" 44 44 tokio = { version = "1.43.0", features = ["full"] } 45 45 tokio-stream = { version = "0.1.17", features = ["full"] } 46 + tracing = "0.1.41"
+1
crates/googledrive/Cargo.toml
··· 44 44 tempfile = "3.19.1" 45 45 tokio = { version = "1.43.0", features = ["full"] } 46 46 tokio-stream = { version = "0.1.17", features = ["full"] } 47 + tracing = "0.1.41"
+1
crates/jetstream/Cargo.toml
··· 38 38 sha256 = "1.6.0" 39 39 time = { version = "0.3.44", features = ["formatting", "macros"] } 40 40 redis = { version = "0.29.0", features = ["aio", "tokio-comp"] } 41 + tracing = "0.1.41"
+1
crates/playlists/Cargo.toml
··· 37 37 hex = "0.4.3" 38 38 jsonwebtoken = "9.3.1" 39 39 sha2 = "0.10.8" 40 + tracing = "0.1.41"
+4
crates/rockskyd/Cargo.toml
··· 20 20 rocksky-spotify = { path = "../spotify" } 21 21 rocksky-tracklist = { path = "../tracklist" } 22 22 rocksky-webscrobbler = { path = "../webscrobbler" } 23 + tracing = "0.1.41" 24 + tracing-subscriber = "0.3.20" 25 + tracing-log = "0.2.0" 26 + owo-colors = "4.2.2"
+12
crates/rockskyd/src/main.rs
··· 1 1 use clap::Command; 2 2 use dotenv::dotenv; 3 + use tracing_subscriber::fmt::format::Format; 3 4 4 5 pub mod cmd; 5 6 ··· 35 36 36 37 #[tokio::main] 37 38 async fn main() -> Result<(), Box<dyn std::error::Error>> { 39 + let format = Format::default() 40 + .with_level(true) 41 + .with_target(true) 42 + .with_ansi(true) 43 + .compact(); 44 + 45 + tracing_subscriber::fmt() 46 + .event_format(format) 47 + .with_max_level(tracing::Level::INFO) 48 + .init(); 49 + 38 50 dotenv().ok(); 39 51 40 52 let args = cli().get_matches();
+6 -9
crates/scrobbler/Cargo.toml
··· 3 3 4 4 5 5 6 + license.workspace = true 7 + repository.workspace = true 6 8 9 + [dependencies] 10 + serde = { version = "1.0.217", features = ["derive"] } 11 + serde_json = "1.0.139" 7 12 8 13 9 14 ··· 32 37 33 38 34 39 35 - 36 - 37 - 38 - 39 - 40 - 41 - 42 - 43 - 44 40 actix-limitation = "0.5.1" 45 41 actix-session = "0.10.1" 46 42 tokio-stream = { version = "0.1.17", features = ["full"] } 43 + tracing = "0.1.41"
+1
crates/spotify/Cargo.toml
··· 38 38 ] } 39 39 tokio = { version = "1.43.0", features = ["full"] } 40 40 tokio-stream = { version = "0.1.17", features = ["full"] } 41 + tracing = "0.1.41"
+1
crates/storage/Cargo.toml
··· 26 26 ] } 27 27 actix-web = "4.9.0" 28 28 tokio-stream = { version = "0.1.17", features = ["full"] } 29 + tracing = "0.1.41"
+1
crates/tracklist/Cargo.toml
··· 22 22 clap = "4.5.31" 23 23 rand = "0.9.2" 24 24 uuid = { version = "1.18.0", features = ["v4"] } 25 + tracing = "0.1.41"
+6 -9
crates/webscrobbler/Cargo.toml
··· 3 3 4 4 5 5 6 + license.workspace = true 7 + repository.workspace = true 6 8 9 + [dependencies] 10 + serde = { version = "1.0.217", features = ["derive"] } 11 + serde_json = "1.0.139" 7 12 8 13 9 14 ··· 30 35 31 36 32 37 33 - 34 - 35 - 36 - 37 - 38 - 39 - 40 - 41 - 42 38 tokio-stream = { version = "0.1.17", features = ["full"] } 43 39 actix-session = "0.10.1" 44 40 actix-limitation = "0.5.1" 41 + tracing = "0.1.41"
+2 -2
crates/dropbox/src/cmd/serve.rs
··· 27 27 req: HttpRequest, 28 28 ) -> Result<impl Responder, actix_web::Error> { 29 29 let method = req.match_info().get("method").unwrap_or("unknown"); 30 - println!("Method: {}", method.bright_green()); 30 + tracing::info!(method = %method.bright_green(), "API call"); 31 31 32 32 let conn = data.get_ref().clone(); 33 33 handle(method, &mut payload, &req, conn) ··· 41 41 let addr = format!("{}:{}", host, port); 42 42 43 43 let url = format!("http://{}", addr); 44 - println!("Listening on {}", url.bright_green()); 44 + tracing::info!(url = %url.bright_green(), "Listening on"); 45 45 46 46 let pool = PgPoolOptions::new() 47 47 .max_connections(5)
+8
crates/dropbox/src/handlers/files.rs
··· 2 2 3 3 use actix_web::{web, HttpRequest, HttpResponse}; 4 4 use anyhow::Error; 5 + use owo_colors::OwoColorize; 5 6 use sqlx::{Pool, Postgres}; 6 7 use tokio_stream::StreamExt; 7 8 ··· 24 25 let body = read_payload!(payload); 25 26 let params = serde_json::from_slice::<GetFilesParams>(&body)?; 26 27 let refresh_token = find_dropbox_refresh_token(&pool.clone(), &params.did).await?; 28 + tracing::info!(did = %params.did.bright_green(), "dropbox.getFiles"); 27 29 28 30 if refresh_token.is_none() { 29 31 return Ok(HttpResponse::Unauthorized().finish()); ··· 48 50 let body = read_payload!(payload); 49 51 let params = serde_json::from_slice::<GetFilesParams>(&body)?; 50 52 let refresh_token = find_dropbox_refresh_token(&pool.clone(), &params.did).await?; 53 + tracing::info!(did = %params.did.bright_green(), "dropbox.createMusicFolder"); 51 54 52 55 if refresh_token.is_none() { 53 56 return Ok(HttpResponse::Unauthorized().finish()); ··· 72 75 let body = read_payload!(payload); 73 76 let params = serde_json::from_slice::<GetFilesAtParams>(&body)?; 74 77 let refresh_token = find_dropbox_refresh_token(&pool.clone(), &params.did).await?; 78 + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.getFilesAt"); 75 79 76 80 if refresh_token.is_none() { 77 81 return Ok(HttpResponse::Unauthorized().finish()); ··· 96 100 let body = read_payload!(payload); 97 101 let params = serde_json::from_slice::<DownloadFileParams>(&body)?; 98 102 let refresh_token = find_dropbox_refresh_token(&pool.clone(), &params.did).await?; 103 + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.downloadFile"); 99 104 100 105 if refresh_token.is_none() { 101 106 return Ok(HttpResponse::Unauthorized().finish()); ··· 118 123 let body = read_payload!(payload); 119 124 let params = serde_json::from_slice::<DownloadFileParams>(&body)?; 120 125 let refresh_token = find_dropbox_refresh_token(&pool.clone(), &params.did).await?; 126 + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.getTemporaryLink"); 121 127 122 128 if refresh_token.is_none() { 123 129 return Ok(HttpResponse::Unauthorized().finish()); ··· 142 148 let body = read_payload!(payload); 143 149 let params = serde_json::from_slice::<DownloadFileParams>(&body)?; 144 150 let refresh_token = find_dropbox_refresh_token(&pool.clone(), &params.did).await?; 151 + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.getMetadata"); 145 152 146 153 if refresh_token.is_none() { 147 154 return Ok(HttpResponse::Unauthorized().finish()); ··· 165 172 ) -> Result<HttpResponse, Error> { 166 173 let body = read_payload!(payload); 167 174 let params = serde_json::from_slice::<ScanFolderParams>(&body)?; 175 + tracing::info!(did = %params.did.bright_green(), path = %params.path.bright_green(), "dropbox.scanFolder"); 168 176 169 177 let pool = pool.clone(); 170 178 thread::spawn(move || {
+60 -74
crates/dropbox/src/scan.rs
··· 91 91 .await?; 92 92 93 93 if res.status().as_u16() == 400 || res.status().as_u16() == 409 { 94 - println!("Path not found: {}", path.bright_red()); 94 + tracing::error!(path = %path.bright_red(), "Path not found"); 95 95 return Ok(()); 96 96 } 97 97 98 98 let entry = res.json::<Entry>().await?; 99 99 100 100 if entry.tag.clone().unwrap().as_str() == "folder" { 101 - println!("Scanning folder: {}", path.bright_green()); 101 + tracing::info!(path = %path.bright_green(), "Scanning folder"); 102 102 103 103 let parent_path = Path::new(&path) 104 104 .parent() ··· 160 160 161 161 let client = Client::new(); 162 162 163 - println!("Downloading file: {}", path.bright_green()); 163 + tracing::info!(path = %path.bright_green(), "Downloading file"); 164 164 165 165 let res = client 166 166 .post(&format!("{}/files/download", CONTENT_URL)) ··· 176 176 let mut tmpfile = File::create(&tmppath)?; 177 177 tmpfile.write_all(&bytes)?; 178 178 179 - println!( 180 - "Reading file: {}", 181 - &tmppath.clone().display().to_string().bright_green() 182 - ); 179 + tracing::info!(path = %tmppath.clone().display().to_string().bright_green(), "Reading file"); 183 180 184 181 let tagged_file = match Probe::open(&tmppath)?.read() { 185 182 Ok(tagged_file) => tagged_file, 186 183 Err(e) => { 187 - println!("Error opening file: {}", e); 184 + tracing::error!(path = %tmppath.clone().display().to_string().bright_red(), "Error reading file: {}", e); 188 185 return Ok(()); 189 186 } 190 187 }; ··· 193 190 let tag = match primary_tag { 194 191 Some(tag) => tag, 195 192 None => { 196 - println!("No tag found in file"); 193 + tracing::error!(path = %tmppath.clone().display().to_string().bright_red(), "No tag found in file"); 197 194 return Ok(()); 198 195 } 199 196 }; 200 197 201 198 let pictures = tag.pictures(); 202 199 203 - println!( 204 - "Title: {}", 205 - tag.get_string(&lofty::tag::ItemKey::TrackTitle) 206 - .unwrap_or_default() 207 - .bright_green() 208 - ); 209 - println!( 210 - "Artist: {}", 211 - tag.get_string(&lofty::tag::ItemKey::TrackArtist) 212 - .unwrap_or_default() 213 - .bright_green() 200 + tracing::info!( 201 + title = %tag 202 + .get_string(&lofty::tag::ItemKey::TrackTitle) 203 + .unwrap_or_default(), 214 204 ); 215 - println!( 216 - "Album Artist: {}", 217 - tag.get_string(&lofty::tag::ItemKey::AlbumArtist) 218 - .unwrap_or_default() 219 - .bright_green() 205 + tracing::info!( 206 + artist = %tag 207 + .get_string(&lofty::tag::ItemKey::TrackArtist) 208 + .unwrap_or_default(), 220 209 ); 221 - println!( 222 - "Album: {}", 223 - tag.get_string(&lofty::tag::ItemKey::AlbumTitle) 224 - .unwrap_or_default() 225 - .bright_green() 210 + tracing::info!( 211 + album = %tag 212 + .get_string(&lofty::tag::ItemKey::AlbumTitle) 213 + .unwrap_or_default(), 226 214 ); 227 - println!( 228 - "Lyrics: {}", 229 - tag.get_string(&lofty::tag::ItemKey::Lyrics) 230 - .unwrap_or_default() 231 - .bright_green() 215 + tracing::info!( 216 + album_artist = %tag 217 + .get_string(&lofty::tag::ItemKey::AlbumArtist) 218 + .unwrap_or_default(), 232 219 ); 233 - println!("Year: {}", tag.year().unwrap_or_default().bright_green()); 234 - println!( 235 - "Track Number: {}", 236 - tag.track().unwrap_or_default().bright_green() 220 + tracing::info!( 221 + lyrics = %tag 222 + .get_string(&lofty::tag::ItemKey::Lyrics) 223 + .unwrap_or_default(), 237 224 ); 238 - println!( 239 - "Track Total: {}", 240 - tag.track_total().unwrap_or_default().bright_green() 225 + tracing::info!(year = %tag.year().unwrap_or_default()); 226 + tracing::info!(track_number = %tag.track().unwrap_or_default()); 227 + tracing::info!(track_total = %tag.track_total().unwrap_or_default()); 228 + tracing::info!( 229 + release_date = %tag 230 + .get_string(&lofty::tag::ItemKey::OriginalReleaseDate) 231 + .unwrap_or_default(), 241 232 ); 242 - println!( 243 - "Release Date: {:?}", 244 - tag.get_string(&lofty::tag::ItemKey::OriginalReleaseDate) 245 - .unwrap_or_default() 246 - .bright_green() 233 + tracing::info!( 234 + recording_date = %tag 235 + .get_string(&lofty::tag::ItemKey::RecordingDate) 236 + .unwrap_or_default(), 247 237 ); 248 - println!( 249 - "Recording Date: {:?}", 250 - tag.get_string(&lofty::tag::ItemKey::RecordingDate) 251 - .unwrap_or_default() 252 - .bright_green() 238 + tracing::info!( 239 + copyright_message = %tag 240 + .get_string(&lofty::tag::ItemKey::CopyrightMessage) 241 + .unwrap_or_default(), 253 242 ); 254 - println!( 255 - "Copyright Message: {}", 256 - tag.get_string(&lofty::tag::ItemKey::CopyrightMessage) 257 - .unwrap_or_default() 258 - .bright_green() 259 - ); 260 - println!("Pictures: {:?}", pictures); 243 + tracing::info!(pictures = ?pictures); 261 244 262 245 let title = tag 263 246 .get_string(&lofty::tag::ItemKey::TrackTitle) ··· 290 273 291 274 match track { 292 275 Some(track) => { 293 - println!("Track exists: {}", title.bright_green()); 276 + tracing::info!(title = %title.bright_green(), "Track exists"); 294 277 let parent_path = Path::new(&path) 295 278 .parent() 296 279 .map(|p| p.to_string_lossy().to_string()); 297 280 let status = 298 281 create_dropbox_path(&pool, &entry, &track, &dropbox_id, parent_path).await; 299 - println!("status: {:?}", status); 282 + tracing::info!(status = ?status); 300 283 301 284 // TODO: publish file metadata to nats 302 285 } 303 286 None => { 304 - println!("Creating track: {}", title.bright_green()); 287 + tracing::info!(title = %title.bright_green(), "Creating track"); 305 288 let album_art = 306 289 upload_album_cover(albumart_id.into(), pictures, &access_token).await?; 307 290 let client = Client::new(); ··· 338 321 })) 339 322 .send() 340 323 .await?; 341 - println!("Track Saved: {} {}", title, response.status()); 324 + tracing::info!(title = title, status = %response.status(), "Track saved"); 342 325 tokio::time::sleep(std::time::Duration::from_secs(3)).await; 343 326 344 327 let track = get_track_by_hash(&pool, &hash).await?; ··· 353 336 return Ok(()); 354 337 } 355 338 356 - println!("Failed to create track: {}", title.bright_green()); 339 + tracing::error!(title = %title.bright_red(), "Failed to create track"); 357 340 } 358 341 } 359 342 ··· 413 396 .send() 414 397 .await?; 415 398 416 - println!("Cover uploaded: {}", response.status()); 399 + tracing::info!(status = %response.status(), "Cover uploaded"); 417 400 418 401 Ok(Some(name)) 419 402 } ··· 433 416 let meta_opts = MetadataOptions::default(); 434 417 let format_opts = FormatOptions::default(); 435 418 436 - let probed = 437 - match symphonia::default::get_probe().format(&hint, media_source, &format_opts, &meta_opts) 438 - { 439 - Ok(probed) => probed, 440 - Err(_) => { 441 - println!("Error probing file"); 442 - return Ok(duration); 443 - } 444 - }; 419 + let probed = match symphonia::default::get_probe().format( 420 + &hint, 421 + media_source, 422 + &format_opts, 423 + &meta_opts, 424 + ) { 425 + Ok(probed) => probed, 426 + Err(e) => { 427 + tracing::error!(path = %path.display().to_string().bright_red(), "Error probing file: {}", e); 428 + return Ok(duration); 429 + } 430 + }; 445 431 446 432 if let Some(track) = probed.format.tracks().first() { 447 433 if let Some(duration) = track.codec_params.n_frames {
+2 -2
crates/googledrive/src/cmd/serve.rs
··· 27 27 req: HttpRequest, 28 28 ) -> Result<impl Responder, actix_web::Error> { 29 29 let method = req.match_info().get("method").unwrap_or("unknown"); 30 - println!("Method: {}", method.bright_green()); 30 + tracing::info!(method = %method.bright_green(), "API call"); 31 31 32 32 let conn = data.get_ref().clone(); 33 33 handle(method, &mut payload, &req, conn) ··· 41 41 let addr = format!("{}:{}", host, port); 42 42 43 43 let url = format!("http://{}", addr); 44 - println!("Listening on {}", url.bright_green()); 44 + tracing::info!(url = %url.bright_green(), "Listening on"); 45 45 46 46 let pool = PgPoolOptions::new() 47 47 .max_connections(5)
+6 -1
crates/googledrive/src/repo/google_drive_path.rs
··· 1 + use owo_colors::OwoColorize; 1 2 use sqlx::{Pool, Postgres}; 2 3 3 4 use crate::{ ··· 47 48 .execute(pool) 48 49 .await?; 49 50 50 - println!("{:?}", result); 51 + tracing::info!( 52 + file_id = %file.id.bright_green(), 53 + rows_affected = %result.rows_affected(), 54 + "Google Drive path created" 55 + ); 51 56 52 57 sqlx::query( 53 58 r#"
+27 -79
crates/googledrive/src/scan.rs
··· 104 104 let file = res.json::<File>().await?; 105 105 106 106 if file.mime_type == "application/vnd.google-apps.folder" { 107 - println!("Scanning folder: {}", file.name.bright_green()); 107 + tracing::info!(folder = %file.name.bright_green(), "Scanning folder"); 108 108 109 109 create_google_drive_directory( 110 110 &pool, ··· 172 172 return Ok(()); 173 173 } 174 174 175 - println!("Downloading file: {}", file.name.bright_green()); 175 + tracing::info!(file = %file.name.bright_green(), "Downloading file"); 176 176 177 177 let client = Client::new(); 178 178 ··· 191 191 let mut tmpfile = std::fs::File::create(&tmppath)?; 192 192 tmpfile.write_all(&bytes)?; 193 193 194 - println!( 195 - "Reading file: {}", 196 - &tmppath.clone().display().to_string().bright_green() 197 - ); 194 + tracing::info!(path = %tmppath.display(), "Reading file"); 198 195 199 196 let tagged_file = match Probe::open(&tmppath)?.read() { 200 197 Ok(tagged_file) => tagged_file, 201 198 Err(e) => { 202 - println!("Error opening file: {}", e); 199 + tracing::warn!(file = %file.name.bright_green(), error = %e, "Failed to open file with lofty"); 203 200 return Ok(()); 204 201 } 205 202 }; ··· 208 205 let tag = match primary_tag { 209 206 Some(tag) => tag, 210 207 None => { 211 - println!("No tag found in file"); 208 + tracing::warn!(file = %file.name.bright_green(), "No tag found in file"); 212 209 return Ok(()); 213 210 } 214 211 }; 215 212 216 213 let pictures = tag.pictures(); 217 214 218 - println!( 219 - "Title: {}", 220 - tag.get_string(&lofty::tag::ItemKey::TrackTitle) 221 - .unwrap_or_default() 222 - .bright_green() 223 - ); 224 - println!( 225 - "Artist: {}", 226 - tag.get_string(&lofty::tag::ItemKey::TrackArtist) 227 - .unwrap_or_default() 228 - .bright_green() 229 - ); 230 - println!( 231 - "Album Artist: {}", 232 - tag.get_string(&lofty::tag::ItemKey::AlbumArtist) 233 - .unwrap_or_default() 234 - .bright_green() 235 - ); 236 - println!( 237 - "Album: {}", 238 - tag.get_string(&lofty::tag::ItemKey::AlbumTitle) 239 - .unwrap_or_default() 240 - .bright_green() 241 - ); 242 - println!( 243 - "Lyrics: {}", 244 - tag.get_string(&lofty::tag::ItemKey::Lyrics) 245 - .unwrap_or_default() 246 - .bright_green() 247 - ); 248 - println!("Year: {}", tag.year().unwrap_or_default().bright_green()); 249 - println!( 250 - "Track Number: {}", 251 - tag.track().unwrap_or_default().bright_green() 252 - ); 253 - println!( 254 - "Track Total: {}", 255 - tag.track_total().unwrap_or_default().bright_green() 256 - ); 257 - println!( 258 - "Release Date: {:?}", 259 - tag.get_string(&lofty::tag::ItemKey::OriginalReleaseDate) 260 - .unwrap_or_default() 261 - .bright_green() 262 - ); 263 - println!( 264 - "Recording Date: {:?}", 265 - tag.get_string(&lofty::tag::ItemKey::RecordingDate) 266 - .unwrap_or_default() 267 - .bright_green() 268 - ); 269 - println!( 270 - "Copyright Message: {}", 271 - tag.get_string(&lofty::tag::ItemKey::CopyrightMessage) 272 - .unwrap_or_default() 273 - .bright_green() 274 - ); 275 - println!("Pictures: {:?}", pictures); 215 + tracing::info!(title = %tag.get_string(&lofty::tag::ItemKey::TrackTitle).unwrap_or_default(), "Title"); 216 + tracing::info!(artist = %tag.get_string(&lofty::tag::ItemKey::TrackArtist).unwrap_or_default(), "Artist"); 217 + tracing::info!(album_artist = %tag.get_string(&lofty::tag::ItemKey::AlbumArtist).unwrap_or_default(), "Album artist"); 218 + tracing::info!(album = %tag.get_string(&lofty::tag::ItemKey::AlbumTitle).unwrap_or_default(), "Album"); 219 + tracing::info!(lyrics = %tag.get_string(&lofty::tag::ItemKey::Lyrics).unwrap_or_default(), "Lyrics"); 220 + tracing::info!(year = %tag.year().unwrap_or_default(), "Year"); 221 + tracing::info!(track_number = %tag.track().unwrap_or_default(), "Track number"); 222 + tracing::info!(track_total = %tag.track_total().unwrap_or_default(), "Track total"); 223 + tracing::info!(release_date = %tag.get_string(&lofty::tag::ItemKey::OriginalReleaseDate).unwrap_or_default(), "Release date"); 224 + tracing::info!(recording_date = %tag.get_string(&lofty::tag::ItemKey::RecordingDate).unwrap_or_default(), "Recording date"); 225 + tracing::info!(copyright = %tag.get_string(&lofty::tag::ItemKey::CopyrightMessage).unwrap_or_default(), "Copyright message"); 226 + tracing::info!(pictures = %pictures.len(), "Pictures found"); 276 227 277 228 let title = tag 278 229 .get_string(&lofty::tag::ItemKey::TrackTitle) ··· 304 255 305 256 match track { 306 257 Some(track) => { 307 - println!("Track exists: {}", title.bright_green()); 258 + tracing::info!(title = %title.bright_green(), "Track exists"); 308 259 let parent_drive_id = parent_drive_file_id.as_deref(); 309 - let status = create_google_drive_path( 260 + create_google_drive_path( 310 261 &pool, 311 262 &file, 312 263 &track, ··· 315 266 ) 316 267 .await?; 317 268 318 - println!("status: {:?}", status); 319 269 // TODO: publish file metadata to nats 320 270 } 321 271 None => { 322 - println!("Creating track: {}", title.bright_green()); 272 + tracing::info!(title = %title.bright_green(), "Creating track"); 323 273 324 274 let albumart = 325 275 upload_album_cover(albumart_id.into(), pictures, &access_token).await?; ··· 358 308 })) 359 309 .send() 360 310 .await?; 361 - println!("Track Saved: {} {}", title, response.status()); 311 + tracing::info!(status = %response.status(), "Track saved"); 362 312 tokio::time::sleep(std::time::Duration::from_secs(3)).await; 363 313 364 314 let track = get_track_by_hash(&pool, &hash).await?; 365 315 if let Some(track) = track { 366 316 let parent_drive_id = parent_drive_file_id.as_deref(); 367 - let status = create_google_drive_path( 317 + create_google_drive_path( 368 318 &pool, 369 319 &file, 370 320 &track, 371 321 &google_drive_id, 372 322 parent_drive_id.unwrap_or(""), 373 323 ) 374 - .await; 375 - 376 - println!("status: {:?}", status); 324 + .await?; 377 325 378 326 // TODO: publish file metadata to nats 379 327 ··· 382 330 return Ok(()); 383 331 } 384 332 385 - println!("Failed to create track: {}", title.bright_green()); 333 + tracing::warn!(title = %title.bright_green(), "Failed to create track"); 386 334 } 387 335 } 388 336 ··· 442 390 .send() 443 391 .await?; 444 392 445 - println!("Cover uploaded: {}", response.status()); 393 + tracing::info!(status = %response.status(), "Cover uploaded"); 446 394 447 395 Ok(Some(name)) 448 396 } ··· 466 414 match symphonia::default::get_probe().format(&hint, media_source, &format_opts, &meta_opts) 467 415 { 468 416 Ok(probed) => probed, 469 - Err(_) => { 470 - println!("Error probing file"); 417 + Err(e) => { 418 + tracing::warn!(path = %path.display(), error = %e, "Failed to probe media"); 471 419 return Ok(duration); 472 420 } 473 421 };
+25 -68
crates/jetstream/src/repo.rs
··· 56 56 57 57 let user_id = save_user(&mut tx, did).await?; 58 58 59 - println!( 60 - "Saving scrobble: {} ", 61 - format!( 62 - "{} - {} - {}", 63 - scrobble_record.title, scrobble_record.artist, scrobble_record.album 64 - ) 65 - .magenta() 66 - ); 59 + tracing::info!(title = %scrobble_record.title.magenta(), artist = %scrobble_record.artist.magenta(), album = %scrobble_record.album.magenta(), "Saving scrobble"); 67 60 68 61 sqlx::query( 69 62 r#" ··· 144 137 { 145 138 Ok(_) => {} 146 139 Err(e) => { 147 - eprintln!("Failed to push to webhook queue: {}", e); 140 + tracing::error!(error = %e, "Failed to push to webhook queue"); 148 141 } 149 142 } 150 143 } ··· 188 181 } 189 182 } 190 183 _ => { 191 - println!("Unsupported operation: {}", commit.operation); 184 + tracing::warn!(operation = %commit.operation, "Unsupported operation"); 192 185 } 193 186 } 194 187 Ok(()) ··· 341 334 .await?; 342 335 343 336 if !albums.is_empty() { 344 - println!("Album already exists: {}", albums[0].title.magenta()); 337 + tracing::info!(name = %albums[0].title.magenta(), "Album already exists"); 345 338 return Ok(albums[0].xata_id.clone()); 346 339 } 347 340 348 - println!("Saving album: {}", scrobble_record.album.magenta()); 341 + tracing::info!(name = %scrobble_record.album, "Saving new album"); 349 342 350 343 let uri: Option<String> = None; 351 344 let artist_uri: Option<String> = None; ··· 402 395 .await?; 403 396 404 397 if !artists.is_empty() { 405 - println!("Artist already exists: {}", artists[0].name.magenta()); 398 + tracing::info!(name = %scrobble_record.album_artist, "Artist already exists"); 406 399 return Ok(artists[0].xata_id.clone()); 407 400 } 408 401 409 - println!("Saving artist: {}", scrobble_record.album_artist.magenta()); 402 + tracing::info!(name = %scrobble_record.album_artist, "Saving new artist"); 410 403 411 404 let uri: Option<String> = None; 412 405 let picture = ""; ··· 450 443 .await?; 451 444 452 445 if !album_tracks.is_empty() { 453 - println!( 454 - "Album track already exists: {}", 455 - format!("{} - {}", album_id, track_id).magenta() 456 - ); 446 + tracing::info!(album_id = %album_id, track_id = %track_id, "Album track already exists"); 457 447 return Ok(()); 458 448 } 459 449 460 - println!( 461 - "Saving album track: {}", 462 - format!("{} - {}", album_id, track_id).magenta() 463 - ); 450 + tracing::info!(album_id = %album_id, track_id = %track_id, "Saving album track"); 464 451 465 452 sqlx::query( 466 453 r#" ··· 492 479 .await?; 493 480 494 481 if !artist_tracks.is_empty() { 495 - println!( 496 - "Artist track already exists: {}", 497 - format!("{} - {}", artist_id, track_id).magenta() 498 - ); 482 + tracing::info!(artist_id = %artist_id, track_id = %track_id, "Artist track already exists"); 499 483 return Ok(()); 500 484 } 501 485 502 - println!( 503 - "Saving artist track: {}", 504 - format!("{} - {}", artist_id, track_id).magenta() 505 - ); 486 + tracing::info!(artist_id = %artist_id, track_id = %track_id, "Saving artist track"); 506 487 507 488 sqlx::query( 508 489 r#" ··· 534 515 .await?; 535 516 536 517 if !artist_albums.is_empty() { 537 - println!( 538 - "Artist album already exists: {}", 539 - format!("{} - {}", artist_id, album_id).magenta() 540 - ); 518 + tracing::info!(artist_id = %artist_id, album_id = %album_id, "Artist album already exists"); 541 519 return Ok(()); 542 520 } 543 521 544 - println!( 545 - "Saving artist album: {}", 546 - format!("{} - {}", artist_id, album_id).magenta() 547 - ); 522 + tracing::info!(artist_id = %artist_id, album_id = %album_id, "Saving artist album"); 548 523 549 524 sqlx::query( 550 525 r#" ··· 585 560 586 561 match artists.is_empty() { 587 562 true => { 588 - println!("Saving artist: {}", record.name.magenta()); 563 + tracing::info!(name = %record.name, "Artist not found in database, inserting new artist"); 589 564 let did = users[0].did.clone(); 590 565 sqlx::query( 591 566 r#" ··· 632 607 .await?; 633 608 634 609 if !user_artists.is_empty() { 635 - println!( 636 - "User artist already exists: {}", 637 - format!("{} - {}", user_id, artist_id).magenta() 638 - ); 610 + tracing::info!(user_id = %user_id, artist_id = %artist_id, "Updating user artist"); 639 611 sqlx::query( 640 612 r#" 641 613 UPDATE user_artists ··· 652 624 return Ok(()); 653 625 } 654 626 655 - println!( 656 - "Saving user artist: {}", 657 - format!("{} - {}", user_id, artist_id).magenta() 658 - ); 627 + tracing::info!(user_id = %user_id, artist_id = %artist_id, "Inserting user artist"); 659 628 660 629 sqlx::query( 661 630 r#" ··· 699 668 700 669 match albums.is_empty() { 701 670 true => { 702 - println!("Saving album: {}", record.title.magenta()); 671 + tracing::info!(title = %record.title, artist = %record.artist, "Album not found in database, inserting new album"); 703 672 let did = users[0].did.clone(); 704 673 sqlx::query( 705 674 r#" ··· 752 721 .await?; 753 722 754 723 if !user_albums.is_empty() { 755 - println!( 756 - "User album already exists: {}", 757 - format!("{} - {}", user_id, album_id).magenta() 758 - ); 724 + tracing::info!(user_id = %user_id, album_id = %album_id, "Updating user album"); 759 725 sqlx::query( 760 726 r#" 761 727 UPDATE user_albums ··· 772 738 return Ok(()); 773 739 } 774 740 775 - println!( 776 - "Saving user album: {}", 777 - format!("{} - {}", user_id, album_id).magenta() 778 - ); 741 + tracing::info!(user_id = %user_id, album_id = %album_id, "Inserting user album"); 779 742 780 743 sqlx::query( 781 744 r#" ··· 822 785 823 786 match tracks.is_empty() { 824 787 true => { 825 - println!("Saving track: {}", record.title.magenta()); 788 + tracing::info!(title = %record.title, artist = %record.artist, album = %record.album, "Track not found in database, inserting new track"); 826 789 let did = users[0].did.clone(); 827 790 sqlx::query( 828 791 r#" ··· 894 857 .await?; 895 858 896 859 if !user_tracks.is_empty() { 897 - println!( 898 - "User track already exists: {}", 899 - format!("{} - {}", user_id, track_id).magenta() 900 - ); 860 + tracing::info!(user_id = %user_id, track_id = %track_id, "Updating user track"); 901 861 sqlx::query( 902 862 r#" 903 863 UPDATE user_tracks ··· 914 874 return Ok(()); 915 875 } 916 876 917 - println!( 918 - "Saving user track: {}", 919 - format!("{} - {}", user_id, track_id).magenta() 920 - ); 877 + tracing::info!(user_id = %user_id, track_id = %track_id, "Inserting user track"); 921 878 922 879 sqlx::query( 923 880 r#" ··· 954 911 .await?; 955 912 956 913 if artists.is_empty() { 957 - println!("Artist not found: {}", record.name.magenta()); 914 + tracing::warn!(name = %record.name, "Artist not found in database"); 958 915 return Ok(()); 959 916 } 960 917 ··· 1023 980 .fetch_all(&mut **tx) 1024 981 .await?; 1025 982 if albums.is_empty() { 1026 - println!("Album not found: {}", record.title.magenta()); 983 + tracing::warn!(title = %record.title, "Album not found in database"); 1027 984 return Ok(()); 1028 985 } 1029 986 let album_id = &albums[0].xata_id; ··· 1082 1039 .await?; 1083 1040 1084 1041 if tracks.is_empty() { 1085 - println!("Track not found: {}", record.title.magenta()); 1042 + tracing::warn!(title = %record.title, "Track not found in database"); 1086 1043 return Ok(()); 1087 1044 } 1088 1045
+6 -9
crates/jetstream/src/subscriber.rs
··· 40 40 let pool = Arc::new(Mutex::new(pool)); 41 41 42 42 let (mut ws_stream, _) = connect_async(&self.service_url).await?; 43 - println!( 44 - "Connected to jetstream at {}", 45 - self.service_url.bright_green() 46 - ); 43 + tracing::info!(url = %self.service_url.bright_green(), "Connected to jetstream at"); 47 44 48 45 while let Some(msg) = ws_stream.next().await { 49 46 match msg { 50 47 Ok(msg) => { 51 48 if let Err(e) = handle_message(state.clone(), pool.clone(), msg).await { 52 - eprintln!("Error handling message: {}", e); 49 + tracing::error!(error = %e, "Error handling message"); 53 50 } 54 51 } 55 52 Err(e) => { 56 - eprintln!("WebSocket error: {}", e); 53 + tracing::error!(error = %e, "WebSocket error"); 57 54 break; 58 55 } 59 56 } ··· 76 73 return Ok::<(), Error>(()); 77 74 } 78 75 79 - println!("Received message: {:#?}", message); 76 + tracing::info!(message = %text.bright_green(), "Received message"); 80 77 if let Some(commit) = message.commit { 81 78 match save_scrobble(state, pool, &message.did, commit).await { 82 79 Ok(_) => { 83 - println!("Scrobble saved successfully"); 80 + tracing::info!(user_id = %message.did.bright_green(), "Scrobble saved successfully"); 84 81 } 85 82 Err(e) => { 86 - eprintln!("Error saving scrobble: {}", e); 83 + tracing::error!(error = %e, "Error saving scrobble"); 87 84 } 88 85 } 89 86 }
+2 -2
crates/jetstream/src/webhook/discord/mod.rs
··· 37 37 embeds: Vec<DiscordEmbed>, 38 38 ) -> reqwest::Result<()> { 39 39 if discord_webhook_url.is_empty() { 40 - println!("DISCORD_WEBHOOK_URL is not set, skipping webhook post"); 40 + tracing::warn!("DISCORD_WEBHOOK_URL is not set, skipping webhook post"); 41 41 return Ok(()); 42 42 } 43 43 ··· 48 48 let res = http.post(discord_webhook_url).json(&body).send().await?; 49 49 if !res.status().is_success() { 50 50 let text = res.text().await.unwrap_or_default(); 51 - eprintln!("Failed to post to Discord webhook: {}", text); 51 + tracing::error!(error = %text, "Failed to post to Discord webhook"); 52 52 } 53 53 Ok(()) 54 54 }
+2 -2
crates/jetstream/src/webhook_worker.rs
··· 79 79 } 80 80 Ok(None) => break, 81 81 Err(e) => { 82 - eprintln!("Failed to pop from Redis: {}", e); 82 + tracing::error!(error = %e, "Failed to pop from Redis"); 83 83 break; 84 84 } 85 85 } ··· 93 93 tokens -= 1; 94 94 95 95 if let Err(e) = discord::post_embeds(&http, &discord_webhook_url, embeds).await { 96 - eprintln!("Failed to post to Discord webhook: {}", e); 96 + tracing::error!(error = %e, "Failed to post to Discord webhook"); 97 97 } 98 98 } 99 99 }
+1 -1
crates/scrobbler/src/auth.rs
··· 37 37 let expected_password = md5::compute(expected_password); 38 38 let expected_password = format!("{:x}", expected_password); 39 39 if expected_password != password_md5 { 40 - println!("{} != {}", expected_password, password_md5); 40 + tracing::error!(expected = %expected_password, provided = %password_md5, "Invalid password"); 41 41 return Err(Error::msg("Invalid password")); 42 42 } 43 43 Ok(())
+1 -1
crates/scrobbler/src/handlers/v1/nowplaying.rs
··· 18 18 let a = form.get("a").unwrap().to_string(); 19 19 let t = form.get("t").unwrap().to_string(); 20 20 21 - println!("Now playing: {} - {} {}", a, t, s.cyan()); 21 + tracing::info!(artist = %a, track = %t, user = %s.cyan(), "Now playing"); 22 22 23 23 let user_id = verify_session_id(cache, &s); 24 24 if let Err(e) = user_id {
+5 -6
crates/scrobbler/src/handlers/v1/submission.rs
··· 1 + use actix_web::HttpResponse; 2 + use anyhow::Error; 3 + use serde_json::json; 4 + use std::{collections::BTreeMap, sync::Arc}; 1 5 2 6 3 7 ··· 21 25 22 26 23 27 24 - 25 - 26 - 27 - 28 - 29 28 } 30 29 31 30 let user_id = user_id.unwrap(); 32 - println!("Submission: {} - {} {} {} {}", a, t, i, user_id, s.cyan()); 31 + tracing::info!(artist = %a, track = %t, timestamp = %i, user_id = %user_id, "Submission"); 33 32 34 33 match scrobble_v1(pool, cache, &form).await { 35 34 Ok(_) => Ok(HttpResponse::Ok().body("OK\n")),
+1 -4
crates/scrobbler/src/lib.rs
··· 56 56 .parse::<u16>() 57 57 .unwrap_or(7882); 58 58 59 - println!( 60 - "Starting Scrobble server @ {}", 61 - format!("{}:{}", host, port).green() 62 - ); 59 + tracing::info!(url = %format!("http://{}:{}", host, port).bright_green(), "Starting Scrobble server @"); 63 60 64 61 let limiter = web::Data::new( 65 62 Limiter::builder("redis://127.0.0.1")
+2 -8
crates/scrobbler/src/listenbrainz/core/submit.rs
··· 17 17 token: &str, 18 18 ) -> Result<HttpResponse, Error> { 19 19 if payload.listen_type != "playing_now" { 20 - println!("skipping listen type: {}", payload.listen_type.cyan()); 20 + tracing::info!(listen_type = %payload.listen_type.cyan(), "Skipping listen type"); 21 21 return Ok(HttpResponse::Ok().json(json!({ 22 22 "status": "ok", 23 23 "payload": { ··· 62 62 63 63 cache.del(&format!("listenbrainz:cache:{}:{}:{}", artist, track, did))?; 64 64 65 - println!( 66 - "Retryable error on attempt {}/{}: {}", 67 - attempt, 68 - RETRIES, 69 - e.to_string().yellow() 70 - ); 71 - println!("{:#?}", payload); 65 + tracing::error!(error = %e, attempt = attempt, "Retryable error submitting listens for {} - {} (attempt {}/{})", artist, track, attempt, RETRIES); 72 66 73 67 if attempt == RETRIES { 74 68 return Ok(HttpResponse::BadRequest().json(serde_json::json!({
+1 -1
crates/scrobbler/src/listenbrainz/core/validate_token.rs
··· 12 12 }, 13 13 }))), 14 14 Err(e) => { 15 - println!("Error validating token: {}", e); 15 + tracing::error!(error = %e, "Failed to validate token"); 16 16 Ok(HttpResponse::BadRequest().json(serde_json::json!({ 17 17 "error": 4, 18 18 "message": format!("Failed to validate token: {}", e)
+12 -13
crates/scrobbler/src/listenbrainz/handlers.rs
··· 58 58 let body = String::from_utf8_lossy(&payload); 59 59 let req = serde_json::from_str::<SubmitListensRequest>(&body) 60 60 .map_err(|e| { 61 - println!("{}", body); 62 - println!("Error parsing request body: {}", e); 61 + tracing::error!(body = %body, error = %e, "Error parsing request body"); 63 62 e 64 63 }) 65 64 .map_err(actix_web::error::ErrorBadRequest)?; ··· 116 115 })); 117 116 } 118 117 Err(e) => { 119 - println!("Error validating token: {}", e); 118 + tracing::error!(error = %e, "Error validating token"); 120 119 return HttpResponse::InternalServerError().finish(); 121 120 } 122 121 } ··· 127 126 query: web::Query<String>, 128 127 data: web::Data<Arc<Pool<Postgres>>>, 129 128 ) -> impl Responder { 130 - let pool = data.get_ref(); 129 + let _pool = data.get_ref(); 131 130 let query = query.into_inner(); 132 131 133 132 match search_users(&query).await { 134 133 Ok(users) => HttpResponse::Ok().json(users), 135 134 Err(e) => { 136 - println!("Error searching users: {}", e); 135 + tracing::error!(error = %e, "Error searching users"); 137 136 HttpResponse::InternalServerError().finish() 138 137 } 139 138 } ··· 145 144 match get_listens(&user_name).await { 146 145 Ok(listens) => HttpResponse::Ok().json(listens), 147 146 Err(e) => { 148 - println!("Error getting listens for user {}: {}", user_name, e); 147 + tracing::error!(error = %e, "Error getting listens for user {}", user_name); 149 148 HttpResponse::InternalServerError().finish() 150 149 } 151 150 } ··· 157 156 match get_listen_count(&user_name).await { 158 157 Ok(count) => HttpResponse::Ok().json(count), 159 158 Err(e) => { 160 - println!("Error getting listen count for user {}: {}", user_name, e); 159 + tracing::error!(error = %e, "Error getting listen count for user {}", user_name); 161 160 HttpResponse::InternalServerError().finish() 162 161 } 163 162 } ··· 169 168 match get_playing_now(&user_name).await { 170 169 Ok(playing_now) => HttpResponse::Ok().json(playing_now), 171 170 Err(e) => { 172 - println!("Error getting playing now for user {}: {}", user_name, e); 171 + tracing::error!(error = %e, "Error getting playing now for user {}", user_name); 173 172 HttpResponse::InternalServerError().finish() 174 173 } 175 174 } ··· 181 180 match get_top_artists(&user_name).await { 182 181 Ok(artists) => HttpResponse::Ok().json(artists), 183 182 Err(e) => { 184 - println!("Error getting top artists: {}", e); 183 + tracing::error!(error = %e, "Error getting top artists"); 185 184 HttpResponse::InternalServerError().finish() 186 185 } 187 186 } ··· 193 192 match get_top_releases(&user_name).await { 194 193 Ok(releases) => HttpResponse::Ok().json(releases), 195 194 Err(e) => { 196 - println!("Error getting top releases: {}", e); 195 + tracing::error!(error = %e, "Error getting top releases"); 197 196 HttpResponse::InternalServerError().finish() 198 197 } 199 198 } ··· 205 204 match get_top_recordings(&user_name).await { 206 205 Ok(recordings) => HttpResponse::Ok().json(recordings), 207 206 Err(e) => { 208 - println!("Error getting sitewide recordings: {}", e); 207 + tracing::error!(error = %e, "Error getting top recordings"); 209 208 HttpResponse::InternalServerError().finish() 210 209 } 211 210 } ··· 217 216 match get_top_release_groups(&user_name).await { 218 217 Ok(release_groups) => HttpResponse::Ok().json(release_groups), 219 218 Err(e) => { 220 - println!("Error getting top release groups: {}", e); 219 + tracing::error!(error = %e, "Error getting top release groups"); 221 220 HttpResponse::InternalServerError().finish() 222 221 } 223 222 } ··· 229 228 match get_top_recordings(&user_name).await { 230 229 Ok(recordings) => HttpResponse::Ok().json(recordings), 231 230 Err(e) => { 232 - println!("Error getting top recordings: {}", e); 231 + tracing::error!(error = %e, "Error getting top recordings"); 233 232 HttpResponse::InternalServerError().finish() 234 233 } 235 234 }
-66
crates/scrobbler/src/main.rs
··· 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 - 21 - 22 - 23 - 24 - 25 - 26 - 27 - 28 - 29 - 30 - 31 - 32 - 33 - 34 - 35 - 36 - 37 - 38 - 39 - 40 - 41 - 42 - 43 - 44 - 45 - 46 - 47 - 48 - 49 - 50 - 51 - 52 - 53 - 54 - 55 - 56 - 57 - 58 - .parse::<u16>() 59 - .unwrap_or(7882); 60 - 61 - println!( 62 - "Starting Scrobble server @ {}", 63 - format!("{}:{}", host, port).green() 64 - ); 65 - 66 - let limiter = web::Data::new(
+3 -4
crates/scrobbler/src/rocksky.rs
··· 25 25 let token = generate_token(did)?; 26 26 let client = Client::new(); 27 27 28 - println!("Scrobbling track: \n {:#?}", track); 28 + tracing::info!(did = %did, track = ?track, "Scrobbling track"); 29 29 30 30 let response = client 31 31 .post(&format!("{}/now-playing", ROCKSKY_API)) ··· 35 35 .await?; 36 36 37 37 let status = response.status(); 38 - println!("Response status: {}", status); 38 + tracing::info!(did = %did, artist = %track.artist, track = %track.title, status = %status, "Scrobble response"); 39 39 if !status.is_success() { 40 40 let response_text = response.text().await?; 41 - println!("did: {}", did); 42 - println!("Failed to scrobble track: {}", response_text); 41 + tracing::error!(did = %did, response = %response_text, "Failed to scrobble track"); 43 42 return Err(Error::msg(format!( 44 43 "Failed to scrobble track: {}", 45 44 response_text
+25 -56
crates/scrobbler/src/scrobbler.rs
··· 1 + use std::{collections::BTreeMap, env}; 1 2 3 + use anyhow::Error; 4 + use rand::Rng; 5 + use sqlx::{Pool, Postgres}; 2 6 3 7 4 8 ··· 125 129 126 130 127 131 128 - 129 - 130 - 131 - 132 - 133 132 ); 134 133 let cached = cache.get(&key)?; 135 134 if cached.is_some() { 136 - println!("{}", format!("Cached: {}", key).yellow()); 135 + tracing::info!(key = %key, "Cached:"); 137 136 let track = serde_json::from_str::<Track>(&cached.unwrap())?; 138 137 scrobble.album = Some(track.album.clone()); 139 138 rocksky::scrobble(cache, &did, track, scrobble.timestamp).await?; ··· 144 143 if let Some(mbid) = &scrobble.mbid { 145 144 // let result = repo::track::get_track_by_mbid(pool, mbid).await?; 146 145 let result = mb_client.get_recording(mbid).await?; 147 - println!("{}", "Musicbrainz (mbid)".yellow()); 146 + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (mbid)"); 148 147 scrobble.album = Some(Track::from(result.clone()).album); 149 148 rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; 150 149 tokio::time::sleep(std::time::Duration::from_secs(1)).await; ··· 154 153 let result = repo::track::get_track(pool, &scrobble.track, &scrobble.artist).await?; 155 154 156 155 if let Some(track) = result { 157 - println!("{}", "Xata (track)".yellow()); 156 + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Xata (track)"); 158 157 scrobble.album = Some(track.album.clone()); 159 158 let album = repo::album::get_album_by_track_id(pool, &track.xata_id).await?; 160 159 let artist = repo::artist::get_artist_by_track_id(pool, &track.xata_id).await?; ··· 204 203 .await?; 205 204 206 205 if let Some(track) = result.tracks.items.first() { 207 - println!("{}", "Spotify (track)".yellow()); 206 + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Spotify (track)"); 208 207 scrobble.album = Some(track.album.name.clone()); 209 208 let mut track = track.clone(); 210 209 ··· 232 231 233 232 if let Some(recording) = result.recordings.first() { 234 233 let result = mb_client.get_recording(&recording.id).await?; 235 - println!("{}", "Musicbrainz (recording)".yellow()); 234 + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (recording)"); 236 235 scrobble.album = Some(Track::from(result.clone()).album); 237 236 rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; 238 237 tokio::time::sleep(std::time::Duration::from_secs(1)).await; 239 238 continue; 240 239 } 241 240 242 - println!( 243 - "{} {} - {}, skipping", 244 - "Track not found: ".yellow(), 245 - scrobble.artist, 246 - scrobble.track 247 - ); 241 + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Track not found, skipping"); 248 242 scrobble.ignored = Some(true); 249 243 } 250 244 ··· 313 307 ); 314 308 let cached = cache.get(&key)?; 315 309 if cached.is_some() { 316 - println!("{}", format!("Cached: {}", key).yellow()); 310 + tracing::info!(key = %key, "Cached:"); 317 311 let track = serde_json::from_str::<Track>(&cached.unwrap())?; 318 312 scrobble.album = Some(track.album.clone()); 319 313 rocksky::scrobble(cache, &did, track, scrobble.timestamp).await?; ··· 324 318 if let Some(mbid) = &scrobble.mbid { 325 319 // let result = repo::track::get_track_by_mbid(pool, mbid).await?; 326 320 let result = mb_client.get_recording(mbid).await?; 327 - println!("{}", "Musicbrainz (mbid)".yellow()); 321 + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (mbid)"); 328 322 scrobble.album = Some(Track::from(result.clone()).album); 329 323 rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; 330 324 tokio::time::sleep(std::time::Duration::from_secs(1)).await; ··· 334 328 let result = repo::track::get_track(pool, &scrobble.track, &scrobble.artist).await?; 335 329 336 330 if let Some(track) = result { 337 - println!("{}", "Xata (track)".yellow()); 331 + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Xata (track)"); 338 332 scrobble.album = Some(track.album.clone()); 339 333 let album = repo::album::get_album_by_track_id(pool, &track.xata_id).await?; 340 334 let artist = repo::artist::get_artist_by_track_id(pool, &track.xata_id).await?; ··· 384 378 .await?; 385 379 386 380 if let Some(track) = result.tracks.items.first() { 387 - println!("{}", "Spotify (track)".yellow()); 381 + tracing::info!(artist = %scrobble.artist, track = %scrobble.track, "Spotify (track)"); 388 382 scrobble.album = Some(track.album.name.clone()); 389 383 let mut track = track.clone(); 390 384 ··· 412 406 413 407 if let Some(recording) = result.recordings.first() { 414 408 let result = mb_client.get_recording(&recording.id).await?; 415 - println!("{}", "Musicbrainz (recording)".yellow()); 409 + tracing::info!(%scrobble.artist, %scrobble.track, "Musicbrainz (recording)"); 416 410 scrobble.album = Some(Track::from(result.clone()).album); 417 411 rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; 418 412 tokio::time::sleep(std::time::Duration::from_secs(1)).await; 419 413 return Ok(()); 420 414 } 421 415 422 - println!( 423 - "{} {} - {}, skipping", 424 - "Track not found: ".yellow(), 425 - artist, 426 - track 427 - ); 416 + tracing::info!(artist = %artist, track = %track, "Track not found, skipping"); 428 417 429 418 Ok(()) 430 419 } ··· 435 424 req: &SubmitListensRequest, 436 425 token: &str, 437 426 ) -> Result<(), Error> { 438 - println!("Listenbrainz\n{:#?}", req); 427 + tracing::info!(req = ?req, "Listenbrainz submission"); 439 428 440 429 if req.payload.is_empty() { 441 430 return Err(Error::msg("No payload found")); ··· 481 470 .get(&format!("listenbrainz:cache:{}:{}:{}", artist, track, did))? 482 471 .is_some() 483 472 { 484 - println!( 485 - "{} {} - {}, recently scrobbled", 486 - "Already scrobbled: ".yellow(), 487 - artist, 488 - track 489 - ); 473 + tracing::info!(artist= %artist, track = %track, "Recently scrobbled, skipping"); 490 474 return Ok(()); 491 475 } 492 476 ··· 496 480 .get(&format!("{}:current", spotify_user.email))? 497 481 .is_some() 498 482 { 499 - println!( 500 - "{} {} - {}, currently scrobbling, skipping", 501 - "Currently scrobbling: ".yellow(), 502 - artist, 503 - track 504 - ); 483 + tracing::info!(artist= %artist, track = %track, "Currently scrobbling, skipping"); 505 484 return Ok(()); 506 485 } 507 486 } 508 487 509 488 if cache.get(&format!("nowplaying:{}", did))?.is_some() { 510 - println!( 511 - "{} {} - {}, currently scrobbling, skipping", 512 - "Currently scrobbling: ".yellow(), 513 - artist, 514 - track 515 - ); 489 + tracing::info!(artist= %artist, track = %track, "Currently scrobbling, skipping"); 516 490 return Ok(()); 517 491 } 518 492 ··· 565 539 ); 566 540 let cached = cache.get(&key)?; 567 541 if cached.is_some() { 568 - println!("{}", format!("Cached: {}", key).yellow()); 542 + tracing::info!(key = %key, "Cached"); 569 543 let track = serde_json::from_str::<Track>(&cached.unwrap())?; 570 544 scrobble.album = Some(track.album.clone()); 571 545 rocksky::scrobble(cache, &did, track, scrobble.timestamp).await?; ··· 576 550 if let Some(mbid) = &scrobble.mbid { 577 551 // let result = repo::track::get_track_by_mbid(pool, mbid).await?; 578 552 let result = mb_client.get_recording(mbid).await?; 579 - println!("{}", "Musicbrainz (mbid)".yellow()); 553 + tracing::info!("Musicbrainz (mbid)"); 580 554 scrobble.album = Some(Track::from(result.clone()).album); 581 555 rocksky::scrobble(cache, &did, result.into(), scrobble.timestamp).await?; 582 556 tokio::time::sleep(std::time::Duration::from_secs(1)).await; ··· 586 560 let result = repo::track::get_track(pool, &scrobble.track, &scrobble.artist).await?; 587 561 588 562 if let Some(track) = result { 589 - println!("{}", "Xata (track)".yellow()); 563 + tracing::info!("Xata (track)"); 590 564 scrobble.album = Some(track.album.clone()); 591 565 let album = repo::album::get_album_by_track_id(pool, &track.xata_id).await?; 592 566 let artist = repo::artist::get_artist_by_track_id(pool, &track.xata_id).await?; ··· 636 610 .await?; 637 611 638 612 if let Some(track) = result.tracks.items.first() { 639 - println!("{}", "Spotify (track)".yellow()); 613 + tracing::info!("Spotify (track)"); 640 614 scrobble.album = Some(track.album.name.clone()); 641 615 let mut track = track.clone(); 642 616 ··· 676 650 } 677 651 */ 678 652 679 - println!( 680 - "{} {} - {}, skipping", 681 - "Track not found: ".yellow(), 682 - artist, 683 - track 684 - ); 653 + tracing::warn!(artist = %artist, track = %track, "Track not found, skipping"); 685 654 686 655 Ok(()) 687 656 }
+2 -10
crates/scrobbler/src/spotify/client.rs
··· 36 36 let data = response.text().await?; 37 37 38 38 if data == "Too many requests" { 39 - println!( 40 - "> retry-after {}", 41 - headers.get("retry-after").unwrap().to_str().unwrap() 42 - ); 43 - println!("> {} [get_album]", data); 39 + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_album"); 44 40 return Ok(None); 45 41 } 46 42 ··· 56 52 let data = response.text().await?; 57 53 58 54 if data == "Too many requests" { 59 - println!( 60 - "> retry-after {}", 61 - headers.get("retry-after").unwrap().to_str().unwrap() 62 - ); 63 - println!("> {} [get_artist]", data); 55 + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_artist"); 64 56 return Ok(None); 65 57 } 66 58
+7 -14
crates/webscrobbler/src/handlers.rs
··· 32 32 req: HttpRequest, 33 33 ) -> Result<impl Responder, actix_web::Error> { 34 34 let id = req.match_info().get("id").unwrap(); 35 - println!("Received scrobble for ID: {}", id.cyan()); 35 + tracing::info!(id = %id.bright_green(), "Received scrobble"); 36 36 37 37 let pool = data.get_ref().clone(); 38 38 ··· 50 50 let body = read_payload!(payload); 51 51 let params = serde_json::from_slice::<ScrobbleRequest>(&body).map_err(|err| { 52 52 let body = String::from_utf8_lossy(&body); 53 - println!("Failed to parse JSON: {}", body); 54 - println!("Failed to parse JSON: {}", err); 53 + tracing::error!(body = %body, error = %err, "Failed to parse JSON"); 55 54 actix_web::error::ErrorBadRequest(format!("Failed to parse JSON: {}", err)) 56 55 })?; 57 56 58 - println!("Parsed scrobble request: {:#?}", params); 57 + tracing::info!(params = ?params, "Parsed scrobble request"); 59 58 60 59 if params.event_name != "scrobble" { 61 - println!("Skipping non-scrobble event: {}", params.event_name.green()); 60 + tracing::info!(event_name = %params.event_name.cyan(), "Skipping non-scrobble event"); 62 61 return Ok(HttpResponse::Ok().body("Skipping non-scrobble event")); 63 62 } 64 63 ··· 75 74 })?; 76 75 77 76 if spotify_token.is_some() { 78 - println!("User has a Spotify token, skipping scrobble"); 77 + tracing::info!("User has a Spotify token, skipping scrobble"); 79 78 return Ok(HttpResponse::Ok().body("User has a Spotify token, skipping scrobble")); 80 79 } 81 80 } ··· 91 90 )); 92 91 93 92 if cached.is_err() { 94 - println!( 95 - "Failed to check cache for Emby scrobble: {}", 96 - cached.unwrap_err() 97 - ); 93 + tracing::error!(artist = %artist, track = %track, error = %cached.unwrap_err(), "Failed to check cache for Emby scrobble"); 98 94 return Ok(HttpResponse::Ok().body("Failed to check cache for Emby scrobble")); 99 95 } 100 96 101 97 if cached.unwrap().is_some() { 102 - println!( 103 - "Skipping duplicate scrobble for Emby: {} - {}", 104 - artist, track 105 - ); 98 + tracing::warn!(artist = %artist, track = %track, "Skipping duplicate scrobble for Emby"); 106 99 return Ok(HttpResponse::Ok().body("Skipping duplicate scrobble for Emby")); 107 100 } 108 101 }
+1 -4
crates/webscrobbler/src/lib.rs
··· 44 44 .parse::<u16>() 45 45 .unwrap_or(7883); 46 46 47 - println!( 48 - "Starting WebScrobbler Webhook @ {}", 49 - format!("{}:{}", host, port).green() 50 - ); 47 + tracing::info!(url = %format!("http://{}:{}", host, port).bright_green(), "Starting WebScrobbler server @"); 51 48 52 49 let limiter = web::Data::new( 53 50 Limiter::builder("redis://127.0.0.1")
+4 -8
crates/webscrobbler/src/rocksky.rs
··· 1 1 use anyhow::Error; 2 - use owo_colors::OwoColorize; 3 2 use reqwest::Client; 4 3 5 4 use crate::{auth::generate_token, cache::Cache, types::Track}; ··· 26 25 let token = generate_token(did)?; 27 26 let client = Client::new(); 28 27 29 - println!("Scrobbling track: \n {:#?}", track); 28 + tracing::info!(did = %did, track = ?track, "Scrobbling track"); 30 29 31 30 let response = client 32 31 .post(&format!("{}/now-playing", ROCKSKY_API)) ··· 36 35 .await?; 37 36 38 37 if !response.status().is_success() { 39 - println!( 40 - "Failed to scrobble track: {}", 41 - response.status().to_string() 42 - ); 38 + tracing::error!(did = %did, artist = %track.artist, track = %track.title, status = %response.status(), "Failed to scrobble track"); 43 39 let text = response.text().await?; 44 - println!("Response: {}", text); 40 + tracing::error!(did = %did, response = %text, "Response"); 45 41 return Err(Error::msg(format!("Failed to scrobble track: {}", text))); 46 42 } 47 43 48 - println!("Scrobbled track: {}", track.title.green()); 44 + tracing::info!(did = %did, artist = %track.artist, track = %track.title, "Scrobbled track"); 49 45 50 46 Ok(()) 51 47 }
+4 -9
crates/webscrobbler/src/scrobbler.rs
··· 34 34 35 35 let cached = cache.get(&key)?; 36 36 if cached.is_some() { 37 - println!("{}", format!("Cached: {}", key).yellow()); 37 + tracing::info!(artist = %scrobble.data.song.parsed.artist, track = %scrobble.data.song.parsed.track, "Using cached track"); 38 38 let track = serde_json::from_str::<Track>(&cached.unwrap())?; 39 39 rocksky::scrobble(cache, &did, track, scrobble.time).await?; 40 40 tokio::time::sleep(std::time::Duration::from_secs(1)).await; ··· 127 127 let result = spotify_client.search(&query).await?; 128 128 129 129 if let Some(track) = result.tracks.items.first() { 130 - println!("{}", "Spotify (track)".yellow()); 130 + tracing::info!("Spotify (track)"); 131 131 let mut track = track.clone(); 132 132 133 133 if let Some(album) = spotify_client.get_album(&track.album.id).await? { ··· 154 154 155 155 if let Some(recording) = result.recordings.first() { 156 156 let result = mb_client.get_recording(&recording.id).await?; 157 - println!("{}", "Musicbrainz (recording)".yellow()); 157 + tracing::info!("Musicbrainz (recording)"); 158 158 rocksky::scrobble(cache, &did, result.into(), scrobble.time).await?; 159 159 tokio::time::sleep(std::time::Duration::from_secs(1)).await; 160 160 return Ok(()); 161 161 } 162 162 163 - println!( 164 - "{} {} - {}, skipping", 165 - "Track not found: ".yellow(), 166 - scrobble.data.song.parsed.artist, 167 - scrobble.data.song.parsed.track 168 - ); 163 + tracing::warn!(artist = %scrobble.data.song.parsed.artist, track = %scrobble.data.song.parsed.track, "Track not found, skipping"); 169 164 170 165 Ok(()) 171 166 }
+2 -10
crates/webscrobbler/src/spotify/client.rs
··· 36 36 let data = response.text().await?; 37 37 38 38 if data == "Too many requests" { 39 - println!( 40 - "> retry-after {}", 41 - headers.get("retry-after").unwrap().to_str().unwrap() 42 - ); 43 - println!("> {} [get_album]", data); 39 + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_album"); 44 40 return Ok(None); 45 41 } 46 42 ··· 56 52 let data = response.text().await?; 57 53 58 54 if data == "Too many requests" { 59 - println!( 60 - "> retry-after {}", 61 - headers.get("retry-after").unwrap().to_str().unwrap() 62 - ); 63 - println!("> {} [get_artist]", data); 55 + tracing::info!(retry_after = %headers.get("retry-after").unwrap().to_str().unwrap(), data = %data, "Rate limited on get_artist"); 64 56 return Ok(None); 65 57 } 66 58
-50
crates/analytics/src/main.rs
··· 1 - use core::create_tables; 2 - use std::{ 3 - env, 4 - sync::{Arc, Mutex}, 5 - }; 6 - 7 - use clap::Command; 8 - use cmd::{serve::serve, sync::sync}; 9 - use dotenv::dotenv; 10 - use duckdb::Connection; 11 - use sqlx::postgres::PgPoolOptions; 12 - 13 - pub mod cmd; 14 - pub mod core; 15 - pub mod handlers; 16 - pub mod subscriber; 17 - pub mod types; 18 - pub mod xata; 19 - 20 - fn cli() -> Command { 21 - Command::new("analytics") 22 - .version(env!("CARGO_PKG_VERSION")) 23 - .about("Rocksky Analytics CLI built with Rust and DuckDB") 24 - .subcommand(Command::new("sync").about("Sync data from Xata to DuckDB")) 25 - .subcommand(Command::new("serve").about("Serve the Rocksky Analytics API")) 26 - } 27 - 28 - #[tokio::main] 29 - async fn main() -> Result<(), Box<dyn std::error::Error>> { 30 - dotenv().ok(); 31 - 32 - let pool = PgPoolOptions::new() 33 - .max_connections(5) 34 - .connect(&env::var("XATA_POSTGRES_URL")?) 35 - .await?; 36 - let conn = Connection::open("./rocksky-analytics.ddb")?; 37 - 38 - create_tables(&conn).await?; 39 - 40 - let args = cli().get_matches(); 41 - let conn = Arc::new(Mutex::new(conn)); 42 - 43 - match args.subcommand() { 44 - Some(("sync", _)) => sync(conn, &pool).await?, 45 - Some(("serve", _)) => serve(conn).await?, 46 - _ => serve(conn).await?, 47 - } 48 - 49 - Ok(()) 50 - }
-37
crates/dropbox/src/main.rs
··· 1 - use clap::Command; 2 - use cmd::{scan::scan, serve::serve}; 3 - use dotenv::dotenv; 4 - 5 - pub mod client; 6 - pub mod cmd; 7 - pub mod consts; 8 - pub mod crypto; 9 - pub mod handlers; 10 - pub mod repo; 11 - pub mod scan; 12 - pub mod token; 13 - pub mod types; 14 - pub mod xata; 15 - 16 - fn cli() -> Command { 17 - Command::new("dropbox") 18 - .version(env!("CARGO_PKG_VERSION")) 19 - .about("Rocksky Dropbox Service") 20 - .subcommand(Command::new("scan").about("Scan Dropbox Music Folder")) 21 - .subcommand(Command::new("serve").about("Serve Rocksky Dropbox API")) 22 - } 23 - 24 - #[tokio::main] 25 - async fn main() -> Result<(), Box<dyn std::error::Error>> { 26 - dotenv().ok(); 27 - 28 - let args = cli().get_matches(); 29 - 30 - match args.subcommand() { 31 - Some(("scan", _)) => scan().await?, 32 - Some(("serve", _)) => serve().await?, 33 - _ => serve().await?, 34 - } 35 - 36 - Ok(()) 37 - }
-37
crates/googledrive/src/main.rs
··· 1 - use clap::Command; 2 - use cmd::{scan::scan, serve::serve}; 3 - use dotenv::dotenv; 4 - 5 - pub mod client; 6 - pub mod cmd; 7 - pub mod consts; 8 - pub mod crypto; 9 - pub mod handlers; 10 - pub mod repo; 11 - pub mod scan; 12 - pub mod token; 13 - pub mod types; 14 - pub mod xata; 15 - 16 - fn cli() -> Command { 17 - Command::new("googledrive") 18 - .version(env!("CARGO_PKG_VERSION")) 19 - .about("Rocksky Google Drive Service") 20 - .subcommand(Command::new("scan").about("Scan Google Drive Music Folder")) 21 - .subcommand(Command::new("serve").about("Serve Rocksky Google Drive API")) 22 - } 23 - 24 - #[tokio::main] 25 - async fn main() -> Result<(), Box<dyn std::error::Error>> { 26 - dotenv().ok(); 27 - 28 - let args = cli().get_matches(); 29 - 30 - match args.subcommand() { 31 - Some(("scan", _)) => scan().await?, 32 - Some(("serve", _)) => serve().await?, 33 - _ => serve().await?, 34 - } 35 - 36 - Ok(()) 37 - }
-37
crates/jetstream/src/main.rs
··· 1 - use std::{env, sync::Arc}; 2 - 3 - use dotenv::dotenv; 4 - use subscriber::ScrobbleSubscriber; 5 - use tokio::sync::Mutex; 6 - 7 - use crate::webhook_worker::AppState; 8 - 9 - pub mod profile; 10 - pub mod repo; 11 - pub mod subscriber; 12 - pub mod types; 13 - pub mod webhook; 14 - pub mod webhook_worker; 15 - pub mod xata; 16 - 17 - #[tokio::main] 18 - async fn main() -> Result<(), anyhow::Error> { 19 - dotenv()?; 20 - let jetstream_server = env::var("JETSTREAM_SERVER") 21 - .unwrap_or_else(|_| "wss://jetstream2.us-west.bsky.network".to_string()); 22 - let url = format!( 23 - "{}/subscribe?wantedCollections=app.rocksky.*", 24 - jetstream_server 25 - ); 26 - let subscriber = ScrobbleSubscriber::new(&url); 27 - 28 - let redis_url = env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379".to_string()); 29 - let redis = redis::Client::open(redis_url)?; 30 - let queue_key = 31 - env::var("WEBHOOK_QUEUE_KEY").unwrap_or_else(|_| "rocksky:webhook_queue".to_string()); 32 - 33 - let state = Arc::new(Mutex::new(AppState { redis, queue_key })); 34 - 35 - subscriber.run(state).await?; 36 - Ok(()) 37 - }
-65
crates/playlists/src/main.rs
··· 1 - use core::{create_tables, find_spotify_users, load_users, save_playlists}; 2 - use std::{ 3 - env, 4 - sync::{Arc, Mutex}, 5 - }; 6 - 7 - use anyhow::Error; 8 - use async_nats::connect; 9 - use dotenv::dotenv; 10 - use duckdb::Connection; 11 - use owo_colors::OwoColorize; 12 - use rocksky_playlists::subscriber::subscribe; 13 - use spotify::get_user_playlists; 14 - use sqlx::postgres::PgPoolOptions; 15 - 16 - pub mod core; 17 - pub mod crypto; 18 - pub mod spotify; 19 - pub mod types; 20 - pub mod xata; 21 - 22 - #[tokio::main] 23 - async fn main() -> Result<(), Error> { 24 - dotenv().ok(); 25 - 26 - let conn = Connection::open("./rocksky-playlists.ddb")?; 27 - let conn = Arc::new(Mutex::new(conn)); 28 - create_tables(conn.clone())?; 29 - 30 - subscribe(conn.clone()).await?; 31 - 32 - let pool = PgPoolOptions::new() 33 - .max_connections(5) 34 - .connect(&env::var("XATA_POSTGRES_URL")?) 35 - .await?; 36 - let users = find_spotify_users(&pool, 0, 100).await?; 37 - 38 - load_users(conn.clone(), &pool).await?; 39 - 40 - sqlx::query(r#" 41 - CREATE UNIQUE INDEX IF NOT EXISTS user_playlists_unique_index ON user_playlists (user_id, playlist_id) 42 - "#) 43 - .execute(&pool) 44 - .await?; 45 - let conn = conn.clone(); 46 - 47 - let addr = env::var("NATS_URL").unwrap_or_else(|_| "nats://localhost:4222".to_string()); 48 - let nc = connect(&addr).await?; 49 - let nc = Arc::new(Mutex::new(nc)); 50 - println!("Connected to NATS server at {}", addr.bright_green()); 51 - 52 - for user in users { 53 - let token = user.1.clone(); 54 - let did = user.2.clone(); 55 - let user_id = user.3.clone(); 56 - let playlists = get_user_playlists(token).await?; 57 - save_playlists(&pool, conn.clone(), nc.clone(), playlists, &user_id, &did).await?; 58 - } 59 - 60 - println!("Done!"); 61 - 62 - loop { 63 - tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; 64 - } 65 - }
-12
crates/webscrobbler/src/main.rs
··· 1 - use anyhow::Error; 2 - use dotenv::dotenv; 3 - use rocksky_webscrobbler::start_server; 4 - 5 - #[tokio::main] 6 - async fn main() -> Result<(), Error> { 7 - dotenv().ok(); 8 - 9 - start_server().await?; 10 - 11 - Ok(()) 12 - }

History

1 round 0 comments
sign up or login to add to the discussion
5 commits
expand
feat: update dependencies to include tracing and improve logging throughout the application
Refactor logging to use tracing instead of println and eprintln
feat: remove unused crate main files for analytics, dropbox, googledrive, jetstream, playlists, scrobbler, and webscrobbler
feat: remove unused binary entries for scrobbler and webscrobbler
feat: remove unused owo_colors dependency from submission and scrobbler modules
expand 0 comments
pull request successfully merged