Format Log

Format Log #

Caddy menyediakan beberapa format log bawaan dan kemampuan kustomisasi yang cukup dalam — kamu bisa memilih field mana yang disertakan, mengubah nama field, memfilter informasi sensitif, dan bahkan menulis format kustom untuk kompatibilitas dengan sistem parsing yang sudah ada.

Format yang Tersedia #

json          → Setiap log entry adalah objek JSON satu baris
               Cocok untuk: production, log aggregation, parsing programatik

console       → Format teks manusia-readable dengan warna (jika terminal)
               Cocok untuk: development, debugging interaktif

single_field  → Satu field JSON spesifik diekstrak sebagai string
               Cocok untuk: integrasi dengan sistem yang hanya butuh satu nilai

JSON Format dengan Field Selector #

Kamu bisa mengontrol field mana saja yang muncul di log JSON menggunakan sub-encoder filter:

example.com {
    log {
        output file /var/log/caddy/access.log
        format filter {
            # Gunakan encoder json sebagai base
            wrap json
            
            # Hapus field yang tidak diperlukan
            fields {
                # Hapus request headers (bisa sangat besar)
                request>headers delete
                
                # Hapus info TLS detail (jika tidak diperlukan)
                request>tls delete
                
                # Hapus response headers kecuali Content-Type
                resp_headers>Content-Encoding delete
                resp_headers>Server delete
            }
        }
    }
    
    file_server { root /var/www/html }
}

Menghapus Data Sensitif dari Log #

Sangat penting untuk tidak mencatat informasi sensitif seperti password, token, atau data pribadi:

example.com {
    log {
        output file /var/log/caddy/access.log
        format filter {
            wrap json
            fields {
                # Hash IP address untuk privasi (GDPR compliance)
                request>remote_ip hash
                
                # Hapus header Authorization (berisi token/password)
                request>headers>Authorization delete
                
                # Hapus header Cookie (berisi session token)
                request>headers>Cookie delete
                
                # Hapus query parameter yang mungkin berisi password
                # (gunakan query_replace atau custom handler untuk ini)
            }
        }
    }
    
    reverse_proxy backend:3000
}

Transformasi Nilai #

example.com {
    log {
        output file /var/log/caddy/access.log
        format filter {
            wrap json
            fields {
                # Hash nilai field (satu arah, tidak bisa di-decode)
                request>remote_ip hash
                
                # Replace dengan nilai statis
                request>headers>Authorization replace "[REDACTED]"
                
                # Delete field sepenuhnya
                request>tls delete
            }
        }
    }
    
    file_server
}

Format Console Kustom #

Format console menggunakan template string untuk mengontrol tampilan:

example.com {
    log {
        output stderr
        format console
        # Output default:
        # 2024/01/15 14:30:45.123 INFO handled request ... {request: {...}}
    }
}

Single Field Format #

Untuk integrasi dengan sistem yang hanya memproses satu nilai:

example.com {
    log {
        output file /var/log/caddy/combined.log
        
        # Ambil hanya field 'msg' sebagai output
        format single_field msg
    }
}

Format Mirip Apache/Nginx Combined Log #

Untuk kompatibilitas dengan tools yang sudah familiar dengan format Apache/Nginx:

example.com {
    log {
        output file /var/log/caddy/access.log
        
        # Format yang menghasilkan log mirip Apache Combined Log Format:
        # 203.0.113.1 - - [15/Jan/2024:14:30:45 +0700] "GET /path HTTP/2.0" 200 1234
        format transform `{request.remote_ip} - - [{ts}] "{request.method} {request.uri} {request.proto}" {status} {size}` {
            time_format "02/Jan/2006:15:04:05 -0700"
        }
    }
    
    file_server
}

Multi-Output Log (Log ke Beberapa Tempat Sekaligus) #

{
    # Tidak ada built-in multi-output di Caddy
    # Tapi bisa menggunakan named pipes atau log shipper
}

# Solusi 1: Gunakan tee dengan named pipe
# mkfifo /tmp/caddy-log-pipe
# tee /var/log/caddy/access.log < /tmp/caddy-log-pipe | \
#     /usr/bin/logger -t caddy &  # Kirim ke syslog juga

# Solusi 2: Log ke stdout, pipe ke multiple destinations
# Caddyfile: output stdout
# Di shell: caddy run 2>/dev/null | tee /var/log/caddy/access.log | logstash-forwarder

Log Format untuk Berbagai Kebutuhan #

Format untuk Elasticsearch/OpenSearch #

example.com {
    log {
        output file /var/log/caddy/access.log
        format filter {
            wrap json
            fields {
                # Hapus headers untuk mengurangi ukuran dokumen
                request>headers delete
                request>tls delete
                resp_headers delete
            }
        }
    }
}

Filebeat config untuk ingest ke Elasticsearch:

# /etc/filebeat/filebeat.yml
filebeat.inputs:
  - type: log
    paths:
      - /var/log/caddy/access.log
    json.keys_under_root: true
    json.overwrite_keys: true
    
processors:
  - timestamp:
      field: ts
      layouts:
        - UNIX_MS

output.elasticsearch:
  hosts: ["https://elasticsearch:9200"]
  index: "caddy-access-%{+yyyy.MM.dd}"

Format untuk Prometheus/Grafana #

# Hitung metrics dari log untuk Prometheus
# (atau gunakan plugin metrics Caddy)

# Script yang membaca log dan expose metrics
cat > /usr/local/bin/caddy-log-metrics.sh << 'EOF'
#!/bin/bash
LOG_FILE="/var/log/caddy/access.log"
METRICS_FILE="/var/lib/prometheus/caddy_metrics.prom"

# Hitung request count per status code
STATUS_COUNTS=$(cat "$LOG_FILE" | jq '.status' | sort | uniq -c)

cat > "$METRICS_FILE" << METRICS
# HELP caddy_http_requests_total Total HTTP requests
# TYPE caddy_http_requests_total counter
$(echo "$STATUS_COUNTS" | awk '{print "caddy_http_requests_total{status=\""$2"\"} "$1}')
METRICS
EOF
chmod +x /usr/local/bin/caddy-log-metrics.sh
# Jalankan via cron setiap menit

Log Rotation Manual #

Selain rotation otomatis bawaan Caddy, kamu juga bisa menggunakan logrotate:

# /etc/logrotate.d/caddy
/var/log/caddy/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 caddy caddy
    
    # Setelah rotate, kirim sinyal USR1 ke Caddy untuk reopen file
    # (Caddy mendukung USR1 untuk log rotation)
    postrotate
        systemctl kill --signal=USR1 caddy 2>/dev/null || true
    endscript
}

Ringkasan #

  • Gunakan format filter { wrap json } untuk mengontrol field mana yang muncul di log JSON — hapus header sensitif (Authorization, Cookie) dan field besar yang tidak dibutuhkan.
  • Hash IP address (request>remote_ip hash) di log untuk compliance dengan regulasi privasi seperti GDPR.
  • Format JSON standar adalah yang paling fleksibel — bisa diparse oleh Elasticsearch, Loki, Datadog, dan hampir semua log aggregation tool tanpa konfigurasi tambahan.
  • Gunakan logrotate bersama signal USR1 untuk rotation eksternal, atau konfigurasi roll_size dan roll_keep bawaan Caddy untuk rotation otomatis.
  • Untuk debugging sementara, format console lebih mudah dibaca manusia — kembalikan ke json setelah selesai troubleshoot.
  • Selalu filter data sensitif sebelum log ditulis ke disk — jauh lebih mudah mencegah pencatatan data sensitif daripada membersihkannya setelah tersimpan.

← Sebelumnya: Error Log   Berikutnya: Log Output →


Format Log yang Kompatibel dengan GoAccess #

GoAccess adalah analyzer log web real-time yang populer. Agar GoAccess bisa membaca log Caddy dalam format JSON:

# Install GoAccess
sudo apt install goaccess  # Ubuntu/Debian

# Buat file konfigurasi GoAccess untuk Caddy JSON log
cat > ~/.goaccessrc << 'EOF'
log-format CADDY
EOF

# Jalankan GoAccess dengan log Caddy
# Format CADDY perlu didefinisikan di goaccess.conf:
# log-format {"ts":%dT%t,"request":{"remote_ip":"%h","method":"%m","uri":"%U","proto":"%H"},"status":%s,"size":%b,"duration":%T}

# Atau gunakan opsi custom format:
goaccess /var/log/caddy/access.log \
    --log-format='{"ts":%^,"request":{"remote_ip":"%h"%^,"method":"%m","uri":"%U"%^},"status":%s,"size":%b}' \
    --output report.html

Menambahkan Field Kustom ke Log #

example.com {
    # Tambahkan request ID ke setiap request
    header X-Request-ID {http.request.uuid}
    
    log {
        output file /var/log/caddy/access.log
        format json
        # Request ID otomatis muncul dalam log jika response header di-set
    }
    
    reverse_proxy backend:3000
}

Field kustom dari response headers backend juga akan tercatat di log jika menggunakan format JSON penuh — memudahkan korelasi antara log Caddy dan log backend menggunakan request ID yang sama.


Pola Format untuk Compliance PCI-DSS dan GDPR #

Untuk aplikasi yang memproses data pembayaran (PCI-DSS) atau data pribadi (GDPR), log harus memenuhi persyaratan tertentu:

payment.example.com {
    log {
        output file /var/log/caddy/payment-access.log {
            roll_keep_days 365  # PCI-DSS: simpan 1 tahun
            roll_keep 52        # 52 file mingguan
        }
        format filter {
            wrap json
            fields {
                # GDPR: hash atau hapus IP
                request>remote_ip hash
                # Hapus semua header yang mungkin berisi PII
                request>headers delete
                # Jangan log body request (mungkin berisi nomor kartu)
            }
        }
    }
    
    reverse_proxy payment-backend:8443
}
About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact