mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 08:28:19 +01:00
Add new LogManager module
This commit is contained in:
parent
177f573792
commit
3b75f5f0a5
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -170,4 +170,6 @@ dist
|
||||||
config/config.toml
|
config/config.toml
|
||||||
config/config.internal.toml
|
config/config.internal.toml
|
||||||
uploads/
|
uploads/
|
||||||
pages/dist
|
pages/dist
|
||||||
|
log.txt
|
||||||
|
*.log
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
* @file configmanager.ts
|
* @file configmanager.ts
|
||||||
* @summary ConfigManager system to retrieve and modify system configuration
|
* @summary ConfigManager system to retrieve and modify system configuration
|
||||||
* @description Can read from a hand-written file, config.toml, or from a machine-saved file, config.internal.toml
|
* @description Can read from a hand-written file, config.toml, or from a machine-saved file, config.internal.toml
|
||||||
|
* @deprecated Use the new ConfigManager class instead
|
||||||
* Fuses both and provides a way to retrieve individual values
|
* Fuses both and provides a way to retrieve individual values
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
61
packages/log-manager/index.ts
Normal file
61
packages/log-manager/index.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
import type { BunFile } from "bun";
|
||||||
|
import { appendFile } from "fs/promises";
|
||||||
|
|
||||||
|
export enum LogLevel {
|
||||||
|
DEBUG = "debug",
|
||||||
|
INFO = "info",
|
||||||
|
WARNING = "warning",
|
||||||
|
ERROR = "error",
|
||||||
|
CRITICAL = "critical",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for handling logging to disk or to stdout
|
||||||
|
* @param output BunFile of output (can be a normal file or something like Bun.stdout)
|
||||||
|
*/
|
||||||
|
export class LogManager {
|
||||||
|
constructor(private output: BunFile) {
|
||||||
|
void this.write(
|
||||||
|
`--- INIT LogManager at ${new Date().toISOString()} --`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a message to the output
|
||||||
|
* @param level Importance of the log
|
||||||
|
* @param entity Emitter of the log
|
||||||
|
* @param message Message to log
|
||||||
|
* @param showTimestamp Whether to show the timestamp in the log
|
||||||
|
*/
|
||||||
|
async log(
|
||||||
|
level: LogLevel,
|
||||||
|
entity: string,
|
||||||
|
message: string,
|
||||||
|
showTimestamp = true
|
||||||
|
) {
|
||||||
|
await this.write(
|
||||||
|
`${showTimestamp ? new Date().toISOString() + " " : ""}[${level.toUpperCase()}] ${entity}: ${message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async write(text: string) {
|
||||||
|
if (this.output == Bun.stdout) {
|
||||||
|
await Bun.write(Bun.stdout, text + "\n");
|
||||||
|
} else {
|
||||||
|
if (!this.output.name) {
|
||||||
|
throw new Error(`Output file doesnt exist (and isnt stdout)`);
|
||||||
|
}
|
||||||
|
await appendFile(this.output.name, text + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs an error to the output, wrapper for log
|
||||||
|
* @param level Importance of the log
|
||||||
|
* @param entity Emitter of the log
|
||||||
|
* @param error Error to log
|
||||||
|
*/
|
||||||
|
async logError(level: LogLevel, entity: string, error: Error) {
|
||||||
|
await this.log(level, entity, error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
packages/log-manager/package.json
Normal file
6
packages/log-manager/package.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "log-manager",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"main": "index.ts",
|
||||||
|
"dependencies": { }
|
||||||
|
}
|
||||||
94
packages/log-manager/tests/log-manager.test.ts
Normal file
94
packages/log-manager/tests/log-manager.test.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
// FILEPATH: /home/jessew/Dev/lysand/packages/log-manager/log-manager.test.ts
|
||||||
|
import { LogManager, LogLevel } from "../index";
|
||||||
|
import type fs from "fs/promises";
|
||||||
|
import {
|
||||||
|
describe,
|
||||||
|
it,
|
||||||
|
beforeEach,
|
||||||
|
expect,
|
||||||
|
jest,
|
||||||
|
mock,
|
||||||
|
type Mock,
|
||||||
|
test,
|
||||||
|
} from "bun:test";
|
||||||
|
import type { BunFile } from "bun";
|
||||||
|
|
||||||
|
describe("LogManager", () => {
|
||||||
|
let logManager: LogManager;
|
||||||
|
let mockOutput: BunFile;
|
||||||
|
let mockAppend: Mock<typeof fs.appendFile>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
mockOutput = Bun.file("test.log");
|
||||||
|
mockAppend = jest.fn();
|
||||||
|
await mock.module("fs/promises", () => ({
|
||||||
|
appendFile: mockAppend,
|
||||||
|
}));
|
||||||
|
logManager = new LogManager(mockOutput);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should initialize and write init log", () => {
|
||||||
|
expect(mockAppend).toHaveBeenCalledWith(
|
||||||
|
mockOutput.name,
|
||||||
|
expect.stringContaining("--- INIT LogManager at")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should log message with timestamp", async () => {
|
||||||
|
await logManager.log(LogLevel.INFO, "TestEntity", "Test message");
|
||||||
|
expect(mockAppend).toHaveBeenCalledWith(
|
||||||
|
mockOutput.name,
|
||||||
|
expect.stringContaining("[INFO] TestEntity: Test message")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should log message without timestamp", async () => {
|
||||||
|
await logManager.log(
|
||||||
|
LogLevel.INFO,
|
||||||
|
"TestEntity",
|
||||||
|
"Test message",
|
||||||
|
false
|
||||||
|
);
|
||||||
|
expect(mockAppend).toHaveBeenCalledWith(
|
||||||
|
mockOutput.name,
|
||||||
|
"[INFO] TestEntity: Test message\n"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.skip("should write to stdout", async () => {
|
||||||
|
logManager = new LogManager(Bun.stdout);
|
||||||
|
await logManager.log(LogLevel.INFO, "TestEntity", "Test message");
|
||||||
|
|
||||||
|
const writeMock = jest.fn();
|
||||||
|
|
||||||
|
await mock.module("Bun", () => ({
|
||||||
|
stdout: Bun.stdout,
|
||||||
|
write: writeMock,
|
||||||
|
}));
|
||||||
|
|
||||||
|
expect(writeMock).toHaveBeenCalledWith(
|
||||||
|
Bun.stdout,
|
||||||
|
expect.stringContaining("[INFO] TestEntity: Test message")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should throw error if output file does not exist", () => {
|
||||||
|
mockAppend.mockImplementationOnce(() => {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error("Output file doesnt exist (and isnt stdout)")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
logManager.log(LogLevel.INFO, "TestEntity", "Test message")
|
||||||
|
).rejects.toThrow(Error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should log error message", async () => {
|
||||||
|
const error = new Error("Test error");
|
||||||
|
await logManager.logError(LogLevel.ERROR, "TestEntity", error);
|
||||||
|
expect(mockAppend).toHaveBeenCalledWith(
|
||||||
|
mockOutput.name,
|
||||||
|
expect.stringContaining("[ERROR] TestEntity: Test error")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue