@setoelkahfi / svara / commits / 7e00bc3

feat: crash logging

mellbacon committed Oct 1, 2023 at 16:32 UTC 7e00bc3d09f84af8795259736cd261edf2490443
1 file changed +100 -58
src-tauri/src/main.rs
+100 -58
@@ -10,20 +10,19 @@ const LOG_TARGETS: [LogTarget; 3] = [LogTarget::Stdout, LogTarget::Webview, LogT
10 const LOG_TARGETS: [LogTarget; 2] = [LogTarget::Stdout, LogTarget::LogDir];
11
12 use std::collections::HashMap;
13 -use std::ffi::OsStr;
13 use std::fs::File;
14 use std::io::Write;
15 use std::path::{Path, PathBuf};
17 -use std::{env, fs};
16 use std::process::Command;
17 +use std::{env, fs};
18
20 -use tauri::{Manager, Wry, App};
19 +use tauri::{App, Manager, Wry};
20
21 mod encoding;
22 use encoding::BOM;
23 +use log::{error, info};
24 use tauri::plugin::TauriPlugin;
25 use tauri_plugin_log::{LogTarget, RotationStrategy};
26 -use log::{info, error};
26
27 use crate::encoding::convert_to_u16;
28
@@ -62,34 +61,34 @@ fn delete_file(path: &str, perm: bool) {
61 match fs::remove_file(path) {
62 Ok(_) => {
63 info!("{:?} sucessfully deleted.", PathBuf::from(path).file_name());
65 - },
64 + }
65 Err(err) => error!("Cannot remove {}. Error: {}.", path, err),
66 }
68 - }
69 - else {
67 + } else {
68 match fs::remove_dir_all(path) {
69 Ok(_) => info!("Path {} deleted sucessfully.", path),
72 - Err(err) => error!("Cannot remove {}. Error: {}.", path, err)
70 + Err(err) => error!("Cannot remove {}. Error: {}.", path, err),
71 }
72 }
75 - }
76 - else {
73 + } else {
74 match trash::delete(path) {
75 Ok(_) => {
79 - info!("{:?} sucessfully moved to trash.", PathBuf::from(path).file_name());
80 - },
76 + info!(
77 + "{:?} sucessfully moved to trash.",
78 + PathBuf::from(path).file_name()
79 + );
80 + }
81 Err(err) => error!("Cannot remove {}. Error: {}.", path, err),
82 }
83 }
84 }
85
86 -#[derive(Hash, Eq, PartialEq, Debug)]
87 -#[derive(serde::Serialize)]
86 +#[derive(Hash, Eq, PartialEq, Debug, serde::Serialize)]
87 struct FileData {
88 text: String,
89 encoding: String,
90 extension: String,
92 - bom: bool
91 + bom: bool,
92 }
93
94 #[tauri::command]
@@ -100,22 +99,45 @@ fn read_file(path: &str) -> FileData {
99 match fs::read(path) {
100 Ok(b) => {
101 bytes = b;
103 - },
104 - Err(err) => error!("Cannot read {}. Error: {}", path, err)
102 + }
103 + Err(err) => error!("Cannot read {}. Error: {}", path, err),
104 }
106 - let ext = Path::new(path).extension().and_then(OsStr::to_str).unwrap();
105 +
106 + let ext = match Path::new(path).extension() {
107 + Some(v) => {
108 + v.to_str().unwrap()
109 + }
110 + None => {
111 + error!("No extension found for {}", path);
112 + ""
113 + }
114 + };
115 +
116 let file_data: FileData;
117
118 // encode based on bom if present otherwise just default to utf8
119 if let Some(data) = encoding_rs::Encoding::for_bom(&bytes) {
120 let (text, encoding, _) = data.0.decode(&bytes);
112 - file_data = FileData {text: text.to_string(), encoding: encoding.name().to_string(), extension: ext.to_string(), bom: true};
121 +
122 + file_data = FileData {
123 + text: text.to_string(),
124 + encoding: encoding.name().to_string(),
125 + extension: ext.to_string(),
126 + bom: true,
127 + };
128 info!("File BOM found. Encoding with {}...", encoding.name());
114 - }
115 - else {
129 + } else {
130 let (text, encoding, _) = encoding_rs::UTF_8.decode(&bytes);
117 - file_data = FileData {text: text.to_string(), encoding: encoding.name().to_string(), extension: ext.to_string(), bom: false};
118 - info!("No file BOM found. Defaulting to {} encoding...", encoding.name());
131 + file_data = FileData {
132 + text: text.to_string(),
133 + encoding: encoding.name().to_string(),
134 + extension: ext.to_string(),
135 + bom: false,
136 + };
137 + info!(
138 + "No file BOM found. Defaulting to {} encoding...",
139 + encoding.name()
140 + );
141 }
142 file_data
143 }
@@ -133,11 +155,9 @@ fn write_file(path: &str, content: &str, enc: &str, has_bom: bool) {
155 info!("Encoding file to {} encoding...", enc);
156 if enc == "UTF-8" {
157 bom = b"\xEF\xBB\xBF".to_vec();
136 - }
137 - else if enc == "UTF-16BE" {
158 + } else if enc == "UTF-16BE" {
159 c_bytes = convert_to_u16(content, BOM::BigEndian);
139 - }
140 - else if enc == "UTF-16LE" {
160 + } else if enc == "UTF-16LE" {
161 c_bytes = convert_to_u16(content, BOM::LittleEndian);
162 }
163 }
@@ -152,37 +172,41 @@ fn write_file(path: &str, content: &str, enc: &str, has_bom: bool) {
172 match file {
173 Ok(mut f) => {
174 f.write_all(&output).unwrap();
155 - },
156 - Err(err) => error!("Cannot write to {}. Error: {}", path, err)
175 + }
176 + Err(err) => error!("Cannot write to {}. Error: {}", path, err),
177 }
178 }
179
180 fn configure_log() -> TauriPlugin<Wry> {
181 tauri_plugin_log::Builder::default()
162 - .format(move |out, message, record| {
163 - let format = time::format_description::parse(
164 - "[[[year]-[month]-[day]][[[hour]:[minute]:[second]]",
165 - )
166 - .unwrap();
167 - out.finish(format_args!(
168 - "{}[{}] {}",
169 - time::OffsetDateTime::now_local().unwrap().format(&format).unwrap(),
170 - record.level(),
171 - message
172 - ))
173 - })
174 - .targets(LOG_TARGETS)
175 - .rotation_strategy(RotationStrategy::KeepAll)
176 - .build()
182 + .format(move |out, message, record| {
183 + let format = time::format_description::parse(
184 + "[[[year]-[month]-[day]][[[hour]:[minute]:[second]]",
185 + )
186 + .unwrap();
187 + out.finish(format_args!(
188 + "{}[{}][{}] {}",
189 + time::OffsetDateTime::now_local()
190 + .unwrap()
191 + .format(&format)
192 + .unwrap(),
193 + record.target(),
194 + record.level(),
195 + message
196 + ))
197 + })
198 + .targets(LOG_TARGETS)
199 + .rotation_strategy(RotationStrategy::KeepAll)
200 + .build()
201 }
202
203 fn configure_log_path(app: &mut App) {
204 let app_log_dir = tauri::api::path::app_log_dir(&app.config()).unwrap();
181 - let format = time::format_description::parse(
182 - "[year]-[month]-[day]-[hour][minute]",
183 - )
184 - .unwrap();
185 - let time = time::OffsetDateTime::now_local().unwrap().format(&format).unwrap();
205 + let format = time::format_description::parse("[year]-[month]-[day]-[hour][minute]").unwrap();
206 + let time = time::OffsetDateTime::now_local()
207 + .unwrap()
208 + .format(&format)
209 + .unwrap();
210 let log_name = format!("nucleus_log-{}.log", time);
211
212 // changing the default log name to something more meaningful
@@ -192,7 +216,6 @@ fn configure_log_path(app: &mut App) {
216 }
217
218 fn load_settings(app: &mut App) {
195 -
219 info!("Loading default settings:");
220
221 let default_settings = serde_json::json!(
@@ -216,26 +239,45 @@ fn load_settings(app: &mut App) {
239
240 if !settings_path.try_exists().unwrap() {
241 fs::write(&settings_path, default_settings.to_string()).unwrap();
219 - info!("Default settings file not found. Created a new default settings file. Path: {:?}", &settings_path);
220 - }
221 - else {
242 + info!(
243 + "Default settings file not found. Created a new default settings file. Path: {:?}",
244 + &settings_path
245 + );
246 + } else {
247 info!("Settings path: {:?}:", settings_path);
248 }
249
250 let mut defaults = HashMap::new();
251 for settings in default_settings.as_object().unwrap() {
227 - defaults.entry(settings.0.clone()).or_insert_with(|| settings.1.clone());
252 + defaults
253 + .entry(settings.0.clone())
254 + .or_insert_with(|| settings.1.clone());
255 }
256
230 - let mut settings_store = tauri_plugin_store::StoreBuilder::new(app.handle(), settings_path).defaults(defaults).build();
257 + let mut settings_store = tauri_plugin_store::StoreBuilder::new(app.handle(), settings_path)
258 + .defaults(defaults)
259 + .build();
260
261 settings_store.load().unwrap();
233 -
262 }
263
264 fn main() {
265 + let original = std::panic::take_hook();
266 + std::panic::set_hook(Box::new(move |info| {
267 + // log panics/crashes
268 + original(info);
269 + error!("[FATAL]: {:?}", info.to_string());
270 + }));
271 tauri::Builder::default()
238 - .invoke_handler(tauri::generate_handler![open_in_explorer, delete_file, attempt_file_access, is_file, is_folder, read_file, write_file])
272 + .invoke_handler(tauri::generate_handler![
273 + open_in_explorer,
274 + delete_file,
275 + attempt_file_access,
276 + is_file,
277 + is_folder,
278 + read_file,
279 + write_file
280 + ])
281 .plugin(tauri_plugin_fs_watch::init())
282 .plugin(tauri_plugin_store::Builder::default().build())
283 .plugin(configure_log())
@@ -243,7 +285,7 @@ fn main() {
285 configure_log_path(app);
286 load_settings(app);
287 Ok(())
246 - })
288 + })
289 .run(tauri::generate_context!())
290 .expect("error while running tauri application");
291 }