/** * Erweiterter Logger mit Request-ID-Unterstützung und Server-Kommunikation. */ export class SecureLogger { static enabled = true; static apiEndpoint = '/api/log'; static requestId = null; static log(...args) { this._write('log', args); } static warn(...args) { this._write('warn', args) } static info(...args) { this._write('info', args); } static error(...args) { this._write('error', args); } static _write(level, args) { if(!this.enabled) return; const date = new Date(); const timestamp = date.toLocaleTimeString('de-DE'); const requestIdStr = this.requestId ? `[${this.requestId}] ` : ''; const message = args.map(a => typeof a === 'object' ? JSON.stringify(a) : a).join(' '); const formattedMessage = `[${timestamp}] ${requestIdStr}[${level.toUpperCase()}] ${message}`; // Lokales Logging in der Konsole console[level](formattedMessage); // An den Server senden (wenn nicht in Produktion) this._sendToServer(level, message, args.find(a => typeof a === 'object')); } static _sendToServer(level, message, context) { fetch(this.apiEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Request-ID': this.requestId || '' }, body: JSON.stringify({ level, message, context }) }) .then(response => { // Request-ID aus dem Header extrahieren const requestId = response.headers.get('X-Request-ID'); if (requestId) { // Nur den ID-Teil ohne Signatur speichern const idPart = requestId.split('.')[0]; if (idPart) { this.requestId = idPart; } } return response.json(); }) .catch(err => { console.error('Fehler beim Senden des Logs:', err); }); } /** * Request-ID aus dem Document laden */ static initFromDocument() { // Versuche die Request-ID aus einem Meta-Tag zu lesen const meta = document.querySelector('meta[name="request-id"]'); if (meta) { const fullRequestId = meta.getAttribute('content'); // Nur den ID-Teil ohne Signatur verwenden this.requestId = fullRequestId.split('.')[0] || null; } } } // Request-ID initialisieren, wenn das DOM geladen ist document.addEventListener('DOMContentLoaded', () => { SecureLogger.initFromDocument(); // Abfangen aller unbehandelten Fehler und Logging window.addEventListener('error', (event) => { SecureLogger.error('Unbehandelter Fehler:', event.error || event.message); }); // Abfangen aller unbehandelten Promise-Rejects window.addEventListener('unhandledrejection', (event) => { SecureLogger.error('Unbehandelte Promise-Ablehnung:', event.reason); }); });