Spaces:
Running
Running
| // ===== KIMI ERROR MANAGEMENT SYSTEM ===== | |
| class KimiErrorManager { | |
| constructor() { | |
| this.errorLog = []; | |
| this.maxLogSize = 100; | |
| this.errorHandlers = new Map(); | |
| this.setupGlobalHandlers(); | |
| } | |
| setupGlobalHandlers() { | |
| // Handle unhandled promise rejections | |
| window.addEventListener("unhandledrejection", event => { | |
| this.logError("UnhandledPromiseRejection", event.reason, { | |
| promise: event.promise, | |
| timestamp: new Date().toISOString() | |
| }); | |
| event.preventDefault(); | |
| }); | |
| // Handle JavaScript errors | |
| window.addEventListener("error", event => { | |
| this.logError("JavaScriptError", event.error || event.message, { | |
| filename: event.filename, | |
| lineno: event.lineno, | |
| colno: event.colno, | |
| timestamp: new Date().toISOString() | |
| }); | |
| }); | |
| } | |
| logError(type, error, context = {}) { | |
| const errorEntry = { | |
| id: this.generateErrorId(), | |
| type, | |
| message: error?.message || error, | |
| stack: error?.stack, | |
| context, | |
| timestamp: new Date().toISOString(), | |
| severity: this.determineSeverity(type, error) | |
| }; | |
| this.errorLog.push(errorEntry); | |
| // Keep log size manageable | |
| if (this.errorLog.length > this.maxLogSize) { | |
| this.errorLog.shift(); | |
| } | |
| // Console logging with appropriate level | |
| this.consoleLog(errorEntry); | |
| // Trigger registered handlers | |
| this.triggerHandlers(errorEntry); | |
| return errorEntry.id; | |
| } | |
| generateErrorId() { | |
| return "err_" + Date.now() + "_" + Math.random().toString(36).substr(2, 9); | |
| } | |
| determineSeverity(type, error) { | |
| const criticalTypes = ["UnhandledPromiseRejection", "DatabaseError", "InitializationError"]; | |
| const criticalMessages = ["failed to fetch", "network error", "connection refused"]; | |
| if (criticalTypes.includes(type)) return "critical"; | |
| const message = (error?.message || error || "").toLowerCase(); | |
| if (criticalMessages.some(cm => message.includes(cm))) return "critical"; | |
| return "warning"; | |
| } | |
| consoleLog(errorEntry) { | |
| const { type, message, severity, context } = errorEntry; | |
| switch (severity) { | |
| case "critical": | |
| console.error(`π¨ [${type}]`, message, context); | |
| break; | |
| case "warning": | |
| console.warn(`β οΈ [${type}]`, message, context); | |
| break; | |
| default: | |
| console.info(`βΉοΈ [${type}]`, message, context); | |
| } | |
| } | |
| triggerHandlers(errorEntry) { | |
| const handlers = this.errorHandlers.get(errorEntry.type) || []; | |
| handlers.forEach(handler => { | |
| try { | |
| handler(errorEntry); | |
| } catch (handlerError) { | |
| console.error("Error in error handler:", handlerError); | |
| } | |
| }); | |
| } | |
| registerHandler(errorType, handler) { | |
| if (!this.errorHandlers.has(errorType)) { | |
| this.errorHandlers.set(errorType, []); | |
| } | |
| this.errorHandlers.get(errorType).push(handler); | |
| } | |
| unregisterHandler(errorType, handler) { | |
| const handlers = this.errorHandlers.get(errorType); | |
| if (handlers) { | |
| const index = handlers.indexOf(handler); | |
| if (index > -1) { | |
| handlers.splice(index, 1); | |
| } | |
| } | |
| } | |
| getErrorLog(filter = null) { | |
| if (!filter) return [...this.errorLog]; | |
| return this.errorLog.filter(entry => { | |
| if (filter.type && entry.type !== filter.type) return false; | |
| if (filter.severity && entry.severity !== filter.severity) return false; | |
| if (filter.since && new Date(entry.timestamp) < filter.since) return false; | |
| return true; | |
| }); | |
| } | |
| clearErrorLog() { | |
| this.errorLog.length = 0; | |
| } | |
| // Helper methods for different error types | |
| logInitError(component, error, context = {}) { | |
| return this.logError("InitializationError", error, { component, ...context }); | |
| } | |
| logDatabaseError(operation, error, context = {}) { | |
| return this.logError("DatabaseError", error, { operation, ...context }); | |
| } | |
| logAPIError(endpoint, error, context = {}) { | |
| return this.logError("APIError", error, { endpoint, ...context }); | |
| } | |
| logValidationError(field, error, context = {}) { | |
| return this.logError("ValidationError", error, { field, ...context }); | |
| } | |
| logUIError(component, error, context = {}) { | |
| return this.logError("UIError", error, { component, ...context }); | |
| } | |
| // Async wrapper for functions | |
| async wrapAsync(fn, errorContext = {}) { | |
| try { | |
| return await fn(); | |
| } catch (error) { | |
| this.logError("AsyncOperationError", error, errorContext); | |
| throw error; | |
| } | |
| } | |
| // Sync wrapper for functions | |
| wrapSync(fn, errorContext = {}) { | |
| try { | |
| return fn(); | |
| } catch (error) { | |
| this.logError("SyncOperationError", error, errorContext); | |
| throw error; | |
| } | |
| } | |
| // Debug helpers for development | |
| getErrorSummary() { | |
| const summary = { | |
| totalErrors: this.errorLog.length, | |
| critical: this.errorLog.filter(e => e.severity === "critical").length, | |
| warning: this.errorLog.filter(e => e.severity === "warning").length, | |
| recent: this.errorLog.filter(e => { | |
| const errorTime = new Date(e.timestamp); | |
| const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000); | |
| return errorTime > fiveMinutesAgo; | |
| }).length, | |
| types: [...new Set(this.errorLog.map(e => e.type))] | |
| }; | |
| return summary; | |
| } | |
| printErrorSummary() { | |
| const summary = this.getErrorSummary(); | |
| console.group("π Kimi Error Manager Summary"); | |
| console.log(`π Total Errors: ${summary.totalErrors}`); | |
| console.log(`π¨ Critical: ${summary.critical}`); | |
| console.log(`β οΈ Warnings: ${summary.warning}`); | |
| console.log(`β° Recent (5min): ${summary.recent}`); | |
| console.log(`π Error Types:`, summary.types); | |
| if (summary.totalErrors > 0) { | |
| console.log(`π‘ Use kimiErrorManager.getErrorLog() to see details`); | |
| } | |
| console.groupEnd(); | |
| return summary; | |
| } | |
| clearAndSummarize() { | |
| const summary = this.getErrorSummary(); | |
| this.clearErrorLog(); | |
| console.log("π§Ή Error log cleared. Previous summary:", summary); | |
| return summary; | |
| } | |
| } | |
| // Create global instance | |
| window.kimiErrorManager = new KimiErrorManager(); | |
| // Export class for manual instantiation if needed | |
| window.KimiErrorManager = KimiErrorManager; | |
| // Global debugging helper | |
| window.kimiDebugErrors = () => window.kimiErrorManager.printErrorSummary(); | |