Apache ile WordPress Hataları: Özel Log Yapılandırması

WordPress siteniz gece yarısı çöktüğünde ve müşteriniz sizi arıyor olduğunda, elinizde tek silahınız log dosyalarıdır. Ama varsayılan Apache log yapılandırmasıyla WordPress hatalarını bulmak, karanlıkta iğne aramak gibidir. Bu yazıda Apache’yi WordPress için özel olarak nasıl yapılandıracağınızı, hangi hataların nerede kayıt altına alındığını ve gerçek dünya senaryolarında bu logları nasıl analiz edeceğinizi konuşacağız.

Apache Log Sistemini Anlamak

Apache’nin log mekanizması iki temel dosya üzerine kuruludur: access.log ve error.log. Varsayılan yapılandırmada tüm sanal hostlar ya tek bir log dosyasına yazıyor ya da çok genel bir formatta tutuluyor. WordPress gibi karmaşık bir uygulama çalıştırıyorsanız bu yaklaşım yetersiz kalıyor.

WordPress’in kendine has bir yapısı var. PHP hataları, .htaccess kaynaklı 500 hataları, wp-cron sorunları, eklenti çakışmaları… Bunların hepsini tek bir log dosyasında takip etmeye çalışmak, zamanla log dosyasının içinde kaybolmanıza yol açıyor. Çözüm ise her WordPress sitesi için özelleştirilmiş bir log yapılandırması oluşturmak.

Apache’nin log sistemi şu bileşenlerden oluşur:

  • ErrorLog: Sunucu hatalarının yazıldığı dosya
  • CustomLog: Erişim loglarının yazıldığı dosya ve formatı
  • LogLevel: Hangi seviyedeki hataların loglanacağı
  • LogFormat: Log satırlarının nasıl görüneceği

Özel Log Formatı Oluşturmak

Varsayılan combined log formatı çoğu zaman yeterli değildir. WordPress için özellikle şu bilgilere ihtiyaç duyarsınız: hangi PHP dosyası çalıştı, yanıt süresi ne kadardı, hangi WordPress sayfası tetikledi.

Önce Apache’nin global yapılandırma dosyasını açalım:

sudo nano /etc/apache2/apache2.conf
# veya CentOS/RHEL için:
sudo nano /etc/httpd/conf/httpd.conf

Aşağıdaki özel log formatını ekleyin:

# WordPress için özel log formatı
LogFormat "%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i" %D %{X-Forwarded-For}i" wordpress_combined

LogFormat "%{%Y-%m-%d %H:%M:%S}t [%L] %h "%r" %>s %D" wordpress_debug

LogFormat "%h %t "%r" %>s %b "%{Referer}i" %T/%D" wordpress_performance

Bu formatlardaki parametrelerin anlamları:

  • %h: İstek yapan IP adresi
  • %t: İsteğin zaman damgası
  • %r: HTTP istek satırı (GET/POST ve URL)
  • %>s: Son yanıt durum kodu
  • %O: Yanıtta gönderilen toplam byte sayısı
  • %D: İsteğin işlenme süresi mikrosaniye cinsinden
  • %{Referer}i: Referer header bilgisi
  • %{X-Forwarded-For}i: Proxy arkasındaki gerçek IP
  • %T: İşlem süresi saniye cinsinden
  • %L: İstek için benzersiz log ID

WordPress Virtual Host Yapılandırması

Her WordPress sitesi için ayrı bir virtual host dosyası oluşturun ve log direktiflerini bu dosyaya özelleştirin:

sudo nano /etc/apache2/sites-available/wordpress-site.conf
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/wordpress

    # Özel log dizini
    ErrorLog /var/log/apache2/wordpress/error.log
    CustomLog /var/log/apache2/wordpress/access.log wordpress_combined

    # Hata seviyesi - WordPress için warn yeterli, sorun varsa debug'a çek
    LogLevel warn

    # PHP hataları için ek log
    php_admin_value error_log /var/log/apache2/wordpress/php-errors.log
    php_admin_flag log_errors on
    php_admin_value error_reporting E_ALL

    # Yavaş istek loglaması - 3 saniyeden uzun istekleri logla
    # mod_log_forensic veya özel pipe kullanımı
    CustomLog /var/log/apache2/wordpress/slow-requests.log wordpress_performance env=slow_request

    <Directory /var/www/wordpress>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Log dizinini oluşturun ve izinleri ayarlayın:

sudo mkdir -p /var/log/apache2/wordpress
sudo chown www-data:adm /var/log/apache2/wordpress
sudo chmod 750 /var/log/apache2/wordpress

PHP Hatalarını Ayrı Loglamak

WordPress’in büyük bir kısmı PHP üzerinde çalıştığı için PHP hatalarını Apache error log’undan ayırmak hayat kurtarır. Yukarıdaki virtual host yapılandırmasına ek olarak php.ini veya php-fpm yapılandırmasını da güncelleyin.

PHP-FPM kullanıyorsanız (ki modern sunucularda genellikle kullanılır):

sudo nano /etc/php/8.1/fpm/pool.d/wordpress.conf
[wordpress]
user = www-data
group = www-data
listen = /run/php/php8.1-fpm-wordpress.sock
listen.owner = www-data
listen.group = www-data

; WordPress'e özel PHP hata loglama
php_admin_value[error_log] = /var/log/apache2/wordpress/php-errors.log
php_admin_flag[log_errors] = on
php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT

; Yavaş log - 5 saniyeden uzun PHP işlemlerini logla
slowlog = /var/log/apache2/wordpress/php-slow.log
request_slowlog_timeout = 5s
request_terminate_timeout = 120s

PHP-FPM servisini yeniden başlatın:

sudo systemctl restart php8.1-fpm
sudo systemctl reload apache2

WordPress Taraflı Debug Loglaması

Apache ve PHP loglarının yanı sıra WordPress’in kendi debug sistemini de aktif etmek gerekiyor. wp-config.php dosyasına şunları ekleyin:

sudo nano /var/www/wordpress/wp-config.php
// WordPress debug modunu aç
define('WP_DEBUG', true);

// Hataları ekrana yazdırma, sadece logla
define('WP_DEBUG_DISPLAY', false);

// Hata loglamasını aktif et
define('WP_DEBUG_LOG', true);

// WordPress debug log dosyasının yolu
// Varsayılan: wp-content/debug.log - Güvenlik için değiştirin
define('WP_DEBUG_LOG', '/var/log/apache2/wordpress/wp-debug.log');

// Sorgu loglaması (performans analizi için)
define('SAVEQUERIES', false); // Sadece gerektiğinde true yap

// Script debug modu
define('SCRIPT_DEBUG', false);

Bu yapılandırmayla artık dört ayrı log kaynağınız var:

  • /var/log/apache2/wordpress/error.log – Apache sunucu hataları
  • /var/log/apache2/wordpress/access.log – HTTP erişim logları
  • /var/log/apache2/wordpress/php-errors.log – PHP hataları
  • /var/log/apache2/wordpress/wp-debug.log – WordPress uygulama hataları

Gerçek Dünya Senaryosu: 500 Internal Server Error Avı

Bir müşteri sitesi sürekli 500 hatası veriyor. Kullanıcılar şikayet ediyor ama hata aralıklı, yani her zaman olmuyor. Bu klasik bir “üretim ortamında aralıklı hata” senaryosu.

Önce Apache error log’una bakın:

# Son 100 satırı gerçek zamanlı izle
sudo tail -f -n 100 /var/log/apache2/wordpress/error.log

# Sadece 500 hatalarını filtrele
sudo grep -i "error|crit|alert|emerg" /var/log/apache2/wordpress/error.log | tail -50

# Belirli bir zaman aralığını incele
sudo awk '/[Thu Nov 14/ || /[Fri Nov 15/' /var/log/apache2/wordpress/error.log

Çıktıda şöyle bir şey görüyorsunuz:

[Thu Nov 14 02:15:33.412847 2024] [php:error] [pid 12453] [client 185.x.x.x:52341] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes) in /var/www/wordpress/wp-content/plugins/woocommerce/includes/class-wc-product-query.php on line 284

Hafıza sorunu ve gece 2’de oluyor. WooCommerce’in büyük ürün sorgusu hafızayı bitiriyor. Çözüm:

# PHP-FPM pool yapılandırmasına ekle
sudo nano /etc/php/8.1/fpm/pool.d/wordpress.conf

# Şunu ekle:
php_admin_value[memory_limit] = 512M

Gerçek Dünya Senaryosu: Yavaş Sayfa Yüklemeleri

Bir diğer yaygın senaryo: site çalışıyor ama yavaş. Kullanıcılar şikayet ediyor, Google PageSpeed kötü puan veriyor.

wordpress_performance formatıyla oluşturduğumuz access log’u analiz edelim:

# İşlem süresi 2 saniyeden uzun istekleri bul (mikrosaniye cinsinden 2000000)
sudo awk '$NF > 2000000 {print $0}' /var/log/apache2/wordpress/access.log

# En yavaş 10 isteği listele
sudo awk '{print $NF, $7}' /var/log/apache2/wordpress/access.log | sort -rn | head -10

# wp-admin ve wp-cron isteklerini ayır
sudo grep "wp-cron|wp-admin/admin-ajax" /var/log/apache2/wordpress/access.log | 
awk '{print $NF, $7}' | sort -rn | head -20

Sıkça karşılaşılan senaryo: admin-ajax.php her istekte 3-4 saniye sürüyor. Bu genellikle bir eklentinin kontrolsüz AJAX çağrısından kaynaklanır.

WordPress slow query logunu da kontrol edin:

sudo cat /var/log/apache2/wordpress/php-slow.log | grep "pool|script|function" | head -30

Log Rotasyonu Yapılandırması

WordPress sitesi aktifse loglar hızla büyür. Logrotate yapılandırması zorunludur:

sudo nano /etc/logrotate.d/wordpress-apache
/var/log/apache2/wordpress/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 640 www-data adm
    sharedscripts
    postrotate
        # Apache'ye yeni log dosyası açmasını söyle
        if invoke-rc.d apache2 status > /dev/null 2>&1; then
            invoke-rc.d apache2 reload > /dev/null 2>&1
        fi
        # PHP-FPM'i de yeniden yükle
        if invoke-rc.d php8.1-fpm status > /dev/null 2>&1; then
            invoke-rc.d php8.1-fpm reload > /dev/null 2>&1
        fi
    endscript
}

Çoklu WordPress Sitesi İçin Merkezi Log Yönetimi

Sunucunuzda birden fazla WordPress sitesi varsa logları merkezi bir noktadan yönetmek işinizi kolaylaştırır. Şu bash scriptini kullanabilirsiniz:

#!/bin/bash
# /usr/local/bin/wp-log-check.sh
# WordPress log özetini gösteren script

SITES=("site1" "site2" "site3")
LOG_BASE="/var/log/apache2"
REPORT_DATE=$(date '+%Y-%m-%d')

echo "=== WordPress Log Raporu: $REPORT_DATE ==="
echo ""

for SITE in "${SITES[@]}"; do
    LOG_DIR="$LOG_BASE/$SITE"

    if [ ! -d "$LOG_DIR" ]; then
        echo "[$SITE] Log dizini bulunamadi: $LOG_DIR"
        continue
    fi

    echo "--- $SITE ---"

    # Bugünkü 500 hata sayısı
    ERROR_500=$(grep "" 500 " "$LOG_DIR/access.log" 2>/dev/null | 
        grep "$(date '+%d/%b/%Y')" | wc -l)
    echo "  500 Hata: $ERROR_500"

    # PHP fatal error sayısı
    PHP_FATAL=$(grep "PHP Fatal error" "$LOG_DIR/php-errors.log" 2>/dev/null | 
        grep "$(date '+%d-%b-%Y|%Y-%m-%d')" | wc -l)
    echo "  PHP Fatal: $PHP_FATAL"

    # WordPress debug hata sayısı
    WP_ERRORS=$(grep "PHP (Fatal|Warning|Notice)" 
        "$LOG_DIR/wp-debug.log" 2>/dev/null | 
        grep "$(date '+%d-%b-%Y')" | wc -l)
    echo "  WP Debug Hatalar: $WP_ERRORS"

    # En son hata
    LAST_ERROR=$(tail -1 "$LOG_DIR/error.log" 2>/dev/null)
    if [ -n "$LAST_ERROR" ]; then
        echo "  Son Hata: ${LAST_ERROR:0:120}..."
    fi

    echo ""
done

# Disk kullanimi
echo "=== Log Disk Kullanimi ==="
du -sh $LOG_BASE/*/  2>/dev/null | sort -rh | head -10

Script’i çalıştırılabilir yapın ve günlük cron’a ekleyin:

sudo chmod +x /usr/local/bin/wp-log-check.sh
sudo crontab -e

# Sabah 8'de rapor gönder
0 8 * * * /usr/local/bin/wp-log-check.sh | mail -s "WordPress Log Raporu" [email protected]

mod_status ile Anlık Durum İzleme

Apache’nin mod_status modülü, aktif bağlantıları ve sunucu durumunu anlık görmenizi sağlar. WordPress sorunlarını debug ederken bu modül altın değerinde:

sudo a2enmod status
sudo nano /etc/apache2/mods-enabled/status.conf
<Location "/server-status">
    SetHandler server-status
    Require ip 127.0.0.1
    Require ip 192.168.1.0/24
</Location>

# Genişletilmiş durum bilgisi
ExtendedStatus On

Anlık durum kontrolü için:

# Komut satırından anlık durum
watch -n 2 'curl -s http://localhost/server-status?auto | grep -E "BusyWorkers|IdleWorkers|Total Accesses|ReqPerSec"'

# Hangi URL'lerin işlendiğini gör
curl -s http://localhost/server-status | grep "GET|POST" | awk '{print $13, $12}' | sort | uniq -c | sort -rn

Güvenlik Odaklı Log Analizi

WordPress siteleri sürekli brute-force ve exploit denemelerine maruz kalır. Log’lardan bu saldırıları tespit etmek:

# wp-login.php'ye çok fazla POST isteği gönderen IP'leri bul
sudo awk '/POST /wp-login.php/ {print $1}' /var/log/apache2/wordpress/access.log | 
    sort | uniq -c | sort -rn | head -20

# 404 hatası üretip exploit arayan IP'ler
sudo awk '$9 == "404" {print $1}' /var/log/apache2/wordpress/access.log | 
    sort | uniq -c | sort -rn | head -20

# xmlrpc.php'ye saldırı girişimleri
sudo grep "xmlrpc.php" /var/log/apache2/wordpress/access.log | 
    awk '{print $1}' | sort | uniq -c | sort -rn | head -10

Şüpheli IP’leri otomatik olarak engellemek için fail2ban entegrasyonu yapılabilir ama bu ayrı bir yazı konusu.

Apache ErrorDocument ile Özel Hata Sayfaları ve Loglama

WordPress’te özelleştirilmiş hata yakalama için virtual host yapılandırmasına ErrorDocument ekleyin:

# Virtual host içine ekle
ErrorDocument 404 /index.php?error=404
ErrorDocument 500 /index.php?error=500
ErrorDocument 503 /maintenance.php

# 404'leri ayrı dosyaya logla
SetEnvIf Request_URI "^/(wp-content|wp-includes)" static_file
CustomLog /var/log/apache2/wordpress/404-errors.log wordpress_combined env=!static_file

Bu sayede static dosya 404’lerini uygulama 404’lerinden ayırabilirsiniz. WordPress’in medya dosyası kayıplarını gerçek sayfa hatalarından ayırt etmek çok önemli.

Log Analizi için Temel Komutlar

Günlük hayatta sık kullandığım log analizi komutlarını paylaşayım:

# Son 1 saatteki hata özeti
sudo awk -v date="$(date -d '1 hour ago' '+%d/%b/%Y:%H')" 
    '$0 ~ date {print}' /var/log/apache2/wordpress/access.log | 
    awk '{print $9}' | sort | uniq -c | sort -rn

# Belirli bir eklentiye ait hataları bul
sudo grep "wp-content/plugins/woocommerce" /var/log/apache2/wordpress/php-errors.log | 
    awk -F': ' '{print $2}' | sort | uniq -c | sort -rn | head -10

# Ortalama yanıt süresi hesapla (mikrosaniye cinsinden)
sudo awk '{sum += $NF; count++} END {print "Ortalama:", sum/count, "us =", sum/count/1000000, "s"}' 
    /var/log/apache2/wordpress/access.log

# İstek başına byte dağılımı
sudo awk '{print $10}' /var/log/apache2/wordpress/access.log | 
    awk 'BEGIN{small=0;medium=0;large=0} 
    $1<1000{small++} $1>=1000&&$1<100000{medium++} $1>=100000{large++} 
    END{print "Kucuk(<1KB):", small, "Orta(1-100KB):", medium, "Buyuk(>100KB):", large}'

Sonuç

Apache log yapılandırmasını WordPress için özelleştirmek, başlangıçta fazladan iş gibi görünse de uzun vadede saatlerce hata ayıklama zamanı kazandırır. Her site için ayrı log dizini, PHP hatalarını ayrı loglamak, performance formatı kullanmak ve log rotasyonunu doğru ayarlamak, sorun anında durumu hızlıca anlamanızı sağlar.

Burada anlattığım yapılandırmayı kendi ortamınıza uyarlarken birkaç noktaya dikkat edin: disk alanını gözetin, log seviyesini production’da warn veya error seviyesinde tutun (debug çok fazla yazma işlemi yapar), ve logları düzenli olarak analiz edin, sadece sorun çıktığında değil. Proaktif log analizi, sorunu kullanıcı şikayet etmeden önce tespit etmenizi sağlar.

Son olarak, log dosyalarının güvenliğini de gözetmek gerekiyor. Müşteri IP’leri, kullanıcı davranışları hassas verilerdir. Log dizinine dışarıdan erişimi engelleyin, log dosyalarını şifreli alanlara taşıyın ve GDPR uyumluluğu için gerekli saklama sürelerini logrotate yapılandırmasında belirtin.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir