Files
LogWhispererAI/tools/fake-backend/server.js
Luca Sacchi Ricciardi 8eb7dfb00e feat: add fake-backend mock API server for frontend development
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
2026-04-03 16:57:14 +02:00

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