KODUMUN LOGLARI

Furkan Şahin Kulaksız
10 min readNov 22, 2024

--

GÖRSELDEKI QR KODU KULLANARAK ILETISIM KANALLARIMDAN BANA ULASABILIRSINIZ

Tam da bu satırları yazdığım tarih 19 Kasım 2024 Saat 23.21

Basit bir makale gibi görünse de, bazen önemli detaylar, en basit yerlerden yakalanır.

Çalıştığım firmada bugün bir hata ile karşılaştım. Altyapısal olarak çok güzel bir mail sistemi kurmuşlar. İnanılmaz straightforward bir şekilde configlerinizi geçiyorsunuz. Gerekli yerlere kodunuzu ekliyorsunuz ve job tetiklendiğinde mail atılıyor.

Bende aynılarını yaptım ve ne oldu bilin bakalım. Mail gitmedi. Takım arkadaşım dedi ki “datadog’dan log bak”

Evet, çok mantıklı. Logları inceleyip nerede hata aldığını anlamak inanılmaz güzel bir practice. Ama bu practice’in sağlanması için bir yerlerde bir şekilde log basılması gerekiyor. Bu log’lar da ya kibanadan okunur ya datadog’dan okunur ya da başka bir tool’dan.

Ama asıl problem log’ların güzelce bir yere yazılması.

Loglama için kullanılabilecek olan teknolojiler ise; Logstash olabilir, log4j olabilir, spring’in kendi içerisinde bulunan loglama mekanizması olabilir. Ya da farklı bir teknoloji… Ben, spring’in kendi içinde gelen loglama yöntemini kullanacağım ve lombok’un SLF4J’sini kullanacağım.

1.ADIM — SPRING BOOT UYGULAMASININ HAZIRLANMASI

Spring Boot zaten Logback’i varsayılan loglama kütüphanesi olarak kullanır. Ekstra bir bağımlılık eklemenize gerek yok.

Çok basit bir uygulama ayağa kaldırıyoruz. Ben sadece spring-web ve lombok bağımlılıklarını ekledim.

Sonrasında main class’ı ile aynı hizaya aşağıdaki gibi bir kod geliştirdim.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoggingController {

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

@GetMapping("/")
public String index() {
logger.info("info message");
return "Logging tested";
}
}

Burada dikkat edilmesi gereken husus,

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

burada getLogger içerisine, bulunduğu class’ı parametre olarak vermek gerekiyor.

2.ADIM — LOGLARIN YAZILMASI

a) logback-spring.xml dosyası

Spring Boot projemizin src -> main -> resources klasörü altına logback-spring.xmldosyamızı oluşturuyoruz.

b) logback-spring.xml dosyasının yazılması

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %p %m%n</Pattern>
</layout>
</appender>
...
</configuration>

İlk tag’imiz Console Appender. Burası konsolda çalıştığımız appender için gözüken yerler. Burada aşağıdaki şekilde log yazabiliriz.

En içten dışa doğru giderek tag’leri incelediğimizde;

<pattern> bizim için log mesajlarının nasıl formatlanacağını belirleyen bir şablondur. pattern’in temel amaçları aşağıdaki gibidir.

  • Log mesajlarının formatını belirlemek
  • Hangi bilgilerin gösterileceğini seçmek
  • Bu bilgilerin hangi sırayla gösterileceğini belirlemek

En çok kullanılan pattern sembolleri ise aşağıdaki gibidir.

%d                --> Tarih/Saat (örn: 2024-03-20 14:30:45,123)

%p veya %level --> Log seviyesi (ERROR, WARN, INFO, DEBUG, TRACE)

%t --> Thread adı

%c veya %logger --> Logger adı (genellikle sınıf adı)

%C --> Sınıf adı

%F --> Dosya adı

%L --> Satır numarası

%m veya %msg --> Log mesajı

%n --> Yeni satır

%r --> Uygulamanın başlangıcından itibaren geçen milisaniye

Kodu bu şekilde çalıştırdığımızda

Konsolda hiç bir log görmeyeceğiz çünkü en minimalist şekliyle logback dosyası aşağıdaki gibi olmalıdır.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console Appender -->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d %p %m%n</Pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="Console" />
</root>
</configuration>

root tagı ile info level’indeki logları konsolda görebileceğiz.

Kodu çalıştırıp istek attığımızda ise loglarımz aşağıdaki şekilde olacak.

pattern’imize verdiğimiz değerler %d , %p , %m , %n
%dtarih
%pLog Seviyesi
%mmessage
%nyeni bir satır

Farklı pattern örnekleri için ise aşağıdaki kodlara bakabiliriz.

<!-- Basit format -->
<Pattern>%d %p %m%n</Pattern>
Çıktı: 2024-03-20 15:30:45,123 INFO Bu bir log mesajıdır

<!-- Thread bilgisi eklenmiş hali -->
<Pattern>%d [%t] %p %m%n</Pattern>
Çıktı: 2024-03-20 15:30:45,123 [main] INFO Bu bir log mesajıdır

<!-- Sınıf adı eklenmiş hali -->
<Pattern>%d %p %C{1} - %m%n</Pattern>
Çıktı: 2024-03-20 15:30:45,123 INFO LoggingController - Bu bir log mesajıdır

<!-- Renkli ve detaylı format hali -->
<Pattern>%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n</Pattern>
Çıktı: 2024-03-20 15:30:45,123 INFO [main] LoggingController: Bu bir log mesajıdır

Diğer configlere gelecek olursak;

  • appenderlogları bir hedefe yönlendiren yapı taşlarıdır. Logları konsola, veritabanına, bir dosyaya ya da ağ üzerinde bir başka sisteme yazdırabiliriz. nameile bu appender’a bir isim veriyoruz. Bu isim appender’i tanımlamak için kullanılır. class=ch.qos.logback.core.ConsoleAppenderile de bu logların konsola yazılacağını söylüyoruz.
  • layoutlogların NASIL formatlanacağını belirler. En yaygın kullanılan layout ise Pattern Layouttur. Çünkü desene dayalı bir layout oluşturmamıza imkan verir.
  <!-- XML formatında loglama için -->
class="ch.qos.logback.classic.layout.XMLLayout"

<!-- HTML formatında loglama için -->
class="ch.qos.logback.classic.html.HTMLLayout"

<!-- JSON formatında loglama için -->
class="ch.qos.logback.contrib.json.classic.JsonLayout"

3.ADIM — FILE APPENDER

Logback dosyamızı en son aşağıdaki haline getirdik.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console Appender -->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable
</Pattern>

</layout>
</appender>

<root level="info">
<appender-ref ref="Console" />
</root>
</configuration>

Artık bu noktada aşağıdaki kodu ekleyeceğiz.

    <!-- File Appender -->
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/application.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/archived/application-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>

Burada bir dosyaya log yazmayı sağlayanRollingFileAppenderkullanıyoruz.

  • nameBu appender’a “File” adını veriyoruz. Daha sonra bu ismi referans göstererek logları bu appendere yönlendirebiliriz.
  • ch.qos.logback.core.rolling.RollingFileAppenderLog dosyalarını zaman veya boyut bazlı arşivleme yapabilen bir appender sınıfı.
  • fileBu tag, logların yazılacağı ana dosyanın adını ve konumunu belirtir. Proje kök dizinindeki logs klasörüne application.log adında bir dosya oluşturulacak ve loglar bu dosyaya yazılacak. Eğer dosya yoksa da otomatik olarak oluşturulacak.
  • encodelogların biçimlendirilmesini (formatını) sağlar.
    class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"Logların biçimlendirilmesi için kullanılan encoder sınıfıdır.
  • rollingPolicyArşivleme, log dosyasının büyümesini kontrol altına alır. Zaman bazlı bir politika kullanılarak eski loglar ayrı dosyalara taşınır. class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"Log dosyalarını belirli bir zaman dilimine göre arşivler. Örneğin, günlük, haftalık, aylık log dosyaları oluşturabiliriz. fileNamePattern Arşivlenen log dosyalarının adını ve konumunu belirtir. logs/archived/Arşivlenen log dosyaları bu klasöre taşınır.application-%d{yyyy-MM-dd}.log Arşivlenen log dosyalarının adını belirler. %d{yyyy-MM-dd} Tarihi log dosyasının adına ekler (örneğin, application-2024-11-20.log).
  • maxHistoryArşivlenen log dosyalarının kaç gün boyunca saklanacağını belirtir. Örneğin, burada 30 gün boyunca eski loglar tutulur. 30 günden daha eski loglar otomatik olarak silinir.
  • totalSizeCap Arşivlenmiş log dosyalarının toplam boyut sınırını belirler. Burada toplam 10 GB’ı geçerse, en eski log dosyaları silinir.

logback-spring.xml dosyamızın son hali de aşağıdaki şekilde oldu.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console Appender -->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable
</Pattern>

</layout>
</appender>

<!-- File Appender -->
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/application.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/archived/application-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>

<root level="info">
<appender-ref ref="Console" />
<appender-ref ref="File" />
</root>
</configuration>

Tabi burada aslında güzel bir practice olarak <encoder>…</encoder> tag’leri arasına <charset>UTF-8</charset> eklemek güzel bir practice olabilir. Ve yine güzel bir practice olarak, <file> tag’ına ${user.dir}`eklenebilir. Bu, sistemde ilgili dizini direkt olarak işaret eder. Günün sonunda xml dosyası aşağıdaki halini alacak.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console Appender -->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>
%black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable
</Pattern>

</layout>
</appender>

<!-- File Appender -->
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${user.dir}/logs/application.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<charset>UTF-8</charset>
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/archived/application-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>

<root level="info">
<appender-ref ref="Console" />
<appender-ref ref="File" />
</root>
</configuration>

Uygulamayı çalıştırıp istek attığımızda hem console’da hem de file dosyamızda log’ları görebiliriz.

4.ADIM — LOG SEVİYELERİ

Log seviyeleri, bir yazılımın çalışması sırasında üretilen log mesajlarının önem derecesini ve önceliğini belirlemek için kullanılan kategorilerdir. Bu seviyeler, bir uygulamanın davranışını izlemek, hataları çözmek ve performansını değerlendirmek için önemlidir.

  • TRACE
    -> Amaç:
    En ayrıntılı log seviyesidir. Uygulamanın en ince detaylarını bile kaydeder.
    -> Kullanım: Uygulamanın akışını izlemek için genellikle geliştirme ve hata ayıklama sırasında kullanılır.
  • DEBUG
    -> Amaç:
    Uygulamanın iç mantığını anlamaya yardımcı olacak bilgiler sağlar.
    -> Kullanım: Uygulama geliştirme sırasında, sistemin nasıl çalıştığını anlamak ve sorunları tespit etmek için kullanılır.
  • INFO
    -> Amaç:
    Normal iş akışı sırasında kullanıcıya ya da sistem yöneticisine bilgi vermek için kullanılır.
    -> Kullanım: Uygulamanın önemli olaylarını kaydeder. Örneğin, bir işlemin başarıyla tamamlanması gibi.
  • WARN
    -> Amaç:
    Potansiyel bir problem olduğunu veya beklenmeyen bir durumun oluştuğunu belirtir. Ancak bu durum uygulamanın çalışmasını engellemez.
    -> Kullanım: Önlem almayı gerektiren durumları kaydetmek için kullanılır.
  • ERROR
    -> Amaç:
    Uygulamanın işleyişini etkileyen bir hata olduğunu belirtir.
    -> Kullanım: Kullanıcı veya sistem yöneticisi tarafından hızlıca ele alınması gereken ciddi sorunları belirtir.
  • FATAL
    -> Amaç:
    Uygulamanın çalışmasını tamamen durdurabilecek kritik bir hatayı belirtir.
    -> Kullanım: Çok ciddi durumlarda, örneğin sistemin veya uygulamanın çökmesine neden olan bir hata olduğunda kullanılır.

Şu ana kadar geldiğimiz noktada sadece info log’undan yararlandık. Spring Boot tarafındaki controller class’ımızı aşağıdaki şekilde güncelleyelim.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoggingController {

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

@GetMapping("/")
public String index() {
logger.info("info message");
logger.debug("debug message");
logger.error("error message");
logger.warn("warn message");
logger.trace("trace message");
return "Logging tested";
}
}

Eğer ben bütün log seviyelerindeki mesajları görmek istersem xml dosyama aşağıdaki şekilde configleri geçmem gerekiyor.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console Appender -->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<charset>UTF-8</charset>
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>
</appender>

<!-- File Appender -->
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
<prudent>true</prudent>
<file>${user.dir}/logs/application.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<charset>UTF-8</charset>
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${user.dir}/logs/archived/application-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>

<!-- Root seviyesini TRACE yaparak tüm logları görebiliriz -->
<root level="trace">
<appender-ref ref="Console" />
<appender-ref ref="File" />
</root>
</configuration>

Yani aslında root seviyesini TRACE yapmamız yeterli çünkü en üst seviyedeki log TRACE log’u. Kodumuzu çalıştırdığımızda ise;

Gayet güzel bir şekilde log’larımız karşımıza geldi.

Güzel Bir Not: Eğer Spring Boot frameworkünün arkada nasıl çalıştığını anlamak isterseniz, log level’ini trace yapıp çıkan log’ları okuyun. ((:

Peki ben sadece 2 ya da 3 tane log görmek istersem ne yapalıyım.? O zaman’da aşağıdaki gibi configleri eklemelisiniz.

<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch> <!-- Log INFO ise: KABUL ET -->
<onMismatch>NEUTRAL</onMatch> <!-- Log INFO değilse: SONRAKİ FİLTREYE GEÇ -->
</filter>

<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch> <!-- Log WARN ise: KABUL ET -->
<onMismatch>DENY</onMatch> <!-- Log WARN değilse: REDDET -->
</filter>
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console Appender -->
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>UTF-8</charset>
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>
<!-- Sadece WARN ve INFO mesajlarını filtreleyen filter -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- File Appender -->
<appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${user.dir}/logs/application.log</file>
<encoder>
<charset>UTF-8</charset>
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>
<!-- Aynı filtreleri File Appender için de ekleyelim -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>NEUTRAL</onMismatch>
</filter>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>

<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${user.dir}/logs/archived/application-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
<totalSizeCap>10GB</totalSizeCap>
</rollingPolicy>
</appender>

<root level="info">
<appender-ref ref="Console" />
<appender-ref ref="File" />
</root>
</configuration>

Bu şekilde kodu çalıştırdığımda aşağıdaki gibi sadece log ve warn mesajlarını göreceğim.

SORULARA EL CEVAPLAR

SORU1 — LOGBACK.XML yerine Application.yml kullansam olmaz mı?

Eğer kabataslak işlemler yapılacaksa evet, application.yml işimizi çözer. Ama daha kompleks işlemler olacaksa o zaman logback.xml dosyasına ihtiyacımız var.

logging:
level:
root: INFO
org.fsk: INFO

file:
name: logs/application.log

pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

logback:
rollingpolicy:
file-name-pattern: logs/archived/application-%d{yyyy-MM-dd}.log
max-file-size: 10MB
max-history: 30
total-size-cap: 10GB

SORU2 — SADECE KENDİ LOGLARIMI GÖRMEK İSTİYORUM. SİSTEM SEVİYESİNDEKİ LOGLARI GÖRMEK İSTEMİYORUM. BU MÜMKÜN MÜ.?

Evet, mümkün.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<charset>UTF-8</charset>
<Pattern>%d %p %C{1} [%t] %m%n</Pattern>
</encoder>
</appender>

<!-- Tüm logları kapat -->
<root level="OFF">
<appender-ref ref="Console" />
</root>

<!-- Sadece org.fsk paketindeki logları gösterir -->
<logger name="org.fsk" level="INFO" additivity="false">
<appender-ref ref="Console" />
</logger>
</configuration>

SORU3 — CONDITION KULLANARAK LOG BASABİLİR MİYİM.?

Evet. Conditionlar ile log basılabilir. Mesela dev ve prod ortamları için ayrı ayrı log basılabilir. Mesela DEV ortamı için, error mesajlarını file’a, info mesajlarını konsola yazdıralım.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Property'leri Spring Boot'tan alıyoruz. -->
<springProperty scope="context" name="environment" source="ENV"/>

<!-- Console Appender - Sadece INFO için -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- File Appender - Dev ortamı için -->
<appender name="FILE_DEV" class="ch.qos.logback.core.FileAppender">
<file>logs/dev_error.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- File Appender - Prod ortamı için -->
<appender name="FILE_PROD" class="ch.qos.logback.core.FileAppender">
<file>logs/prod_error.log</file>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- Dev ortamı için config geçiyoruz-->
<if condition='property("environment").equals("dev")'>
<then>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE_DEV" />
</root>
</then>
</if>

<!-- Prod ortamı için config geçiyoruz. -->
<if condition='property("environment").equals("prod")'>
<then>
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="FILE_PROD" />
</root>
</then>
</if>

</configuration>

application.properties dosyamız ise çok basit şekilde aşağıdaki gibi olmalı.

spring.application.name=logging
ENV=dev

Önemli Not:

if — then yapısını kullanmak için pom.xml’e farklı bir bağımlılık eklemem gerekiyor. Aşağıda bu bağımlılığı ekleyip if — then yapısını kullanabiliriz.

        <dependency>
<groupId>org.codehaus.janino</groupId>
<artifactId>janino</artifactId>
<version>3.1.12</version>
</dependency>

Tabi farklı environment’ler için farklı logback dosyaları da kullanılabilir. Ben buna değinmedim çünkü geliştireceğim proje için benim buna ihtiyacım yok.

Sevgili, Burak Kızılkaya çok güzel bir yorumda bulundu.

SORU4 — LOGLARI DÜZGÜN BİR ŞEKİLDE NASIL YAZABİLİRİM.?

String interpolated yaklaşımı ile aslında çok da güzel loglar hazırlanabilir.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoggingController {

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

@GetMapping("/")
public String index(@RequestParam("name") String name) {
logger.info(name + " ==> Query Param");
return "Logging tested";
}
}

Bu şekilde log mesajı yazdırılabilir. Ama bunun en doğru yöntemi,

logger.info("{} ==> QueryParam", name);

şeklindedir. Eğer log mesajı birden fazla parametre alacaksa da o zaman süslü parantezlerin sırasına göre çalışır.

logger.info("Bu bir log mesajıdır. {} tarafından {} tarihinde {} adlı kisiye gonderilmistir.", 
name, date, to);

şeklinde bir durum olabilir. Tabi burda, 3 çift tırnak syntax’ı ile de bu log’lar basılabilir. Yani

logger.info("""
Bu bir log mesajıdır. {} tarafından {} tarihinde {}
adlı kisiye gonderilmistir.
""",
name, date, to);

İletişim, İşbirlikleri ve Teklifler için,

github: https://github.com/fsk

bitbucket: https://bitbucket.org/furkandev

twitter: https://twitter.com/0xfsk

mail: furkansahinkulaksiz@gmail.com

linkedIn: https://www.linkedin.com/in/frknshnklksz/

superpeer: https://superpeer.com/fsk

--

--

No responses yet