Spring Boot Logging (Günlükleme)
System.out.println hata ayıklamak için yeterli görünür ama üretimde işe yaramaz: seviye yok, zaman damgası yok, kapatılamaz, dosyaya yazılamaz, performansı bozar. Profesyonel uygulamalar logging kullanır. Spring Boot,…
Spring Boot Logging (Günlükleme)
System.out.println hata ayıklamak için yeterli görünür ama üretimde işe yaramaz: seviye yok,
zaman damgası yok, kapatılamaz, dosyaya yazılamaz, performansı bozar. Profesyonel uygulamalar
logging kullanır. Spring Boot, SLF4J (cephe API) + Logback (uygulama) ile hazır,
yapılandırılmış bir günlükleme altyapısı sunar — hiçbir bağımlılık eklemene gerek kalmadan.
SLF4J ile logger almak
Her sınıf kendi logger'ını alır (genelde sınıf adıyla):
private static final Logger log = LoggerFactory.getLogger(Ornek1.class);
SLF4J bir cephe (facade) API'sidir; arkasındaki uygulama (Logback) değişse de kodun
değişmez. (Lombok kullanıyorsan @Slf4j anotasyonu bu satırı otomatik üretir.)
Log seviyeleri
En ayrıntılıdan en kritiğe doğru bir hiyerarşi vardır; ayarlanan seviye ve üstü görünür:
TRACE < DEBUG < INFO < WARN < ERROR
| Seviye | Ne zaman |
|---|---|
TRACE | Çok ayrıntılı iz (nadiren) |
DEBUG | Geliştirme/teşhis ayrıntısı |
INFO | Normal akış olayları (varsayılan görünür seviye) |
WARN | Beklenmedik ama kurtarılabilir durum |
ERROR | Hata; işlem başarısız |
Örnek 1 (./Ornek1.java) tüm seviyeleri, parametreli loglamayı ve istisna loglamayı gösterir.
Parametreli loglama: {}
String birleştirme yerine yer tutucu kullan:
log.info("Kullanıcı {} {}. kez giriş yaptı", kullanici, deneme); // İYİ log.info("Kullanıcı " + kullanici + " giriş yaptı"); // KÖTÜ
Neden? {} tembeldir: log seviyesi kapalıysa string hiç oluşturulmaz (performans). Ayrıca
daha okunaklı ve güvenlidir. İstisnayı son argüman olarak verirsen stack trace otomatik basılır:
log.error("Başarısız", e).
Yapılandırma
application.properties ile seviyeleri ve çıktıyı ayarlarsın:
logging.level.root=INFO # genel seviye logging.level.com.egitim=DEBUG # belirli paket için DEBUG logging.level.org.springframework.web=WARN logging.file.name=uygulama.log # dosyaya yaz logging.pattern.console=%d{HH:mm:ss} %-5level %logger - %msg%n
Örnek 1, logging.level.com.egitim.springboot.logging=DEBUG ile DEBUG mesajlarını görünür kılar.
Üretimde günlükleme
- Yapılandırılmış (JSON) loglama: Log toplama sistemleri (ELK, Loki, Datadog) için JSON formatı; sorgulama/filtreleme kolaylaşır.
- Korelasyon (trace) kimliği: Her isteğe bir id ekle (MDC / filter — topic 12) → dağıtık sistemde bir isteğin tüm loglarını birbirine bağla.
- Seviye yönetimi: Üretimde
INFO/WARN; sorun anında belirli paketiDEBUG'a çek (Actuator ile çalışırken bile değiştirilebilir — topic 06). - Hassas veri loglama! Parola, token, kişisel veri loglanmaz.
Özet
Spring Boot'un SLF4J + Logback ile hazır günlükleme altyapısını öğrendik: logger alma, log
seviyeleri (TRACE→ERROR), tembel parametreli loglama ({}) ve istisna loglama (Örnek 1);
application.properties ile yapılandırma ve üretim pratiklerini (JSON, trace id, hassas veri)
gördük. println yerine her zaman logger kullan. Sırada, başka servislerin API'lerini çağırmak:
REST tüketimi (RestClient/RestTemplate).
▶ Kod Örnekleri(1)
Ornek1
ortam gerekir1// Ornek1: Logging — SLF4J + Logback (Spring Boot'un yerleşik günlükleme altyapısı).
2// Çalıştırma: portal gömülü Tomcat ile başlatır, log çıktıları görünür.
3package com.egitim.springboot.logging;
4
5import org.slf4j.Logger;
6import org.slf4j.LoggerFactory;
7import org.springframework.boot.CommandLineRunner;
8import org.springframework.boot.autoconfigure.SpringBootApplication;
9import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
10import org.springframework.boot.builder.SpringApplicationBuilder;
11import org.springframework.context.annotation.Bean;
12
13@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
14public class Ornek1 {
15
16 // Her sınıf kendi logger'ını alır (sınıf adıyla). System.out.println YERİNE bunu kullan.
17 private static final Logger log = LoggerFactory.getLogger(Ornek1.class);
18
19 public static void main(String[] args) {
20 // Log seviyesini programatik ayarla (gerçekte: logging.level.com.egitim=DEBUG application.properties'te).
21 new SpringApplicationBuilder(Ornek1.class)
22 .properties("logging.level.com.egitim.springboot.logging=DEBUG")
23 .run(args);
24 }
25
26 @Bean
27 CommandLineRunner selfTest() {
28 return args -> {
29 System.out.println("\n========= LOGGING SELF-TEST =========");
30
31 // Log SEVİYELERİ (en ayrıntılıdan en kritiğe): TRACE < DEBUG < INFO < WARN < ERROR
32 log.trace("TRACE: çok ayrıntılı (varsayılan gizli)");
33 log.debug("DEBUG: geliştirme ayrıntısı (seviye DEBUG'a çekildi -> görünür)");
34 log.info("INFO: normal akış bilgisi — uygulama {} modunda başladı", "üretim");
35 log.warn("WARN: dikkat — disk %{} dolu", 85);
36 log.error("ERROR: hata — bağlantı kurulamadı: {}", "timeout");
37
38 // PARAMETRELİ loglama ({}): string birleştirmeden DAHA İYİ (tembel, hızlı, güvenli).
39 String kullanici = "ada"; int deneme = 3;
40 log.info("Kullanıcı {} {}. kez giriş yaptı", kullanici, deneme);
41
42 // İstisna loglama: mesaj + exception (stack trace otomatik basılır).
43 try { throw new IllegalStateException("örnek hata"); }
44 catch (Exception e) { log.error("İşlem başarısız oldu", e); }
45
46 System.out.println("=====================================");
47 };
48 }
49}Bu örnek Spring / Spring Boot (Gradle) ortamı gerektirir; tek dosya olarak java Ornek1.java ile çalışmaz. Orijinal portal bunu gömülü Tomcat / Spring context ile koşuyordu. Beklenen davranış yukarıdaki anlatım ve kodda açıklanmıştır.