mirror of
https://git.stamm.me/OpenServer/NodeLogging.git
synced 2024-11-25 09:59:23 +00:00
Redesign File writing and some tweaks
This commit is contained in:
parent
55344fb638
commit
29fee51b63
52
out/index.d.ts
vendored
52
out/index.d.ts
vendored
@ -1,27 +1,37 @@
|
|||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
export declare class Logging {
|
export interface LoggingBaseOptions {
|
||||||
private static logFileLocation;
|
logfile: string;
|
||||||
static stdout: boolean;
|
errorfile: string;
|
||||||
private static fileStream;
|
console_out: boolean;
|
||||||
private static errorStream;
|
|
||||||
private static fileSize;
|
|
||||||
private static errorSize;
|
|
||||||
private static writing;
|
|
||||||
private static queue;
|
|
||||||
static events: EventEmitter;
|
|
||||||
static config(logfolder: string, stdout: boolean): void;
|
|
||||||
static debug(...message: any[]): void;
|
|
||||||
static log(...message: any[]): void;
|
|
||||||
static warning(...message: any[]): void;
|
|
||||||
static logWithCustomColors(type: LoggingTypes, colors: string, ...message: any[]): void;
|
|
||||||
static error(error: Error | string): void;
|
|
||||||
static errorMessage(...message: any[]): void;
|
|
||||||
private static message(type, message, customColors?);
|
|
||||||
private static writeMessageToFile(message, error?);
|
|
||||||
private static checkQueue();
|
|
||||||
private static initializeFile();
|
|
||||||
}
|
}
|
||||||
|
export declare class LoggingBase {
|
||||||
|
private config;
|
||||||
|
private writeLock;
|
||||||
|
private fileStream;
|
||||||
|
private errorStream;
|
||||||
|
private fileSize;
|
||||||
|
private errorSize;
|
||||||
|
private queue;
|
||||||
|
constructor(options?: Partial<LoggingBaseOptions>);
|
||||||
|
console_out: boolean;
|
||||||
|
waitForSetup(): Promise<void>;
|
||||||
|
private setup();
|
||||||
|
events: EventEmitter;
|
||||||
|
debug(...message: any[]): void;
|
||||||
|
log(...message: any[]): void;
|
||||||
|
warning(...message: any[]): void;
|
||||||
|
logWithCustomColors(type: LoggingTypes, colors: string, ...message: any[]): void;
|
||||||
|
error(error: Error | string): void;
|
||||||
|
errorMessage(...message: any[]): void;
|
||||||
|
private message(type, message, customColors?);
|
||||||
|
private writeMessageToFile(message, error?);
|
||||||
|
private checkQueue();
|
||||||
|
private writeToLogFile(data);
|
||||||
|
private writeToErrorFile(data);
|
||||||
|
private initializeFile(file, new_file?);
|
||||||
|
}
|
||||||
|
export declare const Logging: LoggingBase;
|
||||||
export default Logging;
|
export default Logging;
|
||||||
export declare enum LoggingTypes {
|
export declare enum LoggingTypes {
|
||||||
Log = 0,
|
Log = 0,
|
||||||
|
252
out/index.js
252
out/index.js
@ -4,6 +4,7 @@ const util = require("util");
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const events_1 = require("events");
|
const events_1 = require("events");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
const lock_1 = require("./lock");
|
||||||
const Reset = "\x1b[0m";
|
const Reset = "\x1b[0m";
|
||||||
const Bright = "\x1b[1m";
|
const Bright = "\x1b[1m";
|
||||||
const Dim = "\x1b[2m";
|
const Dim = "\x1b[2m";
|
||||||
@ -29,36 +30,71 @@ const BgCyan = "\x1b[46m";
|
|||||||
const BgWhite = "\x1b[47m";
|
const BgWhite = "\x1b[47m";
|
||||||
const maxFileSize = 500000000;
|
const maxFileSize = 500000000;
|
||||||
const OriginalErrorStackFunction = Error.prototype.prepareStackTrace;
|
const OriginalErrorStackFunction = Error.prototype.prepareStackTrace;
|
||||||
class Logging {
|
class LoggingBase {
|
||||||
static config(logfolder, stdout) {
|
constructor(options) {
|
||||||
this.logFileLocation = logfolder;
|
this.writeLock = new lock_1.default();
|
||||||
this.stdout = stdout;
|
this.fileSize = 0;
|
||||||
|
this.errorSize = 0;
|
||||||
|
this.queue = new Array();
|
||||||
|
this.events = new events_1.EventEmitter();
|
||||||
|
if (!options)
|
||||||
|
options = {};
|
||||||
|
this.config = Object.assign({
|
||||||
|
console_out: true,
|
||||||
|
logfile: "./logs/all.log",
|
||||||
|
errorfile: "./logs/error.log"
|
||||||
|
}, options);
|
||||||
|
this.setup();
|
||||||
}
|
}
|
||||||
static debug(...message) {
|
get console_out() {
|
||||||
Logging.message(LoggingTypes.Debug, message);
|
return this.config.console_out;
|
||||||
}
|
}
|
||||||
static log(...message) {
|
set console_out(value) {
|
||||||
Logging.message(LoggingTypes.Log, message);
|
this.config.console_out = value;
|
||||||
}
|
}
|
||||||
static warning(...message) {
|
async waitForSetup() {
|
||||||
Logging.message(LoggingTypes.Warning, message);
|
(await this.writeLock.getLock()).release();
|
||||||
}
|
}
|
||||||
static logWithCustomColors(type, colors, ...message) {
|
async setup() {
|
||||||
Logging.message(type, message, colors);
|
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, true);
|
||||||
|
this.errorStream = f.stream;
|
||||||
|
this.errorSize = f.size;
|
||||||
|
}
|
||||||
|
lock.release();
|
||||||
|
this.checkQueue();
|
||||||
}
|
}
|
||||||
static error(error) {
|
debug(...message) {
|
||||||
|
this.message(LoggingTypes.Debug, message);
|
||||||
|
}
|
||||||
|
log(...message) {
|
||||||
|
this.message(LoggingTypes.Log, message);
|
||||||
|
}
|
||||||
|
warning(...message) {
|
||||||
|
this.message(LoggingTypes.Warning, message);
|
||||||
|
}
|
||||||
|
logWithCustomColors(type, colors, ...message) {
|
||||||
|
this.message(type, message, colors);
|
||||||
|
}
|
||||||
|
error(error) {
|
||||||
if (typeof error === "string") {
|
if (typeof error === "string") {
|
||||||
let e = new Error();
|
let e = new Error();
|
||||||
Logging.message(LoggingTypes.Error, [error, ":", e.stack]);
|
this.message(LoggingTypes.Error, [error, ":", e.stack]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Logging.message(LoggingTypes.Error, [error.name, ":", error.message, ":", error.stack]);
|
this.message(LoggingTypes.Error, [error.name, ":", error.message, ":", error.stack]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static errorMessage(...message) {
|
errorMessage(...message) {
|
||||||
Logging.message(LoggingTypes.Error, message);
|
this.message(LoggingTypes.Error, message);
|
||||||
}
|
}
|
||||||
static async message(type, message, customColors) {
|
async message(type, message, customColors) {
|
||||||
var consoleLogFormat = Reset;
|
var consoleLogFormat = Reset;
|
||||||
if (!customColors) {
|
if (!customColors) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -97,132 +133,122 @@ class Logging {
|
|||||||
}
|
}
|
||||||
let file = getCallerFile();
|
let file = getCallerFile();
|
||||||
let date = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
|
let date = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
|
||||||
var m = `[${LoggingTypes[type]}][${file.file}:${file.line}][${date}]: ${mb}`;
|
let prefix = `[${LoggingTypes[type]}][${file.file}:${file.line}][${date}]: `;
|
||||||
if (this.stdout)
|
let message_lines = mb.split("\n").map(line => prefix + line);
|
||||||
console.log(consoleLogFormat + m + Reset);
|
if (this.config.console_out)
|
||||||
|
message_lines.forEach(line => console.log(consoleLogFormat + line + Reset));
|
||||||
|
let m = message_lines.join("\n");
|
||||||
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, "");
|
m = m.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
|
||||||
if (this.logFileLocation) {
|
this.writeMessageToFile(m, type === LoggingTypes.Error);
|
||||||
if ((!this.fileStream || !this.errorStream) && !this.writing) {
|
this.events.emit("message", { type: type, message: mb });
|
||||||
Logging.initializeFile();
|
|
||||||
}
|
|
||||||
Logging.writeMessageToFile(m, type === LoggingTypes.Error);
|
|
||||||
}
|
|
||||||
Logging.events.emit("message", { type: type, message: mb });
|
|
||||||
}
|
}
|
||||||
static writeMessageToFile(message, error) {
|
writeMessageToFile(message, error) {
|
||||||
Logging.queue.push({ message: message.replace("\n", " "), error: error });
|
if (!this.writeLock.locked && !this.fileStream && !(error || this.errorStream))
|
||||||
Logging.checkQueue();
|
return;
|
||||||
|
this.queue.push({ message: message.replace("\n", " "), error: error });
|
||||||
|
this.checkQueue();
|
||||||
}
|
}
|
||||||
static async checkQueue() {
|
async checkQueue() {
|
||||||
try {
|
try {
|
||||||
if (Logging.writing)
|
if (this.writeLock.locked)
|
||||||
return;
|
return;
|
||||||
if (Logging.queue.length <= 0)
|
if (this.queue.length <= 0)
|
||||||
return;
|
return;
|
||||||
Logging.writing = true;
|
let lock = await this.writeLock.getLock();
|
||||||
var message = Logging.queue[0];
|
var message = this.queue.shift();
|
||||||
message.message += "\n";
|
message.message += "\n";
|
||||||
let data = new Buffer(message.message, "utf8");
|
let data = new Buffer(message.message, "utf8");
|
||||||
if (data.byteLength < maxFileSize && data.byteLength + Logging.fileSize > maxFileSize) {
|
await this.writeToLogFile(data);
|
||||||
Logging.fileStream.close();
|
if (message.error)
|
||||||
if (await fsExists(this.logFileLocation + "all.log.old"))
|
await this.writeToErrorFile(data);
|
||||||
await fsUnlink(this.logFileLocation + "all.log.old");
|
lock.release();
|
||||||
await fsMove(this.logFileLocation + "all.log", this.logFileLocation + "all.log.old");
|
if (this.queue.length > 0)
|
||||||
Logging.fileStream = fs.createWriteStream(this.logFileLocation + "all.log");
|
this.checkQueue();
|
||||||
Logging.fileSize = 0;
|
|
||||||
}
|
|
||||||
Logging.fileSize += data.byteLength;
|
|
||||||
Logging.fileStream.write(data, async () => {
|
|
||||||
if (message.error) {
|
|
||||||
if (data.byteLength < maxFileSize && data.byteLength + Logging.errorSize > maxFileSize) {
|
|
||||||
Logging.errorStream.close();
|
|
||||||
if (await fsExists(this.logFileLocation + "error.log.old"))
|
|
||||||
await fsUnlink(this.logFileLocation + "error.log.old");
|
|
||||||
await fsMove(this.logFileLocation + "error.log", this.logFileLocation + "error.log.old");
|
|
||||||
Logging.errorStream = fs.createWriteStream(this.logFileLocation + "error.log");
|
|
||||||
Logging.errorSize = 0;
|
|
||||||
}
|
|
||||||
Logging.errorSize += data.byteLength;
|
|
||||||
Logging.errorStream.write(data, () => {
|
|
||||||
Logging.queue.splice(Logging.queue.indexOf(message), 1);
|
|
||||||
Logging.writing = false;
|
|
||||||
Logging.checkQueue();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Logging.queue.splice(Logging.queue.indexOf(message), 1);
|
|
||||||
Logging.writing = false;
|
|
||||||
Logging.checkQueue();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static async initializeFile() {
|
async writeToLogFile(data) {
|
||||||
if (this.fileStream && this.errorStream)
|
if (data.byteLength < maxFileSize && this.fileSize + data.byteLength > maxFileSize) {
|
||||||
return;
|
let f = await this.initializeFile(this.config.logfile, true);
|
||||||
if (!this.logFileLocation)
|
this.fileStream = f.stream;
|
||||||
return;
|
this.fileSize = f.size;
|
||||||
this.writing = true;
|
}
|
||||||
|
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 {
|
try {
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
fs.exists(this.logFileLocation, (exists) => {
|
const folder = path.dirname(file);
|
||||||
if (!exists) {
|
if (folder)
|
||||||
fs.mkdir(this.logFileLocation, (err) => {
|
fs.exists(folder, (exists) => {
|
||||||
if (err) {
|
if (!exists) {
|
||||||
reject(err);
|
fs.mkdir(folder, (err) => {
|
||||||
}
|
if (err) {
|
||||||
else {
|
reject(err);
|
||||||
resolve();
|
}
|
||||||
}
|
else {
|
||||||
});
|
resolve();
|
||||||
}
|
}
|
||||||
else
|
});
|
||||||
resolve();
|
}
|
||||||
});
|
else
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
if (await fsExists(this.logFileLocation + "all.log")) {
|
let size = 0;
|
||||||
if (await fsExists(this.logFileLocation + "all.log.old"))
|
if (await fsExists(file)) {
|
||||||
await fsUnlink(this.logFileLocation + "all.log.old");
|
let stats = await fsStat(file);
|
||||||
await fsMove(this.logFileLocation + "all.log", this.logFileLocation + "all.log.old");
|
if (new_file || stats.size > maxFileSize) {
|
||||||
}
|
if (await fsExists(file + ".old"))
|
||||||
if (await fsExists(this.logFileLocation + "error.log")) {
|
await fsUnlink(file + ".old");
|
||||||
let stats = await fsStat(this.logFileLocation + "error.log");
|
await fsMove(file, file + ".old");
|
||||||
if (stats.size > maxFileSize) {
|
|
||||||
if (await fsExists(this.logFileLocation + "error.log.old"))
|
|
||||||
await fsUnlink(this.logFileLocation + "error.log.old");
|
|
||||||
await fsMove(this.logFileLocation + "error.log", this.logFileLocation + "error.log.old");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.errorSize = stats.size;
|
size = stats.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fileStream = fs.createWriteStream(this.logFileLocation + "all.log", { flags: "a" });
|
return { stream: fs.createWriteStream(file, { flags: "a" }), size: size };
|
||||||
this.errorStream = fs.createWriteStream(this.logFileLocation + "error.log", { flags: "a" });
|
// if (await fsExists(this.logFileLocation + "error.log")) {
|
||||||
this.writing = false;
|
// let stats = await fsStat(this.logFileLocation + "error.log")
|
||||||
this.checkQueue();
|
// if (stats.size > maxFileSize) {
|
||||||
|
// if (await fsExists(this.logFileLocation + "error.log.old"))
|
||||||
|
// await fsUnlink(this.logFileLocation + "error.log.old");
|
||||||
|
// await fsMove(this.logFileLocation + "error.log", this.logFileLocation + "error.log.old")
|
||||||
|
// } else {
|
||||||
|
// this.errorSize = stats.size;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// this.fileStream = fs.createWriteStream(this.logFileLocation + "all.log", { flags: "a" });
|
||||||
|
// this.errorStream = fs.createWriteStream(this.logFileLocation + "error.log", { flags: "a" });
|
||||||
|
// this.writing = false;
|
||||||
|
// this.checkQueue();
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
return { size: 0, stream: undefined };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Logging.logFileLocation = "./logs/";
|
exports.LoggingBase = LoggingBase;
|
||||||
Logging.stdout = true;
|
exports.Logging = new LoggingBase();
|
||||||
Logging.fileSize = 0;
|
exports.default = exports.Logging;
|
||||||
Logging.errorSize = 0;
|
|
||||||
Logging.writing = false;
|
|
||||||
Logging.queue = new Array();
|
|
||||||
Logging.events = new events_1.EventEmitter();
|
|
||||||
exports.Logging = Logging;
|
|
||||||
exports.default = Logging;
|
|
||||||
function fsUnlink(path) {
|
function fsUnlink(path) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fs.unlink(path, (err) => {
|
fs.unlink(path, (err) => {
|
||||||
|
File diff suppressed because one or more lines are too long
12
out/lock.d.ts
vendored
Normal file
12
out/lock.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export declare type Release = {
|
||||||
|
release: () => void;
|
||||||
|
};
|
||||||
|
export default class Lock {
|
||||||
|
private _locked;
|
||||||
|
readonly locked: boolean;
|
||||||
|
private toCome;
|
||||||
|
constructor();
|
||||||
|
getLock(): Promise<Release>;
|
||||||
|
private lock();
|
||||||
|
private release();
|
||||||
|
}
|
37
out/lock.js
Normal file
37
out/lock.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
class Lock {
|
||||||
|
constructor() {
|
||||||
|
this._locked = false;
|
||||||
|
this.toCome = [];
|
||||||
|
this.release = this.release.bind(this);
|
||||||
|
}
|
||||||
|
get locked() {
|
||||||
|
return this._locked;
|
||||||
|
}
|
||||||
|
async getLock() {
|
||||||
|
if (!this._locked)
|
||||||
|
return { release: this.lock() };
|
||||||
|
else {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
this.toCome.push(() => {
|
||||||
|
resolve({ release: this.lock() });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lock() {
|
||||||
|
this._locked = true;
|
||||||
|
return this.release;
|
||||||
|
}
|
||||||
|
async release() {
|
||||||
|
if (this.toCome.length > 0) {
|
||||||
|
this.toCome.shift()();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.default = Lock;
|
||||||
|
//# sourceMappingURL=lock.js.map
|
1
out/lock.js.map
Normal file
1
out/lock.js.map
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"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"}
|
10
out/test.js
10
out/test.js
@ -11,8 +11,10 @@ index_1.Logging.log("\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m TEST \x1b[
|
|||||||
let err = new Error();
|
let err = new Error();
|
||||||
if (typeof err.stack !== "string")
|
if (typeof err.stack !== "string")
|
||||||
console.log("Stacktrace invalid", err.stack);
|
console.log("Stacktrace invalid", err.stack);
|
||||||
index_1.Logging.stdout = false;
|
index_1.Logging.console_out = false;
|
||||||
for (let i = 0; i < 7000; i++) {
|
index_1.Logging.waitForSetup().then(() => {
|
||||||
index_1.Logging.log(crypto_1.randomBytes(50000).toString("hex"));
|
for (let i = 0; i < 7000; i++) {
|
||||||
}
|
index_1.Logging.log(crypto_1.randomBytes(50000).toString("hex"));
|
||||||
|
}
|
||||||
|
});
|
||||||
//# sourceMappingURL=test.js.map
|
//# sourceMappingURL=test.js.map
|
@ -1 +1 @@
|
|||||||
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;AAAA,mCAAkC;AAClC,mCAAqC;AAErC,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,eAAO,CAAC,MAAM,GAAG,KAAK,CAAC;AACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;IAC5B,eAAO,CAAC,GAAG,CAAC,oBAAW,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;CACjD"}
|
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":";;AAAA,mCAAkC;AAClC,mCAAqC;AAErC,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;AAC/E,eAAO,CAAC,WAAW,GAAG,KAAK,CAAC;AAC5B,eAAO,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;QAC5B,eAAO,CAAC,GAAG,CAAC,oBAAW,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAA;KACjD;AACJ,CAAC,CAAC,CAAC"}
|
257
src/index.ts
257
src/index.ts
@ -2,6 +2,7 @@ import * as util from "util";
|
|||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { EventEmitter } from "events";
|
import { EventEmitter } from "events";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
import Lock from "./lock";
|
||||||
|
|
||||||
const Reset = "\x1b[0m"
|
const Reset = "\x1b[0m"
|
||||||
const Bright = "\x1b[1m"
|
const Bright = "\x1b[1m"
|
||||||
@ -33,55 +34,94 @@ const maxFileSize = 500000000;
|
|||||||
|
|
||||||
const OriginalErrorStackFunction = (<any>Error.prototype).prepareStackTrace
|
const OriginalErrorStackFunction = (<any>Error.prototype).prepareStackTrace
|
||||||
|
|
||||||
export class Logging {
|
export interface LoggingBaseOptions {
|
||||||
private static logFileLocation: string = "./logs/";
|
logfile: string;
|
||||||
public static stdout: boolean = true;
|
errorfile: string;
|
||||||
|
console_out: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
private static fileStream: fs.WriteStream;
|
export class LoggingBase {
|
||||||
private static errorStream: fs.WriteStream;
|
private config: LoggingBaseOptions;
|
||||||
private static fileSize: number = 0;
|
private writeLock = new Lock();
|
||||||
private static errorSize: number = 0;
|
|
||||||
|
|
||||||
private static writing = false;
|
private fileStream: fs.WriteStream;
|
||||||
private static queue = new Array<{ message: string, error: boolean }>();
|
private errorStream: fs.WriteStream;
|
||||||
|
private fileSize: number = 0;
|
||||||
|
private errorSize: number = 0;
|
||||||
|
|
||||||
static events: EventEmitter = new EventEmitter();
|
private queue = new Array<{ message: string, error: boolean }>();
|
||||||
|
|
||||||
static config(logfolder: string, stdout: boolean) {
|
constructor(options?: Partial<LoggingBaseOptions>) {
|
||||||
this.logFileLocation = logfolder;
|
if (!options) options = {};
|
||||||
this.stdout = stdout;
|
this.config = Object.assign(<LoggingBaseOptions>{
|
||||||
|
console_out: true,
|
||||||
|
logfile: "./logs/all.log",
|
||||||
|
errorfile: "./logs/error.log"
|
||||||
|
}, options);
|
||||||
|
this.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static debug(...message: any[]) {
|
get console_out() {
|
||||||
Logging.message(LoggingTypes.Debug, message);
|
return this.config.console_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static log(...message: any[]) {
|
set console_out(value) {
|
||||||
Logging.message(LoggingTypes.Log, message);
|
this.config.console_out = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static warning(...message: any[]) {
|
public async waitForSetup() {
|
||||||
Logging.message(LoggingTypes.Warning, message);
|
(await this.writeLock.getLock()).release();
|
||||||
}
|
}
|
||||||
|
|
||||||
static logWithCustomColors(type: LoggingTypes, colors: string, ...message: any[]) {
|
private async setup() {
|
||||||
Logging.message(type, message, colors);
|
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, true);
|
||||||
|
this.errorStream = f.stream;
|
||||||
|
this.errorSize = f.size;
|
||||||
|
}
|
||||||
|
lock.release();
|
||||||
|
this.checkQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
static error(error: Error | string) {
|
events: EventEmitter = new EventEmitter();
|
||||||
|
|
||||||
|
debug(...message: any[]) {
|
||||||
|
this.message(LoggingTypes.Debug, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(...message: any[]) {
|
||||||
|
this.message(LoggingTypes.Log, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
warning(...message: any[]) {
|
||||||
|
this.message(LoggingTypes.Warning, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
logWithCustomColors(type: LoggingTypes, colors: string, ...message: any[]) {
|
||||||
|
this.message(type, message, colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(error: Error | string) {
|
||||||
if (typeof error === "string") {
|
if (typeof error === "string") {
|
||||||
let e = new Error()
|
let e = new Error()
|
||||||
Logging.message(LoggingTypes.Error, [error, ":", e.stack]);
|
this.message(LoggingTypes.Error, [error, ":", e.stack]);
|
||||||
} else {
|
} else {
|
||||||
Logging.message(LoggingTypes.Error, [error.name, ":", error.message, ":", error.stack]);
|
this.message(LoggingTypes.Error, [error.name, ":", error.message, ":", error.stack]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static errorMessage(...message: any[]) {
|
errorMessage(...message: any[]) {
|
||||||
Logging.message(LoggingTypes.Error, message);
|
this.message(LoggingTypes.Error, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async message(type: LoggingTypes, message: any[] | string, customColors?: string) {
|
private async message(type: LoggingTypes, message: any[] | string, customColors?: string) {
|
||||||
var consoleLogFormat = Reset;
|
var consoleLogFormat = Reset;
|
||||||
if (!customColors) {
|
if (!customColors) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -116,9 +156,12 @@ export class Logging {
|
|||||||
}
|
}
|
||||||
let file = getCallerFile()
|
let file = getCallerFile()
|
||||||
let date = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
|
let date = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
|
||||||
var m = `[${LoggingTypes[type]}][${file.file}:${file.line}][${date}]: ${mb}`;
|
let prefix = `[${LoggingTypes[type]}][${file.file}:${file.line}][${date}]: `;
|
||||||
if (this.stdout) console.log(consoleLogFormat + m + Reset);
|
let message_lines = mb.split("\n").map(line => prefix + line);
|
||||||
|
|
||||||
|
if (this.config.console_out) message_lines.forEach(line => console.log(consoleLogFormat + line + Reset));
|
||||||
|
|
||||||
|
let m = message_lines.join("\n");
|
||||||
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);
|
||||||
@ -126,111 +169,107 @@ export class Logging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m = m.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
|
m = m.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
|
||||||
|
this.writeMessageToFile(m, type === LoggingTypes.Error);
|
||||||
if (this.logFileLocation) {
|
this.events.emit("message", { type: type, message: mb });
|
||||||
if ((!this.fileStream || !this.errorStream) && !this.writing) {
|
|
||||||
Logging.initializeFile();
|
|
||||||
}
|
|
||||||
Logging.writeMessageToFile(m, type === LoggingTypes.Error);
|
|
||||||
}
|
|
||||||
Logging.events.emit("message", { type: type, message: mb });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static writeMessageToFile(message: string, error?: boolean) {
|
private writeMessageToFile(message: string, error?: boolean) {
|
||||||
Logging.queue.push({ message: message.replace("\n", " "), error: error });
|
if (!this.writeLock.locked && !this.fileStream && !(error || this.errorStream)) return;
|
||||||
Logging.checkQueue();
|
this.queue.push({ message: message.replace("\n", " "), error: error });
|
||||||
|
this.checkQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async checkQueue() {
|
private async checkQueue() {
|
||||||
try {
|
try {
|
||||||
if (Logging.writing) return;
|
if (this.writeLock.locked) return;
|
||||||
if (Logging.queue.length <= 0) return;
|
if (this.queue.length <= 0) return;
|
||||||
Logging.writing = true;
|
let lock = await this.writeLock.getLock();
|
||||||
var message = Logging.queue[0];
|
var message = this.queue.shift();
|
||||||
message.message += "\n";
|
message.message += "\n";
|
||||||
let data = new Buffer(message.message, "utf8");
|
let data = new Buffer(message.message, "utf8");
|
||||||
if (data.byteLength < maxFileSize && data.byteLength + Logging.fileSize > maxFileSize) {
|
await this.writeToLogFile(data);
|
||||||
Logging.fileStream.close();
|
if (message.error) await this.writeToErrorFile(data);
|
||||||
if (await fsExists(this.logFileLocation + "all.log.old"))
|
lock.release();
|
||||||
await fsUnlink(this.logFileLocation + "all.log.old");
|
if (this.queue.length > 0) this.checkQueue();
|
||||||
await fsMove(this.logFileLocation + "all.log", this.logFileLocation + "all.log.old")
|
|
||||||
Logging.fileStream = fs.createWriteStream(this.logFileLocation + "all.log");
|
|
||||||
Logging.fileSize = 0;
|
|
||||||
}
|
|
||||||
Logging.fileSize += data.byteLength;
|
|
||||||
Logging.fileStream.write(data, async () => {
|
|
||||||
if (message.error) {
|
|
||||||
if (data.byteLength < maxFileSize && data.byteLength + Logging.errorSize > maxFileSize) {
|
|
||||||
Logging.errorStream.close();
|
|
||||||
if (await fsExists(this.logFileLocation + "error.log.old"))
|
|
||||||
await fsUnlink(this.logFileLocation + "error.log.old");
|
|
||||||
await fsMove(this.logFileLocation + "error.log", this.logFileLocation + "error.log.old")
|
|
||||||
Logging.errorStream = fs.createWriteStream(this.logFileLocation + "error.log");
|
|
||||||
Logging.errorSize = 0;
|
|
||||||
}
|
|
||||||
Logging.errorSize += data.byteLength;
|
|
||||||
Logging.errorStream.write(data, () => {
|
|
||||||
Logging.queue.splice(Logging.queue.indexOf(message), 1);
|
|
||||||
Logging.writing = false;
|
|
||||||
Logging.checkQueue();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
Logging.queue.splice(Logging.queue.indexOf(message), 1);
|
|
||||||
Logging.writing = false;
|
|
||||||
Logging.checkQueue();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async initializeFile() {
|
private async writeToLogFile(data: Buffer) {
|
||||||
if (this.fileStream && this.errorStream) return;
|
if (data.byteLength < maxFileSize && this.fileSize + data.byteLength > maxFileSize) {
|
||||||
if (!this.logFileLocation) return;
|
let f = await this.initializeFile(this.config.logfile, true);
|
||||||
this.writing = 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 {
|
try {
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
fs.exists(this.logFileLocation, (exists) => {
|
const folder = path.dirname(file);
|
||||||
if (!exists) {
|
if (folder)
|
||||||
fs.mkdir(this.logFileLocation, (err) => {
|
fs.exists(folder, (exists) => {
|
||||||
if (err) {
|
if (!exists) {
|
||||||
reject(err);
|
fs.mkdir(folder, (err) => {
|
||||||
} else {
|
if (err) {
|
||||||
resolve();
|
reject(err);
|
||||||
}
|
} else {
|
||||||
});
|
resolve();
|
||||||
} else resolve();
|
}
|
||||||
});
|
});
|
||||||
|
} else resolve();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (await fsExists(this.logFileLocation + "all.log")) {
|
let size = 0;
|
||||||
if (await fsExists(this.logFileLocation + "all.log.old"))
|
if (await fsExists(file)) {
|
||||||
await fsUnlink(this.logFileLocation + "all.log.old");
|
let stats = await fsStat(file);
|
||||||
await fsMove(this.logFileLocation + "all.log", this.logFileLocation + "all.log.old")
|
if (new_file || stats.size > maxFileSize) {
|
||||||
}
|
if (await fsExists(file + ".old"))
|
||||||
|
await fsUnlink(file + ".old");
|
||||||
if (await fsExists(this.logFileLocation + "error.log")) {
|
await fsMove(file, file + ".old")
|
||||||
let stats = await fsStat(this.logFileLocation + "error.log")
|
|
||||||
if (stats.size > maxFileSize) {
|
|
||||||
if (await fsExists(this.logFileLocation + "error.log.old"))
|
|
||||||
await fsUnlink(this.logFileLocation + "error.log.old");
|
|
||||||
await fsMove(this.logFileLocation + "error.log", this.logFileLocation + "error.log.old")
|
|
||||||
} else {
|
} else {
|
||||||
this.errorSize = stats.size;
|
size = stats.size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fileStream = fs.createWriteStream(this.logFileLocation + "all.log", { flags: "a" });
|
return { stream: fs.createWriteStream(file, { flags: "a" }), size: size };
|
||||||
this.errorStream = fs.createWriteStream(this.logFileLocation + "error.log", { flags: "a" });
|
|
||||||
this.writing = false;
|
// if (await fsExists(this.logFileLocation + "error.log")) {
|
||||||
this.checkQueue();
|
// let stats = await fsStat(this.logFileLocation + "error.log")
|
||||||
|
// if (stats.size > maxFileSize) {
|
||||||
|
// if (await fsExists(this.logFileLocation + "error.log.old"))
|
||||||
|
// await fsUnlink(this.logFileLocation + "error.log.old");
|
||||||
|
// await fsMove(this.logFileLocation + "error.log", this.logFileLocation + "error.log.old")
|
||||||
|
// } else {
|
||||||
|
// this.errorSize = stats.size;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.fileStream = fs.createWriteStream(this.logFileLocation + "all.log", { flags: "a" });
|
||||||
|
// this.errorStream = fs.createWriteStream(this.logFileLocation + "error.log", { flags: "a" });
|
||||||
|
// this.writing = false;
|
||||||
|
// this.checkQueue();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
|
return { size: 0, stream: undefined };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
export const Logging = new LoggingBase();
|
||||||
export default Logging;
|
export default Logging;
|
||||||
|
|
||||||
function fsUnlink(path) {
|
function fsUnlink(path) {
|
||||||
|
36
src/lock.ts
Normal file
36
src/lock.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
export type Release = { release: () => void };
|
||||||
|
export default class Lock {
|
||||||
|
private _locked: boolean = false;
|
||||||
|
get locked() {
|
||||||
|
return this._locked;
|
||||||
|
}
|
||||||
|
private toCome: (() => void)[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.release = this.release.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getLock(): Promise<Release> {
|
||||||
|
if (!this._locked) return { release: this.lock() };
|
||||||
|
else {
|
||||||
|
return new Promise<Release>((resolve) => {
|
||||||
|
this.toCome.push(() => {
|
||||||
|
resolve({ release: this.lock() });
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lock() {
|
||||||
|
this._locked = true;
|
||||||
|
return this.release;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async release() {
|
||||||
|
if (this.toCome.length > 0) {
|
||||||
|
this.toCome.shift()();
|
||||||
|
} else {
|
||||||
|
this._locked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
src/test.ts
11
src/test.ts
@ -11,8 +11,9 @@ Logging.log("\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m TEST \x1b[31m\x1b[
|
|||||||
|
|
||||||
let err = new Error()
|
let err = new Error()
|
||||||
if (typeof err.stack !== "string") console.log("Stacktrace invalid", err.stack)
|
if (typeof err.stack !== "string") console.log("Stacktrace invalid", err.stack)
|
||||||
|
Logging.console_out = false;
|
||||||
Logging.stdout = false;
|
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"))
|
||||||
}
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user