Create mock backend to simulate AI responses for UI development: Backend Implementation: - tools/fake-backend/server.js: Express server with CORS - POST /api/analyze: Accepts log, returns mock AI analysis with 1.5s delay - GET /health: Health check endpoint - Pattern matching for different log types (PostgreSQL, Nginx, Node.js, Disk) - Error handling: 400 for empty payload, 500 for server errors - Mock responses for common errors (OOM, 502, connection refused, disk full) Container Setup: - Dockerfile: Node.js 20 Alpine container - docker-compose.yml: Added fake-backend service on port 3000 - Health checks for both frontend and backend services - Environment variable VITE_API_URL for frontend Frontend Integration: - InteractiveDemo.tsx: Replaced static data with real fetch() calls - API_URL configurable via env var (default: http://localhost:3000) - Error handling with user-friendly messages - Shows backend URL in demo section - Maintains loading states and UI feedback Documentation: - docs/tools_fake_backend.md: Complete usage guide - README.md: Updated with tools/fake-backend structure and usage Development Workflow: 1. docker compose up -d (starts both frontend and backend) 2. Frontend calls http://fake-backend:3000/api/analyze 3. Backend returns realistic mock responses 4. No OpenRouter API costs during development Safety First: - No real API calls during development - Isolated mock logic in dedicated tool - Easy switch to real backend by changing URL - CORS enabled only for development Refs: Sprint 4 preparation, API development workflow
224 lines
7.8 KiB
JavaScript
224 lines
7.8 KiB
JavaScript
/**
|
|
* Fake Backend Server for LogWhisperer AI
|
|
*
|
|
* Simulates AI analysis responses for frontend development
|
|
* without requiring real backend or OpenRouter API calls.
|
|
*
|
|
* @author LogWhisperer AI Team
|
|
* @version 1.0.0
|
|
*/
|
|
|
|
const express = require('express');
|
|
const cors = require('cors');
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3000;
|
|
const DELAY_MS = parseInt(process.env.DELAY_MS) || 1500;
|
|
|
|
// Enable CORS for all origins (development only!)
|
|
app.use(cors({
|
|
origin: '*',
|
|
methods: ['GET', 'POST'],
|
|
allowedHeaders: ['Content-Type']
|
|
}));
|
|
|
|
// Parse JSON bodies
|
|
app.use(express.json());
|
|
|
|
// Mock responses database
|
|
const MOCK_RESPONSES = {
|
|
// PostgreSQL errors
|
|
'memory': {
|
|
title: 'PostgreSQL Out of Memory',
|
|
description: 'Il database ha esaurito la memoria disponibile. Questo è spesso causato da query troppo pesanti o da un numero eccessivo di connessioni.',
|
|
command: 'ps aux | grep postgres | head -5 && free -h',
|
|
isSafe: true,
|
|
note: 'Verifica processi Postgres e memoria disponibile. Se necessario, riavvia il servizio con: sudo systemctl restart postgresql'
|
|
},
|
|
'oom': {
|
|
title: 'PostgreSQL Out of Memory',
|
|
description: 'Out Of Memory error rilevato. Il sistema ha esaurito la RAM disponibile.',
|
|
command: 'free -h && ps aux --sort=-%mem | head -10',
|
|
isSafe: true,
|
|
note: 'Identifica i processi che consumano più memoria e considera di aumentare la RAM o ottimizzare le query.'
|
|
},
|
|
// Nginx/Connection errors
|
|
'connection refused': {
|
|
title: 'Connessione al Backend Rifiutata',
|
|
description: 'Il reverse proxy (Nginx) non riesce a connettersi al backend. Il servizio potrebbe essere down.',
|
|
command: 'sudo systemctl status app-service && netstat -tlnp | grep 3000',
|
|
isSafe: true,
|
|
note: 'Verifica che il servizio backend sia in esecuzione. Se stopped, avvia con: sudo systemctl start app-service'
|
|
},
|
|
'502': {
|
|
title: 'Nginx 502 Bad Gateway',
|
|
description: 'Nginx riceve errore dal server upstream. Il backend non risponde correttamente.',
|
|
command: 'sudo systemctl status backend && tail -n 50 /var/log/backend/error.log',
|
|
isSafe: true,
|
|
note: 'Controlla i log del backend per errori specifici. Potrebbe essere necessario un riavvio.'
|
|
},
|
|
// Node.js errors
|
|
'econnrefused': {
|
|
title: 'Node.js - Connessione Database Rifiutata',
|
|
description: 'L\'applicazione Node non riesce a connettersi al database PostgreSQL sulla porta 5432.',
|
|
command: 'sudo systemctl status postgresql && sudo netstat -tlnp | grep 5432',
|
|
isSafe: true,
|
|
note: 'Verifica che PostgreSQL sia in esecuzione. Se down, avvia con: sudo systemctl start postgresql'
|
|
},
|
|
'exception': {
|
|
title: 'Node.js Exception',
|
|
description: 'Eccezione non gestita nell\'applicazione Node.js. Potrebbe essere un errore di connessione o configurazione.',
|
|
command: 'pm2 logs app --lines 50',
|
|
isSafe: true,
|
|
note: 'Controlla i log dell\'applicazione per l\'errore completo. Usa pm2 restart app se necessario.'
|
|
},
|
|
// Disk errors
|
|
'disk': {
|
|
title: 'Spazio su Disco Esaurito',
|
|
description: 'Il filesystem ha raggiunto il 100% di utilizzo. Nessuna scrittura possibile.',
|
|
command: 'df -h && du -sh /var/log/* | sort -hr | head -10',
|
|
isSafe: true,
|
|
note: 'Identifica quali directory occupano più spazio. Pulisci log vecchi con: sudo find /var/log -name "*.log" -mtime +7 -delete'
|
|
},
|
|
'no space': {
|
|
title: 'Spazio su Disco Esaurito',
|
|
description: 'Spazio insufficiente sul disco. Impossibile scrivere nuovi dati.',
|
|
command: 'df -h && du -sh /tmp /var/log /var/cache',
|
|
isSafe: true,
|
|
note: 'Libera spazio eliminando file temporanei o log vecchi.'
|
|
}
|
|
};
|
|
|
|
// Default response for unknown errors
|
|
const DEFAULT_RESPONSE = {
|
|
title: 'Errore di Sistema',
|
|
description: 'È stato rilevato un errore nel log. L\'analisi suggerisce di verificare lo stato dei servizi e le risorse di sistema.',
|
|
command: 'sudo systemctl status && df -h && free -h',
|
|
isSafe: true,
|
|
note: 'Esegui il comando sopra per verificare lo stato generale del sistema. Se il problema persiste, controlla i log specifici del servizio.'
|
|
};
|
|
|
|
/**
|
|
* Find matching mock response based on log content
|
|
* @param {string} logContent - The log content to analyze
|
|
* @returns {object} - Matching response or default
|
|
*/
|
|
function findMockResponse(logContent) {
|
|
const logLower = logContent.toLowerCase();
|
|
|
|
for (const [keyword, response] of Object.entries(MOCK_RESPONSES)) {
|
|
if (logLower.includes(keyword.toLowerCase())) {
|
|
return response;
|
|
}
|
|
}
|
|
|
|
return DEFAULT_RESPONSE;
|
|
}
|
|
|
|
/**
|
|
* POST /api/analyze
|
|
* Analyze log and return AI-like response
|
|
*/
|
|
app.post('/api/analyze', (req, res) => {
|
|
const { log } = req.body;
|
|
|
|
// Validate input
|
|
if (!log || typeof log !== 'string' || log.trim().length === 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Bad Request',
|
|
message: 'Il campo "log" è richiesto e non può essere vuoto',
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
|
|
// Simulate AI processing delay
|
|
setTimeout(() => {
|
|
try {
|
|
const analysis = findMockResponse(log);
|
|
|
|
res.json({
|
|
success: true,
|
|
analysis: {
|
|
...analysis,
|
|
originalLog: log.substring(0, 500) // Include first 500 chars for reference
|
|
},
|
|
meta: {
|
|
processingTime: `${DELAY_MS}ms`,
|
|
model: 'fake-backend-mock-v1',
|
|
timestamp: new Date().toISOString()
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('Error processing request:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Internal Server Error',
|
|
message: 'Errore durante l\'analisi del log',
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
}
|
|
}, DELAY_MS);
|
|
});
|
|
|
|
/**
|
|
* GET /health
|
|
* Health check endpoint
|
|
*/
|
|
app.get('/health', (req, res) => {
|
|
res.json({
|
|
status: 'ok',
|
|
timestamp: new Date().toISOString(),
|
|
uptime: process.uptime(),
|
|
version: '1.0.0'
|
|
});
|
|
});
|
|
|
|
/**
|
|
* GET /
|
|
* Root endpoint with API info
|
|
*/
|
|
app.get('/', (req, res) => {
|
|
res.json({
|
|
name: 'LogWhisperer AI - Fake Backend',
|
|
version: '1.0.0',
|
|
description: 'Mock API server for frontend development',
|
|
endpoints: {
|
|
'POST /api/analyze': 'Analyze log and return AI-like response',
|
|
'GET /health': 'Health check endpoint'
|
|
},
|
|
documentation: 'See docs/tools_fake_backend.md'
|
|
});
|
|
});
|
|
|
|
// Error handling middleware
|
|
app.use((err, req, res, next) => {
|
|
console.error('Unhandled error:', err);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Internal Server Error',
|
|
message: 'Errore imprevisto del server',
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
});
|
|
|
|
// Start server
|
|
app.listen(PORT, () => {
|
|
console.log(`
|
|
╔══════════════════════════════════════════════════════════════╗
|
|
║ LogWhisperer AI - Fake Backend Server ║
|
|
║ ║
|
|
║ 🚀 Server running on http://localhost:${PORT} ║
|
|
║ 📖 Documentation: docs/tools_fake_backend.md ║
|
|
║ ⏱️ Simulated delay: ${DELAY_MS}ms ║
|
|
║ ║
|
|
║ Endpoints: ║
|
|
║ POST /api/analyze - Analyze log and get mock AI response ║
|
|
║ GET /health - Health check ║
|
|
║ ║
|
|
║ Press Ctrl+C to stop ║
|
|
╚══════════════════════════════════════════════════════════════╝
|
|
`);
|
|
});
|
|
|
|
module.exports = app; // Export for testing
|