Exporting file handling to seperate class

This commit is contained in:
Fabian Stamm 2018-10-05 13:16:49 +02:00
parent 912a4b3ad8
commit 59c571e860
10 changed files with 258 additions and 235 deletions

21
out/index.d.ts vendored
View File

@ -45,17 +45,11 @@ export interface LoggingBaseOptions {
} }
export declare class LoggingBase { export declare class LoggingBase {
private config; private config;
private writeLock; private logFile;
private setted_up; private errorFile;
private fileStream;
private errorStream;
private fileSize;
private errorSize;
private queue;
constructor(options?: Partial<LoggingBaseOptions> | string); constructor(options?: Partial<LoggingBaseOptions> | string);
console_out: boolean; console_out: boolean;
waitForSetup(): Promise<void>; waitForSetup(): Promise<any[]>;
private setup;
events: EventEmitter; events: EventEmitter;
debug(...message: any[]): void; debug(...message: any[]): void;
log(...message: any[]): void; log(...message: any[]): void;
@ -63,12 +57,7 @@ export declare class LoggingBase {
logWithCustomColors(type: LoggingTypes, colors: string, ...message: any[]): void; logWithCustomColors(type: LoggingTypes, colors: string, ...message: any[]): void;
error(error: Error | string): void; error(error: Error | string): void;
errorMessage(...message: any[]): void; errorMessage(...message: any[]): void;
private message; private message(type, message, customColors?, caller?);
private writeMessageToFile;
private checkQueue;
private writeToLogFile;
private writeToErrorFile;
private initializeFile;
} }
export declare let Logging: LoggingBase; export declare let Logging: LoggingBase;
export default Logging; export default Logging;
@ -76,5 +65,5 @@ export declare enum LoggingTypes {
Log = 0, Log = 0,
Warning = 1, Warning = 1,
Error = 2, Error = 2,
Debug = 3 Debug = 3,
} }

View File

@ -32,13 +32,87 @@ exports.Colors = {
}; };
const maxFileSize = 500000000; const maxFileSize = 500000000;
const OriginalErrorStackFunction = Error.prototype.prepareStackTrace; const OriginalErrorStackFunction = Error.prototype.prepareStackTrace;
class LoggingFiles {
constructor(file) {
this.size = 0;
this.stream = undefined;
this.lock = new lock_1.default();
this.queue = [];
this.file = path.resolve(file);
this.init();
}
static getFile(filename) {
filename = path.resolve(filename);
let file = this.files.find(e => e.file === filename);
if (!file) {
file = new LoggingFiles(filename);
this.files.push(file);
}
return file;
}
async awaitinit() {
(await this.lock.getLock()).release();
}
async init() {
let lock = await this.lock.getLock();
await this.initializeFile();
lock.release();
this.checkQueue();
}
async initializeFile(new_file = false) {
try {
const folder = path.dirname(this.file);
if (folder) {
if (!await fsExists(folder)) {
await fsMkDir(folder).catch(() => { }); //Could happen, if two seperate instances want to create the same folder so ignoring
}
}
let size = 0;
if (await fsExists(this.file)) {
let stats = await fsStat(this.file);
if (new_file || stats.size > maxFileSize) {
if (await fsExists(this.file + ".old"))
await fsUnlink(this.file + ".old");
await fsMove(this.file, this.file + ".old");
}
else {
size = stats.size;
}
}
this.stream = fs.createWriteStream(this.file, { flags: "a" });
this.size = size;
}
catch (e) {
console.log(e);
//ToDo is this the right behavior?
process.exit(1);
}
}
async checkQueue() {
if (this.lock.locked)
return;
let lock = await this.lock.getLock();
let msg;
while (msg = this.queue.shift()) {
await this.write_to_file(msg);
}
lock.release();
}
async write_to_file(data) {
if (data.byteLength < maxFileSize && this.size + data.byteLength > maxFileSize) {
let f = await this.initializeFile(true);
}
this.size += data.byteLength;
this.stream.write(data);
}
write(data) {
this.queue.push(data);
this.checkQueue();
}
}
LoggingFiles.files = [];
class LoggingBase { class LoggingBase {
constructor(options) { constructor(options) {
this.writeLock = new lock_1.default();
this.setted_up = false;
this.fileSize = 0;
this.errorSize = 0;
this.queue = new Array();
this.events = new events_1.EventEmitter(); this.events = new events_1.EventEmitter();
let opt; let opt;
if (!options) if (!options)
@ -67,6 +141,12 @@ class LoggingBase {
if (typeof this[key] === "function") if (typeof this[key] === "function")
this[key] = this[key].bind(this); this[key] = this[key].bind(this);
} }
if (this.config.logfile) {
this.logFile = LoggingFiles.getFile(this.config.logfile);
}
if (this.config.errorfile) {
this.errorFile = LoggingFiles.getFile(this.config.errorfile);
}
} }
get console_out() { get console_out() {
return this.config.console_out; return this.config.console_out;
@ -74,24 +154,13 @@ class LoggingBase {
set console_out(value) { set console_out(value) {
this.config.console_out = value; this.config.console_out = value;
} }
async waitForSetup() { waitForSetup() {
(await this.writeLock.getLock()).release(); let w = [];
} if (this.logFile)
async setup() { w.push(this.logFile.awaitinit());
this.setted_up = true; if (this.errorFile)
let lock = await this.writeLock.getLock(); w.push(this.errorFile.awaitinit());
if (this.config.logfile) { return Promise.all(w);
let f = await this.initializeFile(this.config.logfile, true);
this.fileStream = f.stream;
this.fileSize = f.size;
}
if (this.config.errorfile) {
let f = await this.initializeFile(this.config.errorfile, false);
this.errorStream = f.stream;
this.errorSize = f.size;
}
lock.release();
this.checkQueue();
} }
debug(...message) { debug(...message) {
this.message(LoggingTypes.Debug, message); this.message(LoggingTypes.Debug, message);
@ -119,7 +188,7 @@ class LoggingBase {
errorMessage(...message) { errorMessage(...message) {
this.message(LoggingTypes.Error, message); this.message(LoggingTypes.Error, message);
} }
async message(type, message, customColors, caller) { message(type, message, customColors, caller) {
var consoleLogFormat = exports.Colors.Reset; var consoleLogFormat = exports.Colors.Reset;
if (!customColors) { if (!customColors) {
switch (type) { switch (type) {
@ -145,10 +214,10 @@ class LoggingBase {
mb = message; mb = message;
} }
else { else {
message.forEach(e => { message.forEach((e, i) => {
if (typeof e !== "string") if (typeof e !== "string")
e = util.inspect(e, false, null); e = util.inspect(e, false, null);
if (e.endsWith("\n")) { if (e.endsWith("\n") || i === message.length - 1) {
mb += e; mb += e;
} }
else { else {
@ -167,89 +236,21 @@ class LoggingBase {
message_lines.forEach(line => console.log(consoleLogFormat + prefix + line + exports.Colors.Reset)); message_lines.forEach(line => console.log(consoleLogFormat + prefix + line + exports.Colors.Reset));
} }
let m = message_lines.join("\n"); let m = message_lines.join("\n");
m = m.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
let index = m.indexOf("\x1b"); let index = m.indexOf("\x1b");
while (index >= 0) { while (index >= 0) {
m = m.substring(0, index) + m.substring(index + 5, m.length); m = m.substring(0, index) + m.substring(index + 5, m.length);
index = m.indexOf("\x1b"); index = m.indexOf("\x1b");
} }
m = m.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ""); let data = Buffer.from(m + "\n");
this.writeMessageToFile(m, type === LoggingTypes.Error); if (type === LoggingTypes.Error && this.errorFile) {
this.errorFile.write(data);
}
if (this.logFile) {
this.logFile.write(data);
}
this.events.emit("message", { type: type, message: mb }); this.events.emit("message", { type: type, message: mb });
} }
writeMessageToFile(message, error) {
if (this.setted_up && (!this.fileStream || (error && !this.errorStream)))
return;
this.queue.push({ message: message.replace("\n", " "), error: error });
this.checkQueue();
}
async checkQueue() {
try {
if (this.writeLock.locked)
return;
if (this.queue.length <= 0)
return;
if (!this.setted_up)
return this.setup();
let lock = await this.writeLock.getLock();
var message = this.queue.shift();
message.message += "\n";
let data = new Buffer(message.message, "utf8");
await this.writeToLogFile(data);
if (message.error)
await this.writeToErrorFile(data);
lock.release();
if (this.queue.length > 0)
this.checkQueue();
}
catch (e) {
console.log(e);
}
}
async writeToLogFile(data) {
if (data.byteLength < maxFileSize && this.fileSize + data.byteLength > maxFileSize) {
let f = await this.initializeFile(this.config.logfile, true);
this.fileStream = f.stream;
this.fileSize = f.size;
}
this.fileSize += data.byteLength;
this.fileStream.write(data);
}
async writeToErrorFile(data) {
if (data.byteLength < maxFileSize && this.errorSize + data.byteLength > maxFileSize) {
let f = await this.initializeFile(this.config.errorfile, true);
this.errorStream = f.stream;
this.errorSize = f.size;
}
this.errorSize += data.byteLength;
this.errorStream.write(data);
}
async initializeFile(file, new_file = true) {
try {
const folder = path.dirname(file);
if (folder) {
if (!await fsExists(folder)) {
await fsMkDir(folder).catch(() => { }); //Could happen, if two seperate logger want to create folder so ignoring
}
}
let size = 0;
if (await fsExists(file)) {
let stats = await fsStat(file);
if (new_file || stats.size > maxFileSize) {
if (await fsExists(file + ".old"))
await fsUnlink(file + ".old");
await fsMove(file, file + ".old");
}
else {
size = stats.size;
}
}
return { stream: fs.createWriteStream(file, { flags: "a" }), size: size };
}
catch (e) {
console.log(e);
}
return { size: 0, stream: undefined };
}
} }
exports.LoggingBase = LoggingBase; exports.LoggingBase = LoggingBase;
exports.Logging = undefined; exports.Logging = undefined;

File diff suppressed because one or more lines are too long

4
out/lock.d.ts vendored
View File

@ -7,6 +7,6 @@ export default class Lock {
private toCome; private toCome;
constructor(); constructor();
getLock(): Promise<Release>; getLock(): Promise<Release>;
private lock; private lock();
private release; private release();
} }

View File

@ -1 +1 @@
{"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":";;AACA,MAAqB,IAAI;IAOtB;QANQ,YAAO,GAAY,KAAK,CAAC;QAIzB,WAAM,GAAmB,EAAE,CAAC;QAGjC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAPD,IAAI,MAAM;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACvB,CAAC;IAOD,KAAK,CAAC,OAAO;QACV,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;aAC9C;YACF,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;gBACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;oBACnB,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACrC,CAAC,CAAC,CAAA;YACL,CAAC,CAAC,CAAA;SACJ;IACJ,CAAC;IAEO,IAAI;QACT,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,OAAO;QAClB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;YACzB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;SACxB;aAAM;YACJ,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;SACvB;IACJ,CAAC;CACH;AAlCD,uBAkCC"} {"version":3,"file":"lock.js","sourceRoot":"","sources":["../src/lock.ts"],"names":[],"mappings":";;AACA;IAOG;QANQ,YAAO,GAAY,KAAK,CAAC;QAIzB,WAAM,GAAmB,EAAE,CAAC;QAGjC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,CAAC;IAPD,IAAI,MAAM;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACvB,CAAC;IAOD,KAAK,CAAC,OAAO;QACV,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;aAC9C;YACF,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;gBACrC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE;oBACnB,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACrC,CAAC,CAAC,CAAA;YACL,CAAC,CAAC,CAAA;SACJ;IACJ,CAAC;IAEO,IAAI;QACT,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC;IACvB,CAAC;IAEO,KAAK,CAAC,OAAO;QAClB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;YACzB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;SACxB;aAAM;YACJ,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;SACvB;IACJ,CAAC;CACH;AAlCD,uBAkCC"}

View File

@ -14,7 +14,18 @@ let cus = new index_1.LoggingBase({ name: "test" });
cus.log("Hello from custom Logger"); cus.log("Hello from custom Logger");
let cus2 = new index_1.LoggingBase("test2"); let cus2 = new index_1.LoggingBase("test2");
cus2.log("Hello from custom Logger 2"); cus2.log("Hello from custom Logger 2");
// Logging.console_out = false; let cus22 = new index_1.LoggingBase("test2");
cus22.log("Hello from custom Logger 22");
cus2.log("Hello from custom Logger 2");
cus22.log("Hello from custom Logger 22");
cus2.log("Hello from custom Logger 2");
cus22.log("Hello from custom Logger 22");
cus2.log("Hello from custom Logger 2");
cus22.log("Hello from custom Logger 22");
cus2.log("Hello from custom Logger 2");
cus22.log("Hello from custom Logger 22");
cus2.log("Hello from custom Logger 2");
index_1.Logging.console_out = false;
// Logging.waitForSetup().then(() => { // Logging.waitForSetup().then(() => {
// for (let i = 0; i < 7000; i++) { // for (let i = 0; i < 7000; i++) {
// Logging.log(randomBytes(50000).toString("hex")) // Logging.log(randomBytes(50000).toString("hex"))

View File

@ -1 +1 @@
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;AAAA,mCAA+C;AAG/C,eAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACnB,eAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;AAC1C,eAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;AACvC,eAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;AAClC,eAAO,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAE/C,eAAO,CAAC,GAAG,CAAC,gFAAgF,CAAC,CAAA;AAE7F,IAAI,GAAG,GAAG,IAAI,KAAK,EAAE,CAAA;AACrB,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;IAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;AAE/E,IAAI,GAAG,GAAG,IAAI,mBAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAC5C,GAAG,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAA;AAEnC,IAAI,IAAI,GAAG,IAAI,mBAAW,CAAC,OAAO,CAAC,CAAC;AACpC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AAEtC,+BAA+B;AAC/B,sCAAsC;AACtC,sCAAsC;AACtC,wDAAwD;AACxD,OAAO;AACP,MAAM"} {"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;AAAA,mCAA+C;AAG/C,eAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;AACnB,eAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;AAC1C,eAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;AACvC,eAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;AAClC,eAAO,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAE/C,eAAO,CAAC,GAAG,CAAC,gFAAgF,CAAC,CAAA;AAE7F,IAAI,GAAG,GAAG,IAAI,KAAK,EAAE,CAAA;AACrB,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;IAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,GAAG,CAAC,KAAK,CAAC,CAAA;AAE/E,IAAI,GAAG,GAAG,IAAI,mBAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AAC5C,GAAG,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAA;AAEnC,IAAI,IAAI,GAAG,IAAI,mBAAW,CAAC,OAAO,CAAC,CAAC;AACpC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AAEtC,IAAI,KAAK,GAAG,IAAI,mBAAW,CAAC,OAAO,CAAC,CAAC;AACrC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;AACxC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AACtC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;AACxC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AACtC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;AACxC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AACtC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;AACxC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AACtC,KAAK,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;AACxC,IAAI,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;AAEtC,eAAO,CAAC,WAAW,GAAG,KAAK,CAAC;AAC5B,sCAAsC;AACtC,sCAAsC;AACtC,wDAAwD;AACxD,OAAO;AACP,MAAM"}

View File

@ -1,6 +1,6 @@
{ {
"name": "@hibas123/nodelogging", "name": "@hibas123/nodelogging",
"version": "1.3.15", "version": "1.3.16",
"description": "", "description": "",
"main": "out/index.js", "main": "out/index.js",
"types": "out/index.d.ts", "types": "out/index.d.ts",

View File

@ -55,18 +55,99 @@ export interface LoggingBaseOptions {
console_out: boolean; console_out: boolean;
} }
class LoggingFiles {
private static files: LoggingFiles[] = [];
static getFile(filename: string): LoggingFiles {
filename = path.resolve(filename);
let file = this.files.find(e => e.file === filename);
if (!file) {
file = new LoggingFiles(filename);
this.files.push(file);
}
return file;
}
private file: string;
private size: number = 0;
private stream: fs.WriteStream = undefined;
private lock = new Lock();
private constructor(file: string) {
this.file = path.resolve(file);
this.init();
}
public async awaitinit() {
(await this.lock.getLock()).release();
}
private async init() {
let lock = await this.lock.getLock();
await this.initializeFile()
lock.release();
this.checkQueue()
}
private async initializeFile(new_file = false) {
try {
const folder = path.dirname(this.file);
if (folder) {
if (!await fsExists(folder)) {
await fsMkDir(folder).catch(() => { }); //Could happen, if two seperate instances want to create the same folder so ignoring
}
}
let size = 0;
if (await fsExists(this.file)) {
let stats = await fsStat(this.file);
if (new_file || stats.size > maxFileSize) {
if (await fsExists(this.file + ".old"))
await fsUnlink(this.file + ".old");
await fsMove(this.file, this.file + ".old")
} else {
size = stats.size;
}
}
this.stream = fs.createWriteStream(this.file, { flags: "a" })
this.size = size;
} catch (e) {
console.log(e);
//ToDo is this the right behavior?
process.exit(1);
}
}
private queue: Buffer[] = [];
async checkQueue() {
if (this.lock.locked) return;
let lock = await this.lock.getLock();
let msg: Buffer;
while (msg = this.queue.shift()) {
await this.write_to_file(msg);
}
lock.release();
}
private async write_to_file(data: Buffer) {
if (data.byteLength < maxFileSize && this.size + data.byteLength > maxFileSize) {
let f = await this.initializeFile(true);
}
this.size += data.byteLength;
this.stream.write(data);
}
public write(data: Buffer) {
this.queue.push(data);
this.checkQueue()
}
}
export class LoggingBase { export class LoggingBase {
private config: LoggingBaseOptions; private config: LoggingBaseOptions;
private writeLock = new Lock();
private setted_up = false; private logFile: LoggingFiles;
private errorFile: LoggingFiles;
private fileStream: fs.WriteStream;
private errorStream: fs.WriteStream;
private fileSize: number = 0;
private errorSize: number = 0;
private queue = new Array<{ message: string, error: boolean }>();
constructor(options?: Partial<LoggingBaseOptions> | string) { constructor(options?: Partial<LoggingBaseOptions> | string) {
let opt: Partial<LoggingBaseOptions>; let opt: Partial<LoggingBaseOptions>;
@ -95,6 +176,14 @@ export class LoggingBase {
for (let key in this) { for (let key in this) {
if (typeof this[key] === "function") this[key] = (<any>this[key]).bind(this); if (typeof this[key] === "function") this[key] = (<any>this[key]).bind(this);
} }
if (this.config.logfile) {
this.logFile = LoggingFiles.getFile(this.config.logfile);
}
if (this.config.errorfile) {
this.errorFile = LoggingFiles.getFile(this.config.errorfile);
}
} }
get console_out() { get console_out() {
@ -105,26 +194,11 @@ export class LoggingBase {
this.config.console_out = value; this.config.console_out = value;
} }
public async waitForSetup() { public waitForSetup() {
(await this.writeLock.getLock()).release(); let w = [];
} if (this.logFile) w.push(this.logFile.awaitinit());
if (this.errorFile) w.push(this.errorFile.awaitinit());
private async setup() { return Promise.all(w)
this.setted_up = true;
let lock = await this.writeLock.getLock();
if (this.config.logfile) {
let f = await this.initializeFile(this.config.logfile, true);
this.fileStream = f.stream;
this.fileSize = f.size;
}
if (this.config.errorfile) {
let f = await this.initializeFile(this.config.errorfile, false);
this.errorStream = f.stream;
this.errorSize = f.size;
}
lock.release();
this.checkQueue();
} }
public events: EventEmitter = new EventEmitter(); public events: EventEmitter = new EventEmitter();
@ -159,7 +233,7 @@ export class LoggingBase {
this.message(LoggingTypes.Error, message); this.message(LoggingTypes.Error, message);
} }
private async message(type: LoggingTypes, message: any[] | string, customColors?: string, caller?: { file: string, line: number }) { private message(type: LoggingTypes, message: any[] | string, customColors?: string, caller?: { file: string, line: number }) {
var consoleLogFormat = Colors.Reset; var consoleLogFormat = Colors.Reset;
if (!customColors) { if (!customColors) {
switch (type) { switch (type) {
@ -183,9 +257,9 @@ export class LoggingBase {
if (typeof message === "string") { if (typeof message === "string") {
mb = message; mb = message;
} else { } else {
message.forEach(e => { message.forEach((e, i) => {
if (typeof e !== "string") e = util.inspect(e, false, null); if (typeof e !== "string") e = util.inspect(e, false, null);
if (e.endsWith("\n")) { if (e.endsWith("\n") || i === message.length - 1) {
mb += e; mb += e;
} else { } else {
mb += e + " "; mb += e + " ";
@ -204,88 +278,24 @@ export class LoggingBase {
} }
let m = message_lines.join("\n"); let m = message_lines.join("\n");
m = m.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
let index = m.indexOf("\x1b"); let index = m.indexOf("\x1b");
while (index >= 0) { while (index >= 0) {
m = m.substring(0, index) + m.substring(index + 5, m.length); m = m.substring(0, index) + m.substring(index + 5, m.length);
index = m.indexOf("\x1b"); index = m.indexOf("\x1b");
} }
m = m.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ""); let data = Buffer.from(m + "\n")
this.writeMessageToFile(m, type === LoggingTypes.Error); if (type === LoggingTypes.Error && this.errorFile) {
this.errorFile.write(data);
}
if (this.logFile) {
this.logFile.write(data);
}
this.events.emit("message", { type: type, message: mb }); this.events.emit("message", { type: type, message: mb });
} }
private writeMessageToFile(message: string, error?: boolean) {
if (this.setted_up && (!this.fileStream || (error && !this.errorStream))) return;
this.queue.push({ message: message.replace("\n", " "), error: error });
this.checkQueue();
}
private async checkQueue() {
try {
if (this.writeLock.locked) return;
if (this.queue.length <= 0) return;
if (!this.setted_up) return this.setup();
let lock = await this.writeLock.getLock();
var message = this.queue.shift();
message.message += "\n";
let data = new Buffer(message.message, "utf8");
await this.writeToLogFile(data);
if (message.error) await this.writeToErrorFile(data);
lock.release();
if (this.queue.length > 0) this.checkQueue();
} catch (e) {
console.log(e)
}
}
private async writeToLogFile(data: Buffer) {
if (data.byteLength < maxFileSize && this.fileSize + data.byteLength > maxFileSize) {
let f = await this.initializeFile(this.config.logfile, true);
this.fileStream = f.stream;
this.fileSize = f.size;
}
this.fileSize += data.byteLength;
this.fileStream.write(data);
}
private async writeToErrorFile(data: Buffer) {
if (data.byteLength < maxFileSize && this.errorSize + data.byteLength > maxFileSize) {
let f = await this.initializeFile(this.config.errorfile, true);
this.errorStream = f.stream;
this.errorSize = f.size;
}
this.errorSize += data.byteLength;
this.errorStream.write(data);
}
private async initializeFile(file: string, new_file = true): Promise<{ stream: fs.WriteStream, size: number }> {
try {
const folder = path.dirname(file);
if (folder) {
if (!await fsExists(folder)) {
await fsMkDir(folder).catch(() => { }); //Could happen, if two seperate logger want to create folder so ignoring
}
}
let size = 0;
if (await fsExists(file)) {
let stats = await fsStat(file);
if (new_file || stats.size > maxFileSize) {
if (await fsExists(file + ".old"))
await fsUnlink(file + ".old");
await fsMove(file, file + ".old")
} else {
size = stats.size;
}
}
return { stream: fs.createWriteStream(file, { flags: "a" }), size: size };
} catch (e) {
console.log(e);
}
return { size: 0, stream: undefined };
}
} }
export let Logging: LoggingBase = undefined; export let Logging: LoggingBase = undefined;
@ -312,7 +322,7 @@ function fsStat(path: string) {
}) })
} }
function fsMove(oldPath, newPath) { function fsMove(oldPath: string, newPath: string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let callback = (err?) => { let callback = (err?) => {
@ -348,13 +358,13 @@ function fsMove(oldPath, newPath) {
}) })
} }
function fsExists(path) { function fsExists(path: string) {
return new Promise<boolean>((resolve, reject) => { return new Promise<boolean>((resolve, reject) => {
fs.exists(path, resolve); fs.exists(path, resolve);
}); });
} }
function fsMkDir(path) { function fsMkDir(path: string) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
fs.mkdir(path, (err) => err ? reject(err) : resolve()); fs.mkdir(path, (err) => err ? reject(err) : resolve());
}); });

View File

@ -18,7 +18,19 @@ cus.log("Hello from custom Logger")
let cus2 = new LoggingBase("test2"); let cus2 = new LoggingBase("test2");
cus2.log("Hello from custom Logger 2") cus2.log("Hello from custom Logger 2")
// Logging.console_out = false; let cus22 = new LoggingBase("test2");
cus22.log("Hello from custom Logger 22")
cus2.log("Hello from custom Logger 2")
cus22.log("Hello from custom Logger 22")
cus2.log("Hello from custom Logger 2")
cus22.log("Hello from custom Logger 22")
cus2.log("Hello from custom Logger 2")
cus22.log("Hello from custom Logger 22")
cus2.log("Hello from custom Logger 2")
cus22.log("Hello from custom Logger 22")
cus2.log("Hello from custom Logger 2")
Logging.console_out = false;
// Logging.waitForSetup().then(() => { // Logging.waitForSetup().then(() => {
// for (let i = 0; i < 7000; i++) { // for (let i = 0; i < 7000; i++) {
// Logging.log(randomBytes(50000).toString("hex")) // Logging.log(randomBytes(50000).toString("hex"))