[ OK ]Çekirdek başlatılıyor...
~/im/blog
Benimle Çalışın

Konuşalım

Birlikte çalışmakla ilgileniyor ya da bir sorunuz mu var? Yeni projeleri konuşmaya her zaman açığım.

İletişime geçin

Bağlantı Kurun

Beni sosyal medyada ve profesyonel ağlarda bulabilirsiniz.

Gizlilik Politikası (KVKK)Kullanım Koşulları
© 2026 Irfan MiralGeliştirici:irfanMiral.com
AnasayfaHakkımda/ÖzgeçmişBlogİletişim
2026-10-28• 5 dakika okuma

Tek Bir Server'da Log Management

DevOps Logging Linux Yönetimi Observability

Tek bir server'da bir şey ters gittiğinde, log'lar genelde hepsi orada, /var/log/nginx/, /var/log/postgresql/, systemd journal'ı, ve application'ın kendisinin canının istediği her yere yazdığı şeyler arasında dağılmış halde. İlgili satırı bulmak, beş yerden hangisine bakacağınızı bilmek demek, ve app plain text loglarsa structured bir şey yerine, "son bir saatte bu IP'den gelen tüm request'ler, nginx ve app'in hepsinde" demek, farklı formatlarda birkaç farklı grep komutu demek. Bunların hiçbiri tam olarak broken değil, sadece olması gerekenden daha yavaş, özellikle baskı altında.

Full ELK stack'i (Elasticsearch, Logstash, Kibana) bunu çözüyor, ama tek bir server için gerçekten heavy, Elasticsearch tek başına sadece çalışmak için memory'nin anlamlı bir kısmını istiyor. Tek bir server için kullanışlı orta yol bundan daha küçük.

Structured log'lar her şeyin gerisini kolaylaştırıyor

En yüksek leverage'lı tek değişiklik, application log'larını free-text yerine structured bir formata (JSON) getirmek. Karşılaştırın:

2026-10-28 14:32:01 ERROR Failed to process order 4821 for user 1029: timeout
{"time":"2026-10-28T14:32:01Z","level":"error","msg":"failed to process order","order_id":4821,"user_id":1029,"reason":"timeout"}

İkincisi, ona göz atan bir insan için daha okunaklı değil, ama queryable: "user 1029 için her error" ya da "son bir saatteki her timeout", aynı sayıları içeren ilgisiz text'le de eşleşebilecek bir regex yerine bir field üzerinde bir filter oluyor. Çoğu logging library, bir rewrite değil bir configuration değişikliğiyle structured output'u destekliyor.

journald, insanların kullandığından çok daha fazlasını zaten yapıyor

Bir systemd service olarak çalışan her şey için (ki modern bir Linux server'da bu şeylerin çoğu), journalctl stdout/stderr'i timestamp'lerle zaten merge ediyor, ve birçok insanın başvurmadığı filtering'i destekliyor:

# Everything from the app, last hour
journalctl -u myapp --since "1 hour ago"

# Follow logs from multiple units at once
journalctl -u myapp -u nginx -f

# Only errors, across everything
journalctl -p err --since today

Sonuncusu, tüm sistem boyunca priority'ye göre filtreleme, dağınık bir log dosyası koleksiyonunun external tooling olmadan hiç yapamayacağı bir şey. Application log'ları (ayrı bir dosyaya değil) stdout'a JSON olarak gidiyorsa, journalctl'ın o unit için output'u zaten structured, ve spesifik field'larda filtrelemek için jq'ya pipe'lanabilir.

Dashboard istiyorsanız: lightweight bir stack

Elasticsearch'in footprint'i olmadan gerçek bir log viewer'a daha yakın bir şey için, Grafana Loki plus Promtail genelde önerilen lightweight eşleşme, Promtail log dosyalarını tail'liyor (ya da journal'ı okuyor) ve Loki'ye gönderiyor, Grafana da bunu, zaten kuruluysa Prometheus'tan gelen metric dashboard'larının yanında query edip görüntüleyebiliyor. Loki'nin resource footprint'i, aynı VPS'te bir application'ın yanında rahatça çalışacak kadar küçük, ki Elasticsearch'in olamayacağı yerde burada oturmasının ana sebebi de bu.

# promtail-config.yml (minimal)
scrape_configs:
  - job_name: journal
    journal:
      max_age: 12h
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: 'unit'

Rotation'ı unutmayın

Hiç kimsenin bakmadığı log'larla disk dolarsa, bunların hiçbiri önemli olmuyor. logrotate, yaygın service'ler için genelde zaten configure edilmiş, ama custom bir path'e yazılan application log'larının kendi entry'sine ihtiyacı var:

# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
}

Ve journal'ın kendisi için, size'ını capping etmek, journal'ın sessizce sınırsız büyümesini engelliyor:

# /etc/systemd/journald.conf
SystemMaxUse=1G

Asıl hedef

Bunların hiçbirinin elaborate olması gerekmiyor. Hedef, ilgili satırın göze çarpmasını umarak plain text'te scroll etmek yerine, bir şey bozulduğunda "ne oldu, ve ne zaman" sorusunun, önemli olana göre filtrelemeye (bir user ID, bir error type, bir time range) yetecek structure'la, bakılacak tek, cevaplanabilir bir yerinin olması. Structured logging plus journalctl'ın filtering'i bunun çoğunu ücretsiz kapsıyor. Loki ve Grafana, "ücretsiz" yetmemeye başladığında üstüne browsable bir interface ekliyor.

ÖncekiKüçük Bir VPS'i Prometheus ve Grafana'yla Monitor EtmekSonraki SSH 2FA, Zahmetine Değer mi?