Răsfoiți Sursa

logger setup

Berke 1 an în urmă
părinte
comite
58eb2dd111

+ 2 - 1
.gitignore

@@ -1,4 +1,5 @@
 .DS_Store
 /target
 /.vscode
-dashboard_state.json
+*.json
+*.log

+ 11 - 0
Cargo.lock

@@ -1146,6 +1146,15 @@ dependencies = [
  "simd-adler32",
 ]
 
+[[package]]
+name = "fern"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee"
+dependencies = [
+ "log",
+]
+
 [[package]]
 name = "flate2"
 version = "1.0.30"
@@ -1805,6 +1814,7 @@ dependencies = [
  "bytes",
  "chrono",
  "fastwebsockets",
+ "fern",
  "futures",
  "futures-util",
  "hex",
@@ -1815,6 +1825,7 @@ dependencies = [
  "iced",
  "iced_futures 0.12.0",
  "iced_table",
+ "log",
  "native-tls",
  "reqwest",
  "rustc-hash 2.0.0",

+ 2 - 0
Cargo.toml

@@ -36,6 +36,8 @@ tokio-rustls = "0.24.0"
 webpki-roots = "0.23.0"
 uuid = { version = "1.10.0", features = ["v4"] }
 rustc-hash = "2.0.0"
+fern = "0.6.2"
+log = "0.4.22"
 [dependencies.async-tungstenite]
 version = "0.25"
 features = ["tokio-rustls-webpki-roots"]

+ 12 - 13
src/data_providers/binance/market_data.rs

@@ -191,7 +191,7 @@ fn feed_de(bytes: &Bytes) -> Result<StreamData> {
                         stream_type = Some(StreamWrapper::Kline);
                     },
 					_ => {
-                        eprintln!("Unknown stream name");
+                        log::warn!("Unknown stream name");
                     }
 				}
 			}
@@ -224,11 +224,11 @@ fn feed_de(bytes: &Bytes) -> Result<StreamData> {
                     return Ok(StreamData::Kline(ticker, kline_wrap.kline));
                 },
 				_ => {
-					eprintln!("Unknown stream type");
+					log::error!("Unknown stream type");
 				}
 			}
 		} else {
-			eprintln!("Unknown data: {:?}", k);
+			log::error!("Unknown data: {:?}", k);
 		}
 	}
 
@@ -270,7 +270,6 @@ async fn connect(domain: &str, streams: &str) -> Result<FragmentCollector<TokioI
 	let tls_stream: tokio_rustls::client::TlsStream<TcpStream> = tls_connector.connect(domain, tcp_stream).await?;
 
     let url = format!("wss://{}/stream?streams={}", &addr, streams);
-    println!("Connecting to {}", url);
 
 	let req: Request<Empty<Bytes>> = Request::builder()
 	.method("GET")
@@ -396,7 +395,7 @@ pub fn connect_market_stream(ticker: Ticker) -> impl Stream<Item = Event> {
                                             },
                                             StreamData::Depth(de_depth) => {
                                                 if already_fetching {
-                                                    println!("Already fetching...\n");
+                                                    log::warn!("Already fetching...\n");
     
                                                     continue;
                                                 }
@@ -408,7 +407,7 @@ pub fn connect_market_stream(ticker: Ticker) -> impl Stream<Item = Event> {
                                                 }
     
                                                 if prev_id == 0 && (de_depth.first_id > last_update_id + 1) || (last_update_id + 1 > de_depth.final_id) {
-                                                    println!("Out of sync at first event. Trying to resync...\n");
+                                                    log::warn!("Out of sync at first event. Trying to resync...\n");
     
                                                     let (tx, rx) = tokio::sync::oneshot::channel();
                                                     already_fetching = true;
@@ -487,23 +486,23 @@ pub fn connect_market_stream(ticker: Ticker) -> impl Stream<Item = Event> {
     
                                                     prev_id = de_depth.final_id;
                                                 } else {
-                                                    eprintln!("Out of sync...\n");
+                                                    log::error!("Out of sync...\n");
                                                 }
                                             },
                                             _ => {}
                                         }
                                     } else {
-                                        eprintln!("\nUnknown data: {:?}", &json_bytes);
+                                        log::error!("\nUnknown data: {:?}", &json_bytes);
                                     }
                                 }
                                 OpCode::Close => {
-                                    eprintln!("Connection closed");
+                                    log::error!("Connection closed");
                                     let _ = output.send(Event::Disconnected).await;
                                 }
                                 _ => {}
                             },
                             Err(e) => {
-                                println!("Error reading frame: {}", e);
+                                log::error!("Error reading frame: {}", e);
                             }
                         };
                     }
@@ -577,13 +576,13 @@ pub fn connect_kline_stream(streams: Vec<(Ticker, Timeframe)>) -> impl Stream<It
                                             let _ = output.send(Event::KlineReceived(ticker, kline, timeframe.1)).await;
                                         }
                                     } else {
-                                        eprintln!("\nUnknown data: {:?}", &json_bytes);
+                                        log::error!("\nUnknown data: {:?}", &json_bytes);
                                     }
                                 }
                                 _ => {}
                             }, 
                             Err(e) => {
-                                eprintln!("Error reading frame: {}", e);
+                                log::error!("Error reading frame: {}", e);
                             }
                         }
                     }
@@ -595,7 +594,7 @@ pub fn connect_kline_stream(streams: Vec<(Ticker, Timeframe)>) -> impl Stream<It
 
 fn str_f32_parse(s: &str) -> f32 {
     s.parse::<f32>().unwrap_or_else(|e| {
-        eprintln!("Failed to parse float: {}, error: {}", s, e);
+        log::error!("Failed to parse float: {}, error: {}", s, e);
         0.0
     })
 }

+ 6 - 6
src/data_providers/binance/user_data.rs

@@ -69,11 +69,11 @@ pub fn connect_user_stream(listen_key: String) -> impl Stream<Item = Event> {
                         )
                         .await {
                             state = State::Connected(websocket);
-                            dbg!("Connected to user stream");
+                            log::info!("Connected to user stream");
                         } else {
                             tokio::time::sleep(tokio::time::Duration::from_secs(1))
                             .await;
-                            dbg!("Failed to connect to user stream");
+                            log::info!("Failed to connect to user stream");
                             let _ = output.send(Event::Disconnected).await;
                         }
                     }
@@ -121,12 +121,12 @@ pub fn connect_user_stream(listen_key: String) -> impl Stream<Item = Event> {
                                                 let _ = output.send(event).await;
                                             },
                                             Err(e) => {
-                                                dbg!(e, message);
+                                                log::error!("Failed to parse message: {e:?}");
                                             }
                                         }
                                     }
                                     Err(_) => {
-                                        dbg!("Disconnected from user stream");
+                                        log::info!("Disconnected from user stream");
                                         let _ = output.send(Event::Disconnected).await;
                                         state = State::Disconnected;
                                     }
@@ -160,7 +160,7 @@ pub fn fetch_user_stream(api_key: &str, secret_key: &str) -> impl Stream<Item =
                             let _ = output.send(Event::FetchedPositions(positions)).await;
                         }
                         Err(e) => {
-                            eprintln!("Error fetching positions: {e:?}");
+                            log::error!("Error fetching positions: {e:?}");
                         }
                     }
 
@@ -169,7 +169,7 @@ pub fn fetch_user_stream(api_key: &str, secret_key: &str) -> impl Stream<Item =
                             let _ = output.send(Event::FetchedBalance(balance)).await;
                         }
                         Err(e) => {
-                            eprintln!("Error fetching balance: {e:?}");
+                            log::error!("Error fetching balance: {e:?}");
                         }
                     }
 

+ 11 - 11
src/data_providers/bybit/market_data.rs

@@ -184,7 +184,7 @@ fn feed_de(bytes: &Bytes) -> Result<StreamData> {
                         topic_ticker = ticker;
                     },
                     _ => {
-                        eprintln!("Unknown stream name");
+                        log::error!("Unknown stream name");
                     }
                 }
             }
@@ -216,7 +216,7 @@ fn feed_de(bytes: &Bytes) -> Result<StreamData> {
                     return Ok(StreamData::Kline(topic_ticker, kline_wrap));
                 },
                 _ => {
-                    eprintln!("Unknown stream type");
+                    log::error!("Unknown stream type");
                 }
             }
         } else if k == "cts" {
@@ -297,7 +297,7 @@ where
 
 fn str_f32_parse(s: &str) -> f32 {
     s.parse::<f32>().unwrap_or_else(|e| {
-        eprintln!("Failed to parse float: {}, error: {}", s, e);
+        log::error!("Failed to parse float: {}, error: {}", s, e);
         0.0
     })
 }
@@ -344,7 +344,7 @@ pub fn connect_market_stream(ticker: Ticker) -> impl Stream<Item = Event> {
                             }).to_string();
     
                             if let Err(e) = websocket.write_frame(Frame::text(fastwebsockets::Payload::Borrowed(subscribe_message.as_bytes()))).await {
-                                eprintln!("Failed subscribing: {}", e);
+                                log::error!("Failed subscribing: {}", e);
 
                                 let _ = output.send(Event::Disconnected).await;
 
@@ -432,19 +432,19 @@ pub fn connect_market_stream(ticker: Ticker) -> impl Stream<Item = Event> {
                                                 }
                                             },
                                             _ => {
-                                                println!("Unknown data: {:?}", &data);
+                                                log::warn!("Unknown data: {:?}", &data);
                                             }
                                         }
                                     }
                                 },
                                 OpCode::Close => {
-                                    eprintln!("Connection closed");
+                                    log::error!("Connection closed");
                                     let _ = output.send(Event::Disconnected).await;
                                 },
                                 _ => {}
                             },
                             Err(e) => {
-                                println!("Error reading frame: {}", e);
+                                log::error!("Error reading frame: {}", e);
                             }
                         }
                     }
@@ -492,7 +492,7 @@ pub fn connect_kline_stream(streams: Vec<(Ticker, Timeframe)>) -> impl Stream<It
                             }).to_string();
     
                             if let Err(e) = websocket.write_frame(Frame::text(fastwebsockets::Payload::Borrowed(subscribe_message.as_bytes()))).await {
-                                eprintln!("Failed subscribing: {}", e);
+                                log::error!("Failed subscribing: {}", e);
 
                                 let _ = output.send(Event::Disconnected).await;
 
@@ -527,18 +527,18 @@ pub fn connect_kline_stream(streams: Vec<(Ticker, Timeframe)>) -> impl Stream<It
                                             if let Some(timeframe) = string_to_timeframe(&de_kline.interval) {
                                                 let _ = output.send(Event::KlineReceived(ticker, kline, timeframe)).await;
                                             } else {
-                                                eprintln!("Failed to find timeframe: {}, {:?}", &de_kline.interval, streams);
+                                                log::error!("Failed to find timeframe: {}, {:?}", &de_kline.interval, streams);
                                             }
                                         }
                                          
                                     } else {
-                                        eprintln!("\nUnknown data: {:?}", &json_bytes);
+                                        log::error!("\nUnknown data: {:?}", &json_bytes);
                                     }
                                 }
                                 _ => {}
                             },
                             Err(e) => {
-                                eprintln!("Error reading frame: {}", e);
+                                log::error!("Error reading frame: {}", e);
                             }
                         }
                     }

+ 38 - 0
src/logger.rs

@@ -0,0 +1,38 @@
+use fern::Dispatch;
+use chrono::Local;
+use std::fs::File;
+
+pub fn setup(is_debug: bool, log_trace: bool) -> Result<(), anyhow::Error> {
+    let log_level = if log_trace {
+        log::LevelFilter::Trace
+    } else {
+        log::LevelFilter::Info
+    };
+
+    let mut logger = Dispatch::new()
+        .format(|out, message, record| {
+            out.finish(format_args!(
+                "{}:{} [{}:{}] -- {}",
+                Local::now().format("%H:%M:%S%.3f"),
+                record.level(),
+                record.file().unwrap_or("unknown"),
+                record.line().unwrap_or(0),
+                message
+            ))
+        })
+        .level(log_level);
+
+    if is_debug {
+        logger = logger.chain(std::io::stdout());
+    } else {
+        let log_file_path = "output.log";
+        let log_file = File::create(log_file_path)?;
+        log_file.set_len(0)?; 
+
+        let log_file = fern::log_file(log_file_path)?;
+        logger = logger.chain(log_file);
+    }
+
+    logger.apply()?;
+    Ok(())
+}

+ 41 - 33
src/main.rs

@@ -4,6 +4,7 @@ mod data_providers;
 mod charts;
 mod style;
 mod screen;
+mod logger;
 
 use style::{ICON_FONT, ICON_BYTES, Icon};
 use screen::dashboard::{pane::{self, SerializablePane}, read_layout_from_file, write_json_to_file, Dashboard, LayoutId, PaneContent, PaneSettings, PaneState, SavedState, SerializableDashboard, SerializableState, Uuid};
@@ -29,6 +30,8 @@ use iced::widget::{
 };
 
 fn main() -> iced::Result {
+    logger::setup(false, false).expect("Failed to initialize logger");
+
     let saved_state = match read_layout_from_file("dashboard_state.json") {
         Ok(state) => {
             let mut de_state = SavedState {
@@ -138,7 +141,7 @@ fn main() -> iced::Result {
             de_state
         },
         Err(e) => {
-            eprintln!("Failed to load/find layout state: {}. Starting with a new layout.", e);
+            log::error!("Failed to load/find layout state: {}. Starting with a new layout.", e);
 
             SavedState::default()
         }
@@ -285,7 +288,10 @@ impl State {
 
                 match dashboard.update_chart_state(pane_id, message) {
                     Ok(_) => Task::none(),
-                    Err(err) => Task::none()
+                    Err(err) => {
+                        log::error!("{err}");
+                        Task::none()
+                    }
                 }
             },
             Message::SetMinTickSize(min_tick_size, pane_id) => {
@@ -298,7 +304,7 @@ impl State {
                         Task::none()
                     },
                     Err(err) => {
-                        eprintln!("Failed to set min tick size: {err}");
+                        log::error!("Failed to set min tick size: {err}");
 
                         Task::none()
                     }
@@ -314,7 +320,7 @@ impl State {
                         Task::none()
                     },
                     Err(err) => {
-                        eprintln!("{err}");
+                        log::error!("{err}");
 
                         Task::none()
                     }
@@ -353,7 +359,7 @@ impl State {
                         }
                     },
                     Err(err) => {
-                        eprintln!("Failed to change timeframe: {err}");
+                        log::error!("Failed to change timeframe: {err}");
                     }
                 }
 
@@ -371,7 +377,7 @@ impl State {
                         Task::none()
                     },
                     Err(err) => {
-                        eprintln!("{err}");
+                        log::error!("{err}");
 
                         Task::none()
                     }
@@ -382,17 +388,17 @@ impl State {
                 
                 match dashboard.pane_change_ticksize(pane_id, tick_multiply) {
                     Ok(_) => {
-                        dbg!("Ticksize changed");
-
+                        log::info!("Ticksize changed");
+            
                         Task::none()
                     },
                     Err(err) => {
-                        eprintln!("Failed to change ticksize: {err}");
-
+                        log::error!("Failed to change ticksize: {err}");
+            
                         Task::none()
                     }
                 }
-            },  
+            },
             Message::FetchEvent(klines, pane_stream, pane_id) => {
                 let dashboard = self.get_mut_dashboard();
 
@@ -410,7 +416,7 @@ impl State {
                         }
                     },
                     Err(err) => {
-                        eprintln!("{err}");
+                        log::error!("{err}");
                     }
                 }
 
@@ -434,7 +440,7 @@ impl State {
                             };
                             
                             if let Err(err) = dashboard.update_depth_and_trades(stream_type, depth_update_t, depth, trades_buffer) {
-                                eprintln!("{err}, {stream_type:?}");
+                                log::error!("{err}, {stream_type:?}");
 
                                 self.pane_streams
                                     .entry(Exchange::BinanceFutures)
@@ -452,7 +458,7 @@ impl State {
                             };
 
                             if let Err(err) = dashboard.update_latest_klines(&stream_type, &kline) {
-                                eprintln!("{err}, {stream_type:?}");
+                                log::error!("{err}, {stream_type:?}");
 
                                 self.pane_streams
                                     .entry(Exchange::BinanceFutures)
@@ -477,7 +483,7 @@ impl State {
                             };
                             
                             if let Err(err) = dashboard.update_depth_and_trades(stream_type, depth_update_t, depth, trades_buffer) {
-                                eprintln!("{err}, {stream_type:?}");
+                                log::error!("{err}, {stream_type:?}");
 
                                 self.pane_streams
                                     .entry(Exchange::BybitLinear)
@@ -495,7 +501,7 @@ impl State {
                             };
 
                             if let Err(err) = dashboard.update_latest_klines(&stream_type, &kline) {
-                                eprintln!("{err}, {stream_type:?}");
+                                log::error!("{err}, {stream_type:?}");
 
                                 self.pane_streams
                                     .entry(Exchange::BybitLinear)
@@ -515,7 +521,7 @@ impl State {
                 Task::none()
             },
             Message::UserKeyError => {
-                dbg!("Check API keys");
+                log::error!("Check API keys");
                 Task::none()
             },
             Message::Split(axis, pane) => {
@@ -642,12 +648,12 @@ impl State {
                 match serde_json::to_string(&layout) {
                     Ok(layout_str) => {
                         if let Err(e) = write_json_to_file(&layout_str, "dashboard_state.json") {
-                            eprintln!("Failed to write layout state to file: {}", e);
+                            log::error!("Failed to write layout state to file: {}", e);
                         } else {
-                            println!("Successfully wrote layout state to dashboard_state.json");
+                            log::info!("Successfully wrote layout state to dashboard_state.json");
                         }
                     },
-                    Err(e) => eprintln!("Failed to serialize layout: {}", e),
+                    Err(e) => log::error!("Failed to serialize layout: {}", e),
                 }
             
                 window::close(window)
@@ -682,14 +688,14 @@ impl State {
                                 Task::none()
                             },
                             Err(err) => {
-                                eprintln!("Failed to set size filter: {err}");
+                                log::error!("Failed to set size filter: {err}");
         
                                 Task::none()
                             }
                         }
                     }
                     Err(err) => {
-                        eprintln!("{err}");
+                        log::error!("{err}");
                         Task::none()
                     }
                 }
@@ -711,7 +717,7 @@ impl State {
                 Task::none()
             },
             Message::ErrorOccurred(err) => {
-                eprintln!("{err}");
+                log::error!("{err}");
                 Task::none()
             },
             Message::PaneContentSelected(content, pane_id, pane_stream) => {
@@ -736,13 +742,13 @@ impl State {
                 if let Ok(vec_streams) = dashboard.get_pane_stream_mut(pane_id) {
                     *vec_streams = pane_stream.to_vec();
                 } else {
-                    dbg!("No pane found for stream update");
+                    log::error!("No pane found for stream update");
                 }
             
                 if let Err(err) = dashboard.set_pane_content(pane_id, pane_content) {
-                    dbg!("Failed to set pane content: {}", err);
+                    log::error!("Failed to set pane content: {}", err);
                 } else {
-                    dbg!("Pane content set");
+                    log::info!("Pane content set: {content}");
                 }
                 
                 if content == "Footprint chart" || content == "Candlestick chart" || content == "Heatmap chart" {
@@ -780,8 +786,8 @@ impl State {
                     }
                 }
             
-                dbg!(&self.pane_streams);
-            
+                log::info!("{:?}", &self.pane_streams);
+                
                 Task::batch(tasks)
             },
             Message::ReplacePane(pane) => {
@@ -827,11 +833,11 @@ impl State {
                 match klines {
                     Ok(klines) => {
                         if let Err(err) = dashboard.find_and_insert_klines(&stream_type, &klines) {
-                            eprintln!("{err}");
+                            log::error!("{err}");
                         }
                     },
                     Err(err) => {
-                        eprintln!("{err}");
+                        log::error!("{err}");
                     }
                 }
 
@@ -844,11 +850,11 @@ impl State {
                 match min_tick_size {
                     Ok(ticksize) => {
                         if let Err(err) = dashboard.find_and_insert_ticksizes(&stream_type, ticksize) {
-                            eprintln!("{err}");
+                            log::error!("{err}");
                         }
                     },
                     Err(err) => {
-                        eprintln!("{err}");
+                        log::error!("{err}");
                     }
                 }
 
@@ -1440,7 +1446,9 @@ fn view_starter<'a>(
             .align_x(Alignment::Center), |column, &label| {
                 let mut btn = button(label).width(Length::Fill);
                 if let (Some(exchange), Some(ticker)) = (pane.settings.selected_exchange, pane.settings.selected_ticker) {
-                    let timeframe = pane.settings.selected_timeframe.unwrap_or_else(|| { dbg!("No timeframe found"); Timeframe::M1 });
+                    let timeframe = pane.settings.selected_timeframe.unwrap_or_else(
+                        || { log::error!("No timeframe found"); Timeframe::M1 }
+                    );
 
                     let pane_stream: Vec<StreamType> = match label {
                         "Heatmap chart" => vec![StreamType::DepthAndTrades { exchange, ticker }],

+ 0 - 4
src/screen/dashboard.rs

@@ -275,8 +275,6 @@ impl Dashboard {
     }
 
     pub fn find_and_insert_klines(&mut self, stream_type: &StreamType, klines: &Vec<Kline>) -> Result<(), &str> {
-        dbg!(stream_type);
-
         let mut found_match = false;
 
         for (_, pane_state) in self.panes.iter_mut() {
@@ -316,8 +314,6 @@ impl Dashboard {
     }
 
     pub fn find_and_insert_ticksizes(&mut self, stream_type: &StreamType, tick_sizes: f32) -> Result<(), &str> {
-        dbg!(stream_type);
-
         let mut found_match = false;
 
         for (_, pane_state) in self.panes.iter_mut() {