← Kursa Dön
📄 Text · 25 min

ELK Stack Logging

Giriş

Tek bir sunucudaki log dosyasını tail -f ile izlemek basittir. Ancak 50 container'dan, 10 farklı microservice'ten akan logları takip etmeye çalıştığınızda bu yaklaşım çöker. ELK StackElasticsearch, Logstash ve Kibana — log verilerini merkezi bir yerde toplayan, indeksleyen, aranabilir kılan ve görselleştiren endüstri standardı bir çözümdür. Bu derste ELK Stack'in bileşenlerini, Spring Boot entegrasyonunu ve Kibana dashboard'larını inceleyeceğiz.

ELK Stack Bileşenleri

┌──────────┐    ┌──────────┐    ┌──────────────┐    ┌─────────┐
│ Spring   │───▶│ Filebeat │───▶│  Logstash    │───▶│ Elastic │
│ Boot App │    │ (shipper)│    │  (processor) │    │ search  │
│ JSON logs│    └──────────┘    └──────────────┘    └────┬────┘
└──────────┘                                             │
                                                    ┌────▼────┐
                                                    │ Kibana  │
                                                    │ (UI)    │
                                                    └─────────┘

Elasticsearch

Elasticsearch, Apache Lucene üzerine kurulmuş dağıtık bir arama ve analiz motorudur. Log verilerini index adı verilen yapılarda saklar. Her log satırı bir document olur ve tam metin araması, filtreleme, aggregation gibi güçlü sorgulama yetenekleri sunar.

Temel kavramlar:

  • Index: Benzer yapıdaki belgelerin toplandığı mantıksal birim (ör. app-logs-2024.01.15)

  • Document: Tek bir log kaydı (JSON formatında)

  • Shard: Index'in parçalanmış birimi (dağıtık depolama için)

  • Replica: Shard'ların kopyası (yüksek erişilebilirlik için)

Logstash

Logstash, verileri farklı kaynaklardan alan (input), dönüştüren (filter) ve hedef sisteme gönderen (output) bir veri işleme pipeline'ıdır.

Input (Beats, TCP, file) → Filter (grok, mutate, date) → Output (Elasticsearch, file)

Kibana

Kibana, Elasticsearch verilerini görselleştiren web tabanlı bir arayüzdür. Log araması, dashboard oluşturma, alerting ve raporlama gibi yetenekler sunar.

Filebeat

Filebeat, hafif bir log shipper'dır. Sunuculardaki log dosyalarını izler ve Logstash'e (veya doğrudan Elasticsearch'e) gönderir. Logstash'ten çok daha az kaynak tüketir.

Docker Compose ile ELK Kurulumu

version: '3.8'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.12.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
    volumes:
      - es-data:/usr/share/elasticsearch/data

  logstash:
    image: docker.elastic.co/logstash/logstash:8.12.0
    ports:
      - "5044:5044"   # Beats input
      - "5000:5000"   # TCP input
    volumes:
      - ./logstash/pipeline:/usr/share/logstash/pipeline
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:8.12.0
    ports:
      - "5601:5601"
    environment:
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
    depends_on:
      - elasticsearch

  filebeat:
    image: docker.elastic.co/beats/filebeat:8.12.0
    volumes:
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/log/myapp:/var/log/myapp:ro
    depends_on:
      - logstash

volumes:
  es-data:

Logstash Pipeline Yapılandırması

# logstash/pipeline/logstash.conf
input {
  # Filebeat'ten gelen veriler
  beats {
    port => 5044
  }

  # Doğrudan TCP bağlantısı (Logstash appender için)
  tcp {
    port => 5000
    codec => json_lines
  }
}

filter {
  # JSON formatındaki log'u parse et
  if [message] =~ /^\{/ {
    json {
      source => "message"
    }
  }

  # Timestamp'ı düzelt
  date {
    match => ["@timestamp", "ISO8601"]
    target => "@timestamp"
  }

  # Spring Boot log seviyelerini normalize et
  mutate {
    rename => { "level" => "log_level" }
    rename => { "logger_name" => "logger" }
    remove_field => ["host", "agent", "ecs"]
  }

  # Hata loglarından stack trace'i ayıkla
  if [log_level] == "ERROR" {
    mutate {
      add_tag => ["error"]
    }
  }
}

output {
  elasticsearch {
    hosts => ["elasticsearch:9200"]
    index => "app-logs-%{+YYYY.MM.dd}"
  }

  # Debug amaçlı konsola da yaz
  # stdout { codec => rubydebug }
}

Spring Boot — Logstash Appender Entegrasyonu

Log'ları doğrudan Logstash'e TCP üzerinden gönderebilirsiniz:

<!-- pom.xml -->
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>7.4</version>
</dependency>
<!-- logback-spring.xml -->
<springProfile name="production">
    <!-- Logstash'e doğrudan TCP gönderimi -->
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>logstash-host:5000</destination>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <customFields>{"service":"order-service","env":"production"}</customFields>
            <includeMdcKeyName>requestId</includeMdcKeyName>
            <includeMdcKeyName>userId</includeMdcKeyName>
            <includeMdcKeyName>traceId</includeMdcKeyName>
        </encoder>
        <!-- Bağlantı koptuğunda yeniden deneme -->
        <reconnectionDelay>5 seconds</reconnectionDelay>
        <!-- Asenkron gönderim (ana thread'i bloklamaz) -->
        <queueSize>8192</queueSize>
    </appender>

    <!-- Konsol (container logları için) + Logstash -->
    <root level="INFO">
        <appender-ref ref="JSON_CONSOLE"/>
        <appender-ref ref="LOGSTASH"/>
    </root>
</springProfile>

Filebeat Yapılandırması

Alternatif olarak, JSON log dosyalarını Filebeat ile toplayabilirsiniz:

# filebeat/filebeat.yml
filebeat.inputs:
  - type: log
    enabled: true
    paths:
      - /var/log/myapp/*.log
    json.keys_under_root: true
    json.overwrite_keys: true
    json.add_error_key: true
    fields:
      service: order-service
      environment: production
    fields_under_root: true

output.logstash:
  hosts: ["logstash:5044"]

# Veya doğrudan Elasticsearch'e
# output.elasticsearch:
#   hosts: ["elasticsearch:9200"]
#   index: "app-logs-%{+yyyy.MM.dd}"

Kibana'da Log Araştırma

Data View (Index Pattern) Oluşturma

  1. Kibana'da Management → Data Views bölümüne gidin

  2. Create data view tıklayın

  3. Index pattern: app-logs-* yazın

  4. Timestamp field: @timestamp seçin

Discover — Log Araması

Kibana Discover sayfasında güçlü sorgulama yapabilirsiniz:

# KQL (Kibana Query Language) örnekleri:
log_level: "ERROR"
service: "order-service" and log_level: "ERROR"
message: "timeout" or message: "connection refused"
requestId: "a1b2c3d4"
userId: "user42" and log_level: "WARN"

Dashboard Oluşturma

Tipik bir log dashboard'u şu panelleri içerir:

  1. Log Volume: Zaman bazlı log sayısı (bar chart) — ani artışlar anomali göstergesi

  2. Error Rate: Hata loglarının oranı (line chart)

  3. Top Errors: En sık karşılaşılan hata mesajları (data table)

  4. Service Breakdown: Servis bazında log dağılımı (pie chart)

  5. Response Time Heatmap: Yanıt süresi dağılımı

  6. Recent Errors: Son hata logları listesi (saved search)

Log Aggregation Best Practices

  1. JSON formatı kullanın: Yapılandırılmış loglar Elasticsearch'te doğru parse edilir

  2. Index lifecycle management (ILM) uygulayın: Eski logları otomatik silin veya arşivleyin

  3. Field mapping'leri doğru tanımlayın: keyword vs text field tipi seçimi sorgulama performansını etkiler

  4. Shard sayısını optimize edin: Çok fazla shard Elasticsearch'ü yavaşlatır

  5. Sampling uygulayın: Yüksek trafik ortamlarında her logu saklamak yerine örnekleme yapın

  6. Alert kuralları tanımlayın: Kibana alerting ile hata spike'larını otomatik bildirin

# ILM ile 30 günden eski logları sil
# Elasticsearch ILM policy
PUT _ilm/policy/log-retention
{
  "policy": {
    "phases": {
      "hot": { "actions": { "rollover": { "max_size": "50GB", "max_age": "1d" } } },
      "warm": { "min_age": "7d", "actions": { "shrink": { "number_of_shards": 1 } } },
      "delete": { "min_age": "30d", "actions": { "delete": {} } }
    }
  }
}