107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
import path from 'path';
|
|
import { Readable } from 'stream';
|
|
import * as fs from 'fs-extra';
|
|
import { injectable } from 'inversify';
|
|
import { appPath } from '../../core/app-path';
|
|
import { isDev } from '../../core/env';
|
|
import { LogLevel } from './log-level';
|
|
|
|
const loggingDir = path.resolve(appPath, 'logs');
|
|
const logFile = path.resolve(loggingDir, 'default.log');
|
|
const exceptionLogFile = path.resolve(loggingDir, 'exception.log');
|
|
const maxLogSize = 50000;
|
|
|
|
/**
|
|
* A logger not using winston to log to files in the appPath.
|
|
*/
|
|
@injectable()
|
|
export class Logger implements LoggerInterface {
|
|
public constructor() {
|
|
fs.createFileSync(logFile);
|
|
fs.createFileSync(exceptionLogFile);
|
|
}
|
|
|
|
private static writeStream(stream: NodeJS.ReadableStream, filePath: string): Promise<void> {
|
|
return new Promise((resolve) => {
|
|
let buffer = fs.readFileSync(filePath, {
|
|
flag: 'r',
|
|
});
|
|
|
|
stream.on('data', (chunk) => {
|
|
buffer = Buffer.concat([buffer, Buffer.from(chunk)]);
|
|
});
|
|
|
|
stream.on('end', () => {
|
|
const diff = buffer.byteLength - maxLogSize;
|
|
if (diff > 0) {
|
|
buffer = buffer.slice(diff);
|
|
const firstLineBreakIndex = buffer.findIndex((value) => String.fromCharCode(value) === '\n');
|
|
buffer = buffer.slice(firstLineBreakIndex + 1);
|
|
}
|
|
fs.writeFileSync(filePath, buffer);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
private static writeLine(line: string): Promise<void> {
|
|
return Logger.writeStream(Readable.from(`${line}\n`), logFile);
|
|
}
|
|
|
|
private static formatLine(level: LogLevel, message: string): string {
|
|
return `[${new Date().toISOString()}] ${LogLevel[level]}: ${message}`;
|
|
}
|
|
|
|
public getLogFile(): string {
|
|
return logFile;
|
|
}
|
|
|
|
public getExceptionsLogFile(): string {
|
|
return exceptionLogFile;
|
|
}
|
|
|
|
public exception(error: Error): Promise<void> {
|
|
return Logger.writeStream(
|
|
Readable.from(
|
|
`[${new Date().toISOString()}] ${(error as NodeJS.ErrnoException).code ?? 'Error'}: ${error.message}
|
|
${error.stack ?? 'no stack trace'}\n`
|
|
),
|
|
exceptionLogFile
|
|
);
|
|
}
|
|
|
|
public log(level: LogLevel, message: string): Promise<void> {
|
|
if (!isDev() && level === LogLevel.debug) {
|
|
return Promise.resolve();
|
|
}
|
|
return Logger.writeLine(Logger.formatLine(level, message)).catch((error) => {
|
|
// eslint-disable-next-line no-console -- I don't want logging to be a source of a fatal error, but i want to log it somewhere
|
|
console.error(error);
|
|
});
|
|
}
|
|
|
|
public fatal(message: string): Promise<void> {
|
|
return this.log(LogLevel.fatal, message);
|
|
}
|
|
|
|
public error(message: string): Promise<void> {
|
|
return this.log(LogLevel.error, message);
|
|
}
|
|
|
|
public warning(message: string): Promise<void> {
|
|
return this.log(LogLevel.warning, message);
|
|
}
|
|
|
|
public notice(message: string): Promise<void> {
|
|
return this.log(LogLevel.notice, message);
|
|
}
|
|
|
|
public info(message: string): Promise<void> {
|
|
return this.log(LogLevel.info, message);
|
|
}
|
|
|
|
public debug(message: string): Promise<void> {
|
|
return this.log(LogLevel.debug, message);
|
|
}
|
|
}
|