Logging — ILogger, Serilog, sink, structured logging

~20 daq · .NET Backend · Ilg'or ASP.NET Core

Muammodan boshlaylik

Mijoz qo'ng'iroq qiladi: "Kecha soat 23:40 da to'lov o'tmadi, puli yechildi". Serverda nima bo'lgan? Kodda faqat:

Console.WriteLine("Xato!");

Qaysi foydalanuvchi? Qaysi buyurtma? Qanday xato? Production da konsol chiqishi qayerga ketdi? Hech qanday iz yo'q.


Hayotiy o'xshatma

Samolyotning "qora qutisi". Parvoz paytida hamma narsa yozib boriladi: balandlik, tezlik, uchuvchilar gaplari. Hammasi joyida bo'lsa — hech kim o'qimaydi. Lekin muammo bo'lsa — aynan shu yozuvlar nima bo'lganini aniq tiklashga yordam beradi. Log — ilovangizning qora qutisi.


ILogger<T> — o'rnatilgan

ASP.NET Core da logging tayyor — DI orqali olinadi:

public class TolovService(ILogger<TolovService> log, ITolovProvayder provayder)
{
    public async Task<bool> TolaAsync(int buyurtmaId, decimal summa, CancellationToken ct)
    {
        log.LogInformation("To'lov boshlandi: buyurtma {BuyurtmaId}, summa {Summa}", buyurtmaId, summa);

        try
        {
            var natija = await provayder.YechAsync(summa, ct);
            log.LogInformation("To'lov muvaffaqiyatli: buyurtma {BuyurtmaId}, tranzaksiya {TranzaksiyaId}",
                buyurtmaId, natija.TranzaksiyaId);
            return true;
        }
        catch (Exception ex)
        {
            log.LogError(ex, "To'lov xatosi: buyurtma {BuyurtmaId}", buyurtmaId);
            return false;
        }
    }
}

<T> — kategoriya: log da qaysi klassdan kelgani ko'rinadi (MyApp.Services.TolovService).


Log darajalari

Daraja Qachon Misol
Trace Eng mayda tafsilotlar Har bir sikl qadami
Debug Ishlab chiqishda diagnostika Kesh kaliti, oraliq qiymatlar
Information Muhim oddiy hodisalar Buyurtma yaratildi, foydalanuvchi kirdi
Warning Kutilmagan, lekin ishlayapti Qayta urinish, sekin so'rov, eskirgan API
Error Amal muvaffaqiyatsiz To'lov o'tmadi, tashqi servis xatosi
Critical Butun ilova xavf ostida Baza ulanishi yo'q, disk to'ldi
// appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Microsoft.EntityFrameworkCore.Database.Command": "Warning"
    }
  }
}

Production da odatda Information; Development da — Debug. EF Core SQL larini ko'rish uchun Microsoft.EntityFrameworkCore.Database.Command ni Information qiling.


Structured logging — eng muhim qoida

// ❌ satr interpolatsiyasi
log.LogInformation(
quot;Buyurtma {id} yaratildi, summa {summa}"); // ✅ shablon + parametrlar log.LogInformation("Buyurtma {BuyurtmaId} yaratildi, summa {Summa}", id, summa);

Shablon bilan BuyurtmaId va Summa — alohida maydonlar sifatida saqlanadi. Log tizimida (Seq, Elasticsearch, Grafana Loki) qidirish mumkin: BuyurtmaId = 1042 yoki Summa > 1000000. Interpolatsiyada — faqat bitta satr, maydonlar yo'q; har safar yangi satr yaratiladi (daraja o'chiq bo'lsa ham).

[!WARNING] Log ga hech qachon yozmang: parollar, tokenlar, karta raqamlari, to'liq pasport ma'lumotlari, API kalitlar. Log lar ko'p odamga ochiq va uzoq saqlanadi. Butun DTO ni {@Dto} bilan log qilishdan oldin unda maxfiy maydon yo'qligini tekshiring.


Scope — kontekst qo'shish

using (log.BeginScope(new Dictionary<string, object> { ["BuyurtmaId"] = id, ["MijozId"] = mijozId }))
{
    log.LogInformation("Ombor tekshirilmoqda");
    log.LogInformation("To'lov boshlandi");
    // ikkala yozuvda ham BuyurtmaId va MijozId bo'ladi
}

Serilog

O'rnatilgan logger konsol va debug ga yozadi. Fayl, Seq, Elasticsearch va boy formatlash uchun — Serilog:

dotnet add package Serilog.AspNetCore
dotnet add package Serilog.Sinks.File
using Serilog;

builder.Host.UseSerilog((ctx, cfg) => cfg
    .ReadFrom.Configuration(ctx.Configuration)
    .Enrich.FromLogContext()
    .WriteTo.Console()
    .WriteTo.File("logs/ilova-.log",
        rollingInterval: RollingInterval.Day,
        retainedFileCountLimit: 14));

var app = builder.Build();

app.UseSerilogRequestLogging();     // har bir HTTP so'rov — bitta qisqa yozuv
[23:40:12 INF] HTTP POST /api/tolov responded 500 in 1243.5 ms
[23:40:12 ERR] To'lov xatosi: buyurtma 1042
System.TimeoutException: Provayder javob bermadi ...

Kod o'zgarmaydi — hamon ILogger<T> ishlatiladi; Serilog uning ostida ishlaydi.

Konfiguratsiyadan

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": { "Microsoft.AspNetCore": "Warning" }
    }
  }
}

[!TIP] Production da log larni markaziy tizimga yuboring (Seq, Grafana Loki, Elasticsearch, Application Insights) — bir nechta server log larini bitta joyda qidirish va xatolar bo'yicha ogohlantirish. Konteynerlarda (80-dars) — faqat konsolga yozing; to'plashni platforma bajaradi.


Yuqori performance — LoggerMessage

Juda tez-tez chaqiriladigan joylarda — source generator:

public static partial class Loglar
{
    [LoggerMessage(Level = LogLevel.Information, Message = "Buyurtma {BuyurtmaId} yaratildi")]
    public static partial void BuyurtmaYaratildi(this ILogger log, int buyurtmaId);
}

log.BuyurtmaYaratildi(id);

Kompilyatsiya vaqtida generatsiya — ajratmalar (allocation) minimal.


Tez-tez uchraydigan xatolar

Interpolatsiya — structured maydonlar yo'qoladi.

Exception ni xabarga qo'shish: log.LogError("Xato: " + ex.Message) — stack trace yo'qoladi; log.LogError(ex, "...").

Hammasini Information da — log shovqini, haqiqiy muammo ko'rinmaydi va saqlash qimmat.


Xulosa

ILogger<T> — DI orqali, kategoriya klass nomi. Darajalar: Trace → Debug → Information → Warning → Error → Critical; appsettings.json da kategoriya bo'yicha minimal daraja. Structured logging: "... {BuyurtmaId}", id — interpolatsiya emas; exception — birinchi argument.

BeginScope — kontekst qo'shish. Serilog — fayl, Seq va boshqa sink lar, UseSerilogRequestLogging; kod ILogger da qoladi. Maxfiy ma'lumot log ga tushmasin; production da markaziy log tizimi.


Keyingi dars

67-dars: Caching — IMemoryCache, muddat, invalidatsiya