import { LogType } from '../../enum'; import { Nexus } from '../../fg-api'; import { INewSessionArgsDTO } from '../../interfaces/dto/new-session-args-dto.interface'; import { ILogEntry } from '../../interfaces/log-entry.interface'; import { AsyncUtils } from '../../utils/async-utils'; export class LogSession { id: number; token: string | null; entries: ILogEntry[]; autoFlush: boolean; errorInterceptor: Function | null; private _errorCounter: number; private _delay: number; private _interval: any; constructor() { this.id = -1; this.token = null; this.entries = []; this.autoFlush = true; this._errorCounter = 0; this._delay = 0; this._interval = setInterval(() => { if (this.autoFlush) { this._dispatchEntry() } }, 1000); this.errorInterceptor = null; } get isInitialized() { return this.id >= 0 && this.token; } private get _api() { return Nexus.instance.getLogger(); } async initialize(optionalData?: INewSessionArgsDTO) { const { id, token } = await this._api.createSession(optionalData); this.id = id; this.token = token; } debug(message: string, category?: string) { this.addEntry(LogType.Debug, `${message}`, category); } info(message: string, category?: string) { this.addEntry(LogType.Info, `${message}`, category); } log(message: string, category?: string) { this.addEntry(LogType.Info, `${message}`, category); } warning(message: string, category?: string) { this.addEntry(LogType.Warn, `${message}`, category); } warn(message: string, category?: string) { this.addEntry(LogType.Warn, `${message}`, category); } verbose(message: string, category?: string) { this.addEntry(LogType.Verbose, `${message}`, category); } silly(message: string, category?: string) { this.addEntry(LogType.Silly, `${message}`, category); } error(message: string, category?: string) { this.addEntry(LogType.Error, `${message}`, category); } addEntry(type: LogType, message: string, category?: string, _date?: Date, tags?: string[]) { const entry: ILogEntry = { type, message, category, date: _date || new Date(), tags }; this.entries.push(entry); } async flush() { let keepRunning = true; while (this.entries.length > 0 && keepRunning) { keepRunning = await this._dispatchEntry(); } } private async _dispatchEntry() { const entry = this.entries.shift(); if (!entry) { return false; } while (this._delay > 0) { await AsyncUtils.wait(1000); this._delay--; } try { if (!this.token) { throw new Error('Token is missing'); } await this._api.addRawEntry(this.id, this.token, entry); this._errorCounter = 0; } catch (err: any) { this.entries.unshift(entry); this._errorCounter++; this._delay = Math.min(60, Math.pow(2, this._errorCounter)); if (this.errorInterceptor && this.errorInterceptor(err, entry, this._errorCounter) === false) { return false; } throw err; } return true; } async dispose() { if (this.isInitialized) { await this.flush(); if (this.token) { await this._api.closeSession(this.id, this.token); } this.id = -1; if (this._interval) { clearInterval(this._interval); this._interval = null; } } } }