dengun_ai-admin-client
Version:
Cliente simples para integração com o AI Admin Dashboard - Plug and Play
220 lines (219 loc) • 7.06 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ErrorReporter = void 0;
const events_1 = require("events");
/**
* Objetivo 4: Reportar erros, bugs e falhas da aplicação externa
*/
class ErrorReporter extends events_1.EventEmitter {
constructor(config) {
super();
this.connectionManager = null;
this.errorQueue = [];
this.reportInterval = null;
this.isActive = false;
this.errorStats = {
totalErrors: 0,
lastError: 0,
errorsByType: new Map()
};
this.config = config;
this.setupGlobalErrorHandlers();
}
/**
* Iniciar serviço de relatório de erros
*/
async start(connectionManager) {
if (connectionManager) {
this.connectionManager = connectionManager;
}
this.isActive = true;
this.startReportInterval();
this.emit('started');
}
/**
* Definir o gerenciador de conexão
*/
setConnectionManager(connectionManager) {
this.connectionManager = connectionManager;
}
/**
* Parar serviço de relatório de erros
*/
async stop() {
this.isActive = false;
this.stopReportInterval();
// Enviar erros restantes na fila
if (this.errorQueue.length > 0) {
await this.flushQueue();
}
this.emit('stopped');
}
/**
* Reportar erro manualmente
*/
async reportError(error) {
if (!this.isActive)
return;
// Adicionar à fila
this.errorQueue.push(error);
// Atualizar estatísticas
this.updateStats(error);
// Para erros críticos, enviar imediatamente
if (this.isCriticalError(error)) {
await this.flushQueue();
}
this.emit('errorAdded', error);
}
/**
* Reportar erro a partir de exception
*/
async reportException(exception, context) {
const errorReport = {
error: exception.message,
errorCode: exception.name,
stack: exception.stack,
context: {
...context,
type: 'exception'
},
timestamp: Date.now()
};
await this.reportError(errorReport);
}
/**
* Reportar erro de aplicação
*/
async reportAppError(message, errorCode, context, sessionId, userId, tenantId) {
const errorReport = {
sessionId,
userId,
tenantId,
error: message,
errorCode,
context: {
...context,
type: 'application'
},
timestamp: Date.now()
};
await this.reportError(errorReport);
}
/**
* Obter estatísticas de erros
*/
getErrorStats() {
return {
...this.errorStats,
errorsByType: Object.fromEntries(this.errorStats.errorsByType),
pendingReports: this.errorQueue.length
};
}
/**
* Obter erros pendentes na fila
*/
getPendingErrors() {
return [...this.errorQueue];
}
/**
* Forçar envio dos erros na fila
*/
async forceFlush() {
await this.flushQueue();
}
// Métodos privados
setupGlobalErrorHandlers() {
if (typeof process !== 'undefined') {
// Node.js error handlers
process.on('uncaughtException', (error) => {
this.reportException(error, { type: 'uncaughtException' });
});
process.on('unhandledRejection', (reason, promise) => {
const error = reason instanceof Error ? reason : new Error(String(reason));
this.reportException(error, {
type: 'unhandledRejection',
promise: String(promise)
});
});
}
if (typeof window !== 'undefined') {
// Browser error handlers
window.addEventListener('error', (event) => {
this.reportException(event.error || new Error(event.message), {
type: 'windowError',
filename: event.filename,
lineno: event.lineno,
colno: event.colno
});
});
window.addEventListener('unhandledrejection', (event) => {
const error = event.reason instanceof Error ? event.reason : new Error(String(event.reason));
this.reportException(error, { type: 'unhandledRejection' });
});
}
}
startReportInterval() {
var _a;
this.stopReportInterval();
const interval = ((_a = this.config.options) === null || _a === void 0 ? void 0 : _a.reportInterval) || 30000;
this.reportInterval = setInterval(async () => {
await this.flushQueue();
}, interval);
}
stopReportInterval() {
if (this.reportInterval) {
clearInterval(this.reportInterval);
this.reportInterval = null;
}
}
async flushQueue() {
var _a;
if (this.errorQueue.length === 0)
return;
if (!((_a = this.connectionManager) === null || _a === void 0 ? void 0 : _a.isConnectionActive())) {
this.emit('warning', 'Não conectado ao dashboard - erros mantidos na fila');
return;
}
const errorsToSend = [...this.errorQueue];
this.errorQueue = [];
try {
const response = await this.connectionManager.sendData('/api/bots/errors', {
botId: this.config.botId,
errors: errorsToSend
});
if (response.success) {
this.emit('errorsReported', errorsToSend);
}
else {
// Recolocar na fila se falhou
this.errorQueue.unshift(...errorsToSend);
this.emit('error', new Error(response.error || 'Falha ao reportar erros'));
}
}
catch (error) {
// Recolocar na fila se deu erro
this.errorQueue.unshift(...errorsToSend);
this.emit('error', error);
}
}
updateStats(error) {
this.errorStats.totalErrors++;
this.errorStats.lastError = error.timestamp;
const errorType = error.errorCode || 'unknown';
const currentCount = this.errorStats.errorsByType.get(errorType) || 0;
this.errorStats.errorsByType.set(errorType, currentCount + 1);
}
isCriticalError(error) {
const criticalCodes = [
'ECONNREFUSED',
'TIMEOUT',
'AUTH_FAILED',
'CRITICAL_ERROR',
'SECURITY_ERROR'
];
return criticalCodes.includes(error.errorCode || '') ||
error.error.toLowerCase().includes('critical') ||
error.error.toLowerCase().includes('fatal');
}
}
exports.ErrorReporter = ErrorReporter;