Logging strategiyasi
Logging nima, production'da console.log yetarli bo'lmasligi, strukturaviy (JSON) logging, log darajalari (debug/info/warn/error/fatal), maxfiy ma'lumotni loglamaslik, Correlation ID orqali ko'p xizmatli tizimda izlash, markazlashtirilgan logging tizimlari, va sinxron logging'ning Node.js event loop'ga ta'siri.
96-dars
Logging strategiyasi
Tasavvur qiling, samolyot uchyapti. Agar u yiqilib tushsa, tergovchilar **"qora quti" (black box)**ni qidiradi — chunki u parvoz davomida hamma narsani yozib boradi: balandlik, tezlik, dvigatel holati.
Logging — dasturda aynan shu: dastur ishlayotgan paytda nima bo'layotganini yozib borish, shunda biror narsa noto'g'ri ketsa, "qora quti"ni ochib, nima sodir bo'lganini tiklash mumkin bo'ladi.
1. console.log — nega u yetarli emas
console.log('Foydalanuvchi kirdi');
Bu — lokal kompyuterda, siz kod yozayotganda ishlaydi. Lekin production'da (haqiqiy serverda, minglab foydalanuvchi bilan) muammolar boshlanadi.
2. Production'dagi uchta aniq muammo
- Server terminalida
console.logchiqadi, lekin kim uni kuzatib o'tiradi? Server tunda ishlayveradi, hech kim ekranga qarab o'tirmaydi. - Server o'chib-yonib ketsa (restart, crash) — terminaldagi barcha
console.logtarixi yo'qoladi. - 1000 ta foydalanuvchi bir vaqtda ishlasa, konsolda minglab qator aralashib ketadi — kimning muammosi qayerda, ajratib bo'lmaydi.
3. Yechim — strukturaviy logging (structured logging)
Oddiy matn o'rniga, JSON formatida, aniq maydonlar bilan yoziladi:
// YOMON — oddiy matn:
console.log('User 123 login failed');
// YAXSHI — strukturaviy:
logger.error({
event: 'login_failed',
userId: 123,
reason: 'wrong_password',
timestamp: '2026-09-15T10:30:00Z',
ip: '192.168.1.1'
});
Nega bu muhim? Chunki keyinroq siz bu logni qidira olishingiz kerak bo'ladi: "oxirgi 1 soatda nechta login xatosi bo'ldi?", "qaysi IP'dan eng ko'p urinish bo'lgan?". Oddiy matn ustida bunday savolga javob topish — qiyin (matn ichidan regex bilan qidirish kerak). JSON formatida bo'lsa — bu ma'lumotlar bazasidagi qatorga o'xshaydi, oson filtrlash, guruhlash mumkin.
4. Log darajalari (Log Levels) — hammasi bir xil muhim emas
logger.debug('Cache hit: user_123'); // faqat dasturchi uchun, batafsil
logger.info('User logged in'); // odatiy hodisa
logger.warn('API response slow: 3.2s'); // e'tibor kerak, lekin hali muammo emas
logger.error('Payment failed'); // haqiqiy muammo
logger.fatal('Database connection lost'); // tizim ishlamay qoladi
| Daraja | Qachon ishlatiladi | Production'da yoqilganmi |
|---|---|---|
| debug | Dasturchi uchun batafsil ma'lumot | Odatda yo'q (juda ko'p, joy egallaydi) |
| info | Odatiy hodisalar ("user ro'yxatdan o'tdi") | Ha |
| warn | Kutilmagan, lekin dastur ishlayveradi | Ha |
| error | Aniq xato, biror narsa ishlamadi | Ha, muhim |
| fatal | Dastur ishlay olmaydi | Ha, shoshilinch |
Nega darajalar kerak? Chunki production'da debug darajasidagi hamma narsani yozib borsangiz — bir kunda gigabaytlab log to'planadi, orasidan haqiqiy muammoni topish — g'oyibdan qidirish kabi. Darajalar orqali siz "faqat warn va undan yuqorisini ko'rsat" deb filtrlashingiz mumkin.
5. Muhim tamoyil — nima logga yozilmasligi kerak
// XAVFLI — hech qachon bunday qilmang:
logger.info({
event: 'user_login',
password: req.body.password, // ❌ Parol logda!
creditCard: user.cardNumber, // ❌ Karta raqami logda!
});
Bu — jiddiy xavfsizlik xatosi. Log fayllari ko'pincha uzoq vaqt saqlanadi, ko'p odam (jamoa a'zolari, monitoring tizimlari) unga kirish huquqiga ega bo'ladi. Agar parol yoki karta raqami logga tushib qolsa — bu ma'lumotlar sizib chiqishi (data leak) hisoblanadi, hatto agar log fayli "ichki" bo'lsa ham.
To'g'ri yondashuv — maskalash:
logger.info({
event: 'user_login',
email: maskEmail(user.email), // "b***@gmail.com"
cardLast4: user.cardNumber.slice(-4), // faqat oxirgi 4 raqam
});
6. Correlation ID — ko'p qismli tizimda "izni yo'qotmaslik"
Katta tizimda bitta foydalanuvchi so'rovi bir necha xizmat orqali o'tishi mumkin (masalan, Auth xizmati → Order xizmati → Payment xizmati — "Architecture design"da ko'rgan Microservices misoli). Agar har biri alohida log yozsa, ularni bir-biriga bog'lash qiyin bo'ladi.
Yechim — har bir so'rovga noyob ID beriladi, va bu ID hamma joyda birga yuriladi:
// So'rov kirganda — bitta ID yaratiladi:
const requestId = crypto.randomUUID(); // masalan: "a1b2c3d4"
// Har bir keyingi log shu ID bilan yoziladi:
logger.info({ requestId, event: 'auth_checked' });
logger.info({ requestId, event: 'order_created' });
logger.info({ requestId, event: 'payment_processed' });
Endi, agar to'lov muvaffaqiyatsiz bo'lsa, siz requestId: "a1b2c3d4" bo'yicha qidirib, aynan shu so'rov qaysi bosqichlardan o'tganini, qayerda nima noto'g'ri ketganini to'liq ko'rasiz — garchi bu uchta turli xizmatda, uchta turli log faylida yozilgan bo'lsa ham.
7. Logni qayerga yozish — fayldan markazlashtirilgan tizimgacha
Daraja 1 — eng oddiy:
console.log() → terminalga chiqadi → yo'qoladi (server restart bo'lsa)
Daraja 2 — faylga yozish:
logger → app.log fayliga yoziladi → saqlanadi, lekin bitta serverda
Daraja 3 — markazlashtirilgan tizim:
logger → barcha serverlardan → markaziy joyga (masalan, Elasticsearch,
Datadog, Grafana Loki) yig'iladi → qidirish, filtrlash, grafik
chizish mumkin
Agar sizda 10 ta server bo'lsa (masalan, yuk taqsimlash — load balancing tufayli), va foydalanuvchi muammoga duch kelsa — siz qaysi serverda muammo bo'lganini bilmaysiz. Markazlashtirilgan logging tizimi — barcha 10 ta serverning loglarini bitta joyda yig'ib, requestId bo'yicha qidirish imkonini beradi.
8. V8/Node.js darajasida — logging'ning yashirin narxi
Bu — kam odam o'ylaydigan, lekin real performance muammosiga aylanadigan joy.
// XAVFLI — hot path ichida sinxron logging:
function processRequest(req) {
console.log(`So'rov keldi: ${JSON.stringify(req)}`); // MUAMMO
// ...
}
Nega bu muammo?
console.log— Node.js'da sinxron operatsiya. Bu degani — log yozilib bo'lguncha, event loop bloklanadi (Event Loop mavzusini eslang). Agar sekundiga minglab so'rov kelsa, va har biri log yozsa, bu sezilarli sekinlashuv beradi.JSON.stringify(req)—reqobyekti ko'pincha katta, chuqur struktura (HTTP headers, body, va h.k.). Uni har safar stringify qilish — protsessor vaqtini yeydi, va agarreqichida circular reference (o'zini-o'ziga ishora qiluvchi obyekt) bo'lsa —JSON.stringifyxato tashlaydi va dasturni yiqitadi.
To'g'ri yechim — asinxron, tuzilgan logger ishlatish (masalan, pino yoki winston kabi kutubxonalar):
// pino kabi kutubxonalar:
logger.info({ method: req.method, url: req.url }); // faqat kerakli maydonlar
Bunday kutubxonalar ichida:
- Log yozish asinxron navbatga (buffer) qo'yiladi, keyin fonda, event loop'ni bloklamasdan diskka/tarmoqqa yoziladi
- Faqat kerakli maydonlar tanlab olinadi, butun
reqobyekti emas — bu stringify narxini kamaytiradi - Circular reference'lardan avtomatik himoyalangan
9. Muhim muvozanat — "hamma narsani logla" vs "kerak narsani logla"
Yangi boshlovchilar ko'pincha ikki xatoning birini qiladi:
| Xato | Natija |
|---|---|
| Juda kam loglash | Muammo bo'lganda, "nima sodir bo'ldi" tikllab bo'lmaydi |
| Juda ko'p loglash | Log hajmi (va narxi — chunki markazlashtirilgan tizimlar hajm bo'yicha pul oladi) portlab ketadi, haqiqiy muammoni keraksiz shovqin ichidan topish qiyinlashadi |
Amaliy qoida: loglang — qaror qabul qilingan joylarni (masalan, "nega bu so'rov rad etildi"), tashqi tizim bilan gaplashgan joylarni (API chaqiruv, DB so'rov — bular xato berishi mumkin bo'lgan joylar), va kutilmagan holatlarni. Oddiy, "hammasi yaxshi ketyapti" degan har bir qadamni loglash shart emas.
Yakuniy xulosa
- Logging — dasturning "qora qutisi", muammo bo'lganda nima sodir bo'lganini tiklash uchun.
- Strukturaviy (JSON) logging — qidirish va filtrlashni osonlashtiradi.
- Log darajalari (debug/info/warn/error) — nima muhim, nima muhim emasligini ajratadi.
- Parol, karta raqami kabi maxfiy ma'lumot hech qachon logga yozilmasligi kerak.
requestId(correlation ID) — ko'p xizmatli tizimda bitta so'rovni oxirigacha kuzatish imkonini beradi.- Sinxron, katta obyektni stringify qiladigan logging — hot path'da performance muammosiga aylanishi mumkin; asinxron, tuzilgan logger kutubxonalari (pino, winston) shu uchun ishlatiladi.