IlmHamroh
JavaScript Full-stack/30-qism. NestJS29/65-dars17 daqiqa
Mundarija (31)

NestJS logger: o'rnatilgan Logger, ConsoleLogger JSON va nestjs-pino

Qisqacha: Nest'ning o'z logger'i bor: new Logger("Kontekst").log(...) — [Nest] … LOG [Kontekst] xabar ko'rinishida matn chiqaradi. Ishga tushish, marshrutlar va ushlanmagan xatolar haqidagi tizim xabarlarini ham u yozadi. Prodakshnda bitta format kerak — JSON. Buning uchun app.useLogger(...) bilan Nest'ga boshqa logger beriladi: ConsoleLogger({ json: true }) yoki nestjs-pino. bufferLogs: true ishga tushish xabarlarini yangi logger ulangunicha ushlab turadi. Tuzoq: nestjs-pino ning to'liq rejimi ba'zi so'rovlarni (400, statik fayl) umuman loglamaydi.

Bu darsda

  • O'rnatilgan Logger va oltita log darajasini haqiqiy chiqish bilan ishlatasiz.
  • ConsoleLogger({ json: true }) va o'z LoggerService ingizni yozasiz, error imzosidagi tuzoqni bilasiz.
  • bufferLogs va useLogger nima uchun kerakligini tushuntirasiz.
  • nestjs-pino ning ikki rejimini o'lchov bilan solishtirasiz va kanon nega useExisting ni tanlaganini bilasiz.
  • vazifalar-api da Nest tizim loglari bizning pino JSON logimizga o'tadi.

Oldin bilishingiz kerak: Logging asoslari, Pino chuqur, Correlation ID va so'rov kuzatuvi, Middleware Nest'da, Config validatsiyasi va namespace'lar.

O'tgan darsda config to'liq DI ichiga o'tdi va main.ts sakkiz parametrdan qutuldi. Lekin bitta parametr qoldi — nestLogi: ["error", "warn"]. Bu darsda u ham ketadi.

1. Nega bu kerak?

25-qismda vazifalar-api ga strukturali log qo'shgandik: Pino, har qator — JSON, har so'rovda sorovId (Pino chuqur). Nest'ga ko'chgach, stdout'ga ikkinchi "muallif" qo'shildi — Nest'ning o'zi. O'tgan darsdagi PORT=abc chiqishini eslang:

text
[Nest] …   ERROR [ExceptionHandler] ConfigXatosi: Sozlama noto'g'ri:

Shu jarayonning boshqa qatorlari esa JSON:

text
{"daraja":"info","ilova":"vazifalar-api","msg":"vazifalar-api: …"}

Bitta ilova, ikki format. Log yig'uvchi tizim (34-qismda ko'radigan Loki kabi) JSON qatorni maydonlarga ajratadi, matn qatorni esa ajrata olmaydi. Natija: eng muhim xabar — ilova nega yiqilgani — qidiruvda topilmaydi.

O'xshatish: kassa daftari. Kassirlar bir xil jadvalga yozadi: sana, summa, kim. Bir kassir esa erkin matn bilan yozadi: "kechqurun bir oz pul oldim". Oy oxirida hisob yig'ilmaydi. Log — ilovaning kassa daftari: hamma bir formatda yozishi kerak.

2. O'rnatilgan Logger

2.1 Xizmat ichida

Nest'da logger olish uchun DI ham shart emas — Logger klassini o'zingiz yaratasiz:

ts
@Injectable()
class BuyurtmaXizmati {
  private readonly log = new Logger(BuyurtmaXizmati.name);
  yarat(): void {
    this.log.log("buyurtma yaratildi");
    this.log.warn("ombor kam qoldi");
    this.log.error("to'lov rad etildi");
    this.log.debug("narx hisoblandi");
    this.log.verbose("batafsil iz");
  }
}

BuyurtmaXizmati.name — klass nomi satr sifatida ("BuyurtmaXizmati"). U kontekst bo'ladi: har qatorda kvadrat qavsda turadi, log qayerdan kelganini ko'rsatadi. Nom o'zgarsa, kontekst ham o'zi yangilanadi.

Biz demo loyihada sinadik (biz ishga tushirdik: NestJS 12.2.0; jarayon raqami va vaqt … bilan almashtirildi):

text
[Nest] …     LOG [NestFactory] Starting Nest application...
[Nest] …     LOG [InstanceLoader] M dependencies initialized
[Nest] …     LOG [BuyurtmaXizmati] buyurtma yaratildi
[Nest] …    WARN [BuyurtmaXizmati] ombor kam qoldi
[Nest] …   ERROR [BuyurtmaXizmati] to'lov rad etildi
[Nest] …   DEBUG [BuyurtmaXizmati] narx hisoblandi
[Nest] … VERBOSE [BuyurtmaXizmati] batafsil iz

Birinchi ikki qator — bizniki emas. Bular Nest'ning tizim loglari: ilova ko'tarilmoqda, modul tayyor. Ular ham xuddi shu logger orqali chiqadi. Real ilovada ular ko'p: har modul, har marshrut (Mapped {/vazifalar, GET}), ushlanmagan xato (ExceptionHandler).

2.2 Darajalar

Nest'da oltita daraja bor: fatal, error, warn, log, debug, verbose. Ularni NestFactory.create ning logger sozlamasi bilan cheklash mumkin:

ts
NestFactory.createApplicationContext(M, {
  logger: ["error", "warn"],
});
text
[Nest] …    WARN [BuyurtmaXizmati] ombor kam qoldi
[Nest] …   ERROR [BuyurtmaXizmati] to'lov rad etildi

Ishga tushish xabarlari ham yo'qoldi — ular log darajasida. logger: false — umuman jim (testlarda qulay). Pino'dagi darajalar bilan solishtirish:

Nest Pino Ma'nosi
fatal fatal jarayon to'xtaydi
error error amal bajarilmadi
warn warn g'alati, lekin ishlayapti
log info oddiy voqea
debug debug dasturchi uchun
verbose trace eng batafsil

Farq — nomda: Nest'ning log i pino'da info, verbose i — trace. nestjs-pino ularni shunday moslaydi. log → info ni pastdagi loyiha logida o'z ko'zingiz bilan ko'rasiz; verbose → trace — kutubxona hujjati bo'yicha.

Tekshirib ko'ring: Prodakshnda logger: ["error", "warn"] qo'yildi. Ilova ishga tushdimi yoki yo'qligini logdan qanday bilasiz?

Javob

Nest'ning tizim loglaridan — bila olmaysiz: Nest application successfully started — log darajasida, u o'chirilgan. Shuning uchun kanonda main.ts o'zi info darajasida vazifalar-api: http://… qatorini yozadi. Umumiy qoida: "ishga tushdim" xabari doim ko'rinadigan darajada bo'lsin.

3. Logger'ni almashtirish

3.1 ConsoleLogger({ json: true })

Nest 11 dan beri o'rnatilgan logger JSON yoza oladi — kutubxonasiz. Logger nusxasi NestFactory ga beriladi:

ts
NestFactory.createApplicationContext(M, {
  logger: new ConsoleLogger({ json: true }),
});
text
{"level":"log","pid":…,"timestamp":…,"message":"Starting Nest application...","context":"NestFactory"}
{"level":"log","pid":…,"timestamp":…,"message":"M dependencies initialized","context":"InstanceLoader"}
{"level":"log","pid":…,"timestamp":…,"message":"buyurtma yaratildi","context":"BuyurtmaXizmati"}
{"level":"warn","pid":…,"timestamp":…,"message":"ombor kam qoldi","context":"BuyurtmaXizmati"}
{"level":"error","pid":…,"timestamp":…,"message":"to'lov rad etildi","context":"BuyurtmaXizmati"}
{"level":"debug","pid":…,"timestamp":…,"message":"narx hisoblandi","context":"BuyurtmaXizmati"}
{"level":"verbose","pid":…,"timestamp":…,"message":"batafsil iz","context":"BuyurtmaXizmati"}

(pid va timestamp qiymatlarini … bilan almashtirdik; timestamp — epoch millisekund.)

Endi JSON. Lekin bizning pino logimizdan farqli JSON: level — "log" (pino'da "info"), vaqt — timestamp raqami (bizda time ISO satri), xabar — message (bizda msg). Bitta stdout'da ikki xil JSON — yarim yechim. Bundan tashqari bu logger so'rovlarni umuman loglamaydi — faqat siz chaqirgan log(...) va Nest tizim xabarlari.

3.2 O'z LoggerService ingiz

logger sozlamasiga LoggerService interfeysiga mos har qanday obyekt berish mumkin: log, error, warn majburiy, debug, verbose, fatal ixtiyoriy.

ts
class OzLogger implements LoggerService {
  log(m: unknown, k?: string) {
    console.log(`[o'z] INFO ${String(k)}: ${String(m)}`);
  }
  error(m: unknown, k?: string) {
    console.log(`[o'z] XATO ${String(k)}: ${String(m)}`);
  }
  warn(m: unknown, k?: string) {
    console.log(`[o'z] OGOH ${String(k)}: ${String(m)}`);
  }
}
text
[o'z] INFO NestFactory: Starting Nest application...
[o'z] INFO InstanceLoader: M dependencies initialized
[o'z] INFO BuyurtmaXizmati: buyurtma yaratildi
[o'z] OGOH BuyurtmaXizmati: ombor kam qoldi
[o'z] XATO undefined: to'lov rad etildi

Ikki narsaga qarang. Birinchisi: debug va verbose qatorlari yo'q — biz bu metodlarni yozmadik, Nest ularni jim o'tkazib yubordi. Ikkinchisi — tuzoq: XATO undefined. log va warn da ikkinchi argument kontekst edi, error da esa emas. error ning imzosi: error(xabar, stack?, kontekst?) — Nest ikkinchi o'ringa stack qo'yadi (bu yerda bo'sh), kontekst — oxirgi argument. Shuning uchun real LoggerService larda error(message: unknown, ...optionalParams: unknown[]) yoziladi va kontekst optionalParams.at(-1) dan olinadi.

4. bufferLogs va useLogger

Logger'ni NestFactory.create ga nusxa sifatida bersa bo'ladi. Lekin pino logger'imiz DI ichida yaratiladi (LOG provider'i config'ga tayanadi). DI esa create paytida yig'iladi. Tuxum va tovuq: logger'ni olish uchun ilova kerak, ilova ko'tarilayotganda yozilgan xabarlar uchun logger kerak.

Nest'ning yechimi — ikki qadam:

ts
const app = await NestFactory.create(AppModule, {
  bufferLogs: true, // tizim xabarlarini ushlab tur
});
app.useLogger(app.get(Logger)); // endi shu logger orqali chiqar

bufferLogs: true — Nest ishga tushish xabarlarini xotirada yig'adi. useLogger chaqirilganda ular yangi logger orqali chiqadi. Natija: ishga tushish xabarlari ham JSON, ham bizning formatda.

Bir istisno bor — kanon uni o'lchab topgan. Agar ilova useLogger ga yetib kelmasa (fabrika yiqildi), yig'ilgan xabarlar Nest'ning sukut matnli ConsoleLogger iga chiqadi. Biz ham buni ko'rdik: «Loyiha qadami» bo'limida PORT=abc bilan sinaymiz.

5. nestjs-pino: ikki rejim

5.1 To'liq rejim

nestjs-pino — Nest uchun pino ko'prigi. Uning hujjatidagi asosiy ulash:

ts
@Module({
  imports: [
    LoggerModule.forRoot({ pinoHttp: { level: "info" } }),
  ],
})
export class AppModule {}
// main.ts
const app = await NestFactory.create(AppModule, { bufferLogs: true });
app.useLogger(app.get(Logger)); // Logger — nestjs-pino'dan

Bu rejimda paket uch ish qiladi: Nest tizim loglarini pino'ga yo'naltiradi; xizmatlarga PinoLogger beradi; va pino-http ni o'zi ulaydi — so'rov loglari uchun. Uchinchisi — Nest modul middleware'i sifatida (Middleware Nest'da).

5.2 Kanon tajribasi: qaysi so'rov loglandi?

Kanon tajribasi bir xil ilovaga to'rt so'rov yubordi: GET /v (oddiy), POST /v yaroqsiz JSON bilan (400), GET /index.html (statik fayl) va GET /yoq (404). Uch variant solishtirildi. Natija (kanon o'lchovi, IlmHamroh, 2026-10, NestJS 12.2.0; kanon chiqishi o'zgarishsiz):

text
A) nestjs-pino TO'LIQ (pino-http — Nest modul middleware'i)
  bootstrap qatorlari: 7 (birinchisi: {"level":30,"context":"NestFactory","msg":"Starting Nest application..."})
  so'rovlardan keyingi qatorlar:
    GET /v → undefined "xizmat logi (PinoLogger)"
    GET /v → 200 "request completed"
    GET /yoq → 404 "request completed"

B) KANON: pino-http app.use (Nest'dan oldin) + nestjs-pino useExisting
  bootstrap qatorlari: 7 (birinchisi: {"level":30,"context":"NestFactory","msg":"Starting Nest application..."})
  so'rovlardan keyingi qatorlar:
    GET /v → undefined "xizmat logi (PinoLogger)"
    GET /v → 200 "request completed"
    POST /v → 400 "request completed"
    GET /index.html → 200 "request completed"
    GET /yoq → 404 "request completed"

C) ConsoleLogger({ json: true }) — o'rnatilgan
  bootstrap qatorlari: 6 (birinchisi: {"level":"log","pid":16072,"timestamp":1793115874514,"message":"Starting Nest application...","context":"NestF)
  so'rovlardan keyingi qatorlar:
      (ilova) controller logi

Natijani jadvalga yig'amiz:

So'rov A (to'liq) B (kanon) C (JSON Console)
GET /v 200 bor bor yo'q
POST /v 400 yo'q bor yo'q
GET /index.html yo'q bor yo'q
GET /yoq 404 bor bor yo'q

A variantda ikki so'rov izsiz o'tdi. Yaroqsiz JSON — hujum yoki buzuq mijozning eng tipik belgisi. Aynan u logda yo'q.

5.3 Nega yo'qoldi?

Sabab — middleware tartibi. 25-qismdagi zanjirni eslang: so'rov middleware'lardan ketma-ket o'tadi, kimdir javob bersa, keyingilari ishlamaydi (Middleware va request lifecycle).

flowchart TB
  S["so'rov"] --> P["pino-http (app.use) — B"]
  P --> ST["statik fayllar"]
  ST -->|"index.html topildi"| J1["javob 200"]
  ST --> JS["express.json"]
  JS -->|"yaroqsiz JSON"| J2["javob 400"]
  JS --> NM["Nest modul middleware — A"]
  NM --> C["controller"]

A variantda pino-http — Nest modul middleware'i. U faqat so'rov Nest marshrutlariga yetib kelganda ishlaydi. Statik fayl undan oldin javob topdi, yaroqsiz JSON esa express.json da 400 bilan to'xtadi. Ikkalasi pino-http gacha yetmadi. B variantda pino-http — eng boshida, app.use bilan. U har so'rovni ko'radi va javob yopilganda yozadi — kim javob berganidan qat'i nazar.

5.4 useExisting: true

Kanondagi ulash:

ts
LoggerModule.forRootAsync({
  inject: [LOG],
  useFactory: (log: Log) => ({
    pinoHttp: { logger: log },
    useExisting: true,
  }),
}),
  • forRootAsync + inject: [LOG] — o'tgan darsdan oldingi naqsh: nestjs-pino bizning LOG provider'imizdagi pino nusxasini oladi. Yangi logger yaratilmaydi — format, redact, ilova maydoni hammasi o'sha.
  • useExisting: true — "o'z pino-http ingni ulama, so'rov logi allaqachon bor". nestjs-pino faqat Nest tizim loglarini yo'naltiradi. So'rov logini 25-qismdagi sorovLogi() yozadi — app.use bilan, eng boshida.

Natija: B qatori — hamma so'rov loglanadi va Nest tizim xabarlari ham bitta JSON formatda.

Diqqat: Kanon ham nestjs-pino dan foydalanadi — faqat to'liq rejimidan emas. Paketni tashlash shart emas; uning middleware'ini o'zingiz to'g'ri joyga qo'yasiz.

6. Express'da qanday edi, Nest'da qanday

25–27 (Express) Nest (kanon)
So'rov logi pino-http, app.use o'sha — app.use, Nest'dan oldin
Xizmat logi joriyLog(log) o'sha (keyingi darsda — CLS orqali)
Tizim xabarlari yo'q edi nestjs-pino → bizning pino
Ishga tushish xatosi console.error Nest matni + console.error

Express'da tizim xabarlari umuman yo'q edi — Express jim ishga tushadi. Nest esa ko'p gapiradi: biz yurgizgan loyiha logida ishga tushishning o'zi 30 dan ortiq qator (har modul, har marshrut). Prodakshnda bu shovqin: LOG_LEVEL=warn qo'yilsa, ular yo'qoladi, lekin main.ts dagi "ishga tushdim" ham info da. Kanon info ni qoldiradi — marshrutlar ro'yxati deploy'dan keyin "qaysi versiya ishlayapti" savoliga javob beradi.

7. Ko'p uchraydigan xatolar

Belgi Sabab Davosi
Ishga tushish loglari matnda, qolgani JSON bufferLogs yo'q bufferLogs: true + useLogger
400 va statik so'rovlar logda yo'q nestjs-pino to'liq rejimi pino-http — app.use, useExisting: true
XATO undefined: … error ning 2-argumenti — stack ...optionalParams, kontekst — oxirgisi
debug loglari chiqmaydi LoggerService da metod yo'q yoki daraja yuqori metodni yozing, darajani tekshiring
Ikki xil JSON bir stdout'da ConsoleLogger({ json: true }) + pino bitta logger: nestjs-pino
Yiqilishda xato matnli logger ulanmasdan fabrika yiqildi kutilgan; main.ts o'z qisqa xabarini yozadi

8. Mashqlar

Mashqlar kurs/mashqlar/30/29-nestjs-logger/ da.

1-mashq (oson): daraja va joy

To'ldiring:

  • Nest'ning log darajasi pino'da —
  • Pino'da trace ga mos Nest darajasi —
  • logger: ["error", "warn"] da Nest application successfully started chiqadimi? —
  • Yaroqsiz JSON (400) logda bo'lishi uchun pino-http qayerda ulanadi? app. bilan, Nest marshrutlaridan oldin.
Yechim
  • info va verbose — jadvaldagi moslik.
  • yo'q — bu xabar log darajasida.
  • use — app.use(sorovLogi(l)); Nest modul middleware'i 400 dan keyin ishlamaydi.

2-mashq (o'rta): daraja filtri

Brauzerda ishlaydigan loggerYasa(daraja) yozing. U Nest uslubidagi obyekt qaytarsin: log, warn, error, debug, verbose metodlari. Har metod xabarni pino darajasiga moslab (log → info, verbose → trace), faqat chegaradan yuqori yoki teng bo'lsa JSON qilib chiqarsin: {"daraja":"info","context":"…","msg":"…"}. Pino tartibi: trace 10, debug 20, info 30, warn 40, error 50. Ishora: obyekt bo'ylab yurish va JSON.stringify.

Yechim
js
const MOSLIK = {
  verbose: "trace", debug: "debug", log: "info",
  warn: "warn", error: "error",
};
const RAQAM = { trace: 10, debug: 20, info: 30, warn: 40, error: 50 };

function loggerYasa(daraja) {
  const chegara = RAQAM[daraja];
  const logger = {};
  for (const [nest, pinoD] of Object.entries(MOSLIK)) {
    logger[nest] = (msg, context) => {
      if (RAQAM[pinoD] < chegara) return;
      console.log(JSON.stringify({ daraja: pinoD, context, msg }));
    };
  }
  return logger;
}

const l = loggerYasa("info");
l.log("buyurtma yaratildi", "BuyurtmaXizmati");
l.debug("narx hisoblandi", "BuyurtmaXizmati");
l.warn("ombor kam qoldi", "BuyurtmaXizmati");
const t = loggerYasa("trace");
t.verbose("batafsil iz", "BuyurtmaXizmati");

Konsolda:

text
{"daraja":"info","context":"BuyurtmaXizmati","msg":"buyurtma yaratildi"}
{"daraja":"warn","context":"BuyurtmaXizmati","msg":"ombor kam qoldi"}
{"daraja":"trace","context":"BuyurtmaXizmati","msg":"batafsil iz"}

debug qatori info chegarasida chiqmadi. Bu LOG_LEVEL ning ishi: kanonda u config'dan pino'ga beriladi, nestjs-pino esa Nest xabarlarini shu pino orqali o'tkazadi — filtr bitta joyda.

3-mashq (qiyin): bufferLogs modeli

ilovaYarat({ bufer, yiqil }) modelini yozing. Ishga tushish uch xabar yozadi ("Starting Nest application...", "AppModule dependencies initialized", "Nest application successfully started"). bufer: true bo'lsa, xabarlar massivda yig'iladi. yiqil: true bo'lsa, ikkinchi xabardan keyin Error("ConfigXatosi") tashlanadi. Logger ulanishi (useLogger) — muvaffaqiyatli yaratilgandan keyin. Qoida: ulanganda yig'ilganlar JSON logger'ga, yiqilganda — sukut matnli logger'ga chiqsin ([Nest] LOG xabar). bufer: false da har xabar darhol matnli chiqadi.

Yechim
js
const matnli = (m) => console.log(`[Nest] LOG ${m}`);
const json = (m) =>
  console.log(JSON.stringify({ daraja: "info", msg: m }));

function ilovaYarat({ bufer, yiqil }) {
  const yigilgan = [];
  const yoz = (m) => (bufer ? yigilgan.push(m) : matnli(m));
  try {
    yoz("Starting Nest application...");
    yoz("AppModule dependencies initialized");
    if (yiqil) throw new Error("ConfigXatosi");
    yoz("Nest application successfully started");
  } catch (e) {
    yigilgan.forEach(matnli); // useLogger'ga yetmadik
    console.log(`[Nest] ERROR ${e.message}`);
    return null;
  }
  yigilgan.forEach(json); // useLogger: yig'ilganlar yangi logger'ga
  return { useLogger: true };
}

console.log("— bufer, muvaffaqiyat");
ilovaYarat({ bufer: true, yiqil: false });
console.log("— bufer, yiqildi");
ilovaYarat({ bufer: true, yiqil: true });
console.log("— bufersiz");
ilovaYarat({ bufer: false, yiqil: false });

Konsolda:

text
— bufer, muvaffaqiyat
{"daraja":"info","msg":"Starting Nest application..."}
{"daraja":"info","msg":"AppModule dependencies initialized"}
{"daraja":"info","msg":"Nest application successfully started"}
— bufer, yiqildi
[Nest] LOG Starting Nest application...
[Nest] LOG AppModule dependencies initialized
[Nest] ERROR ConfigXatosi
— bufersiz
[Nest] LOG Starting Nest application...
[Nest] LOG AppModule dependencies initialized
[Nest] LOG Nest application successfully started

Ikkinchi holat — loyiha qadamidagi PORT=abc chiqishining modeli: yig'ilgan xabarlar matnda chiqdi, chunki JSON logger hali yaratilmagan edi. Uchinchisi — bufferLogs siz Nest: ishga tushish xabarlari doim sukut logger'da.

9. Loyiha qadami: Nest tizim loglari — bizning pino orqali

Config, log va so'rov konteksti qadamining uchinchi qismi. Commit — keyingi darsda.

9.1 Paket

bash
npm install --save-exact nestjs-pino@5.3.1

pino 10.4.0 va pino-http 11.0.0 — 25-qismdan beri bor.

9.2 app.module.ts

Importlarga ikki qator:

ts
import { LoggerModule } from "nestjs-pino";
import { LOG } from "./tokenlar.ts";
import type { Log } from "./umumiy/log.ts";

imports massivida BogliqliklarModule.forRoot(b) dan keyin — «useExisting: true» bo'limidagi LoggerModule.forRootAsync(...) bloki. LOG provider'i global BogliqliklarModule da — inject: [LOG] uni ko'radi.

9.3 ilova.ts

nestLogi parametri va LogLevel importi o'chadi. Import qo'shiladi: import { Logger } from "nestjs-pino";. Ilova yaratish:

ts
  // bufferLogs — Nest loglari pino Logger ulangunicha yig'iladi
  const app = await NestFactory.create<NestExpressApplication>(
    AppModule.forRoot({
      ombor, config, log, xabarchi, tz, idempotentlikOmbori,
    }),
    { bodyParser: false, bufferLogs: true, abortOnError: false },
  );
  app.useLogger(app.get(Logger));

Logger — nestjs-pino niki, @nestjs/common dagi emas. Nomlar bir xil — import qatoriga qarang. app.get(Logger) — LoggerModule yaratgan, LoggerService interfeysiga mos obyekt.

9.4 main.ts

Oxirgi parametr ham ketadi:

ts
  ishlayotgan = await ishgaTushir({ bogliqliklar: {} });

{} — "hech narsani ustidan yozma, hammasi config'dan".

9.5 Natija: bitta format

npm run build, keyin SAQLASH=xotira node dist/main.js va uch so'rov: oddiy POST, yaroqsiz JSON va /index.html. Biz yurgizdik (biz ishga tushirdik; time maydonini olib tashladik, 34 qatordan boshi va oxiri):

text
{"daraja":"info","ilova":"vazifalar-api","context":"NestFactory","msg":"Starting Nest application..."}
{"daraja":"info","ilova":"vazifalar-api","context":"InstanceLoader","msg":"ConfigHostModule dependencies initialized"}
{"daraja":"info","ilova":"vazifalar-api","context":"InstanceLoader","msg":"ConfigModule dependencies initialized"}
{"daraja":"info","ilova":"vazifalar-api","context":"RouterExplorer","msg":"Mapped {/vazifalar, GET} (version: 1,Neutral) route"}
{"daraja":"info","ilova":"vazifalar-api","context":"NestApplication","msg":"Nest application successfully started"}
{"daraja":"info","ilova":"vazifalar-api","manzil":"http://127.0.0.1:45829","muhit":"development","saqlash":"xotira","msg":"vazifalar-api: http://127.0.0.1:45829"}
{"daraja":"info","ilova":"vazifalar-api","sorovId":"aziz-0001","vazifaId":1,"msg":"vazifa yaratildi"}
{"daraja":"info","ilova":"vazifalar-api","sorovId":"aziz-0001","req":{"method":"POST","url":"/v1/vazifalar","ip":"127.0.0.1","userAgent":"node"},"res":{"status":201},"ms":27,"msg":"POST /v1/vazifalar 201"}
{"daraja":"warn","ilova":"vazifalar-api","sorovId":"aziz-0002","req":{"method":"POST","url":"/v1/vazifalar","ip":"127.0.0.1","userAgent":"node"},"res":{"status":400},"ms":3,"msg":"POST /v1/vazifalar 400"}
{"daraja":"info","ilova":"vazifalar-api","sorovId":"aziz-0003","req":{"method":"GET","url":"/index.html","ip":"127.0.0.1","userAgent":"node"},"res":{"status":200},"ms":3,"msg":"GET /index.html 200"}

Hamma qator — bitta format: daraja, ilova, msg. Nest'ning xabarlarida qo'shimcha context (NestFactory, RouterExplorer). Nest LOG i — "daraja":"info": darajalar jadvalidagi moslik. Yaroqsiz JSON (aziz-0002) va statik fayl (aziz-0003) — logda. Ular kanon tajribasining B qatori.

O'tgan darsda, bu o'zgarishdan oldin, xuddi shu so'rovlarda logda faqat oxirgi to'rt qator bor edi — Nest'ning 30 dan ortiq ishga tushish xabari logger: ["error", "warn"] bilan o'chirilgan edi.

9.6 Yiqilishda — matn

bash
PORT=abc node dist/main.js; echo "exit $?"
text
[Nest] …     LOG [NestFactory] Starting Nest application...
[Nest] …   ERROR [ExceptionHandler] ConfigXatosi: Sozlama noto'g'ri:
✖ butun son bo'lishi kerak (bo'sh qiymat — xato)
  → at PORT
    at configYukla (file:///C:/Users/…/dist/config.js:74:15)
    at InstanceWrapper.metatype (file:///C:/Users/…/dist/bogliqliklar.module.js:24:59)
Sozlama noto'g'ri:
✖ butun son bo'lishi kerak (bo'sh qiymat — xato)
  → at PORT
exit 78

(Jarayon raqami, vaqt, lokal yo'llar qisqartirildi; Nest injektorining sakkiz qatori olib tashlandi.)

Endi birinchi qatorda LOG [NestFactory] Starting… ham bor — bufferLogs uni yig'ib turgan edi. Lekin JSON emas, matn. Sabab: LoggerModule LOG ga, LOG esa CONFIG ga tayanadi — CONFIG fabrikasi yiqildi va pino logger umuman yaratilmadi. useLogger ga navbat kelmadi, yig'ilgan xabarlar sukut logger'ga chiqdi — 3-mashqdagi ikkinchi holat. Bu tuzatib bo'lmaydigan cheklov: logger'ning o'zi config'ga muhtoj. Kanon buni qabul qiladi — main.ts dagi qisqa console.error qatori va exit 78 baribir aniq.

9.7 Tekshiruv

bash
npm run tip && npm run lint && npm test && npm run build

Biz holat nusxasida yurgizdik (Postgres'siz): tip 0, lint 0, build o'tdi. Vitest bir yugurishda 1 failed | 74 passed | 6 skipped berdi — yiqilgani jarayon.test.ts ("unhandledRejection … let it crash"). Yolg'iz yurgizilganda u 3 s da o'tdi, keyingi to'liq yugurishda ham 75 passed | 6 skipped. Bu test bola jarayon ishga tushiradi va 20 s kutadi. Parallel testlar bilan band mashinada bola jarayon kechikadi — kanon ham shuni ko'rgan. Tuzatish — keyingi darsdagi timeout'lar. Sizda ham bir marta yiqilsa — qayta yurgizing. Hali commit qilmang.

10. Real ishda

  • Nest loyihalarida nestjs-pino — eng ko'p ishlatiladigan logger paketi. Uning PinoLogger va @InjectPinoLogger dekoratorini ko'p kodda uchratasiz.
  • Log yig'ish (Loki, ELK, CloudWatch) faqat JSON bilan to'g'ri ishlaydi — matnli [Nest] qatorlari alohida qoida talab qiladi. Bitta format — operatsiya jamoasining birinchi talabi.
  • Middleware tartibi — "nega bu xato logda yo'q?" savolining eng ko'p uchraydigan javobi. Logger zanjirning eng boshida bo'lsin.
  • Intervyu: "Nest'da logger'ni qanday almashtirasiz?", "bufferLogs nima uchun?", "nestjs-pino qaysi so'rovlarni loglamasligi mumkin?".

Xulosa

  • new Logger(Klass.name) — kontekstli log; darajalar: fatal, error, warn, log, debug, verbose.
  • Nest tizim xabarlari ham shu logger orqali; logger: [...] — daraja ro'yxati, false — jim.
  • ConsoleLogger({ json: true }) — kutubxonasiz JSON, lekin pino formatidan farqli va so'rov logisiz.
  • LoggerService.error ning ikkinchi argumenti — stack; kontekst — oxirgi.
  • bufferLogs + useLogger — ishga tushish xabarlari ham yangi logger orqali; fabrika yiqilsa — sukut matn.
  • nestjs-pino to'liq rejimi 400 va statik so'rovlarni loglamaydi; kanon — pino-http app.use bilan + useExisting: true.

Keyingi dars: So'rov konteksti: nestjs-cls — 25-qismdagi o'z AsyncLocalStorage imizni nestjs-cls ga almashtiramiz va loyiha qadamini commit qilamiz.

Manbalar

  • NestJS hujjati — Logger (darajalar, JSON rejimi, bufferLogs, useLogger, LoggerService): https://docs.nestjs.com/techniques/logger
  • nestjs-pino README (forRootAsync, useExisting, darajalar mosligi): https://github.com/iamolegga/nestjs-pino
  • pino-http: https://github.com/pinojs/pino-http
  • Kanon (IlmHamroh, 2026-10-27): config/log/kontekst qadami — LoggerModule.forRootAsync + useExisting, bufferLogs; uch variantli so'rov logi tajribasi (NestJS 12.2.0, nestjs-pino 5.3.1). O'rnatilgan Logger, ConsoleLogger({ json: true }), LoggerService tajribalari, loyihaning ishga tushish logi va PORT=abc chiqishi — biz ishga tushirdik (2026-11-02, NestJS 12.2.0, Node 24.21.0).
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
NestJS logger: o'rnatilgan Logger, ConsoleLogger JSON va nestjs-pino — IlmHamroh