@@ -263,6 +263,7 @@ impl<S: Sleeper> AsyncClient<S> {
263263 let url = format ! ( "{}{}" , self . url, path) ;
264264 let body = serialize :: < T > ( & body) . to_lower_hex_string ( ) ;
265265
266+ self . log_request ( & url, "POST" ) ;
266267 let response = self . client . post ( url) . body ( body) . send ( ) . await ?;
267268
268269 if !response. status ( ) . is_success ( ) {
@@ -466,6 +467,7 @@ impl<S: Sleeper> AsyncClient<S> {
466467 let mut attempts = 0 ;
467468
468469 loop {
470+ self . log_request ( url, "GET" ) ;
469471 match self . client . get ( url) . send ( ) . await ? {
470472 resp if attempts < self . max_retries && is_status_retryable ( resp. status ( ) ) => {
471473 S :: sleep ( delay) . await ;
@@ -476,6 +478,40 @@ impl<S: Sleeper> AsyncClient<S> {
476478 }
477479 }
478480 }
481+
482+ /// Lexe patch: Log every request, so we know
483+ ///
484+ /// 1) which endpoints we're calling,
485+ /// 2) how many requests we're making, and
486+ /// 3) which services these requests are sent to.
487+ ///
488+ /// TODO(max): Eventually this should be done with metrics, not logs.
489+ fn log_request ( & self , url : & str , method : & str ) {
490+ let base_url = & self . url ;
491+
492+ // For user privacy, log only the part of the path up to the first `/`.
493+ let path_prefix = path_prefix ( & self . url , url) ;
494+
495+ // "Esplora request: GET https://blockstream.info/api/address"
496+ // "Esplora request: POST https://mempool.space/api/tx"
497+ debug ! ( "Esplora request: {method} {base_url}/{path_prefix}" ) ;
498+ }
499+ }
500+
501+ /// `base_url`: "https://mempool.space/api"
502+ /// `url`: "/tx/foo"
503+ /// => `path_prefix`: "/tx"
504+ fn path_prefix < ' a > ( base_url : & str , url : & ' a str ) -> & ' a str {
505+ if url. len ( ) <= base_url. len ( ) + 1 {
506+ return url;
507+ }
508+
509+ let path = & url[ base_url. len ( ) + 1 ..] ;
510+ if let Some ( slash_idx) = path. find ( '/' ) {
511+ & url[ ..base_url. len ( ) + 1 + slash_idx]
512+ } else {
513+ url
514+ }
479515}
480516
481517fn is_status_retryable ( status : reqwest:: StatusCode ) -> bool {
@@ -498,3 +534,34 @@ impl Sleeper for DefaultSleeper {
498534 tokio:: time:: sleep ( dur)
499535 }
500536}
537+
538+ #[ cfg( test) ]
539+ mod test {
540+ use super :: * ;
541+
542+ /// $ cargo test test_sanitize -- --show-output
543+ #[ test]
544+ fn test_path_prefix ( ) {
545+ let base_url = "https://mempool.space/api" ;
546+ let test_cases = [
547+ [ "https://mempool.space" , "https://mempool.space" ] ,
548+ [ "https://mempool.space/api/" , "https://mempool.space/api/" ] ,
549+ [
550+ "https://mempool.space/api/tx" ,
551+ "https://mempool.space/api/tx" ,
552+ ] ,
553+ [
554+ "https://mempool.space/api/tx/foo" ,
555+ "https://mempool.space/api/tx" ,
556+ ] ,
557+ ] ;
558+
559+ for [ url, expected] in test_cases {
560+ let sanitized = path_prefix ( base_url, url) ;
561+ assert_eq ! ( sanitized, expected) ;
562+ println ! ( "Original URL: {url}" ) ;
563+ println ! ( "Sanitized: {sanitized}" ) ;
564+ println ! ( "---" ) ;
565+ }
566+ }
567+ }
0 commit comments