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
}