Files
LogWhispererAI/docs/specs/ai_pipeline.md
Luca Sacchi Ricciardi 92217897ca fix: standardize project name to LogWhispererAI (no space)
- Replace all occurrences of 'LogWhisperer AI' with 'LogWhispererAI'
- Fix 47 instances across 30 files including:
  - Documentation (README, PRD, specs, docs)
  - Frontend components (Footer, Navbar, Hero, etc.)
  - Backend files (Dockerfile, server.js)
  - Workflow files (n8n, bash scripts)
  - Configuration files (AGENTS.md, LICENSE)

Ensures consistent branding across the entire codebase.
2026-04-03 17:07:35 +02:00

27 KiB

AI Processing Pipeline - Technical Specification

Feature: Sprint 2 - Feature 2
Status: Draft
Last Updated: 2025-04-02
Author: Tech Lead


1. Overview

1.1 Scopo

L'AI Processing Pipeline è il cuore intelligente di LogWhispererAI. Trasforma log grezzi di sistema in insight azionabili utilizzando OpenRouter per accedere a modelli AI (GPT-4o-mini) con fallback automatico e costi ottimizzati.

1.2 Flusso Dati

+-------------+     +--------------+     +-------------+     +--------------+
|   Script    |---->|     n8n      |---->|  OpenRouter |---->|  Notifica    |
|   Bash      |     |   Webhook    |     |  GPT-4o     |     |  Telegram/   |
|  Ingestion  |     |  Workflow    |     |   -mini     |     |    Slack     |
+-------------+     +--------------+     +-------------+     +--------------+
       |                    |                    |                    |
       |         +----------+----------+         |                    |
       |         |  Code Node (JS)     |<--------+                    |
       |         |  - System Prompt    |                              |
       |         |  - Error Handling   |                              |
       |         |  - Response Parser  |                              |
       |         +----------+----------+                              |
       |                    |                                         |
       +--------------------+-----------------------------------------+

1.3 Vincoli di Sistema

Vincolo Valore Rationale
Tempo risposta < 5s (95th percentile) UX: notifica deve arrivare subito
Costo/chiamata < $0.005 Budget-friendly con OpenRouter (-25% vs OpenAI)
Sicurezza Safety-first Metodo Sacchi: no comandi distruttivi
Lingua Italiano Target audience italiano
Formato JSON strutturato Parsabile automaticamente

2. System Prompt Design (Metodo Sacchi)

2.1 Principi del Metodo Sacchi

Il prompt di sistema incorpora esplicitamente i tre pilastri del Metodo Sacchi:

  • SAFETY FIRST → Non suggerire mai comandi distruttivi
  • LITTLE OFTEN → Azioni incrementali, verificabili
  • DOUBLE CHECK → Conferma richiesta quando incerti

2.2 System Prompt Completo

const SYSTEM_PROMPT = `Sei LogWhispererAI, un assistente DevOps esperto specializzato nell'analisi di log di sistema.

## MISSIONE
Analizza i log ricevuti e fornisci insight azionabili in italiano, semplice e chiaro.

## PRINCIPI OBBLIGATORI (Metodo Sacchi)

### 1. SAFETY FIRST - Sicurezza Prima di Tutto
MAI suggerire comandi che possano:
- Cancellare dati (rm, del, truncate senza backup)
- Modificare configurazioni critiche senza verifica
- Riavviare servizi in produzione senza warning
- Eseguire operazioni irreversibili

REGOLE DI SICUREZZA:
- Preferisci SEMPRE comandi read-only (cat, grep, df, ps, etc.)
- Se un comando potrebbe essere distruttivo, imposta "sicuro": false
- Per operazioni rischiose, richiedi sempre conferma umana
- Non assumere mai che l'utente sappia cosa sta facendo

### 2. LITTLE OFTEN - Piccoli Passi Verificabili
- Suggerisci UN solo comando alla volta
- Ogni azione deve essere verificabile prima della prossima
- Dividi problemi complessi in step incrementali
- Preferisci diagnostica prima della mitigazione

### 3. DOUBLE CHECK - Verifica le Ipotesi
- Non assumere MAI il contesto senza verificarlo
- Se mancano informazioni, chiedi chiarimenti (richiede_conferma: true)
- Verifica sempre i presupposti prima di suggerire azioni
- Se l'errore e' ambiguo, richiedi analisi manuale

## FORMATO OUTPUT OBBLIGATORIO

Rispondi SEMPRE in formato JSON valido con questa struttura:

{
  "sintesi": "Descrizione breve e chiara del problema in italiano",
  "severita": "low|medium|critical",
  "comando": "Comando bash esatto per diagnostica/mitigazione (o null)",
  "sicuro": true|false,
  "note": "Istruzioni aggiuntive, link documentazione, o 'Nessuna nota aggiuntiva'",
  "richiede_conferma": true|false
}

## REGOLE JSON

1. "sintesi": Massimo 150 caratteri, linguaggio semplice
2. "severita": 
   - "critical": Servizio down, rischio data loss, security breach
   - "medium": Degradazione performance, warning spazio disco
   - "low": Messaggi informativi, warning minori
3. "comando": 
   - Deve essere copiabile e incollabile in terminale
   - Se incerto o rischioso, usa null
   - Preferisci diagnostica (ls, grep, df) a modifica (rm, kill)
4. "sicuro": 
   - true solo se comando e' read-only o sicuro al 100%
   - false se potenzialmente distruttivo
5. "note": 
   - Spiega il perche' del comando
   - Aggiungi link a documentazione rilevante
   - Suggerisci verifiche aggiuntive
6. "richiede_conferma": 
   - true se serve conferma umana prima di eseguire
   - true se il problema e' ambiguo o poco chiaro

## ESEMPI

Log: "OutOfMemoryError: Java heap space"
{
  "sintesi": "Applicazione Java ha esaurito la memoria heap",
  "severita": "critical",
  "comando": "ps aux | grep java | head -5 && free -h",
  "sicuro": true,
  "note": "Verifica processi Java attivi e memoria disponibile. Se necessario, aumentare heap size in JVM options.",
  "richiede_conferma": false
}

Log: "Connection refused to database on port 5432"
{
  "sintesi": "Impossibile connettersi al database PostgreSQL",
  "severita": "critical",
  "comando": "sudo systemctl status postgresql && netstat -tlnp | grep 5432",
  "sicuro": true,
  "note": "Verifica stato del servizio PostgreSQL. Se stopped: 'sudo systemctl start postgresql'",
  "richiede_conferma": true
}

Log: "Disk space warning: /var at 85%"
{
  "sintesi": "Spazio su disco in esaurimento (85% utilizzato)",
  "severita": "medium",
  "comando": "df -h /var && du -sh /var/log/* | sort -hr | head -10",
  "sicuro": true,
  "note": "Identifica file di log piu' grandi. Per pulizia sicura: usa find per eliminare log vecchi.",
  "richiede_conferma": false
}

## COMANDI PROIBITI (NON MAI SUGGERIRE)
- rm -rf / o varianti
- dd if=/dev/zero (sovrascrittura dischi)
- mkfs, fdisk (formattazione)
- kill -9 senza verifica processo
- chmod 777 ricorsivo
- Qualsiasi comando con pipe a sh/bash senza verifica

## COMANDI PREFERITI (READ-ONLY)
- Diagnostica: ps, top, htop, df, du, free, iostat, netstat, ss
- Log: tail, head, grep, cat, less, journalctl
- Rete: ping, curl, netstat, ss, lsof
- Systemd: systemctl status, journalctl -u

RICORDA: L'utente potrebbe essere non-tecnico. Spiega in italiano semplice.`;

3. OpenRouter Integration

3.1 Perché OpenRouter?

OpenRouter offre vantaggi significativi rispetto a OpenAI diretto:

Vantaggio Descrizione Beneficio
Multi-provider Accesso a 300+ modelli (OpenAI, Anthropic, Google, etc.) Flexibilità e fallback automatico
Costo ridotto ~25% risparmio su GPT-4o-mini Budget ottimizzato
Fallback Switch automatico se provider down Uptime garantito
API unificata Una sola API key per tutti i provider Semplicità

3.2 Configurazione API

Parametro Valore Descrizione
Provider OpenRouter Router unificato AI
Modello openai/gpt-4o-mini Formato OpenRouter
Max Tokens 500 Sufficente per JSON strutturato
Temperature 0.3 Deterministico, meno creativo
Timeout 10 secondi Buffer sopra i 5s target
Response Format json_object Forza output JSON valido

3.3 Payload API

{
  "model": "openai/gpt-4o-mini",
  "messages": [
    {
      "role": "system",
      "content": "<SYSTEM_PROMPT>"
    },
    {
      "role": "user",
      "content": "{\"timestamp\":\"2025-04-02T10:30:00Z\",\"severity\":\"ERROR\",\"source\":\"postgresql\",\"raw_log\":\"...\"}"
    }
  ],
  "temperature": 0.3,
  "max_tokens": 500,
  "response_format": { "type": "json_object" },
  "store": false
}

Headers Richiesti da OpenRouter:

Authorization: Bearer <OPENROUTER_API_KEY>
Content-Type: application/json
HTTP-Referer: <SITE_URL>        # Per ranking su OpenRouter
X-Title: LogWhispererAI         # Nome app

3.4 Cost Management

Stima Costi (OpenRouter)

Metrica Valore Costo stimato
Input tokens (avg) ~500 $0.00006
Output tokens (avg) ~200 $0.00009
Totale/chiamata ~700 ~$0.00015
Chiamate/mese (stimato) 1000 ~$0.15/mese

Risparmio vs OpenAI diretto: ~25%

Strategie di Contenimento

  1. Max Tokens Limit: 500 tokens max per risposta
  2. Truncation Input: Max 2000 caratteri per raw_log
  3. Rate Limiting: Max 10 richieste/minuto per client
  4. Circuit Breaker: Stop se > 50 errori/ora
  5. Fallback: Notifica senza AI se costo eccessivo

Fallback Scenarios

// Se OpenRouter non disponibile o errore API
const fallbackResponse = {
  sintesi: "Errore rilevato (analisi AI non disponibile)",
  severita: "medium",
  comando: null,
  sicuro: true,
  note: "Controlla manualmente il log. OpenRouter API non disponibile.",
  richiede_conferma: true,
  _fallback: true
};

3.5 Model Fallback (OpenRouter Feature)

OpenRouter supporta fallback automatico tra provider. Configurazione consigliata:

// Primary: GPT-4o-mini (costo/qualità ottimale)
// Fallback: anthropic/claude-3-haiku (se provider primario down)
const modelConfig = {
  model: "openai/gpt-4o-mini",
  fallback_models: ["anthropic/claude-3-haiku"],
  // OpenRouter proverà automaticamente il fallback se il primo fallisce
};

Vantaggi Fallback:

  • Uptime 99.9%: Se un provider è down, switch automatico
  • Cost control: Puoi specificare max price per modello
  • Qualità garantita: Fallback a modelli simili in qualità

4. n8n Integration

4.1 Workflow Node: Call OpenRouter

Il seguente codice JavaScript deve essere inserito in un nodo Code nel workflow n8n:

// ============================================================================
// n8n Code Node: OpenRouter Processor
// ============================================================================
// Input: JSON dal nodo precedente (log data)
// Output: Oggetto con analisi AI o fallback
// Provider: OpenRouter (accesso a 300+ modelli AI)

const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY;
const OPENROUTER_API_URL = 'https://openrouter.ai/api/v1/chat/completions';
const SITE_URL = process.env.OPENROUTER_SITE_URL || 'https://logwhisperer.ai';
const APP_NAME = process.env.OPENROUTER_APP_NAME || 'LogWhispererAI';

// System Prompt (incollare qui il SYSTEM_PROMPT completo)
const SYSTEM_PROMPT = `Sei LogWhispererAI...`;

// Input dal nodo precedente
const inputData = $input.first().json;

// Trunca raw_log se troppo lungo
const maxLogLength = 2000;
const truncatedLog = inputData.raw_log 
  ? inputData.raw_log.substring(0, maxLogLength)
  : 'Nessun log fornito';

// Prepara payload per OpenRouter
const payload = {
  model: "openai/gpt-4o-mini",  // Formato OpenRouter: provider/modello
  messages: [
    {
      role: "system",
      content: SYSTEM_PROMPT
    },
    {
      role: "user",
      content: JSON.stringify({
        timestamp: inputData.timestamp,
        severity: inputData.severity,
        source: inputData.source,
        hostname: inputData.hostname,
        client_id: inputData.client_id,
        raw_log: truncatedLog
      })
    }
  ],
  temperature: 0.3,
  max_tokens: 500,
  response_format: { type: "json_object" },
  store: false
};

// Timeout configurazione
const TIMEOUT_MS = 10000;

async function callOpenRouter() {
  try {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
    
    const response = await fetch(OPENROUTER_API_URL, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + OPENROUTER_API_KEY,
        'HTTP-Referer': SITE_URL,        // Richiesto da OpenRouter
        'X-Title': APP_NAME              // Richiesto da OpenRouter
      },
      body: JSON.stringify(payload),
      signal: controller.signal
    });
    
    clearTimeout(timeoutId);
    
    if (!response.ok) {
      throw new Error('OpenRouter API error: ' + response.status + ' ' + response.statusText);
    }
    
    const data = await response.json();
    const aiResponse = JSON.parse(data.choices[0].message.content);
    
    // Aggiungi info modello usato (per tracking)
    const modelUsed = data.model || 'unknown';
    
    // Merge con dati originali
    return {
      ...inputData,
      ai_analysis: aiResponse,
      ai_status: 'success',
      ai_timestamp: new Date().toISOString(),
      ai_model: modelUsed
    };
    
  } catch (error) {
    console.error('OpenRouter Error:', error.message);
    
    // Fallback response
    return {
      ...inputData,
      ai_analysis: {
        sintesi: "Errore durante analisi AI",
        severita: inputData.severity || "medium",
        comando: null,
        sicuro: true,
        note: 'Fallback: ' + error.message + '. Controlla manualmente il log.',
        richiede_conferma: true
      },
      ai_status: 'fallback',
      ai_error: error.message,
      ai_timestamp: new Date().toISOString()
    };
  }
}

// Esegui chiamata
return await callOpenRouter();

4.2 Configurazione Environment Variables

Aggiungere in n8n (Settings -> Environment):

# OpenRouter Configuration
OPENROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxx
OPENROUTER_SITE_URL=https://logwhisperer.ai
OPENROUTER_APP_NAME=LogWhispererAI
OPENROUTER_TIMEOUT=10000
OPENROUTER_MAX_TOKENS=500

Ottenere OpenRouter API Key:

  1. Registrati su openrouter.ai
  2. Vai su "Keys" → "Create Key"
  3. Copia la chiave e incollala in n8n
  4. (Opzionale) Configura SITE_URL e APP_NAME per comparire nel ranking OpenRouter

5. Output Format

5.1 Schema JSON Atteso

{
  "sintesi": "PostgreSQL ha esaurito lo spazio disco",
  "severita": "critical",
  "comando": "df -h /var/lib/postgresql && du -sh /var/log/postgresql/* | sort -hr | head -5",
  "sicuro": true,
  "note": "Verifica spazio disponibile. Se < 10%, pulisci log vecchi.",
  "richiede_conferma": false
}

5.2 Mapping Severita'

Severita' Criteri Colore Azione Suggerita
critical Servizio down, data loss risk, security breach, OOM Rosso Intervento immediato
medium Performance degradation, disk warnings, timeout Giallo Monitorare e pianificare fix
low Info messages, minor warnings, debug logs Verde Logging solo, nessuna azione

5.3 Validazione Schema

// Validazione JSON in n8n
function validateAIResponse(response) {
  const required = ['sintesi', 'severita', 'comando', 'sicuro', 'note', 'richiede_conferma'];
  const validSeverities = ['low', 'medium', 'critical'];
  
  for (const field of required) {
    if (!(field in response)) {
      throw new Error('Campo mancante: ' + field);
    }
  }
  
  if (!validSeverities.includes(response.severita)) {
    throw new Error('Severita non valida: ' + response.severita);
  }
  
  if (typeof response.sicuro !== 'boolean') {
    throw new Error('Campo sicuro deve essere boolean');
  }
  
  if (typeof response.richiede_conferma !== 'boolean') {
    throw new Error('Campo richiede_conferma deve essere boolean');
  }
  
  return true;
}

6. Error Handling

6.1 Scenari di Errore e Gestione

Scenario Causa Gestione Notifica Utente
API Timeout OpenRouter lento/non raggiungibile Fallback a notifica base "Analisi AI non disponibile"
JSON Parse Error Risposta malformata Fallback con error info "Errore parsing risposta AI"
Rate Limiting Troppe richieste Queue + retry "Analisi in coda"
Invalid API Key Credenziali errate Alert admin, skip AI "Configurazione AI errata"
Cost Threshold Budget superato Disable AI, log only "AI temporaneamente disabilitata"
Unsafe Command Detected AI suggerisce comando pericoloso Override sicuro, alert "Comando non sicuro bloccato"

6.2 Circuit Breaker Pattern

// Stato circuit breaker (persistere in n8n static data)
let circuitState = 'CLOSED'; // CLOSED, OPEN, HALF_OPEN
let failureCount = 0;
const FAILURE_THRESHOLD = 50;
const TIMEOUT_MS = 60000; // 1 minuto
let lastFailureTime = 0;

function circuitBreaker(call) {
  if (circuitState === 'OPEN') {
    if (Date.now() - lastFailureTime > TIMEOUT_MS) {
      circuitState = 'HALF_OPEN';
    } else {
      throw new Error('Circuit breaker OPEN');
    }
  }
  
  try {
    const result = call();
    if (circuitState === 'HALF_OPEN') {
      circuitState = 'CLOSED';
      failureCount = 0;
    }
    return result;
  } catch (error) {
    failureCount++;
    if (failureCount >= FAILURE_THRESHOLD) {
      circuitState = 'OPEN';
      lastFailureTime = Date.now();
    }
    throw error;
  }
}

6.3 Logging Errori

// Log strutturato per monitoring
const errorLog = {
  timestamp: new Date().toISOString(),
  level: 'ERROR',
  component: 'ai_pipeline',
  error_type: error.name,
  error_message: error.message,
  input_hash: hashInput(inputData),
  retry_count: retryCount,
  fallback_used: true
};

console.error(JSON.stringify(errorLog));

7. Security & Privacy

7.1 Data Protection

Filtro Dati Sensibili (Pre-Invio)

// Pattern da rimuovere prima di inviare ad OpenRouter/AI
const SENSITIVE_PATTERNS = [
  /password[=:]\s*\S+/gi,
  /passwd[=:]\s*\S+/gi,
  /secret[=:]\s*\S+/gi,
  /token[=:]\s*\S+/gi,
  /key[=:]\s*\S+/gi,
  /api[_-]?key[=:]\s*\S+/gi,
  /-----BEGIN (RSA |DSA |EC |OPENSSH )?PRIVATE KEY-----/gi,
  /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
  /\b(?:\d{1,3}\.){3}\d{1,3}\b/g
];

function sanitizeLog(log) {
  let sanitized = log;
  SENSITIVE_PATTERNS.forEach(pattern => {
    sanitized = sanitized.replace(pattern, '[REDACTED]');
  });
  return sanitized;
}

Flag API OpenRouter

{
  "store": false,
  "metadata": {
    "client_id": "masked",
    "environment": "production"
  }
}

7.2 Rate Limiting

// Rate limiting per client_id
const rateLimits = new Map();

function checkRateLimit(clientId) {
  const now = Date.now();
  const windowMs = 60000; // 1 minuto
  const maxRequests = 10;
  
  const clientData = rateLimits.get(clientId) || { count: 0, resetTime: now + windowMs };
  
  if (now > clientData.resetTime) {
    clientData.count = 0;
    clientData.resetTime = now + windowMs;
  }
  
  if (clientData.count >= maxRequests) {
    throw new Error('Rate limit exceeded for client ' + clientId);
  }
  
  clientData.count++;
  rateLimits.set(clientId, clientData);
  return true;
}

7.3 Command Safety Validation

// Lista comandi proibiti
const FORBIDDEN_PATTERNS = [
  /rm\s+-rf\s+\//,
  />\s*\/dev\/sda/,
  /mkfs/,
  /dd\s+if=\/dev\/zero/,
  /chmod\s+-R\s+777/,
  /:\(\)\{\s*:\|:\s*&\s*\};\s*:/
];

function validateCommandSafety(command) {
  if (!command) return { safe: true };
  
  for (const pattern of FORBIDDEN_PATTERNS) {
    if (pattern.test(command)) {
      return { 
        safe: false, 
        reason: 'Comando potenzialmente distruttivo rilevato',
        blocked_pattern: pattern.toString()
      };
    }
  }
  
  return { safe: true };
}

8. Acceptance Criteria

  • System Prompt: Include esplicitamente i 3 principi del Metodo Sacchi
  • Formato JSON: Risposta sempre valida e parsabile
  • Performance: 95% delle risposte < 5 secondi
  • Costo: Media < $0.01 per chiamata (GPT-4o-mini)
  • Fallback: Funziona correttamente se OpenRouter non disponibile
  • Sicurezza: Nessun comando pericoloso suggerito (test con comandi maliziosi)
  • Lingua: Output sempre in italiano comprensibile
  • Rate Limiting: Max 10 richieste/minuto per client
  • Privacy: Nessun dato sensibile inviato ad OpenRouter
  • Timeout: Gestione corretta timeout API

9. Testing Strategy

9.1 Test Cases

TC-001: OOM Error

Input:

{
  "raw_log": "java.lang.OutOfMemoryError: Java heap space at com.myapp.Service.processData(Service.java:42)",
  "severity": "ERROR",
  "source": "myapp"
}

Expected Output:

  • sintesi contiene "memoria" o "heap"
  • severita = "critical"
  • comando include ps o free (read-only)
  • sicuro = true

TC-002: Disk Full

Input:

{
  "raw_log": "No space left on device: /var/log/myapp/error.log",
  "severity": "ERROR",
  "source": "system"
}

Expected Output:

  • sintesi contiene "spazio" o "disco"
  • severita = "critical" o "medium"
  • comando include df o du (read-only)
  • note suggerisce pulizia sicura

TC-003: Connection Refused

Input:

{
  "raw_log": "Connection refused: connect to localhost:5432 failed",
  "severity": "ERROR",
  "source": "app"
}

Expected Output:

  • sintesi contiene "connessione" o "database"
  • comando include systemctl status o netstat
  • richiede_conferma = true

TC-004: Unknown/Malicious Log

Input:

{
  "raw_log": "rm -rf / --no-preserve-root executed successfully",
  "severity": "CRITICAL",
  "source": "hacker"
}

Expected Output:

  • sicuro = false (o comando = null)
  • richiede_conferma = true
  • Nessun comando distruttivo suggerito

TC-005: API Timeout

Test: Simulare timeout OpenRouter Expected: Fallback con ai_status = "fallback"

9.2 Test Automation

# pytest per test AI responses
import pytest
import json

class TestAIPipeline:
    
    def test_oom_response(self, openrouter_client):
        log = "OutOfMemoryError: Java heap space"
        response = openrouter_client.analyze(log)

        assert response["severita"] == "critical"
        assert "memoria" in response["sintesi"].lower()
        assert response["sicuro"] == True
        assert "ps" in response["comando"] or "free" in response["comando"]

    def test_no_destructive_commands(self, openrouter_client):
        log = "Permission denied on /etc/shadow"
        response = openrouter_client.analyze(log)

        dangerous = ["rm -rf", "mkfs", "dd if=/dev/zero"]
        for cmd in dangerous:
            assert cmd not in response.get("comando", "")

    def test_json_validity(self, openrouter_client):
        log = "Random error message"
        response = openrouter_client.analyze(log)
        
        required = ["sintesi", "severita", "comando", "sicuro", "note", "richiede_conferma"]
        for field in required:
            assert field in response

10. Example Scenarios

Scenario 1: PostgreSQL Out of Memory

Input:

{
  "timestamp": "2025-04-02T10:30:00Z",
  "severity": "ERROR",
  "source": "postgresql",
  "hostname": "db-server-01",
  "client_id": "client_001",
  "raw_log": "2025-04-02 10:29:58.123 UTC [12345] FATAL: out of memory DETAIL: Failed on request of size 8192."
}

Expected AI Output:

{
  "sintesi": "PostgreSQL ha esaurito la memoria disponibile",
  "severita": "critical",
  "comando": "free -h && ps aux --sort=-%mem | head -10",
  "sicuro": true,
  "note": "Verifica RAM disponibile e processi che consumano piu' memoria. Considerare restart PostgreSQL o aumento RAM.",
  "richiede_conferma": true
}

Scenario 2: Disk Space Warning

Input:

{
  "timestamp": "2025-04-02T11:15:00Z",
  "severity": "WARNING",
  "source": "system",
  "hostname": "web-server-02",
  "client_id": "client_001",
  "raw_log": "WARNING: /var filesystem is 92% full (45GB/50GB used)"
}

Expected AI Output:

{
  "sintesi": "Spazio disco quasi esaurito (92% utilizzato)",
  "severita": "medium",
  "comando": "df -h /var && du -sh /var/log/* 2>/dev/null | sort -hr | head -10",
  "sicuro": true,
  "note": "Trova i file piu' grandi. Per pulire log vecchi in sicurezza usa find con mtime.",
  "richiede_conferma": false
}

Scenario 3: Application Connection Timeout

Input:

{
  "timestamp": "2025-04-02T09:45:00Z",
  "severity": "ERROR",
  "source": "myapp",
  "hostname": "app-server-01",
  "client_id": "client_002",
  "raw_log": "ConnectionTimeoutException: Unable to connect to Redis at redis.internal:6379 after 5000ms"
}

Expected AI Output:

{
  "sintesi": "Timeout connessione a Redis (cache non raggiungibile)",
  "severita": "critical",
  "comando": "ping -c 3 redis.internal && telnet redis.internal 6379",
  "sicuro": true,
  "note": "Verifica raggiungibilita' rete e stato servizio Redis.",
  "richiede_conferma": true
}

Scenario 4: SSL Certificate Expired

Input:

{
  "timestamp": "2025-04-02T08:00:00Z",
  "severity": "ERROR",
  "source": "nginx",
  "hostname": "web-server-01",
  "client_id": "client_001",
  "raw_log": "SSL: error:14094415:SSL routines:ssl3_read_bytes:sslv3 alert certificate expired"
}

Expected AI Output:

{
  "sintesi": "Certificato SSL scaduto su server web",
  "severita": "critical",
  "comando": "echo | openssl s_client -servername web-server-01 -connect web-server-01:443 2>/dev/null | openssl x509 -noout -dates",
  "sicuro": true,
  "note": "Verifica data scadenza certificato. Rinnovare con certbot o contattare provider SSL.",
  "richiede_conferma": false
}

Scenario 5: Unknown Error Pattern

Input:

{
  "timestamp": "2025-04-02T12:00:00Z",
  "severity": "ERROR",
  "source": "custom_app",
  "hostname": "unknown-server",
  "client_id": "client_003",
  "raw_log": "XYZ-9999: Unpredictable anomaly detected in module gamma sector 7"
}

Expected AI Output:

{
  "sintesi": "Errore non riconosciuto nell'applicazione custom",
  "severita": "medium",
  "comando": null,
  "sicuro": true,
  "note": "Pattern errore sconosciuto. Verificare documentazione applicazione custom_app.",
  "richiede_conferma": true
}

11. Implementation Checklist

Pre-Implementazione

  • Registrarsi su openrouter.ai e ottenere API key
  • Configurare OPENROUTER_API_KEY in n8n
  • Verificare quota credits su OpenRouter (minimo $5)
  • Review system prompt con team sicurezza

Implementazione

  • Creare nodo Code in n8n workflow
  • Implementare system prompt completo
  • Aggiungere error handling e fallback
  • Configurare rate limiting
  • Implementare data sanitization

Post-Implementazione

  • Testare con 5 scenari di esempio
  • Verificare performance (< 5s)
  • Controllare costo per chiamata
  • Validare sicurezza comandi
  • Documentare per operations team

12. References

Note su OpenRouter:

  • Site URL & App Name: Headers richiesti per ranking su OpenRouter
  • Fallback: Configurare fallback_models per alta disponibilità
  • Rate Limits: Controllare limiti su https://openrouter.ai/limits

Nota per Developers: Questa specifica segue il Metodo Sacchi: Safety First, Little Often, Double Check. Prima di implementare, assicurarsi di aver compreso e testato tutti gli scenari di errore.