This commit is contained in:
Fabian Stamm 2020-04-09 17:47:43 +02:00
commit b647b8fae6
4 changed files with 377 additions and 275 deletions

View File

@ -1,6 +1,6 @@
{
"name": "@hibas123/logging",
"version": "2.1.5",
"version": "2.2.2",
"description": "",
"main": "out/index.js",
"types": "out/index.d.ts",

View File

@ -1,10 +1,27 @@
import { Observable } from "@hibas123/utils";
import { ConsoleAdapter } from "./consolewriter";
import inspect from "./inspect";
import { Adapter, LoggingTypes, Message, FormatConfig, DefaultFormatConfig, Format, FormatTypes, Colors, FormattedText, FormattedLine } from "./types";
import {
Adapter,
LoggingTypes,
Message,
FormatConfig,
DefaultFormatConfig,
Format,
FormatTypes,
Colors,
FormattedText,
FormattedLine,
} from "./types";
import Logging from ".";
const browser = typeof window !== "undefined";
export function removeColors(text: string) {
text = text.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
text = text.replace(
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
""
);
// let index = text.indexOf("\x1b");
// while (index >= 0) {
@ -18,7 +35,7 @@ export interface LoggingBaseOptions {
/**
* Name will be prefixed on Console output and added to logfiles, if not specified here
*/
name: string,
name: string;
/**
* Prints output to console
*/
@ -26,21 +43,20 @@ export interface LoggingBaseOptions {
}
export class LoggingBase {
private _formatMap: FormatConfig = new DefaultFormatConfig();
public set formatMap(value: FormatConfig) {
this._formatMap = value;
}
private adapter = new Set<Adapter>();
private adapter_init: Promise<void>[] = [];
private timerMap = new Map<string, { name: string; start: any }>();
private messageObservable = new Observable<Message>();
protected _name: string;
private _logLevel = LoggingTypes.Debug;
get logLevel() {
@ -57,7 +73,7 @@ export class LoggingBase {
constructor(options?: Partial<LoggingBaseOptions> | string) {
let opt: Partial<LoggingBaseOptions>;
if (!options) opt = {}
if (!options) opt = {};
else if (typeof options === "string") {
opt = { name: options };
} else {
@ -67,21 +83,20 @@ export class LoggingBase {
let config: LoggingBaseOptions = {
name: undefined,
console: true,
...opt
...opt,
};
if (config.name)
this._name = config.name;
if (config.name) this._name = config.name;
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 (config.console) {
this.addAdapter(new ConsoleAdapter());
}
//Binding function to this
this.debug = this.debug.bind(this);
this.log = this.log.bind(this);
@ -95,7 +110,9 @@ export class LoggingBase {
addAdapter(adapter: Adapter) {
if (!this.adapter.has(adapter)) {
this.adapter.add(adapter);
let prms = Promise.resolve(adapter.init(this.messageObservable.getPublicApi(), this._name));
let prms = Promise.resolve(
adapter.init(this.messageObservable.getPublicApi(), this._name)
);
this.adapter_init.push(prms);
}
}
@ -104,16 +121,18 @@ export class LoggingBase {
flush(sync: false): Promise<void>;
flush(sync: boolean): void | Promise<void> {
if (sync) {
this.adapter.forEach(elm => elm.flush(true));
this.adapter.forEach((elm) => elm.flush(true));
} else {
let adapters: (void | Promise<void>)[] = [];
this.adapter.forEach(elm => adapters.push(elm.flush(false)));
this.adapter.forEach((elm) => adapters.push(elm.flush(false)));
return Promise.all(adapters).then(() => {});
}
}
public close() {
this.adapter.forEach(adapter => adapter.close ? adapter.close() : undefined);
this.adapter.forEach((adapter) =>
adapter.close ? adapter.close() : undefined
);
}
public waitForSetup() {
@ -141,14 +160,18 @@ export class LoggingBase {
}
error(error: Error | string) {
if (this._logLevel > LoggingTypes.Error)
return;
if (!error) error = "Empty ERROR was passed, so no informations available";
if (this._logLevel > LoggingTypes.Error) return;
if (!error)
error = "Empty ERROR was passed, so no informations available";
if (typeof error === "string") {
let e = new Error("This is a fake error, to get a stack trace");
this.message(LoggingTypes.Error, [error, "\n", e.stack]);
} else {
this.message(LoggingTypes.Error, [error.message, "\n", error.stack], getCallerFromExisting(error));
this.message(
LoggingTypes.Error,
[error.message, "\n", error.stack],
getCallerFromExisting(error)
);
}
}
@ -157,8 +180,61 @@ export class LoggingBase {
this.message(LoggingTypes.Error, message);
}
private message(type: LoggingTypes, message: any[], caller?: { file: string, line: number }) {
let date = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
protected getCurrentTime(): any {
if (browser && window.performance && window.performance.now) {
return window.performance.now();
} else {
return Date.now();
}
}
/**
* The time difference in milliseconds (fractions allowed!)
* @param start Start time from getCurrentTime
*/
protected getTimeDiff(start: any) {
if (browser && window.performance && window.performance.now) {
return window.performance.now() - start;
} else {
return Date.now() - start;
}
}
time(id?: string, name = id) {
if (!id) {
id = Math.floor(Math.random() * 899999 + 100000).toString();
}
this.timerMap.set(id, {
name,
start: this.getCurrentTime(),
});
return {
id,
end: () => this.timeEnd(id),
};
}
timeEnd(id: string) {
let timer = this.timerMap.get(id);
if (timer) {
let diff = this.getTimeDiff(timer.start);
Logging.message(LoggingTypes.Debug, [
withColor(Colors.GREEN, `[${timer.name}]`),
`->`,
withColor(Colors.BLUE, diff.toFixed(4)),
"ms",
]);
}
}
private message(
type: LoggingTypes,
message: any[],
caller?: { file: string; line: number }
) {
let date = new Date().toISOString().replace(/T/, " ").replace(/\..+/, "");
let file_raw = caller || getCallerFile();
let file = `${file_raw.file}:${String(file_raw.line).padEnd(3, " ")}`;
@ -184,9 +260,9 @@ export class LoggingBase {
const a = (text: string, formats: Format[] = []) => {
prefix.push({
text,
formats
})
}
formats,
});
};
a("[");
a(date, this._formatMap.date);
@ -198,7 +274,6 @@ export class LoggingBase {
}
a("]: ");
let raw: string[] = [];
const formatted: FormattedLine[] = [];
@ -206,10 +281,10 @@ export class LoggingBase {
const newLine = () => {
if (line && line.length > 0) {
formatted.push(line);
raw.push(line.map(e => e.text).join(""));
raw.push(line.map((e) => e.text).join(""));
}
line = [...prefix];
}
};
newLine();
message.forEach((e, i) => {
@ -219,21 +294,27 @@ export class LoggingBase {
if (e[colorSymbol]) {
formats.push({
type: FormatTypes.COLOR,
color: e[colorSymbol]
})
color: e[colorSymbol],
});
e = e.value;
}
}
if (typeof e !== "string")
e = inspect(e, { colors: true, showHidden: true, depth: 3 }) as string;
e = inspect(e, {
colors: true,
showHidden: true,
depth: 3,
}) as string;
}
removeColors(e).split("\n").map((text, index, { length }) => {
removeColors(e)
.split("\n")
.map((text, index, { length }) => {
line.push({ text, formats });
if (index < length - 1) {
newLine();
}
})
});
if (!e.endsWith("\n") && i < message.length - 1) {
line.push({ text: " ", formats: [] });
@ -248,10 +329,10 @@ export class LoggingBase {
name: this._name,
text: {
raw,
formatted
formatted,
},
type
}
type,
};
this.messageObservable.send(msg);
}
@ -267,8 +348,8 @@ export interface ColorFormat {
export function withColor(color: Colors, value: any): ColorFormat {
return {
[colorSymbol]: color,
value
}
value,
};
}
function getStack() {
@ -277,8 +358,8 @@ function getStack() {
// Override with function that just returns `stack`
(<any>Error).prepareStackTrace = function (_, stack) {
return stack
}
return stack;
};
// Create a new `Error`, which automatically gets `stack`
let err = new Error();
@ -292,7 +373,7 @@ function getStack() {
// Remove superfluous function call on stack
stack.shift(); // getStack --> Error
return stack
return stack;
}
function baseName(path) {
@ -301,7 +382,7 @@ function baseName(path) {
function getCallerFile() {
try {
let stack = getStack()
let stack = getStack();
let current_file = stack.shift().getFileName();
@ -310,24 +391,25 @@ function getCallerFile() {
if (current_file !== caller_file.getFileName())
return {
file: baseName(caller_file.getFileName()),
line: caller_file.getLineNumber()
line: caller_file.getLineNumber(),
};
}
} catch (err) {}
return { file: undefined, line: 0 };
}
function getCallerFromExisting(err: Error): { file: string, line: number } {
function getCallerFromExisting(err: Error): { file: string; line: number } {
if (!err || !err.stack) return { file: "NOFILE", line: 0 };
let lines = err.stack.split("\n");
lines.shift(); // removing first line
while (lines.length > 0) {
let line = lines.shift();
let matches = line.match(/[a-zA-Z_-]+[.][a-zA-Z_-]+[:][0-9]+/g)
let matches = line.match(/[a-zA-Z_-]+[.][a-zA-Z_-]+[:][0-9]+/g);
if (matches && matches.length > 0) {
let [f, line] = matches[0].split(":")
let [f, line] = matches[0].split(":");
return {
file: f, line: Number(line)
file: f,
line: Number(line),
};
}
}

View File

@ -1,11 +1,19 @@
import { ObservableInterface } from "@hibas123/utils";
import { Colors } from "./index";
import {
<<<<<<< HEAD
Adapter,
Message,
FormattedLine,
TerminalFormats,
FormatTypes
=======
Adapter,
Message,
FormattedLine,
TerminalFormats,
FormatTypes,
>>>>>>> facb7e7b403e1dfaa8790426259e6effb0618efb
} from "./types";
const browser = typeof window !== "undefined";
@ -15,7 +23,11 @@ export class ConsoleAdapter implements Adapter {
observable.subscribe(this.onMessage.bind(this));
}
<<<<<<< HEAD
flush() {}
=======
flush() {}
>>>>>>> facb7e7b403e1dfaa8790426259e6effb0618efb
// TODO: Check if required!
// private escape(text: string): string {

View File

@ -1,39 +1,44 @@
import { Logging, LoggingBase, LoggingTypes, Colors, withColor } from ".";
Logging.log("test")
Logging.log("test");
Logging.log("i", "am", { a: "an" }, 1000);
Logging.error(new Error("fehler 001"));
Logging.debug("Some Debug infos");
Logging.errorMessage("i", "am", "an", "error");
Logging.log("\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m TEST \x1b[31m\x1b[31m\x1b[31m")
Logging.log(
"\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m\x1b[31m TEST \x1b[31m\x1b[31m\x1b[31m"
);
Logging.log(withColor(Colors.MAGENTA, "This text should be magenta!"), "This not!")
Logging.log(withColor(Colors.MAGENTA, { somekey: "Some value" }))
Logging.log(
withColor(Colors.MAGENTA, "This text should be magenta!"),
"This not!"
);
Logging.log(withColor(Colors.MAGENTA, { somekey: "Some value" }));
let err = new Error()
if (typeof err.stack !== "string") console.log("Stacktrace invalid", err.stack)
let err = new Error();
if (typeof err.stack !== "string") console.log("Stacktrace invalid", err.stack);
let cus = new LoggingBase({ name: "test" });
cus.log("Hello from custom Logger")
cus.log("Hello from custom Logger");
cus.log("This has some %c symbols inside of it!");
let cus2 = new LoggingBase("test2");
cus2.log("Hello from custom Logger 2")
cus2.log("Hello from custom Logger 2");
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")
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.debug("Only Errors should appear:")
Logging.debug("Only Errors should appear:");
Logging.logLevel = LoggingTypes.Error;
Logging.debug("This should not be there 1");
@ -43,3 +48,6 @@ Logging.warning("This should not be there 4");
Logging.error("This should be there 1");
Logging.errorMessage("This should be there 2");
const timer = Logging.time("timer1", "Test Timer");
setTimeout(() => timer.end(), 1000);