Преглед изворни кода

refactor: added comments and some small code readability changes for LogBook

Kristian Vos пре 2 година
родитељ
комит
d27b3ff34c
1 измењених фајлова са 99 додато и 41 уклоњено
  1. 99 41
      backend/src/LogBook.ts

+ 99 - 41
backend/src/LogBook.ts

@@ -24,11 +24,21 @@ export type LogOutputs = {
 	memory: { enabled: boolean } & Partial<LogFilters>;
 };
 
+// Color escape codes for stdout
+const COLOR_GREEN = "\x1b[32m";
+const COLOR_RED = "\x1b[31m";
+const COLOR_YELLOW = "\x1b[33m";
+const COLOR_CYAN = "\x1b[36m";
+const COLOR_RESET = "\x1b[0m";
+
 export default class LogBook {
+	// A list of log objects stored in memory, if enabled generally
 	private logs: Log[];
 
 	private default: LogOutputs;
 
+	// Settings for different outputs. Currently only memory and outputs is supported as an output
+	// Constructed first via defaults, then via settings set in the config, and then you can make any other changes via a backend command (not persistent)
 	private outputs: LogOutputs;
 
 	/**
@@ -45,16 +55,19 @@ export default class LogBook {
 				data: false,
 				color: true,
 				exclude: [
+					// Success messages for jobs don't tend to be very helpful, so we exclude them by default
 					{
 						category: "jobs",
 						type: "success"
 					},
+					// We don't want to show debug messages in the console by default
 					{
 						type: "debug"
 					}
 				]
 			},
 			memory: {
+				// Log messages in memory never get deleted, so we don't have this output on by default, only when debugging
 				enabled: false
 			}
 		};
@@ -70,55 +83,72 @@ export default class LogBook {
 	}
 
 	/**
-	 * log - Add log
+	 * Log a message to console and/or memory, if the log matches the filters of those outputs
 	 *
-	 * @param log - Log message or object
+	 * @param log - Log message or log object (without timestamp)
 	 */
 	public log(log: string | Omit<Log, "timestamp">) {
+		// Construct the log object
 		const logObject: Log = {
 			timestamp: Date.now(),
 			...(typeof log === "string" ? { message: log } : log)
 		};
+
+		// Whether we want to exclude console or memory, which we get in the next code block
 		const exclude = {
 			console: false,
 			memory: false
 		};
+		// Loop through log object entries
 		(Object.entries(logObject) as [keyof Log, Log[keyof Log]][]).forEach(
 			([key, value]) => {
+				// Timestamp is useless, so just return
+				if (key === "timestamp") return;
+
+				// Loop through outputs to see if they have any include/exclude filters
 				(
 					Object.entries(this.outputs) as [
 						keyof LogOutputs,
 						LogOutputs[keyof LogOutputs]
 					][]
 				).forEach(([outputName, output]) => {
+					// This output has an include array, but the current key/value is not in any of the include filters, so exclude this output
+					if (
+						output.include &&
+						output.include.length > 0 &&
+						output.include.filter(filter => filter[key] === value)
+							.length === 0
+					)
+						exclude[outputName] = true;
+
+					// We have an exclude array, and the current key/value is in one or more of the filters, so exclude this output
 					if (
-						(output.include &&
-							output.include.length > 0 &&
-							output.include.filter(
-								filter =>
-									key !== "timestamp" && filter[key] === value
-							).length === 0) ||
-						(output.exclude &&
-							output.exclude.filter(
-								filter =>
-									key !== "timestamp" && filter[key] === value
-							).length > 0)
+						output.exclude &&
+						output.exclude.filter(filter => filter[key] === value)
+							.length > 0
 					)
 						exclude[outputName] = true;
 				});
 			}
 		);
+
+		// Title will be the jobname, or category of jobname is undefined
 		const title =
-			(logObject.data && logObject.data.jobName) ||
-			logObject.category ||
-			undefined;
+			logObject.data?.jobName ?? logObject.category ?? undefined;
+
+		// If memory is not excluded and memory is enabled, store the log object in the memory (logs array) of this logbook instance
 		if (!exclude.memory && this.outputs.memory.enabled)
 			this.logs.push(logObject);
+
+		// If console is not excluded, format the log object, and then write the formatted message to the console
 		if (!exclude.console) {
 			const message = this.formatMessage(logObject, String(title));
-			const logArgs = this.outputs.console.data
-				? [message]
-				: [message, logObject.data];
+			const logArgs: (string | Record<string, unknown>)[] = [message];
+
+			// Append logObject data, if enabled and it's not falsy
+			if (this.outputs.console.data && logObject.data)
+				logArgs.push(logObject.data);
+
 			switch (logObject.type) {
 				case "debug": {
 					console.debug(...logArgs);
@@ -135,59 +165,84 @@ export default class LogBook {
 	}
 
 	/**
-	 * formatMessage - Format log to string
+	 * Center a string within a given length, by padding spaces at the start and end
+	 *
+	 * @param string - The string we want to center
+	 * @param length - The total amount of space we have to work with
+	 * @returns
+	 */
+	private centerString(string: string, length: number) {
+		const spaces = Array(
+			Math.floor((length - Math.max(0, string.length)) / 2)
+		).join(" ");
+		return `${spaces}${string}${spaces}${
+			string.length % 2 === 0 ? "" : " "
+		}`;
+	}
+
+	/**
+	 * Creates a formatted log message, with various options. Used for console
 	 *
 	 * @param log - Log
 	 * @param title - Log title
 	 * @returns Formatted log string
 	 */
 	private formatMessage(log: Log, title: string | undefined): string {
-		const centerString = (string: string, length: number) => {
-			const spaces = Array(
-				Math.floor((length - Math.max(0, string.length)) / 2)
-			).join(" ");
-			return `| ${spaces}${string}${spaces}${
-				string.length % 2 === 0 ? "" : " "
-			} `;
-		};
 		let message = "";
+
+		// If we want to show colors, prepend the color code
 		if (this.outputs.console.color)
 			switch (log.type) {
 				case "success":
-					message += "\x1b[32m";
+					message += COLOR_GREEN;
 					break;
 				case "error":
-					message += "\x1b[31m";
+					message += COLOR_RED;
 					break;
 				case "debug":
-					message += "\x1b[33m";
+					message += COLOR_YELLOW;
 					break;
 				case "info":
 				default:
-					message += "\x1b[36m";
+					message += COLOR_CYAN;
 					break;
 			}
+
+		// If we want to show timestamps, e.g. 2022-11-28T18:13:28.081Z
 		if (this.outputs.console.timestamp)
 			message += `| ${new Date(log.timestamp).toISOString()} `;
+
+		// If we want to show titles, show it centered and capped at 20 characters
 		if (this.outputs.console.title)
-			message += centerString(title ? title.substring(0, 20) : "", 24);
+			message += `| ${this.centerString(
+				title ? title.substring(0, 20) : "",
+				24
+			)} `;
+
+		// If we want to show the log type, show it centered, in uppercase
 		if (this.outputs.console.type)
-			message += centerString(
+			message += `| ${this.centerString(
 				log.type ? log.type.toUpperCase() : "INFO",
 				10
-			);
+			)} `;
+
+		// If we want to the message, show it
 		if (this.outputs.console.message) message += `| ${log.message} `;
-		if (this.outputs.console.color) message += "\x1b[0m";
+
+		// Reset the color at the end of the message, if we have colors enabled
+		if (this.outputs.console.color) message += COLOR_RESET;
 		return message;
 	}
 
 	/**
-	 * updateOutput - Update output settings
+	 * Update output settings for LogBook
+	 * These are stored in the current instance of LogBook, not saved in a file, so when the backend restarts this data will not be persisted
+	 * LogBook is currently used as a singleton, so changing it will update outputs for the same logbook used everywhere
 	 *
-	 * @param output - Output name
-	 * @param key - Output key to update
-	 * @param action - Update action
-	 * @param values - Updated value
+	 * @param output - Output name (console or memory)
+	 * @param key - Output key to update (include, exclude, enabled, name, type, etc.)
+	 * @param action - Action (set, add or reset)
+	 * @param values - Value we want to set
 	 */
 	public async updateOutput(
 		output: "console" | "memory",
@@ -196,6 +251,7 @@ export default class LogBook {
 		values?: LogOutputOptions[keyof LogOutputOptions]
 	) {
 		switch (key) {
+			// Set, add-to or reset (to) the include/exclude filter lists for a specific output
 			case "include":
 			case "exclude": {
 				if (action === "set" || action === "add") {
@@ -216,6 +272,7 @@ export default class LogBook {
 					);
 				break;
 			}
+			// Set an output to be enabled or disabled
 			case "enabled": {
 				if (output === "memory" && action === "set") {
 					if (values === undefined)
@@ -227,6 +284,7 @@ export default class LogBook {
 					);
 				break;
 			}
+			// Set some other property of an output
 			default: {
 				if (output !== "memory" && action === "set") {
 					if (values === undefined)