@setoelkahfi / svara / commits / bb8d203

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);