Add logging framework with Logger, LoggerFactory, and appenders
- Introduced ILogger interface for logging methods - Implemented Logger class with various logging levels and message formatting - Created LoggerFactory for managing logger instances and appender configuration - Added LoggingLevel enum and mapping for logging level types - Developed ConsoleAppender and TechnikerMeAppender for different logging outputs - Implemented appender management with AppenderFactory and base Appender class - Established Threshold class for controlling logging levels
This commit is contained in:
63
src/logger/appenders/Appender.ts
Normal file
63
src/logger/appenders/Appender.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import {LoggingLevel, type LoggingLevelType} from '../LoggingLevel';
|
||||
import type ILogMessage from './LogMessage';
|
||||
|
||||
export type AppenderOptions = {
|
||||
domain?: string;
|
||||
};
|
||||
|
||||
export default class Appender {
|
||||
private readonly _logRecorderUrl: string = 'https://logserver.techniker.me/api/logs';
|
||||
// @ts-ignore
|
||||
private readonly _domain: string = typeof globalThis !== 'undefined' ? (globalThis.location?.hostname ?? '') : '';
|
||||
private readonly _logMessageQueue: ILogMessage[] = [];
|
||||
private _pendingPostLogMessagePromise: Promise<Response | undefined> | undefined = undefined;
|
||||
|
||||
constructor(logRecorderUrl: string, {domain}: AppenderOptions) {
|
||||
this._logRecorderUrl = logRecorderUrl;
|
||||
this._domain = domain ?? this._domain;
|
||||
}
|
||||
|
||||
public log(timestamp: string, level: LoggingLevelType, category: string, message: string): void {
|
||||
const logMessage = {
|
||||
timestamp,
|
||||
domain: this._domain,
|
||||
level,
|
||||
category,
|
||||
message
|
||||
};
|
||||
this.queueMessage(logMessage);
|
||||
this.postLogMessage();
|
||||
}
|
||||
|
||||
private async postLogMessage(): Promise<void> {
|
||||
const logMessage = this._logMessageQueue.shift();
|
||||
|
||||
if (!logMessage || this._pendingPostLogMessagePromise !== undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof fetch === 'undefined') {
|
||||
console.error('Fetch API is not available in this environment');
|
||||
return;
|
||||
}
|
||||
|
||||
this._pendingPostLogMessagePromise = fetch(this._logRecorderUrl, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json'
|
||||
},
|
||||
mode: 'no-cors',
|
||||
method: 'POST',
|
||||
body: JSON.stringify(logMessage)
|
||||
}).then(() => (this._pendingPostLogMessagePromise = undefined));
|
||||
} catch (e) {
|
||||
console.error('Unable to send logs due to [%o]', e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private queueMessage(logMessage: ILogMessage): void {
|
||||
this._logMessageQueue.push(logMessage);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user