Logging — ILogger, Serilog, sink, structured logging
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