Debug Log WordPress per Agenzie: Configurazione, Rotazione e Monitoraggio [2026]

3 settembre 202612 minSicurezza

Il debug log di WordPress è spento di default. Quando un sito cliente va in bianco, il tuo primo istinto è aprire wp-config.php e inserire define('WP_DEBUG', true);. Il problema? Su 50 siti, farlo a mano ogni volta ti costa ore. E se lo lasci acceso, il file debug.log cresce fino a riempire il disco. In questa guida vediamo come configurare il logging WordPress in modo professionale: errori separati dalle notice, rotazione automatica dei log, invio a un servizio centralizzato, e come leggere quello che WordPress ti sta dicendo.

Questo articolo si integra con la nostra guida alla sicurezza WordPress per agenzie e con il monitoraggio log WordPress per agenzie — il logging è il primo passo per un monitoraggio serio.

TL;DR

  • WP_DEBUG, WP_DEBUG_LOG e WP_DEBUG_DISPLAY sono tre costanti indipendenti — non una sola
  • Imposta WP_DEBUG_LOG a true su tutti i siti di produzione, ma con rotazione automatica del file
  • Usa error_reporting(E_ERROR | E_WARNING | E_PARSE) per filtrare le notice infinite dei plugin scadenti
  • Per agenzie con 10+ siti: invia i log a un servizio centralizzato (Graylog, Papertrail, o anche solo un file per sito con WP_DEBUG_LOG personalizzato)
  • Non lasciare mai WP_DEBUG_DISPLAY attivo in produzione — mostra errori HTML agli utenti

Come Funziona il Debug WordPress (e Perché Quasi Tutti Sbagliano)

WordPress ha tre costanti per il debug, e il 90% degli sviluppatori ne usa una sola. Ecco cosa fanno davvero:

Costante Default Cosa fa Produzione
WP_DEBUG false Attiva il debug mode di WordPress. Controlla anche SCRIPT_DEBUG e WP_DEBUG_DISPLAY indirettamente true (sempre)
WP_DEBUG_LOG false Scrive gli errori in wp-content/debug.log true (con rotazione)
WP_DEBUG_DISPLAY true Mostra gli errori a schermo (HTML). Disabilitato quando WP_DEBUG è false false (sempre)
SCRIPT_DEBUG false Carica i file JS/CSS non minimizzati. Utile solo per debug frontend false

L’errore più comune: impostare WP_DEBUG a true senza toccare WP_DEBUG_DISPLAY. Risultato: gli errori PHP compaiono nell’HTML del sito. I clienti lo notano. A volte sono errori innocui (notice PHP 8.2 su plugin non aggiornati), ma l’impatto visivo è disastroso.

La configurazione corretta per produzione:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', 0);

Sì, WP_DEBUG a true in produzione. Non è pericoloso finché WP_DEBUG_DISPLAY è false. WordPress scriverà tutto nel file debug.log senza mostrare nulla all’utente. Questo ti dà visibilità su problemi che altrimenti scopriresti solo quando un cliente si lamenta.

Configurazione Avanzata: Separare Errori da Notice

Il problema di WP_DEBUG è che scrive TUTTO nel log. Su un sito con 30 plugin, il file debug.log si riempie di notice inutili (“Undefined index: foo in /var/www/wp-content/plugins/some-plugin/functions.php on line 42”). Risultato: gli errori veri (fatal error, warning su query SQL) si perdono nel rumore.

La soluzione è filtrare il livello di error_reporting direttamente nel wp-config.php:

define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', 0);

// Filtra: solo errori, warning e parse errors — no notice, no deprecated
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING);

Se stai facendo un audit di un sito nuovo e vuoi vedere tutto (incluso notice e deprecated), temporaneamente alza il livello:

error_reporting(E_ALL);

Ma non lasciarlo così in produzione. Le notice di WordPress 6.x su PHP 8.2+ sono decine per ogni pagina load, anche su installazioni pulite.

Come Personalizzare il Percorso del File debug.log

Di default WordPress scrive in wp-content/debug.log. Su un server con 50 siti, vuoi i log in un posto solo, non sparsi in 50 cartelle wp-content. Puoi cambiare il percorso definendo WP_DEBUG_LOG come path assoluto invece che boolean:

// Tutti i log di questo sito in /var/log/wordpress/sito-nomecliente.log
define('WP_DEBUG_LOG', '/var/log/wordpress/' . basename(ABSPATH) . '.log');

In questo modo ogni sito ha il suo file di log in /var/log/wordpress/. Facile da grep, facile da ruotare con logrotate.

Assicurati che l’utente del web server (di solito www-data su Debian/Ubuntu) abbia i permessi di scrittura:

sudo mkdir -p /var/log/wordpress
sudo chown www-data:www-data /var/log/wordpress
sudo chmod 755 /var/log/wordpress

Rotazione Automatica dei Log con logrotate

Il debug.log non ha rotazione nativa. Su un sito con molto traffico, un file da 500MB in una settimana è normale. Un file di 5GB rallenta il server quando PHP cerca di scrivere alla fine. La soluzione è logrotate:

# /etc/logrotate.d/wordpress-debug

/var/log/wordpress/*.log {
    daily
    rotate 14
    missingok
    notifempty
    compress
    delaycompress
    copytruncate
    size 50M
    maxsize 500M
}

Cosa fa questa configurazione:

  • daily: controlla ogni giorno
  • rotate 14: tiene 14 giorni di log
  • size 50M: ruota anche se il file supera 50MB (indipendentemente dal giorno)
  • copytruncate: copia il file e tronca quello originale — non serve riavviare PHP o Nginx
  • compress: comprime i log vecchi con gzip

Testa la configurazione:

sudo logrotate -d /etc/logrotate.d/wordpress-debug

Se vedi errori di permessi, controlla che logrotate giri come root (di default nel cron di sistema) o che l’utente www-data possa scrivere nella cartella di destinazione.

Catturare gli Errori Fatali Prima che il Cliente Li Noti

Il debug.log passivo è meglio di niente, ma non ti avvisa quando qualcosa si rompe. Per un’agenzia con 50+ siti, serve un monitoraggio attivo.

L’approccio più semplice: uno script bash che legge i log ogni 5 minuti e invia un alert se trova errori nuovi. Se usi già un sistema di monitoring come Uptime Kuma o Pingdom (di cui abbiamo parlato nel nostro articolo sul monitoraggio uptime con AI), puoi integrarlo.

#!/bin/bash
# /usr/local/bin/wp-debug-check.sh
# Controlla i debug.log di tutti i siti e invia alert su nuovi errori fatali

LOG_DIR="/var/log/wordpress"
STATE_FILE="/var/lib/wp-debug-check/last-seen"
ALERT_WEBHOOK="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

mkdir -p "$(dirname "$STATE_FILE")"

for logfile in "$LOG_DIR"/*.log; do
    [ -f "$logfile" ] || continue
    sitename=$(basename "$logfile" .log)
    last_line=$(wc -l < "$logfile" 2>/dev/null || echo 0)
    prev_line=$(cat "$STATE_FILE/$sitename" 2>/dev/null || echo 0)

    if [ "$last_line" -gt "$prev_line" ]; then
        new_errors=$(tail -n +$((prev_line + 1)) "$logfile" | grep -i "fatal\|parse error\|warning" | head -5)

        if [ -n "$new_errors" ]; then
            payload=$(jq -n --arg text "🔴 $sitename: nuovi errori in debug.log\n\`\`\`\n$new_errors\n\`\`\`" '{text: $text}')
            curl -s -X POST "$ALERT_WEBHOOK" -H "Content-Type: application/json" -d "$payload"
        fi
    fi

    echo "$last_line" > "$STATE_FILE/$sitename"
done

Metti questo script in crontab ogni 5 minuti:

# crontab -e
*/5 * * * * /usr/local/bin/wp-debug-check.sh

Usare WP-CLI per Leggere i Log Velocemente

Se hai accesso SSH, wp-cli può aiutarti a leggere i log senza aprire il file. Non esiste un comando nativo, ma puoi crearne uno breve. Leggi il nostro articolo su WP-CLI per agenzie per la configurazione completa.

Comandi utili per leggere i log da terminale:

# Ultimi 20 errori del sito
tail -20 /var/log/wordpress/sito-cliente.log

# Cerca tutti i fatal error in tutti i siti
grep -ri "fatal" /var/log/wordpress/ | tail -20

# Conta gli errori per sito nell'ultima settimana
for f in /var/log/wordpress/*.log; do
    count=$(grep -c "$(date +%Y-%m-%d | sed 's/-/\\-/g')" "$f" 2>/dev/null || echo 0)
    echo "$(basename $f): $count errori"
done | sort -t: -k2 -rn

# Usa wp-cli per vedere se WP_DEBUG è attivo su un sito
wp config get WP_DEBUG --path=/var/www/sito-cliente
wp config get WP_DEBUG_LOG --path=/var/www/sito-cliente

Logging Strutturato: Oltre il debug.log Nativo

Il debug.log di WordPress è plain text. Va bene per debug veloce, ma per un’agenzia con 50+ siti serve qualcosa di più strutturato. Due opzioni pratiche:

Opzione 1: Monolog via mu-plugin

Se i tuoi siti usano Composer (e dovrebbero), installa monolog/monolog e crea un mu-plugin che logga a un file strutturato:

<?php
// wp-content/mu-plugins/structured-logging.php

use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Formatter\JsonFormatter;

if (!class_exists('Monolog\Logger')) {
    return; // Monolog non installato, fallback al debug.log nativo
}

add_action('init', function() {
    $logger = new Logger('wordpress');
    $handler = new StreamHandler('/var/log/wordpress/' . basename(ABSPATH) . '.json.log');
    $handler->setFormatter(new JsonFormatter());
    $logger->pushHandler($handler);

    // Registra handler per errori PHP
    set_error_handler(function($errno, $errstr, $errfile, $errline) use ($logger) {
        $logger->warning($errstr, [
            'errno' => $errno,
            'file' => $errfile,
            'line' => $errline,
            'url' => $_SERVER['REQUEST_URI'] ?? '',
            'ip' => $_SERVER['REMOTE_ADDR'] ?? '',
        ]);
        return false; // Lascia che il handler nativo continui
    });

    // Registra handler per fatal error
    register_shutdown_function(function() use ($logger) {
        $error = error_get_last();
        if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR])) {
            $logger->critical('Fatal error: ' . $error['message'], [
                'file' => $error['file'],
                'line' => $error['line'],
            ]);
        }
    });
});

I log in JSON possono essere inviati a Graylog, ELK, o qualsiasi sistema di log aggregation. Ogni entry ha timestamp, livello, messaggio e contesto strutturato.

Opzione 2: Invio a un servizio esterno

Se non vuoi gestire un server di log, servizi come Papertrail o Better Stack offrono log management gratuito (o economico) per piccoli volumi. Configura syslog sul server e invia i log via UDP:

# /etc/rsyslog.d/30-wordpress.conf
# Invia i log WordPress a Papertrail

*.* @logsX.papertrailapp.com:XXXXX

Papertrail ti dà ricerca full-text, alert, e dashboard in 5 minuti di setup. Per un’agenzia con 50 siti, il piano gratuito (50MB/mese) basta per iniziare.

Errori Comuni nel Debug WordPress (e Come Evitarli)

1. Lasciare WP_DEBUG_DISPLAY attivo in produzione

Questo è l’errore #1. Gli errori PHP compaiono nell’HTML del sito. Non solo è brutto per il cliente, ma può esporre percorsi del server e informazioni sensibili. WP_DEBUG_DISPLAY deve SEMPRE essere false in produzione.

2. Non ruotare il file debug.log

Abbiamo visto file debug.log da 12GB. PHP diventa lento a scrivere, il disco si riempie, il sito va in 502. Configura logrotate il giorno uno, non dopo il primo incidente.

3. Attivare WP_DEBUG solo quando c’è un problema

Se WP_DEBUG è spento, non logghi niente. Quando il cliente chiama dicendo “il sito era bianco ieri alle 15:00”, non hai nessun log da guardare. Attiva il logging il primo giorno, non quando serve. Il costo è zero (un file di testo che ruota), il beneficio è enorme.

4. Ignorare i warning dei plugin

I warning PHP non rompono il sito, ma indicano problemi. “Undefined index” su un plugin significa che il plugin non gestisce i casi limite. “Deprecated” significa che alla prossima major release di PHP, il sito si rompe. Monitora i warning per programmare gli aggiornamenti prima che diventano emergenze.

5. Usare plugin di error logging invece della configurazione nativa

Esistono plugin come “Error Log Monitor” o “WP Debugging” che aggiungono UI per il debug. Per un’agenzia sono una dipendenza in più da mantenere, un altro plugin da aggiornare, un altro punto di fallimento. La configurazione nativa in wp-config.php + logrotate è più robusta e non richiede accesso admin al sito.

Checklist Configurazione Logging per 50+ Siti

Se stai configurando il logging su molti siti, ecco la sequenza operativa che usiamo noi:

  1. Crea la cartella centralizzata: /var/log/wordpress/ con permessi www-data
  2. Configura logrotate: crea /etc/logrotate.d/wordpress-debug con la configurazione sopra
  3. Modifica wp-config.php di ogni sito: imposta WP_DEBUG, WP_DEBUG_LOG (con path personalizzato), WP_DEBUG_DISPLAY
  4. Aggiungi error_reporting filter: E_ERROR | E_WARNING | E_PARSE per non annegare nelle notice
  5. Verifica con un test: genera un errore volontario (es. trigger_error('test', E_USER_WARNING);) e controlla che appaia nel log
  6. Configura alert: script cron o integrazione con sistema di monitoring esistente
  7. Documenta il setup: per ogni sito, annota dove si trova il log e come accedervi

Per applicare la configurazione su 50 siti in batch, usa uno script bash con WP-CLI:

#!/bin/bash
# /usr/local/bin/wp-enable-logging.sh
# Applica la configurazione di debug a tutti i siti in un server

SITES=$(find /var/www -maxdepth 2 -name "wp-config.php" -exec dirname {} \;)

for site_dir in $SITES; do
    site_name=$(basename "$site_dir")
    log_path="/var/log/wordpress/${site_name}.log"

    # Usa wp-cli per modificare wp-config.php
    wp config set WP_DEBUG true --raw --path="$site_dir" --quiet
    wp config set WP_DEBUG_LOG "$log_path" --path="$site_dir" --quiet
    wp config set WP_DEBUG_DISPLAY false --raw --path="$site_dir" --quiet

    # Aggiungi error_reporting se non presente
    if ! grep -q "error_reporting" "$site_dir/wp-config.php"; then
        sed -i "/define('WP_DEBUG_DISPLAY'/a error_reporting(E_ERROR | E_WARNING | E_PARSE | E_USER_ERROR | E_USER_WARNING);" "$site_dir/wp-config.php"
    fi

    echo "✓ $site_name → $log_path"
done

echo "Done. Verifica con: tail -f /var/log/wordpress/*.log"

FAQ — Debug WordPress per Agenzie

WP_DEBUG rallenta il sito?

No, se WP_DEBUG_DISPLAY è false. Il costo di scrivere una riga in un file di log è trascurabile (meno di 1ms). Il vero rallentamento arriva quando WP_DEBUG_DISPLAY è true e PHP inlinea gli errori nell’HTML, aumentando il tempo di render e rovinando il layout.

Dove si trova il file debug.log?

Di default in wp-content/debug.log. Puoi cambiarlo definendo WP_DEBUG_LOG come stringa (path assoluto) invece che boolean. Per agenzie conviene centralizzare in /var/log/wordpress/nome-sito.log.

Come leggo il debug.log senza accesso SSH?

Se non hai SSH, scarica il file via SFTP o usa un plugin come “Debug Log Manager” che mostra il log nell’admin di WordPress. Per un’agenzia, però, SSH è non-opzionale. Senza SSH non puoi configurare logrotate, grep, o inviare log a un servizio esterno.

Qual è la differenza tra WP_DEBUG e error_reporting?

WP_DEBUG controlla il sistema di debug di WordPress (constant checks nel codice core, SCRIPT_DEBUG). error_reporting controlla il livello di errori PHP che vengono loggati. Sono indipendenti: puoi avere WP_DEBUG true ma error_reporting a solo E_ERROR per loggare solo i fatal.

Devo preoccuparmi che il debug.log contenga informazioni sensibili?

Sì. Il debug.log può contenere query SQL, variabili di sessione, e a volte password in chiaro se un plugin fa var_dump di dati sensibili. Per questo motivo, il file deve avere permessi 600 (solo l’utente del web server) e non deve mai essere accessibile via web. Se usi Nginx, aggiungi un blocco:

location ~* /debug\.log$ {
    deny all;
    return 404;
}

Gestisci i siti WordPress dei tuoi clienti?

AgencyPilot ti dà report AI, uptime monitoring, backup e portale clienti in un’unica dashboard. Gratis per 3 siti.

Prova gratis
Leggi anche
Tutti gli articoli
Tutti gli articoli