generated from nhcarrigan/template
feat: error handling and logger
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* @copyright 2026 NHCarrigan
|
||||
* @license Naomi's Public License
|
||||
* @author Naomi Carrigan
|
||||
*/
|
||||
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
interface LogPayload {
|
||||
level: 'debug' | 'info' | 'warn' | 'error';
|
||||
message: string;
|
||||
context?: string;
|
||||
error?: {
|
||||
name: string;
|
||||
message: string;
|
||||
stack?: string;
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ConsoleLoggerService {
|
||||
private http = inject(HttpClient);
|
||||
private originalConsole = {
|
||||
log: console.log.bind(console),
|
||||
error: console.error.bind(console),
|
||||
warn: console.warn.bind(console),
|
||||
debug: console.debug.bind(console),
|
||||
info: console.info.bind(console)
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialises the console override to pipe logs to the API.
|
||||
*/
|
||||
initialise(): void {
|
||||
console.log = (...args: unknown[]) => {
|
||||
this.originalConsole.log(...args);
|
||||
this.sendLog('info', this.formatArgs(args));
|
||||
};
|
||||
|
||||
console.info = (...args: unknown[]) => {
|
||||
this.originalConsole.info(...args);
|
||||
this.sendLog('info', this.formatArgs(args));
|
||||
};
|
||||
|
||||
console.debug = (...args: unknown[]) => {
|
||||
this.originalConsole.debug(...args);
|
||||
this.sendLog('debug', this.formatArgs(args));
|
||||
};
|
||||
|
||||
console.warn = (...args: unknown[]) => {
|
||||
this.originalConsole.warn(...args);
|
||||
this.sendLog('warn', this.formatArgs(args));
|
||||
};
|
||||
|
||||
console.error = (...args: unknown[]) => {
|
||||
this.originalConsole.error(...args);
|
||||
|
||||
// Check if the first argument is an Error object
|
||||
if (args[0] instanceof Error) {
|
||||
const error = args[0];
|
||||
this.sendLog('error', error.message, 'Console', {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
} else {
|
||||
this.sendLog('error', this.formatArgs(args));
|
||||
}
|
||||
};
|
||||
|
||||
// Global error handlers
|
||||
window.addEventListener('error', (event: ErrorEvent) => {
|
||||
this.originalConsole.error('Uncaught Error:', event.error);
|
||||
this.sendLog('error', event.message, 'Window Error', {
|
||||
name: event.error?.name || 'Error',
|
||||
message: event.message,
|
||||
stack: event.error?.stack
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {
|
||||
this.originalConsole.error('Unhandled Promise Rejection:', event.reason);
|
||||
|
||||
const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
|
||||
this.sendLog('error', error.message, 'Unhandled Rejection', {
|
||||
name: error.name,
|
||||
message: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private formatArgs(args: unknown[]): string {
|
||||
return args.map(arg => {
|
||||
if (typeof arg === 'string') {
|
||||
return arg;
|
||||
}
|
||||
if (arg instanceof Error) {
|
||||
return `${arg.name}: ${arg.message}`;
|
||||
}
|
||||
try {
|
||||
return JSON.stringify(arg);
|
||||
} catch {
|
||||
return String(arg);
|
||||
}
|
||||
}).join(' ');
|
||||
}
|
||||
|
||||
private sendLog(level: LogPayload['level'], message: string, context?: string, error?: LogPayload['error']): void {
|
||||
const payload: LogPayload = {
|
||||
level,
|
||||
message,
|
||||
context,
|
||||
error
|
||||
};
|
||||
|
||||
this.http.post(`${environment.apiUrl}/log`, payload).subscribe({
|
||||
error: (err) => {
|
||||
this.originalConsole.error('Failed to send log to API:', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user