// ========================================
// FICHIER: js/core/browser-logger.js - VERSION NAVIGATEUR
// Système de logging adapté du système ErrorReporting.js pour le navigateur
// ========================================
class BrowserLogger {
constructor() {
this.logs = [];
this.maxLogs = 1000; // Limite pour éviter l'explosion mémoire
this.logContainer = null;
this.isVisible = false;
// Niveaux de log avec couleurs
this.levels = {
TRACE: { value: 10, color: '#6c757d', emoji: '🔍' },
DEBUG: { value: 20, color: '#007bff', emoji: '🐛' },
INFO: { value: 30, color: '#28a745', emoji: 'ℹ️' },
WARN: { value: 40, color: '#ffc107', emoji: '⚠️' },
ERROR: { value: 50, color: '#dc3545', emoji: '❌' }
};
this.minLevel = 'DEBUG'; // Niveau minimum affiché
this.init();
}
init() {
// Créer l'interface de log
this.createLogUI();
// Intercepter les erreurs globales
window.addEventListener('error', (event) => {
this.logSh(`Erreur JavaScript: ${event.error.message}`, 'ERROR');
});
window.addEventListener('unhandledrejection', (event) => {
this.logSh(`Promise rejetée: ${event.reason}`, 'ERROR');
});
logSh('🚀 BrowserLogger initialisé', 'INFO');
}
createLogUI() {
// Créer le conteneur de log
const logContainer = document.createElement('div');
logContainer.id = 'browser-logger';
logContainer.innerHTML = `
${this.formatTime(new Date())}
INFO
Logger initialisé
`;
// Ajouter les styles CSS
const style = document.createElement('style');
style.textContent = `
#browser-logger {
position: fixed;
top: 80px;
right: 10px;
width: 400px;
max-height: 500px;
background: #fff;
border: 2px solid #007bff;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
font-family: 'Consolas', 'Monaco', monospace;
font-size: 12px;
z-index: 10000;
display: none;
}
#browser-logger.visible {
display: block;
}
.logger-header {
background: #007bff;
color: white;
padding: 8px 12px;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 6px 6px 0 0;
}
.logger-header h3 {
margin: 0;
font-size: 14px;
}
.logger-controls {
display: flex;
gap: 5px;
align-items: center;
}
.logger-controls select {
padding: 2px 4px;
font-size: 11px;
border: none;
border-radius: 3px;
}
.logger-controls button {
background: rgba(255,255,255,0.2);
border: none;
color: white;
padding: 2px 6px;
border-radius: 3px;
cursor: pointer;
font-size: 12px;
}
.logger-controls button:hover {
background: rgba(255,255,255,0.3);
}
.logger-content {
max-height: 400px;
overflow-y: auto;
padding: 0;
background: #f8f9fa;
}
.log-entry {
padding: 4px 8px;
border-bottom: 1px solid #e9ecef;
display: flex;
gap: 8px;
font-size: 11px;
line-height: 1.4;
}
.log-entry:hover {
background: #e9ecef;
}
.log-time {
color: #6c757d;
min-width: 60px;
font-weight: bold;
}
.log-level {
min-width: 50px;
font-weight: bold;
text-align: center;
border-radius: 3px;
padding: 1px 4px;
}
.log-level.trace { background: #f8f9fa; color: #6c757d; }
.log-level.debug { background: #cce5ff; color: #007bff; }
.log-level.info { background: #d4edda; color: #28a745; }
.log-level.warn { background: #fff3cd; color: #856404; }
.log-level.error { background: #f8d7da; color: #721c24; }
.log-message {
flex: 1;
word-break: break-word;
}
.log-message.trace { color: #6c757d; }
.log-message.network { color: #17a2b8; font-weight: bold; }
.log-message.auth { color: #6610f2; font-weight: bold; }
`;
document.head.appendChild(style);
document.body.appendChild(logContainer);
this.logContainer = logContainer;
this.logContent = logContainer.querySelector('#logger-content');
// Event listeners
document.getElementById('toggle-logger').addEventListener('click', () => {
this.toggle();
});
document.getElementById('clear-logs').addEventListener('click', () => {
this.clear();
});
document.getElementById('log-level-filter').addEventListener('change', (e) => {
this.minLevel = e.target.value;
this.refreshDisplay();
});
// Raccourci clavier pour toggle
document.addEventListener('keydown', (e) => {
if (e.ctrlKey && e.shiftKey && e.key === 'L') {
this.toggle();
}
});
}
formatTime(date) {
return date.toLocaleTimeString('fr-FR', {
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
}
logSh(message, level = 'INFO') {
// Sécuriser le level pour éviter les erreurs
if (typeof level !== 'string') {
level = 'INFO';
}
const timestamp = new Date();
const logEntry = {
timestamp,
level: level.toUpperCase(),
message,
id: Date.now() + Math.random()
};
// Ajouter à la liste des logs
this.logs.push(logEntry);
// Limiter le nombre de logs en mémoire
if (this.logs.length > this.maxLogs) {
this.logs.shift();
}
// Log aussi dans la console navigateur (gardé pour le debugging)
if (level !== 'TRACE' && level !== 'DEBUG') { // Éviter le spam en console
const consoleMethod = level.toLowerCase() === 'error' ? 'error' :
level.toLowerCase() === 'warn' ? 'warn' : 'log';
console[consoleMethod](`[${this.formatTime(timestamp)}] ${level}: ${message}`);
}
// Mettre à jour l'affichage si visible
if (this.isVisible) {
this.addLogToDisplay(logEntry);
}
return logEntry;
}
addLogToDisplay(logEntry) {
const levelInfo = this.levels[logEntry.level] || this.levels.INFO;
// Vérifier si on doit afficher ce niveau
if (levelInfo.value < this.levels[this.minLevel].value) {
return;
}
const logElement = document.createElement('div');
logElement.className = `log-entry ${logEntry.level.toLowerCase()}`;
logElement.innerHTML = `