Takip et

Java’da Loglama: Kapsamlı Bir Bakış ve Örnekler

Java’da Loglama: Kapsamlı Bir Bakış ve Örnekler Java uygulamaları geliştirirken, kodun doğru çalıştığından emin olmak, hataları tespit

Java’da Loglama: Kapsamlı Bir Bakış ve Örnekler

Java uygulamaları geliştirirken, kodun doğru çalıştığından emin olmak, hataları tespit etmek ve uygulamanın davranışını anlamak kritik öneme sahiptir. Bu noktada “loglama” devreye girer. Loglama, bir uygulamanın çalışma zamanında belirli olayları, durumları veya hata mesajlarını kaydederek, geliştiricilere ve sistem yöneticilerine değerli içgörüler sunan bir mekanizmadır. Bu makalede, Java’da loglamanın neden bu kadar önemli olduğunu, yerleşik loglama API’si java.util.logging‘i, popüler üçüncü parti loglama çerçevelerini (Log4j, Logback, SLF4J) ve iyi loglama pratiklerini detaylı örneklerle inceleyeceğiz.

Giriş: Loglama Neden Önemli?

Yazılım geliştirme sürecinde loglama, sadece hata ayıklama aracı olmaktan çok daha fazlasıdır. Modern, karmaşık ve dağıtık sistemlerde loglar, uygulamanın “kara kutusunu” açan bir pencere görevi görür. Loglamanın başlıca faydaları şunlardır:

* Hata Ayıklama (Debugging): Uygulama çöktüğünde veya beklenmedik bir davranış sergilediğinde, loglar hatanın kök nedenini bulmak için izlenebilecek bir “ekmek kırıntısı” yolu sunar. Hata mesajları, stack trace’ler ve değişken değerleri loglara kaydedilerek sorun tespiti kolaylaşır.
* Uygulama Takibi ve Performans İzleme: Loglar, uygulamanın hangi işlemlerden geçtiğini, ne kadar sürdüğünü ve hangi kaynakları kullandığını gösterir. Bu bilgiler, performans darboğazlarını tespit etmek ve kullanıcı deneyimini iyileştirmek için kullanılabilir.
* Güvenlik Denetimi (Auditing): Kullanıcı girişleri, hassas veri erişimleri, yetkilendirme denemeleri gibi güvenlik açısından önemli olaylar loglanarak, olası güvenlik ihlallerinin tespiti ve analizi sağlanır.
* İş Süreci İzleme: Uygulama içindeki belirli iş akışlarının başarılı olup olmadığını, hangi aşamada takıldığını veya kaç işlem gerçekleştirdiğini loglar aracılığıyla takip edebiliriz. Bu, iş operasyonlarının izlenmesi ve raporlanması için önemlidir.
* Sistem Entegrasyonu: Dağıtık sistemlerde farklı servisler arasındaki etkileşimleri loglamak, entegrasyon sorunlarını anlamak ve gidermek için vazgeçilmezdir.

System.out.println() kullanmak yerine gerçek bir loglama mekanizması kullanmak, bu faydaları sağlamanın tek yoludur. System.out.println(), çıktıyı kontrol etme, filtreleme, farklı hedeflere yönlendirme veya formatlama gibi esneklikler sunmaz ve üretim ortamlarında ciddi performans sorunlarına yol açabilir.

Java’da Temel Loglama Mekanizmaları

Java ekosisteminde birden fazla loglama seçeneği bulunmaktadır. Bunların en temel olanı, Java’nın kendi bünyesinde gelen java.util.logging (JUL) API’sidir.

java.util.logging (JUL)

java.util.logging, Java SE platformunun bir parçasıdır ve herhangi bir harici bağımlılık olmadan kullanılabilir. Daha basit uygulamalar veya hızlı prototipleme için uygun olabilir.

JUL Temel Bileşenleri

* Logger: Loglama mesajlarını oluşturan ana nesnedir. Belirli bir isimle (genellikle sınıfın tam nitelikli adı) alınır.
* Level: Loglama mesajının önem derecesini belirtir. Ön tanımlı seviyeler şunlardır: SEVERE (ciddi hata), WARNING (uyarı), INFO (bilgilendirme), CONFIG (yapılandırma), FINE (detaylı hata ayıklama), FINER, FINEST (en detaylı hata ayıklama). Ayrıca ALL (tüm mesajlar) ve OFF (hiçbir mesaj) seviyeleri de bulunur.
* Handler: Log mesajlarını belirli bir hedefe (konsol, dosya, ağ, veritabanı vb.) yazmaktan sorumludur. Örneğin, ConsoleHandler konsola yazar, FileHandler dosyalara yazar.
* Formatter: Log mesajlarının nasıl biçimlendirileceğini belirler. Örneğin, SimpleFormatter basit metin çıktısı sağlarken, XMLFormatter XML formatında çıktı verir.

JUL Kullanım Örneği
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.io.IOException;

public class JulLoggerExample {

    private static final Logger logger = Logger.getLogger(JulLoggerExample.class.getName());

    public static void main(String[] args) {
        // Varsayılan olarak INFO seviyesindeki mesajlar loglanır.
        // Tüm mesajları görmek için seviyeyi değiştirebiliriz.
        logger.setLevel(Level.ALL);

        // Konsola log yazmak için bir Handler ekleyelim
        ConsoleHandler consoleHandler = new ConsoleHandler();
        consoleHandler.setLevel(Level.ALL); // Handler'ın kendi seviyesi olabilir
        logger.addHandler(consoleHandler);

        // Dosyaya log yazmak için bir Handler ekleyelim
        try {
            FileHandler fileHandler = new FileHandler("my_app_jul.log", true); // true: append modunda
            fileHandler.setLevel(Level.FINE); // Sadece FINE ve üstü seviyeleri dosyaya yaz
            
            // Özel bir Formatter kullanabiliriz
            fileHandler.setFormatter(new SimpleFormatter()); // Veya kendi Formatter'ımızı yazabiliriz
            logger.addHandler(fileHandler);
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Dosya Handler oluşturulurken hata oluştu", e);
        }
        
        // Varsayılan handler'ı (genellikle console) kaldırmak isteyebiliriz
        // logger.setUseParentHandlers(false);

        logger.log(Level.INFO, "Uygulama başlatılıyor...");
        logger.info("Bu bir bilgilendirme mesajıdır."); // logger.info() kısayolu

        try {
            int result = divide(10, 0);
            logger.log(Level.INFO, "Bölme sonucu: " + result);
        } catch (ArithmeticException e) {
            logger.log(Level.SEVERE, "Sıfıra bölme hatası oluştu!", e);
        }

        logger.warning("Bu bir uyarı mesajıdır.");
        logger.fine("Bu detaylı bir hata ayıklama mesajıdır. (Sadece seviye uygunsa görünür)");
        logger.log(Level.CONFIG, "Uygulama ayarları yüklendi.");

        logger.log(Level.INFO, "Uygulama kapatılıyor.");
    }

    public static int divide(int a, int b) {
        return a / b;
    }
}
JUL Avantajları ve Dezavantajları

* Avantajlar: Java’nın yerleşik bir parçasıdır, harici bağımlılık gerektirmez. Basit kullanım senaryoları için yeterlidir.
* Dezavantajlar: Yapılandırma esnekliği sınırlıdır. Özellikle üçüncü parti kütüphanelerin farklı loglama çerçevelerini kullandığı karmaşık uygulamalarda yönetimi zorlaşabilir. Performans açısından Log4j veya Logback kadar optimize değildir.

Üçüncü Parti Loglama Çerçeveleri

JUL’nin sınırlamaları nedeniyle, Java topluluğu daha güçlü ve esnek loglama çözümleri geliştirmiştir. Bunların başında Apache Log4j ve Logback gelir. Ayrıca, bu çerçeveler arasında bir soyutlama katmanı sağlayan SLF4J de yaygın olarak kullanılır.

Log4j (Apache Log4j 2)

Log4j, Apache Software Foundation tarafından geliştirilen, Java’daki en popüler loglama çerçevelerinden biridir. Özellikle Log4j 2, Log4j 1.x’in birçok sorununu gidererek daha iyi performans, esneklik ve yapılandırma seçenekleri sunar.

Log4j 2 Temel Bileşenleri

* Logger: Log mesajlarını oluşturan ana bileşen. Belirli bir isimle (genellikle sınıfın tam adı) alınır.
* Appender: Log mesajlarını belirli bir hedefe (konsol, dosya, veritabanı, JMS kuyruğu, e-posta vb.) yazmaktan sorumludur. ConsoleAppender, FileAppender, RollingFileAppender en yaygın olanlarıdır.
* Layout: Log mesajlarının nasıl biçimlendirileceğini belirler. PatternLayout en yaygın ve güçlü olanıdır, desenler kullanarak çıktıyı özelleştirmeye olanak tanır.
* Level: Log mesajının önem derecesini belirtir. Log4j 2 seviyeleri: OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL.
* Filter: Log mesajlarının Appender’a iletilmeden önce filtrelenmesini sağlar. Belirli bir seviyeden, desenden veya içerikten geçen mesajları filtreleyebiliriz.

Log4j 2 Yapılandırması

Log4j 2 genellikle XML, YAML veya JSON dosyaları aracılığıyla yapılandırılır. log4j2.xml dosyası, sınıf yolunda (classpath) bulunmalıdır.




    
        
        
            
        

        
        
            
            
                
            
             
        
    

    
        
        
            
        

        
        
            
            
        
    
Log4j 2 Kullanım Örneği

Öncelikle Maven bağımlılıklarını eklemeliyiz:


    org.apache.logging.log4j
    log4j-api
    2.23.1


    org.apache.logging.log4j
    log4j-core
    2.23.1
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4j2LoggerExample {

    // Logger örneğini almak için sınıfın adını kullanırız
    private static final Logger logger = LogManager.getLogger(Log4j2LoggerExample.class);

    public static void main(String[] args) {
        logger.trace("Bu bir TRACE mesajıdır.");
        logger.debug("Bu bir DEBUG mesajıdır.");
        logger.info("Uygulama başlatılıyor...");
        logger.warn("Bu bir uyarı mesajıdır.");

        try {
            int result = divide(10, 0);
            logger.info("Bölme sonucu: " + result);
        } catch (ArithmeticException e) {
            // Hata mesajını ve stack trace'i loglamak için e nesnesini doğrudan geçirebiliriz
            logger.error("Sıfıra bölme hatası oluştu!", e);
        }

        logger.fatal("Uygulama kritik bir hata nedeniyle kapatılıyor.");
    }

    public static int divide(int a, int b) {
        return a / b;
    }
}

Logback

Logback, Log4j’nin orijinal yazarı Ceki Gülcü tarafından geliştirilen, Log4j 1.x’in halefi olarak tasarlanmış modern bir loglama çerçevesidir. Spring Boot’un varsayılan loglama çerçevesidir. Logback, Log4j 2’ye benzer bir mimariye sahiptir ve performans, esneklik ve daha zengin özellikler sunar.

Logback Temel Bileşenleri

* Logger: Log mesajlarını oluşturan ana bileşen.
* Appender: Log mesajlarını hedeflere (konsol, dosya, veritabanı vb.) yazan bileşen. ConsoleAppender, FileAppender, RollingFileAppender gibi çeşitleri vardır.
* Encoder: Log mesajlarının nasıl biçimlendirileceğini belirler. Log4j’deki Layout kavramına benzer. PatternLayoutEncoder en yaygın olanıdır.
* Level: Log mesajının önem derecesini belirtir. Logback seviyeleri: TRACE, DEBUG, INFO, WARN, ERROR.

Logback Yapılandırması

Logback genellikle logback.xml veya logback-spring.xml (Spring Boot için) dosyaları aracılığıyla yapılandırılır. Bu dosya da sınıf yolunda bulunmalıdır.



    
    
        
            %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    

    
    
        logs/my_app_logback.log
        
            
            logs/my_app_logback-%d{yyyy-MM-dd}.%i.log.gz
            10MB
            30 
            1GB 
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    

    
    
        
    

    
    
        
        
    
Logback Kullanım Örneği

Maven bağımlılıkları:


    ch.qos.logback
    logback-classic
    1.5.6

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogbackLoggerExample {

    // SLF4J arayüzünü kullanarak Logger'ı alıyoruz, arka planda Logback kullanılıyor
    private static final Logger logger = LoggerFactory.getLogger(LogbackLoggerExample.class);

    public static void main(String[] args) {
        logger.trace("Bu bir TRACE mesajıdır.");
        logger.debug("Bu bir DEBUG mesajıdır.");
        logger.info("Uygulama başlatılıyor...");
        logger.warn("Bu bir uyarı mesajıdır.");

        try {
            int result = divide(10, 0);
            logger.info("Bölme sonucu: " + result);
        } catch (ArithmeticException e) {
            logger.error("Sıfıra bölme hatası oluştu!", e);
        }

        logger.error("Uygulama kritik bir hata nedeniyle kapatılıyor.");
    }

    public static int divide(int a, int b) {
        return a / b;
    }
}

Yukarıdaki örnekte org.slf4j.Logger kullandığımıza dikkat edin. Bunun nedeni, Logback’in genellikle SLF4J ile birlikte kullanılmasıdır.

SLF4J (Simple Logging Facade for Java)

SLF4J, Java uygulamaları için basit bir loglama cephesi (facade) veya soyutlama katmanıdır. Doğrudan bir loglama çerçevesi değildir; bunun yerine, geliştiricilerin kodlarında belirli bir loglama çerçevesine (Log4j, Logback, JUL vb.) bağımlı kalmadan loglama yapmalarını sağlar.

Neden SLF4J Kullanılmalı?

* Esneklik: Uygulamanızın loglama altyapısını istediğiniz zaman değiştirebilirsiniz (örneğin, Log4j’den Logback’e geçmek) kodunuzu değiştirmeden. Sadece bağımlılıkları ve yapılandırma dosyasını güncellersiniz.
* Kütüphane Uyumluğu: Farklı üçüncü parti kütüphaneler farklı loglama çerçeveleri kullanabilir. SLF4J, tüm bu farklı çerçeveleri tek bir standart arayüz altında birleştirerek “loglama karmaşasını” önler.
* Performans: Parametreli log mesajları (logger.debug("Mesaj: {}", parameter);) sayesinde, log seviyesi uygun olmadığında gereksiz String birleştirme işlemlerini önler.

SLF4J Kullanım Örneği (Logback ile Birlikte)

SLF4J kullanmak için iki ana bağımlılığa ihtiyacınız vardır: slf4j-api ve kullanmak istediğiniz loglama çerçevesinin SLF4J uygulaması (örneğin, logback-classic Logback için, log4j-slf4j-impl Log4j 2 için).

Maven bağımlılıkları (Logback ile):


    org.slf4j
    slf4j-api
    2.0.13


    ch.qos.logback
    logback-classic
    1.5.6
    

Java kodu:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Slf4jExample {

    private static final Logger logger = LoggerFactory.getLogger(Slf4jExample.class);

    public static void main(String[] args) {
        String userName = "Alice";
        int userId = 123;

        logger.info("Kullanıcı {} (ID: {}) sisteme giriş yaptı.", userName, userId);
        logger.debug("Kullanıcı detayları getiriliyor...");

        try {
            processData(null);
        } catch (IllegalArgumentException e) {
            logger.error("Veri işlenirken hata oluştu: {}", e.getMessage(), e); // Son parametre throwable için
        }
    }

    public static void processData(String data) {
        if (data == null) {
            throw new IllegalArgumentException("İşlenecek veri boş olamaz.");
        }
        logger.info("Veri başarıyla işlendi.");
    }
}

Bu örnekte, kodunuzda sadece org.slf4j.Logger ve LoggerFactory kullanıyorsunuz. Arka planda hangi loglama çerçevesinin çalıştığı (Logback, Log4j 2 veya JUL) bağımlılıklarınıza ve yapılandırmanıza bağlıdır. Bu sayede, uygulamanızın loglama altyapısını değiştirmek istediğinizde Java kodunuzu yeniden derlemenize gerek kalmaz.

Loglama Seviyeleri (Logging Levels)

Loglama seviyeleri, bir log mesajının önemini ve aciliyetini belirtmek için kullanılır. Bu seviyeler sayesinde, üretim ortamında sadece kritik hataları, geliştirme ortamında ise daha detaylı hata ayıklama mesajlarını görebiliriz. Çoğu loglama çerçevesi benzer seviyeleri kullanır:

* OFF: Hiçbir log mesajı kaydedilmez. Loglama tamamen devre dışı bırakılır.
* FATAL (Log4j 2): Uygulamanın çalışmasını tamamen durduran, kurtarılamaz bir hata. Genellikle uygulamanın çökmesine yol açar.
* ERROR: Uygulamanın normal çalışmasını engelleyen, ancak mutlaka durdurmayan ciddi bir hata. Bir işlemin başarısız olmasına neden olur.
* WARN: Potansiyel bir sorun veya beklenmedik bir durum. Uygulamanın çalışmasını etkilemez ancak gelecekte sorunlara yol açabilir.
* INFO: Uygulamanın genel ilerleyişi hakkında bilgi veren mesajlar. Kullanıcı girişleri, uygulamanın başlatılması/kapatılması gibi olaylar.
* DEBUG: Geliştirme sırasında hata ayıklama için kullanılan detaylı bilgiler. Değişken değerleri, metod çağrıları gibi.
* TRACE: DEBUG seviyesinden daha da detaylı bilgiler. Çok ince taneli işlem adımları. Genellikle sadece çok özel durumlarda kullanılır.
* ALL: Tüm log mesajları kaydedilir.

Loglama seviyeleri hiyerarşiktir. Bir logger’ın seviyesi INFO olarak ayarlandığında, sadece INFO, WARN, ERROR ve FATAL seviyesindeki mesajlar işlenir. DEBUG ve TRACE seviyesindeki mesajlar göz ardı edilir.

Loglama Yapılandırması (Configuration)

Loglama çerçevelerinin gücü, esnek yapılandırma seçeneklerinden gelir. Yapılandırma, logların nereye yazılacağını (konsol, dosya, veritabanı vb.), hangi formatta olacağını, hangi seviyeden itibaren loglanacağını ve log dosyalarının nasıl yönetileceğini belirler.

Yapılandırma genellikle harici dosyalar aracılığıyla yapılır:
* Log4j 2: log4j2.xml, log4j2.yaml, log4j2.json
* Logback: logback.xml, logback-spring.xml
* JUL: logging.properties

Bu dosyalar genellikle uygulamanın sınıf yolu (classpath) içinde bulunur.

Yapılandırma Örnekleri (Tekrar Hatırlatma)

Yukarıdaki Log4j 2 ve Logback örneklerinde detaylı yapılandırma dosyaları verilmiştir. Önemli kısımlar:

* Appender’lar: Logların yazılacağı hedefleri tanımlar.
* ConsoleAppender: Konsola yazar.
* FileAppender: Tek bir dosyaya yazar.
* RollingFileAppender (Log4j 2) / RollingFileAppender (Logback): Belirli bir boyuta veya zamana ulaştığında log dosyasını döndürür (eski dosyayı arşivler ve yeni bir dosya oluşturur). Bu, log dosyalarının çok büyümesini engeller.
* Diğer Appender’lar: SMTPAppender (e-posta gönderir), JDBCAppender (veritabanına yazar), JMSAppender (JMS kuyruğuna gönderir) vb.
* Layout’lar / Encoder’lar: Log mesajlarının formatını belirler. PatternLayout (Log4j 2) ve PatternLayoutEncoder (Logback) en yaygın olanlardır ve %d (tarih), %t (thread adı), %-5level (log seviyesi), %logger (logger adı), %msg (mesaj), %n (yeni satır) gibi desen kodları kullanılarak çıktı özelleştirilebilir.
* Logger’lar: Belirli paketler veya sınıflar için log seviyeleri ve Appender referansları tanımlanır.
* Root Logger: Tüm log mesajları için varsayılan davranışı belirler. Genellikle tüm Appender’lara yönlendirilir.
* Spesifik Logger’lar: Belirli bir paket veya sınıf için level özniteliği ile özel bir log seviyesi ayarlanabilir. additivity="false" ayarı, bu logger’ın mesajlarının Root Logger’a iletilmesini engeller. Bu, logların birden fazla kez yazılmasını önlemek için kullanışlıdır.

İyi Loglama Pratikleri (Best Practices)

Etkili loglama, sadece bir loglama çerçevesi kullanmaktan ibaret değildir. Loglarınızı nasıl oluşturduğunuz, yönettiğiniz ve analiz ettiğiniz de önemlidir.

1. Anlamlı ve Bağlam İçeren Mesajlar Yazın: Log mesajları kısa ve net olmalı, ancak aynı zamanda yeterli bağlamı sağlamalıdır. Sadece “Hata oluştu” demek yerine, “Kullanıcı ID 123 için sipariş işlenirken veritabanı bağlantı hatası oluştu” gibi daha açıklayıcı mesajlar kullanın.
2. Doğru Log Seviyelerini Kullanın: Her mesajın amacına uygun bir seviye atayın.
* TRACE/DEBUG: Geliştirme ve hata ayıklama sırasında detaylı bilgi.
* INFO: Uygulamanın normal akışını gösteren önemli olaylar.
* WARN: Potansiyel sorunlar veya beklenmeyen ancak tolere edilebilir durumlar.
* ERROR: Bir işlemin başarısız olmasına neden olan hatalar.
* FATAL: Uygulamanın çökmesine neden olan kritik hatalar.
3. Hassas Bilgileri Loglamaktan Kaçının: Parolalar, kredi kartı numaraları, kişisel kimlik bilgileri (PII) gibi hassas verileri loglara yazmaktan kesinlikle kaçının. Bu, güvenlik açıkları ve GDPR/KVKK gibi düzenlemelerle uyumsuzluk yaratabilir. Gerekirse bu bilgileri maskeleyin veya anonimleştirin.
4. Parametreli Log Mesajları Kullanın (SLF4J ile): logger.debug("Kullanıcı: {}", username); şeklinde parametreleri kullanarak String birleştirmeden kaçının. Bu, log seviyesi uygun olmadığında String birleştirme maliyetini ortadan kaldırarak performansı artırır.
5. Exception’ları Doğru Loglayın: Hata durumlarında, logger.error("Hata mesajı", e); şeklinde Exception nesnesini log metoduna ikinci parametre olarak geçirin. Bu, stack trace’in loglanmasını sağlar ve hatanın kök nedenini bulmayı kolaylaştırır.
6. Asenkron Loglama Kullanın: Özellikle yüksek performans gerektiren uygulamalarda, loglama işleminin ana uygulama iş parçacığını engellemesini önlemek için asenkron loglama yapılandırmayı düşünün. Log4j 2 ve Logback, asenkron Appender’lar sunar.
7. Logları Yapılandırılmış Formatlarda Tutun (JSON gibi): Dağıtık sistemlerde ve log analizi araçlarıyla (ELK Stack, Splunk) çalışırken, logları JSON gibi yapılandırılmış bir formatta tutmak, logların otomatik olarak ayrıştırılmasını ve sorgulanmasını kolaylaştırır.
8. Korelasyon ID’leri Kullanın: Mikroservis mimarilerinde veya dağıtık sistemlerde, bir isteğin birden fazla servis arasında nasıl ilerlediğini takip etmek zordur. Her istek için benzersiz bir “korelasyon ID” oluşturup, bu ID’yi tüm log mesajlarına dahil etmek, bir isteğin tüm yaşam döngüsünü izlemenizi sağlar.
9. Merkezi Log Yönetimi: Üretim ortamlarında, logları tek bir yerden toplamak, depolamak, aramak ve analiz etmek için merkezi bir log yönetimi çözümü (örneğin, ELK Stack: Elasticsearch, Logstash, Kibana) kullanın.

Örnek Uygulama: SLF4J + Logback Kullanımı

Şimdi, SLF4J ve Logback’i birleştirerek kapsamlı bir örnek oluşturalım.

1. Maven pom.xml Bağımlılıkları:



    4.0.0

    com.example
    java-logging-example
    1.0-SNAPSHOT

    
        11
        11
        UTF-8
        2.0.13
        1.5.6
    

    
        
        
            org.slf4j
            slf4j-api
            ${slf4j.version}
        
        
        
            ch.qos.logback
            logback-classic
            ${logback.version}
        
        
        
            ch.qos.logback
            logback-core
            ${logback.version}
        
    

    
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    ${maven.compiler.source}
                    ${maven.compiler.target}
                
            
            
                org.apache.maven.plugins
                maven-jar-plugin
                3.2.0
                
                    
                        
                            true
                            com.example.logging.Application
                        
                    
                
            
        
    

2. src/main/resources/logback.xml Yapılandırması:


    
    

    
    
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    

    
    
        ${LOG_DIR}/${LOG_FILE_NAME}
        
            ${LOG_DIR}/archived/${LOG_FILE_NAME}.%d{yyyy-MM-dd}.%i.gz
            10MB
            7 
            1GB 
        
        
            %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
        
    

    
    
        ${LOG_DIR}/json_logs/app-json.log
        
            ${LOG_DIR}/json_logs/archived/app-json.%d{yyyy-MM-dd}.%i.json.gz
            10MB
            7
            1GB
        
        
            {"timestamp":"%d{yyyy-MM-dd HH:mm:ss.SSS}", "level":"%level", "thread":"%thread", "logger":"%logger{36}", "message":"%msg"}%n
        
    

    
    
        
        
    

    
    
        
        
        
    

3. src/main/java/com/example/logging/Application.java Sınıfı:

package com.example.logging;

import com.example.logging.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Application {

    // SLF4J Logger'ı kullanarak loglama yapıyoruz
    private static final Logger logger = LoggerFactory.getLogger(Application.class);

    public static void main(String[] args) {
        logger.info("Uygulama başlatılıyor...");

        UserService userService = new UserService();

        // Başarılı bir kullanıcı işlemi
        userService.createUser("Alice", "alice@example.com");

        // Hatalı bir kullanıcı işlemi
        try {
            userService.createUser("Bob", "invalid-email");
        } catch (IllegalArgumentException e) {
            logger.error("Kullanıcı oluşturulurken bir hata oluştu: {}", e.getMessage(), e);
        }

        // Farklı log seviyelerinde mesajlar
        logger.debug("Debug seviyesinde bir mesaj. Sadece debug seviyesi etkinse görünür.");
        logger.trace("Trace seviyesinde bir mesaj. En detaylı seviyedir.");
        logger.warn("Dikkat: Uygulama önbelleği yenilenemedi.");

        logger.info("Uygulama başarıyla tamamlandı.");
    }
}

4. src/main/java/com/example/logging/service/UserService.java Sınıfı:

package com.example.logging.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserService {

    // Servis katmanı için ayrı bir logger
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    public void createUser(String name, String email) {
        logger.debug("Kullanıcı oluşturma isteği alındı: İsim={}, E-posta={}", name, email);

        if (name == null || name.trim().isEmpty()) {
            logger.error("Kullanıcı adı boş olamaz.");
            throw new IllegalArgumentException("Kullanıcı adı boş olamaz.");
        }

        if (!isValidEmail(email)) {
            logger.warn("Geçersiz e-posta formatı algılandı: {}", email);
            throw new IllegalArgumentException("Geçersiz e-posta formatı.");
        }

        // Gerçekte burada veritabanına kaydetme vb. işlemler olurdu.
        logger.info("Kullanıcı '{}' (E-posta: {}) başarıyla oluşturuldu.", name, email);
    }

    private boolean isValidEmail(String email) {
        // Basit bir e-posta doğrulama kontrolü
        return email != null && email.contains("@") && email.contains(".");
    }
}

Bu örnekte, Application sınıfı INFO seviyesinde loglarken, UserService sınıfı için logback.xml içinde özel bir logger tanımı yaparak DEBUG seviyesinde loglama yapmasını sağladık. Böylece, uygulamanın genel akışını INFO seviyesinde izlerken, UserService içindeki daha detaylı adımları DEBUG seviyesinde görebiliriz. Ayrıca, farklı Appender’lar (konsol, metin dosyası, JSON dosyası) kullanarak logların farklı hedeflere ve formatlarda yazılmasını gösterdik.

Sonuç

Java’da loglama, modern yazılım geliştirmenin vazgeçilmez bir parçasıdır. Uygulamalarınızın davranışını anlamak, hataları hızlıca tespit etmek ve performans sorunlarını gidermek için sağlam bir loglama stratejisi oluşturmak hayati öneme sahiptir. java.util.logging basit senaryolar için yeterli olsa da, Log4j 2 ve Logback gibi üçüncü parti çerçeveler, daha fazla esneklik, performans ve zengin özellikler sunar. SLF4J gibi bir soyutlama katmanı kullanmak, uygulamanızı belirli bir loglama çerçevesine bağımlı kılmadan gelecekteki değişikliklere karşı dirençli hale getirir.

Unutmayın ki iyi loglama pratikleri, sadece loglama çerçevesini doğru yapılandırmakla kalmaz, aynı zamanda anlamlı, bağlam içeren ve doğru seviyelerde log mesajları yazmayı da içerir. Bu sayede, loglarınız yalnızca bir dosya yığını olmaktan çıkar ve uygulamanızın kalbine giden değerli bir rehber haline gelir.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

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

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.