UNPKG

baqend

Version:

Baqend JavaScript SDK

349 lines (307 loc) 12.2 kB
import * as msg from '../message'; import type { EntityManager } from '../EntityManager'; import { JsonMap } from '../util'; export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error'; /** * A Logger to store log notes when running the app. */ export class Logger { static readonly LEVELS: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error']; static readonly FORMAT_REGEXP = /%[sdj%]/g; public entityManager: EntityManager = null as any; public levelIndex: number = 2; /** * Creates a Logger instance for the given EntityManager * @param entityManager - Theo owning entityManager * @return The created logger instance */ static create(entityManager: EntityManager): Logger { const proto = this.prototype; const logger = (() => { function LoggerFunction(...args: any[]) { proto.log.apply(LoggerFunction, args as any); } Object.getOwnPropertyNames(proto).forEach((key) => { Object.defineProperty(LoggerFunction, key, Object.getOwnPropertyDescriptor(proto, key)!); }); return LoggerFunction as any as Logger; })(); logger.init(entityManager); return logger; } /** * The log level which will be logged * * The log level can be one of 'trace', 'debug', 'info', 'warn', 'error' * @type string */ get level(): LogLevel { return Logger.LEVELS[this.levelIndex]; } /** * Sets the log level which will be logged * @param value */ set level(value: LogLevel) { const index = Logger.LEVELS.indexOf(value); if (index === -1) { throw new Error(`Unknown logging level ${value}`); } this.levelIndex = index; } /** * Logs a message in the default level 'info' * @param message The message to log, the message string can be interpolated like the node util.format method * @param args The arguments used to interpolated the message string. The last param can be object which will * be included in the log entry * * @see https://nodejs.org/api/util.html#util_util_format_format * * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message */ log(message: string, ...args: any[]): Promise<any>; /** * Logs a message in the default level 'info' * @param message The message to log, the message string can be interpolated like the node util.format method * @param [data=null] An optional object which will be included in the log entry * * @see https://nodejs.org/api/util.html#util_util_format_format * * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message */ log(message: string, data: any): Promise<any>; /** * Logs a message with the given log level * @param level The level used to log the message * @param message The message to log, the message string can be interpolated like the node util.format method * @param args The arguments used to interpolated the message string. The last param can be object which will * be included in the log entry * * @see https://nodejs.org/api/util.html#util_util_format_format * * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message */ log(level: string, message: string, ...args: any[]): Promise<any>; /** * Logs a message with the given log level * @param level The level used to log the message * @param message The message to log, the message string can be interpolated like the node util.format method * @param [data=null] An optional object which will be included in the log entry * * @see https://nodejs.org/api/util.html#util_util_format_format * * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message */ log(level: string, message: string, data: any): Promise<any>; log(...args: any[]): Promise<any> { const level: LogLevel = Logger.LEVELS.indexOf(args[0]) === -1 ? 'info' : args.shift(); if (this.levelIndex > Logger.LEVELS.indexOf(level)) { return Promise.resolve(null); } let message: string = typeof args[0] === 'string' ? this.format(args.shift(), args) : '[no message]'; let data: { data: any } | { name: string, message: string, stack: string, data: {}, status: number } | null = null; if (args.length) { const arg = args.pop(); data = arg; if (typeof arg !== 'object' || Array.isArray(arg)) { data = { data: arg }; } if (arg instanceof Error) { // errors aren't loggable by default, since they do not have any visible property const { // @ts-ignore stack, data: data1, message: message1, name, status, } = arg; data = { name, message: message1, stack, status, data: data1, }; } } if (args.length) { message += `, ${args.join(', ')}`; } return this.logJSON({ date: new Date().toISOString(), message, level, data, ...(this.entityManager.me && { user: this.entityManager.me.id }), }); } format(message: string, args: any) { if (args.length === 0) { return message; } const str = String(message).replace(Logger.FORMAT_REGEXP, (x: string) => { if (x === '%%') { return '%'; } if (!args.length) { return x; } switch (x) { case '%s': return String(args.shift()); case '%d': return String(Number(args.shift())); case '%j': try { return JSON.stringify(args.shift()); } catch (_) { return '[Circular]'; } default: return x; } }); return str; } init(entityManager: EntityManager) { this.entityManager = entityManager; this.levelIndex = 2; Logger.LEVELS.forEach((level) => { this[level] = this.log.bind(this, level); }); } logJSON(json: JsonMap): Promise<any> { if (!this.entityManager.isReady) { return this.entityManager.ready(this.logJSON.bind(this, json)); } return this.entityManager.send(new msg.CreateObject('logs.AppLog', json)); } } export interface Logger { /** * Log message at trace level * @param message The message to log, the message string can be interpolated like the node util.format method * @param args The arguments used to interpolated the message string. The last param can be object which will * be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function trace * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ trace(message: string, ...args: any[]): Promise<any>; /** * Log message at trace level * @param message The message to log, the message string can be interpolated like the node util.format method * @param [data=null] An optional object which will be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function trace * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ trace(message: string, data: any): Promise<any>; /** * Log message at debug level * @param message The message to log, the message string can be interpolated like the node util.format method * @param args The arguments used to interpolated the message string. The last param can be object which will * be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function debug * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ debug(message: string, ...args: any[]): Promise<any>; /** * Log message at debug level * @param message The message to log, the message string can be interpolated like the node util.format method * @param [data=null] An optional object which will be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function debug * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ debug(message: string, data: any): Promise<any>; /** * Log message at info level * @param message The message to log, the message string can be interpolated like the node util.format method * @param args The arguments used to interpolated the message string. The last param can be object which will * be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function info * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ info(message: string, ...args: any[]): Promise<any>; /** * Log message at info level * @param message The message to log, the message string can be interpolated like the node util.format method * @param [data=null] An optional object which will be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function info * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ info(message: string, data: any): Promise<any>; /** * Log message at warn level * @param message The message to log, the message string can be interpolated like the node util.format method * @param args The arguments used to interpolated the message string. The last param can be object which will * be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function warn * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ warn(message: string, ...args: any[]): Promise<any>; /** * Log message at warn level * @param message The message to log, the message string can be interpolated like the node util.format method * @param [data=null] An optional object which will be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function warn * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ warn(message: string, data: any): Promise<any>; /** * Log message at error level * @param message The message to log, the message string can be interpolated like the node util.format method * @param args The arguments used to interpolated the message string. The last param can be object which will * be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function error * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ error(message: string, ...args: any[]): Promise<any>; /** * Log message at error level * @param message The message to log, the message string can be interpolated like the node util.format method * @param [data=null] An optional object which will be included in the log entry * @return A promise which resolves when the log messages was logged, or null if the log level has * skipped the message * @function error * @memberOf util.Logger.prototype * * @see https://nodejs.org/api/util.html#util_util_format_format */ error(message: string, data: any): Promise<any>; }