CodeGym /Kurslar /JAVA 25 SELF /Loqlaşdırmanın əsasları: java.util.logging, Log4j, SLF4J

Loqlaşdırmanın əsasları: java.util.logging, Log4j, SLF4J

JAVA 25 SELF
Səviyyə , Dərs
Mövcuddur

1. Niyə loqlaşdırma lazımdır

Loqlaşdırma ≠ konsola çıxış

Proqramlaşdırmağa yeni başlayanda elə gəlir ki, problemləri tapmaq üçün hər yerə System.out.println("Burada idim!") sıxmaq kifayətdir. Bu, proqram kiçik olanda və sizin kompüterinizdə işə salınanda işləyir. Amma böyük layihəni, 24/7 işləyən serveri və ya minlərlə insanın istifadə etdiyi tətbiqi təsəvvür edin — axı siz hər istifadəçinin arxasında oturub onun konsoluna baxa bilməzsiniz?

Loqlaşdırma — sadəcə mesajların çıxışı deyil. Bu, tətbiqin işi barədə məlumatların — xətaların, xəbərdarlıqların, biznes hadisələrinin, texniki detalların — sistemləşdirilmiş yazılmasıdır. Loqlar fayllarda, verilənlər bazalarında saxlanıla, şəbəkə ilə göndərilə bilər — və proqramın işini icradan sonra və ya elə proses zamanı təhlil etməyə imkan verir.

Loqlar nə üçün lazımdır

  • Problemlərin diaqnostikası: nəsə qaydasında getmədikdə, loqlar — sizin əsas köməkçinizdir. Onlara görə xətanın harada və niyə yarandığını anlamaq olur.
  • Audit və təhlükəsizlik: loqlar istifadəçilərin vacib hərəkətlərini fiksə edir, bu da insidentlərin araşdırılmasına kömək edir.
  • Sazlama: bəzən bağlar yalnız müəyyən şəraitdə üzə çıxır və loqlar olmadan onları tutmaq mümkün olmur.
  • Monitorinq: loqlara görə tətbiqin vəziyyətini, performansını və “sağlamlığını” izləmək olar.

Həyatdan nümunə

Təyyarələrdə “qara qutular” (uçuş loqları) olmasaydı, qəzaların səbəblərini araşdırmaq demək olar ki, mümkün olmazdı. Proqramlaşdırmada loqlar — sizin “qara qutular”ınızdır.

2. Loqlaşdırmanın baza səviyyələri

Loqlaşdırmada mesajların səviyyələrindən (levels) istifadə etmək qəbul olunub. Bu, sanki işıqfor kimidir: qırmızı — təhlükəli, sarı — ehtiyatlı ol, yaşıl — hər şey qaydasındadır.

Əsas səviyyələr (ən “səsli”dən ən “sakit”ə doğru):

Səviyyə Təsvir
ERROR
Kritik xəta, tətbiq işi davam etdirə bilmir
WARN
Xəbərdarlıq: nəsə qaydasında deyil, amma proqram işləyir
INFO
Adi hadisələr barədə informativ mesaj
DEBUG
Sazlama üçün ətraflı məlumat (yalnız tərtibatçılar üçün görünür)
TRACE
Ən ətraflı məlumat — dərin diaqnostika üçün

Nümunə:

  • İstifadəçi parol yanlışdır deyə daxil ola bilmədi — bu, WARN-dır.
  • Verilənlər bazası sıradan çıxdı — bu, ERROR-dır.
  • Tətbiq işə başladı — bu, INFO-dur.
  • Döngüdə dəyişənin dəyərinin çıxarılması — bu, DEBUG və ya TRACE-dir.

Səviyyəni necə seçmək olar

Hər şeyi ERROR səviyyəsində yazmağa dəyməz — əsl xətalar içində boğulacaqsınız. Səviyyələrdən şüurlu istifadə edin: yalnız həqiqətən kritik nasazlıqlar xəta olmalıdır.

3. Java-da standart loqlaşdırma (java.util.logging)

Java daxili loqlaşdırma sistemi ilə gəlir — paket java.util.logging (qısaca JUL). Bu, heç bir kitabxana qoşmasanız da həmişə mövcud olan “doğma” alətdir.

Əsas siniflər:

  • Logger — loqların yazılması üçün əsas sinif.
  • Level — loqlaşdırma səviyyələrinin enumerasiyası (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST).
  • Handler — loqların hara yazılacağını göstərən işləyici (fayl, konsol və s.).
  • Formatter — mesajların formatına cavabdehdir.

JUL-dan istifadə nümunəsi

import java.util.logging.Logger;
import java.util.logging.Level;

public class LoggingExample {
    // Sinifin adına görə loqgeri alırıq
    private static final Logger logger = Logger.getLogger(LoggingExample.class.getName());

    public static void main(String[] args) {
        logger.info("Tətbiq işə salındı");
        logger.warning("Bu, xəbərdarlıqdır!");
        logger.severe("Və bu artıq xətadır!");

        int x = 42;
        logger.fine("Sazlama üçün dəyişən x=" + x); // Standart olaraq göstərilmir
    }
}

Vacib məqam: standart olaraq JUL yalnız INFO və ondan yuxarı səviyyələri göstərir. fine və digər ətraflı mesajları görmək üçün loqlaşdırma səviyyəsini sazlamaq lazımdır.

Fayl vasitəsilə konfiqurasiya

JUL-u logging.properties faylı (adətən JRE qovluğunda olur) ilə sazlamaq olar. Orada aşağıdakıları göstərmək mümkündür:

  • Loqger üçün minimal səviyyə
  • Loqların hara yazılması (fayl, konsol)
  • Mesajların formatlanması

Nümunə sətir logging.properties faylında:

.level=INFO

4. Xarici loqlaşdırma kitabxanaları

Log4j (Apache)

Log4j — Java üçün ən məşhur loqlaşdırma kitabxanalarından biridir. O, çevik və güclüdür, müxtəlif formatları, asinxron yazını, faylların rotasiyasını və daha çoxunu dəstəkləyir.

Ən sadə Log4j 2 konfiqurasiyası (XML) nümunəsi:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Koddakı Log4j 2 istifadəsi nümunəsi:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4jExample {
    private static final Logger logger = LogManager.getLogger(Log4jExample.class);

    public static void main(String[] args) {
        logger.info("Hello from Log4j!");
        logger.error("Bu, Log4j vasitəsilə xətadır");
    }
}

Bunun işləməsi üçün layihənizə Log4j asılılıqlarını əlavə etmək lazımdır (məsələn, Maven və ya Gradle vasitəsilə).

SLF4J: loqlaşdırma fasadı

SLF4J (Simple Logging Facade for Java) — bu, ayrıca loqlaşdırma sistemi deyil, sizin kodunuz ilə konkret reallaşdırma (Log4j, Logback, JUL və s.) arasında “ara qat”dır.

Fasad ona görə lazımdır ki, kodu bir dəfə yazasınız və lazım gəldikdə real loqlaşdırma sistemini kodu yenidən yazmadan dəyişə biləsiniz, hətta müxtəlif kitabxanalar fərqli loqgerlərdən istifadə etsə belə.

SLF4J istifadəsi nümunəsi:

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) {
        logger.info("Salam, SLF4J vasitəsilə loqlaşdırma!");
        logger.warn("Diqqət: nəsə qaydasında getməyə bilər");
        logger.error("SLF4J vasitəsilə xəta");
    }
}

Bu necə işləyir?

  • Siz kodu SLF4J vasitəsilə yazırsınız.
  • Classpath-ə lazım olan reallaşdırmanı əlavə edirsiniz (məsələn, Logback və ya Log4j).
  • SLF4J çağırışları seçilmiş reallaşdırmaya özü “ötürür”.

SLF4J-in digər loqgerlərlə qarşılıqlı işi: SLF4J JUL, Log4j, Logback və s. üzərində işləyə bilir, bu da kodu yenidən yazmadan asan miqrasiya etməyə imkan verir.

5. Təcrübə: System.out.println ilə loqlaşdırmanı müqayisə edirik

Nümunə 1: System.out.println

public class PrintlnExample {
    public static void main(String[] args) {
        System.out.println("Tətbiq işə salındı");
        System.out.println("Xəta baş verdi: nəsə qaydasında getmədi");
    }
}

Nə düzgün deyil:

  • Mesaj səviyyəsi yoxdur (xəta, informasiya, xəbərdarlıq — hamısı eynidir).
  • Zaman, sinifin adı, axın yoxdur.
  • Bütün mesajlar bir yerə qarışır.
  • Çıxışı çevik sazlamaq olmur (məsələn, yalnız xətaları yazmaq).

Nümunə 2: SLF4J + Logback vasitəsilə loqlaşdırma

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

public class LoggingVsPrintln {
    private static final Logger logger = LoggerFactory.getLogger(LoggingVsPrintln.class);

    public static void main(String[] args) {
        logger.info("Tətbiq işə salındı");
        logger.error("Xəta baş verdi: nəsə qaydasında getmədi");
    }
}

Üstünlüklər:

  • Hər mesaj zaman, səviyyə, sinif adı, axın ilə müşayiət olunur.
  • Mesajları səviyyəyə görə filtrələmək olar.
  • Loqları fayla yazmaq, şəbəkə ilə göndərmək, formatlamaq, arxivləşdirmək mümkündür.
  • Loqlaşdırma axınqoruyandır (çoxaxınlı tətbiqlər üçün aktualdır).

Fərqin nümayişi

System.out.println
Loqlaşdırma (SLF4J/Logback)
Tətbiq işə salındı 12:34:56 [main] INFO LoggingVsPrintln - Tətbiq işə salındı
Xəta baş verdi: nəsə qaydasında getmədi 12:34:56 [main] ERROR LoggingVsPrintln - Xəta baş verdi: nəsə qaydasında getmədi

6. Layihənizə loqlaşdırmanı necə əlavə etmək olar

Standart loqger (JUL) üçün

JDK-də hər şey artıq var, dərhal istifadə edə bilərsiniz:

import java.util.logging.Logger;

public class MyApp {
    private static final Logger logger = Logger.getLogger(MyApp.class.getName());

    public static void main(String[] args) {
        logger.info("Bu, info mesajıdır");
    }
}

Log4j və ya SLF4J üçün

  1. Asılılıqları əlavə edin (məsələn, Maven vasitəsilə).

    Log4j 2 üçün:

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.20.0</version>
    </dependency>
    

    SLF4J + Logback üçün:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.7</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.7</version>
    </dependency>
    
  2. Konfiqurasiya faylı yaradın (məsələn, logback.xml — Logback üçün və ya log4j2.xml — Log4j üçün).
  3. Kodunuzda loqgerdən istifadə edin (yuxarıdakı nümunələrə baxın).

7. Mini-tətbiq: loqlaşdırmanı əlavə edirik

Tutaq ki, bizdə sadə bir tətbiq var — komanda sətri kalkulyatoru. Ona loqlaşdırma əlavə edək.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Scanner;

public class CalculatorApp {
    private static final Logger logger = LoggerFactory.getLogger(CalculatorApp.class);

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        logger.info("Kalkulyator işə salındı");

        try {
            System.out.print("Birinci ədədi daxil edin: ");
            int a = Integer.parseInt(scanner.nextLine());
            logger.debug("Birinci ədəd daxil edildi: {}", a);

            System.out.print("İkinci ədədi daxil edin: ");
            int b = Integer.parseInt(scanner.nextLine());
            logger.debug("İkinci ədəd daxil edildi: {}", b);

            int sum = a + b;
            logger.info("Ədədlərin cəmi: {}", sum);
            System.out.println("Nəticə: " + sum);
        } catch (NumberFormatException ex) {
            logger.error("Rəqəm daxil edilməsində xəta", ex);
            System.out.println("Xəta: düzgün rəqəm daxil edin!");
        } catch (Exception ex) {
            logger.error("Naməlum xəta", ex);
            System.out.println("Xəta baş verdi!");
        }
        logger.info("Kalkulyator işi tamamladı");
    }
}

Burada nə baş verir:

  • Bütün əsas hadisələr loqda qeyd olunur.
  • Xətalar ERROR səviyyəsində və tam stack trace ilə loqlaşdırılır.
  • Bütün məlumat proqramın işləməsindən sonra da analiz üçün əlçatandır.

8. Loqlaşdırma ilə işləyərkən tipik səhvlər

Səhv №1: Yalnız System.out.println istifadə etməklə sazlama və diaqnostika aparmaq.
Başlanğıcda rahatdır, amma real tətbiqlər üçün tam uyğun deyil. Mesaj səviyyələrini idarə edə bilməyəcəksiniz, zamanı görməyəcəksiniz, proqram serverdə işləyirsə loqları analiz etmək mümkün olmayacaq.

Səhv №2: Çox böyük həcmdə məlumatı ERROR səviyyəsində loqlaşdırmaq.
Hər şeyi xəta kimi yazsanız, həqiqətən vacib olanı sazlama üçün sadəcə informasiyadan ayırd etmək çətinləşəcək.

Səhv №3: Həssas məlumatların loqlaşdırılması (parollar, tokenlər, kart nömrələri).
Loqlar təhlükəsiz olmalıdır! Orada başqalarının görməməli olduğu məlumatları yazmayın.

Səhv №4: Loqlaşdırmanın konfiqurasiyasının olmaması.
Əgər səviyyələri, formatı, loqların saxlandığı yeri sazlamasanız — gözlənilmədən lazımsız gigabaytlarla “boğula” və ya ümumiyyətlə xətanı görməyə bilərsiniz.

Səhv №5: Böyük layihələrdə loqlaşdırma fasadından (SLF4J) istifadə etməmək.
Layihəniz böyüyərsə, bir kitabxanadan digərinə keçmək — fasadsız ağrılı olacaq. SLF4J loqlaşdırmanın “mühərrikini” kodu yenidən yazmadan asanlıqla dəyişməyə imkan verir.

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION