Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Implement Logger system #1020

Merged
merged 2 commits into from
Sep 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/ace/colorView.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ function afterRender() {
el.classList.add("ace_color");
el.style.cssText = `background-color: ${content}; color: ${fontColorString}; pointer-events: all;`;
} catch (error) {
console.log("Invalid color", content);
window.log("error", `Invalid color: ${content}`);
window.log("error", error);
}
});
}
Expand Down
10 changes: 9 additions & 1 deletion src/ace/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ const commands = [
editor._emit("select-word");
},
},
{
name: "openLogFile",
description: "Open Log File",
exec() {
acode.exec("open-log-file");
},
},
];

export function setCommands(editor) {
Expand Down Expand Up @@ -314,6 +321,7 @@ export async function resetKeyBindings() {
}
await fs.writeFile(content);
} catch (error) {
console.error(error);
window.log("error", "Reset Keybinding failed!");
window.log("error", error);
}
}
2 changes: 1 addition & 1 deletion src/components/palette/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export default function palette(getList, onsSelectCb, placeholder, onremove) {
}

remove = () => {
console.error("Palette already removed");
window.log("warn", "Palette already removed.");
};
}
}
3 changes: 2 additions & 1 deletion src/components/searchbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ function searchBar($list, setHide, onhideCb, searchFunction) {
try {
result = await result;
} catch (error) {
console.error("Search function failed:", error);
window.log("error", "Search function failed:");
window.log("error", error);
result = [];
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/settingsPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ function listItems($list, items, callback) {
return;
}
} catch (error) {
console.log(error);
window.log("error", error);
}

item.value = res;
Expand Down
5 changes: 3 additions & 2 deletions src/lib/actionStack.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ export default {
const copyStack = { ...this };
delete copyStack.windowCopy;
copyStack.pop = (repeat) => {
console.error(
"Deprecated: window.actionStack is deprecated, import actionStack instead",
window.log(
"error",
"Deprecated: `window.actionStack` is deprecated, import `actionStack` instead",
);
this.pop(repeat);
};
Expand Down
4 changes: 4 additions & 0 deletions src/lib/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import commandPalette from "palettes/commandPalette";
import findFile from "palettes/findFile";
import help from "settings/helpSettings";
import mainSettings from "settings/mainSettings";
import Url from "utils/Url";
import { getColorRange } from "utils/color/regex";
import helpers from "utils/helpers";
import checkFiles from "./checkFiles";
Expand Down Expand Up @@ -362,4 +363,7 @@ export default {
});
editorManager.activeFile.eol = eol;
},
"open-log-file"() {
openFile(Url.join(DATA_STORAGE, constants.LOG_FILE_NAME));
},
};
1 change: 1 addition & 0 deletions src/lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ export default {
API_BASE: "https://acode.app/api",
// API_BASE: 'https://192.168.0.102:3001/api', // test api
SKU_LIST: ["basic", "bronze", "silver", "gold", "platinum"],
LOG_FILE_NAME: "Acode.log",
};
14 changes: 9 additions & 5 deletions src/lib/editorFile.js
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,8 @@ export default class EditorFile {

await fs.writeFile(text);
} catch (error) {
console.error(error);
window.log("error", "Writing to cache failed:");
window.log("error", error);
}
}

Expand Down Expand Up @@ -519,7 +520,7 @@ export default class EditorFile {
if (oldText.length !== text.length) return true;
return oldText !== text;
} catch (error) {
console.log(error);
window.log("error", error);
return false;
}
}
Expand Down Expand Up @@ -789,7 +790,8 @@ export default class EditorFile {
if (!(await fs.exists())) return;
fs.renameTo(newId);
} catch (error) {
console.error("renameCacheFile", error);
window.log("error", "renameCacheFile");
window.log("error", error);
}
}

Expand All @@ -802,7 +804,7 @@ export default class EditorFile {
if (!(await fs.exists())) return;
await fs.delete();
} catch (error) {
console.error(error);
window.log("error", error);
}
}

Expand Down Expand Up @@ -838,6 +840,7 @@ export default class EditorFile {
} else if (!cacheExists && fileExists) {
value = await file.readFile(this.encoding);
} else if (!cacheExists && !fileExists) {
window.log("error", "unable to load file");
throw new Error("Unable to load file");
}
}
Expand Down Expand Up @@ -870,7 +873,8 @@ export default class EditorFile {
this.#emit("loaderror", createFileEvent(this));
this.remove();
toast(`Unable to load: ${this.filename}`);
console.log(error);
window.log("error", "Unable to load: " + this.filename);
window.log("error", error);
} finally {
this.#emit("loadend", createFileEvent(this));
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib/fileList.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export async function addRoot({ url, name }) {
emit("add-folder", tree);
} catch (error) {
// ignore
console.error(error);
window.log("error", error);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib/installPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default async function installPlugin(id, name, purchaseToken) {
await fsOperation(DATA_STORAGE).createDirectory("plugins");
}
} catch (error) {
console.error(error);
window.log("error", error);
}

if (!/^(https?|file|content):/.test(id)) {
Expand Down
116 changes: 116 additions & 0 deletions src/lib/logger.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import fsOperation from "fileSystem";
import Url from "utils/Url";
import constants from "./constants";

/*
/**
* Logger class for handling application logging with buffer and file output.
* @class
*/

/**
* Creates a new Logger instance.
* @constructor
* @param {number} [maxBufferSize=1000] - Maximum number of log entries to keep in buffer.
* @param {string} [logLevel="info"] - Minimum log level to record ("error", "warn", "info", "debug").
* @param {number} [flushInterval=30000] - Interval in milliseconds for automatic log flushing.
*/
class Logger {
#logBuffer;
#maxBufferSize;
#logLevel;
#logFileName;
#flushInterval;
#autoFlushInterval;

constructor(maxBufferSize = 1000, logLevel = "info", flushInterval = 30000) {
this.#logBuffer = new Map();
this.#maxBufferSize = maxBufferSize;
this.#logLevel = logLevel;
this.#logFileName = constants.LOG_FILE_NAME;
this.#flushInterval = flushInterval;
this.#startAutoFlush(); // Automatically flush logs at intervals
this.#setupAppLifecycleHandlers(); // Handle app lifecycle events for safe log saving
}

/**
* Logs a message with the specified log level.
* @param {'error' | 'warn' | 'info' | 'debug'} level - The log level.
* @param {string} message - The message to be logged.
*/
log(level, message) {
const levels = ["error", "warn", "info", "debug"];
if (levels.indexOf(level) <= levels.indexOf(this.#logLevel)) {
let logEntry;

// Check if the message is an instance of Error
if (message instanceof Error) {
logEntry = `[${new Date().toISOString()}] [${level.toUpperCase()}] ${message.name}: ${message.message}\nStack trace: ${message.stack}`;
} else {
logEntry = `[${new Date().toISOString()}] [${level.toUpperCase()}] ${message}`;
}
// LRU Mechanism for efficient log buffer management
if (this.#logBuffer.size >= this.#maxBufferSize) {
// Remove oldest entry
const oldestKey = this.#logBuffer.keys().next().value;
this.#logBuffer.delete(oldestKey);
}
this.#logBuffer.set(Date.now(), logEntry); // Using timestamp as key
}
}

flushLogs() {
if (this.#logBuffer.size > 0) {
const logContent = Array.from(this.#logBuffer.values()).join("\n");
this.#writeLogToFile(logContent);
this.#logBuffer.clear(); // Clear the buffer after flushing
}
}

#writeLogToFile = async (logContent) => {
try {
if (
!(await fsOperation(
Url.join(DATA_STORAGE, constants.LOG_FILE_NAME),
).exists())
) {
await fsOperation(window.DATA_STORAGE).createFile(
constants.LOG_FILE_NAME,
logContent,
);
} else {
let existingData = await fsOperation(
Url.join(DATA_STORAGE, constants.LOG_FILE_NAME),
).readFile("utf8");
let newData = existingData + "\n" + logContent;
await fsOperation(
Url.join(DATA_STORAGE, constants.LOG_FILE_NAME),
).writeFile(newData);
}
} catch (error) {
console.error("Error in handling fs operation on log file. Error:", err);
}
};

#startAutoFlush = () => {
this.#autoFlushInterval = setInterval(() => {
this.flushLogs();
}, this.#flushInterval);
};

stopAutoFlush() {
clearInterval(this.#autoFlushInterval);
}

#setupAppLifecycleHandlers = () => {
document.addEventListener(
"pause",
() => {
this.flushLogs(); // Flush logs when app is paused (background)
},
false,
);
};
}

export default Logger;
29 changes: 21 additions & 8 deletions src/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import EditorFile from "lib/editorFile";
import EditorManager from "lib/editorManager";
import lang from "lib/lang";
import loadPlugins from "lib/loadPlugins";
import Logger from "lib/logger";
import openFolder from "lib/openFolder";
import restoreFiles from "lib/restoreFiles";
import settings from "lib/settings";
Expand All @@ -55,6 +56,7 @@ import { getEncoding, initEncodings } from "utils/encodings";
const previousVersionCode = Number.parseInt(localStorage.versionCode, 10);

window.onload = Main;
const logger = new Logger();

async function Main() {
const oldPreventDefault = TouchEvent.prototype.preventDefault;
Expand Down Expand Up @@ -103,12 +105,14 @@ async function onDeviceReady() {
window.PLUGIN_DIR = Url.join(DATA_STORAGE, "plugins");
window.KEYBINDING_FILE = Url.join(DATA_STORAGE, ".key-bindings.json");
window.IS_FREE_VERSION = isFreePackage;
window.log = logger.log.bind(logger);

startAd();

try {
await helpers.promisify(iap.startConnection).catch((e) => {
console.error("connection error:", e);
window.log("error", "connection error");
window.log("error", e);
});

if (localStorage.acode_pro === "true") {
Expand All @@ -127,7 +131,8 @@ async function onDeviceReady() {
}
}
} catch (error) {
console.error("Purchase error:", error);
window.log("error", "Purchase error");
window.log("error", error);
}

try {
Expand Down Expand Up @@ -182,23 +187,26 @@ async function onDeviceReady() {

setTimeout(() => {
if (document.body.classList.contains("loading"))
document.body.setAttribute(
"data-small-msg",
"This is taking unexpectedly long time!",
);
window.log("warn", "App is taking unexpectedly long time!");
document.body.setAttribute(
"data-small-msg",
"This is taking unexpectedly long time!",
);
}, 1000 * 10);

acode.setLoadingMessage("Loading settings...");
window.log("info", "Loading Settings...");
await settings.init();
themes.init();

acode.setLoadingMessage("Loading language...");
window.log("info", "Loading language...");
await lang.set(settings.value.lang);

try {
await loadApp();
} catch (error) {
console.error(error);
window.log("error", error);
toast(`Error: ${error.message}`);
} finally {
setTimeout(() => {
Expand Down Expand Up @@ -338,6 +346,8 @@ async function loadApp() {
});
//#endregion

window.log("info", "App started!");

new EditorFile();

checkPluginsUpdate()
Expand Down Expand Up @@ -369,6 +379,8 @@ async function loadApp() {
try {
await loadPlugins();
} catch (error) {
window.log("error", "Plugins loading failed!");
window.log("error", error);
toast("Plugins loading failed!");
}

Expand All @@ -384,7 +396,8 @@ async function loadApp() {
try {
await restoreFiles(files);
} catch (error) {
console.error(error);
window.log("error", "File loading failed!");
window.log("error", error);
toast("File loading failed!");
}
} else {
Expand Down
Loading