feat: added message locations to logger output
mellbacon committed
Oct 7, 2023 at 00:23 UTC
bb8d203da34be6771f3744936ed610875cb14f3a
8 files changed
+74
-27
src-tauri/src/main.rs
+14
-4
@@ -4,7 +4,7 @@
4
)]
5
6
#[cfg(debug_assertions)]
7
-const LOG_TARGETS: [LogTarget; 3] = [LogTarget::Stdout, LogTarget::Webview, LogTarget::LogDir];
7
+const LOG_TARGETS: [LogTarget; 2] = [LogTarget::Stdout, LogTarget::Webview];
8
9
#[cfg(not(debug_assertions))]
10
const LOG_TARGETS: [LogTarget; 2] = [LogTarget::Stdout, LogTarget::LogDir];
@@ -184,14 +184,20 @@ fn configure_log() -> TauriPlugin<Wry> {
184
"[[[year]-[month]-[day]][[[hour]:[minute]:[second]]",
185
)
186
.unwrap();
187
+ let file_info = record.file().map(|location| format!("::{}", location.split("\\").last().unwrap().to_owned()))
188
+ .unwrap_or("".to_string());
189
+ let line_info = record.line().map(|line| format!(":{}", line))
190
+ .unwrap_or("".to_string());
191
out.finish(format_args!(
188
- "{}[{}][{}] {}",
192
+ "{}[{}][{}{}{}] {}",
193
time::OffsetDateTime::now_local()
194
.unwrap()
195
.format(&format)
196
.unwrap(),
193
- record.target(),
197
record.level(),
198
+ record.target(),
199
+ file_info,
200
+ line_info,
201
message
202
))
203
})
@@ -202,6 +208,11 @@ fn configure_log() -> TauriPlugin<Wry> {
208
209
fn configure_log_path(app: &mut App) {
210
let app_log_dir = tauri::api::path::app_log_dir(&app.config()).unwrap();
211
+ let old_log_path = app_log_dir.join("nucleus.log");
212
+ if !Path::exists(&old_log_path) {
213
+ return;
214
+ }
215
+
216
let format = time::format_description::parse("[year]-[month]-[day]-[hour][minute]").unwrap();
217
let time = time::OffsetDateTime::now_local()
218
.unwrap()
@@ -210,7 +221,6 @@ fn configure_log_path(app: &mut App) {
221
let log_name = format!("nucleus_log-{}.log", time);
222
223
// changing the default log name to something more meaningful
213
- let old_log_path = app_log_dir.join("nucleus.log");
224
let new_log_path = app_log_dir.join(log_name);
225
fs::rename(old_log_path, new_log_path).unwrap();
226
}
src/App.svelte
+5
@@ -11,6 +11,7 @@
11
import InputModal from "./lib/Modals/InputModal.svelte";
12
import RenameModal from "./lib/Modals/RenameModal.svelte";
13
import { loadDefaultSettings } from "./config/config";
14
+ import { error } from "tauri-plugin-log-api";
15
let resolution = writable(0);
16
17
let minPanelSize = 10;
@@ -26,6 +27,10 @@
27
resolution.set(e.payload.width);
28
updateMinPanelSize();
29
})
30
+
31
+ window.onunhandledrejection = (e) => {
32
+ error(e.reason);
33
+ }
34
})
35
36
function updatePanelSize(e) {
src/config/commands.ts
+2
-2
@@ -190,7 +190,7 @@ export const commands = {
190
"keybind": "F2",
191
"command": async (filename, oldpath) => {
192
if (!await fs.exists(oldpath)) {
193
- warn(`Unable to rename file. ${oldpath} does not exist.`);
193
+ warn(`Unable to rename file. ${oldpath} does not exist.`, {file: "commands.ts", line: 193});
194
return;
195
}
196
openRenameModal(`Rename ${filename}`,
@@ -211,7 +211,7 @@ export const commands = {
211
212
export function registerCommand(name: string, keybind: string, command: () => void) {
213
if (commands[name]) {
214
- info(`Command "${name}" already exists, skipping...`)
214
+ info(`Command "${name}" already exists, skipping...`, {file: "commands.ts", line: 214});
215
return;
216
}
217
commands[name] = { "keybind": keybind, "command": command }
src/config/config.ts
+4
-5
@@ -47,12 +47,12 @@ function parseKeybind(keybind: string) {
47
}
48
49
export async function getShortcuts() {
50
- info("Intializing shortcut bindings...")
50
+ info("Intializing shortcut bindings...", {file: "config.ts", line: 50});
51
const shortcuts = getKeybinds();
52
for (const shortcut of shortcuts) {
53
// skip binding shorcuts that are disabled
54
if (shortcut.disabled === "true") {
55
- info(`The keybind "${shortcut.keybind}" is disabled. Skipping and/or falling back to default...`);
55
+ info(`The keybind "${shortcut.keybind}" is disabled. Skipping and/or falling back to default...`, {file: "config.ts", line: 55});
56
continue;
57
}
58
const keybind = parseKeybind(shortcut.keybind);
@@ -61,7 +61,7 @@ export async function getShortcuts() {
61
await fireAction(shortcut.command);
62
});
63
}
64
- info("Shortcuts loaded successfully.");
64
+ info("Shortcuts loaded successfully.", {file: "config.ts", line: 64});
65
}
66
67
async function fireAction(callback: () => Promise<void>, args = []) {
@@ -94,6 +94,5 @@ export async function loadDefaultSettings() {
94
appSettings.onKeyChange("nucleus.theme", (value: string) => {
95
loadTheme(value);
96
})
97
-
98
- info(`Settings initialized.`);
97
+ info("Settings initialized", {file: "config.ts", line: 97});
98
}
\ No newline at end of file
src/config/logger.ts
new
+34
@@ -0,0 +1,34 @@
1
+import { error, warn, info } from "tauri-plugin-log-api";
2
+function getScriptName() {
3
+ let error = new Error()
4
+ let lastStackFrameRegex = new RegExp(/.+\/(.*?):\d+(:\d+)*$/)
5
+ let currentStackFrameRegex = new RegExp(/getScriptName \(.+\/(.*):\d+:\d+\)/);
6
+
7
+ let lastStack = lastStackFrameRegex.exec(error.stack.trim());
8
+ let currentStack = currentStackFrameRegex.exec(error.stack.trim());
9
+
10
+ const result = {"location": "???", stack: error.stack};
11
+ if (lastStack && lastStack[1] != "") {
12
+ result.location = lastStack[1];
13
+ }
14
+ else if (currentStack) {
15
+ result.location = currentStack[1];
16
+ }
17
+ return result;
18
+}
19
+
20
+export function logInfo(message: string, lineNumber: number) {
21
+ const e = getScriptName();
22
+ info(message, {file: e.location, line: lineNumber})
23
+}
24
+export function logWarn(message: string, lineNumber: number) {
25
+ const e = getScriptName();
26
+ warn(message, {file: e.location, line: lineNumber})
27
+}
28
+export function logError(message: string, lineNumber: number, withTrace = false) {
29
+ const e = getScriptName();
30
+ error(message, {file: e.location, line: lineNumber});
31
+ if (withTrace) {
32
+ error(e.stack);
33
+ }
34
+}
src/config/themehandler.ts
+3
-3
@@ -1,5 +1,5 @@
1
-import { info } from "tauri-plugin-log-api";
1
import { themes } from "./themes/themes";
2
+import { info } from "tauri-plugin-log-api";
3
4
export function getThemes() {
5
let themelist = [];
@@ -13,7 +13,7 @@ export function getThemes() {
13
14
const stylesheet = document.styleSheets[0].cssRules[0] as CSSStyleRule;
15
export async function loadTheme(name: string) {
16
- info(`Loading theme: ${name}...`);
16
+ info(`Loading theme: ${name}...`, {file: "themehandler.ts", line: 16});
17
let json = await import(`../config/themes/${name.toLowerCase()}-theme.json`);
18
const theme = Object.entries(json.theme);
19
for (const entries of theme) {
@@ -32,7 +32,7 @@ export async function loadTheme(name: string) {
32
}
33
}
34
}
35
- info("Theme loaded sucessfully.");
35
+ info("Theme loaded sucessfully.", {file: "themehandler.ts", line: 35});
36
}
37
export function getThemeProperty(styleName: string) {
38
for (const style of stylesheet.style) {
src/lib/File.ts
+11
-12
@@ -4,7 +4,7 @@ import { tabs, addEditorTab, renameTab, closeTab, refreshTabs } from "./EditorTa
4
import { filetree } from "./FileTree.svelte";
5
import { watchImmediate } from "tauri-plugin-fs-watch-api";
6
import { openFileTree } from "./Sidebar.svelte";
7
-import { trace, error, warn, info } from "tauri-plugin-log-api";
7
+import { info, trace, warn, error } from "tauri-plugin-log-api";
8
9
export async function openFile() {
10
let newPath = await dialog.open() as string;
@@ -19,9 +19,9 @@ export const dirLoadFail = writable(false);
19
export async function openFolder() {
20
dirLoadFail.set(false);
21
let directory = await dialog.open({directory: true}) as string;
22
- info(`Opening folder in: ${directory}`);
22
+ info(`Opening folder in: ${directory}`, {file: "File.ts", line: 22});
23
if (!directory) {
24
- warn("Directory path is null. Aborting...");
24
+ warn("Directory path is null. Aborting...", {file: "File.ts", line: 24});
25
return
26
};
27
dirToLoad.set(directory.split(path.sep).pop());
@@ -70,14 +70,13 @@ async function updateTree(directory, updateType = "") {
70
error(error);
71
}
72
if (!tree || tree === undefined) {
73
- error(`Cannot load directory: ${tree}.`);
74
-
73
+ error(`Cannot load directory: ${tree}.`, {file: "File.ts", line: 73});
74
cancelDirectoryLoad("Cannot load directory");
75
return null;
76
}
77
78
if (loadTime > 100) {
80
- warn(`Directory load time was too long. Aborting...`);
79
+ warn("Directory load time was too long. Aborting...", {file: "File.ts", line: 79});
80
trace(`Cancelled directory load after ${loadTime} seconds. Directory: ${tree}`);
81
82
cancelDirectoryLoad("Error: Directory load timeout.");
@@ -155,7 +154,7 @@ export async function moveFile(source: string, dest: string, file: string) {
154
tab.path = `${dest}${path.sep}${filename}`;
155
refreshTabs();
156
} catch (error) {
158
- error(`Cannot move ${file} into ${dest}. Error: ${error}`);
157
+ error(`Cannot move ${file} into ${dest}. Error: ${error}`, {file: "File.ts", line: 159});
158
}
159
}
160
@@ -214,25 +213,25 @@ export async function createFolder(p) {
213
try {
214
await fs.createDir(p);
215
} catch (error) {
217
- error(`Cannot create folder in path ${p}. Error: ${error}`);
216
+ error(`Cannot create folder in path ${p}. Error: ${error}`, {file: "File.ts", line: 216});
217
}
218
}
219
export async function createFile(p) {
220
try {
221
await invoke("write_file", {path: p, content: "", enc: "UTF-8", hasBom: false});
222
} catch (error) {
224
- error(`Cannot create file in path ${p}. Error: ${error}`);
223
+ error(`Cannot create file in path ${p}. Error: ${error}`, {file: "File.ts", line: 223});
224
}
225
addEditorTab(p, p.split(path.sep).pop());
226
}
227
228
export async function renameFile(filename: string, oldpath: string) {
229
if (filename.length === 0) {
231
- warn("filename length 0");
230
+ warn("Cannot rename file with length 0", {file: "File.ts", line: 230});
231
return false;
232
}
233
if (await invoke("is_file", {path: oldpath}) && filename.includes(path.sep)) {
235
- warn("invalid filename");
234
+ warn("Cannot rename from invalid file name", {file: "File.ts", line: 234});
235
return false;
236
}
237
let newpath = oldpath.replace(oldpath.split(path.sep).pop(), filename);
@@ -240,7 +239,7 @@ export async function renameFile(filename: string, oldpath: string) {
239
try {
240
await fs.renameFile(oldpath, newpath);
241
} catch (error) {
243
- error(`Cannot rename ${oldpath}. Error: ${error}`);
242
+ error(`Cannot rename ${oldpath}. Error: ${error}`, {file: "File.ts", line: 242})
243
return false;
244
}
245
let tab = get(tabs).find(t => t.active && t.isfile);
src/lib/Tab/Tab.ts
+1
-1
@@ -76,7 +76,7 @@ export class Tab {
76
// TODO: Fix performance issues/loading times on large files
77
fileData = await invoke("read_file", {path: path});
78
} catch (error) {
79
- warn(`Can't read file content in ${path}. Setting to empty string. Error: ${error}`);
79
+ warn(`Can't read file content in ${path}. Setting to empty string. Error: ${error}`, {file: "Tab.ts", line: 79});
80
}
81
let content = new Editor({target: document.getElementById("tabview"), props: {content: fileData.text}});
82
let tab = new this.Tab(this.id, label, content, path);