IlmHamroh
JavaScript Full-stack/24-qism. Node.js49/55-dars18 daqiqa
Mundarija (34)

Node.js diagnostika: process.report, trace bayroqlari, diagnostics_channel va perf_hooks

Qisqacha: Prodakshnda debugger ulab bo'lmaydi. Buning o'rniga Node'ning o'zi "qora quti" beradi. Asosiysi — jarayonning JSON hisoboti (process.report): stek, heap, resurslar va muhit. --report-on-fatalerror va --report-uncaught-exception uni qulash paytida o'zi yozadi. --trace-warnings, --trace-deprecation ogohlantirish qayerdan kelganini ko'rsatadi, --trace-gc — GC har ishlaganini. diagnostics_channel kutubxona ichidan hodisalarni tashqariga chiqaradi, perf_hooks esa vaqtni o'lchaydi.

Bu darsda

  • process.report hisobotini olasiz, bo'limlarini o'qiysiz va undagi sir xavfini bilasiz.
  • Qulash paytida hisobotni avtomatik yozdirasiz va Windows'dagi ikki tuzoqni chetlab o'tasiz.
  • Ogohlantirish va eskirish xabarlarini izi bilan ko'rasiz, o'z eskirish ogohlantirishingizni yozasiz.
  • --trace-gc qatorini o'qiysiz.
  • diagnostics_channel bilan kutubxona ichini kuzatasiz va perf_hooks bilan funksiya vaqtini o'lchaysiz.

Oldin bilishingiz kerak: CPU profiling va flamegraph, Memory leak'ni topish, Node'ni debug qilish, Performansni o'lchash.

1. Nega bu kerak?

Node'ni debug qilish darsida kodni to'xtatib, o'zgaruvchilarga qaradingiz. Bu — o'z kompyuteringizda ajoyib. Lekin tasavvur qiling: server tunda soat 3:14 da qulab tushdi. Ertalab qayta ishga tushirilgan, hamma narsa ishlayapti. Nima bo'lgan edi?

Debugger bu yerda yordam bermaydi: qulash allaqachon o'tib ketgan. Kerakli narsa — voqea paytida yozilgan yozuv. Samolyotlardagi "qora quti" kabi: halokatdan keyin u balandlik, tezlik va dvigatel holatini ko'rsatadi.

Node'da shunday bir nechta vosita bor va ularning hammasi o'rnatilgan — paket kerak emas. Ular bir-birini to'ldiradi:

Savol Vosita
Qulash paytida jarayon qanday holatda edi? process.report
Bu ogohlantirish qayerdan? --trace-warnings, --trace-deprecation
GC qanchalik tez-tez va qancha vaqt ishlaydi? --trace-gc
Kutubxona ichida nima bo'lyapti? diagnostics_channel
Qaysi qism qancha vaqt oladi? perf_hooks

2. process.report: jarayonning hisoboti

2.1 Hisobotni olish

Diagnostika hisoboti (diagnostic report) — bitta JSON hujjat: Node versiyasi, operatsion tizim, JS va native stek, heap statistikasi, CPU va xotira sarfi, libuv handle'lari, muhit o'zgaruvchilari. Uni istalgan paytda koddan olsa bo'ladi:

js
const hisobot = process.report.getReport();
console.log(Object.keys(hisobot).join("\n"));
console.log(typeof hisobot.header.nodejsVersion);

Konsolda:

text
header
javascriptStack
javascriptHeap
nativeStack
resourceUsage
uvthreadResourceUsage
libuv
workers
environmentVariables
sharedObjects
string

Har bo'lim nima beradi:

Bo'lim Ichida
header Node versiyasi, OS, CPU'lar, buyruq qatori, vaqt
javascriptStack Xato xabari va JS stek
javascriptHeap Heap hajmi va har maydon (space) bo'yicha
resourceUsage CPU vaqti, maksimal RSS, disk amallari
libuv Ochiq handle'lar: taymerlar, fayllar, soketlar
environmentVariables Hamma muhit o'zgaruvchilari

Kanon tajribasi (t49-diag.txt, Windows) header dan: nodejsVersion: 'v24.21.0', osName: 'Windows_NT', cpus: 16; libuv da 9 handle, JS stekda 4 qator. glibcVersionRuntime maydoni Windows'da yo'q — u faqat Linux'da bo'ladi (hujjat bo'yicha).

Faylga yozish uchun — process.report.writeReport(). U fayl nomini qaytaradi: report.20261023.141233.3108.0.001.json ko'rinishida (sana, vaqt, PID, tartib raqami).

2.2 Sir xavfi

environmentVariables da hamma muhit o'zgaruvchilari bor. Env va sirlar darsidan eslang: DATABASE_URL, JWT_SECRET, API kalitlari aynan shu yerda yashaydi. Hisobotni issue'ga yoki chatga yuklasangiz — sirlar ham ketadi.

Yechim — --report-exclude-env bayrog'i. Biz sinadik: MAXFIY=sir123 o'zgaruvchisi bilan oddiy hisobotda environmentVariables.MAXFIY — sir123, bayroq bilan esa environmentVariables bo'limi umuman yo'q (undefined). Shunga o'xshash --report-exclude-network tarmoq interfeyslari ma'lumotini olib tashlaydi.

Diqqat: Hisobotni birovga yuborishdan oldin uni oching va qidiring: KEY, SECRET, TOKEN, PASSWORD, :// (ulanish satrlari). Kanondagi hisobot ham shu qadamdan o'tgan.

2.3 Qulash paytida avtomatik hisobot

Asl kuch — hisobotni o'zi yozdirish. Ikki bayroq:

  • --report-uncaught-exception — ushlanmagan xato bo'lganda;
  • --report-on-fatalerror — V8 halokatli xatosida (masalan, heap tugaganda).

Biz cheksiz massivli dasturni 32 MB limit bilan ishga tushirdik:

bash
node --max-old-space-size=32 --report-on-fatalerror \
  --report-dir=hisobot ozish.mjs

Birinchi urinishda hisobot yozilmadi:

text
Failed to open Node.js report file: report.20261023.141223.15508.0.001.json directory: hisobot (errno: 2)

Tarjimasi: "hisobot faylini ochib bo'lmadi … papka: hisobot (xato 2)". errno: 2 — "bunday fayl yoki papka yo'q". Node --report-dir papkasini o'zi yaratmaydi. Qulash allaqachon bo'ldi — hisobot esa yo'qoldi. Papkani oldindan yaratgandan keyin:

text
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
Writing Node.js report to file: report.20261023.141233.3108.0.001.json
Node.js report completed

Hisobot (21 KB) ichida header.event — Allocation failed - JavaScript heap out of memory, header.trigger — OOMError. JS stek esa Unavailable. — heap tugaganda JS kodi to'xtagan bo'ladi. Ushlanmagan xato hisobotida (--report-uncaught-exception) trigger — Exception, javascriptStack.message — Error: kurs topilmadi, stek qatorlari bilan.

Uchinchi bayroq — --report-on-signal (signal kelganda hisobot). Node yordam matni o'zi aytadi: Windows'da qo'llab-quvvatlanmaydi. Linux'da kill -USR2 <pid> bilan ishlaydi (hujjat bo'yicha; biz sinamadik).

Tekshirib ko'ring: Siz serverga --report-on-fatalerror --report-dir=/var/log/ilova qo'shdingiz. Bir hafta o'tib server qulab tushdi, lekin papkada hisobot yo'q. Ikki ehtimoliy sababni ayting.

Javob

(1) Papka yo'q edi — Node uni yaratmaydi va faqat stderr'ga Failed to open Node.js report file deb yozadi. (2) Jarayonning shu papkaga yozish huquqi yo'q. Uchinchi variant ham bor: qulash V8 xatosi emas edi (masalan, process.exit(1) yoki ushlanmagan xato) — --report-on-fatalerror faqat halokatli xatoda ishlaydi, ushlanmagan xato uchun --report-uncaught-exception kerak.

3. Ogohlantirishlar va eskirish

3.1 Ogohlantirish qayerdan?

Node ba'zan stderr'ga ogohlantirish yozadi: MaxListenersExceededWarning, ExperimentalWarning, DeprecationWarning. Muammo: xabar nima bo'lganini aytadi, qayerda — yo'q. Katta loyihada bu satr sizning kodingizdanmi yoki 300 ta bog'liqlikning biridanmi?

--trace-warnings har ogohlantirishga stek qo'shadi. Kanon chiqishi (t49-diag.txt):

text
(node:21748) Warning: sinov ogohlantirish
    at [eval]:1:9
    at runScriptInThisContext (node:internal/vm:219:10)

Birinchi at qatori — ogohlantirish chaqirilgan joy. Eskirish uchun alohida bayroq — --trace-deprecation. Biz eskirgan new Buffer(4) ni ishga tushirdik:

text
(node:16184) [DEP0005] DeprecationWarning: Buffer() is deprecated due to security and usability issues. Please use the Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() methods instead.
(Use `node --trace-deprecation ...` to show where the warning was created)

Tarjimasi: "Buffer() xavfsizlik va qulaylik sababli eskirgan; Buffer.alloc(), Buffer.allocUnsafe() yoki Buffer.from() ishlating". DEP0005 — eskirish kodi; Node hujjatida har kodning tarixi va o'rnini bosuvchi API bor. Buffer darsida nega new Buffer xavfli ekanini ko'rgansiz. --trace-deprecation bilan:

text
(node:7412) [DEP0005] DeprecationWarning: Buffer() is deprecated …
    at showFlaggedDeprecation (node:buffer:224:11)
    at new Buffer (node:buffer:307:3)
    at file:///C:/Users/…/eskirgan.mjs:2:11

Uchinchi qator — bizning faylimiz, 2-qator. Endi qidirish shart emas.

Yana ikki bayroq:

  • --throw-deprecation — eskirishni xatoga aylantiradi. Testlarda foydali: CI'da eskirgan API ishlatilsa, test yiqiladi.
  • --no-deprecation — eskirish ogohlantirishlarini o'chiradi. Muammoni yashiradi — faqat ongli qaror bilan.

3.2 O'z eskirish ogohlantirishingiz

Kutubxona yozsangiz (valyuta ham kutubxona — index.ts eksport qiladi), bir kun funksiya nomini o'zgartirasiz. Eski nomni darhol o'chirish — foydalanuvchilar kodini buzish. To'g'ri yo'l: eskisini qoldirib, ogohlantirish berish. node:util dagi deprecate aynan shuni qiladi:

js
import { deprecate } from "node:util";

process.on("warning", (w) => {
  console.log(`${w.name} [${w.code}]: ${w.message}`);
});

const eskiKonvert = deprecate(
  (miqdor) => miqdor * 11903.15,
  "eskiKonvert() o'rniga konvert() ishlating",
  "VALYUTA001",
);

console.log(eskiKonvert(1));
console.log(eskiKonvert(2));

Konsolda:

text
11903.15
23806.3
DeprecationWarning [VALYUTA001]: eskiKonvert() o'rniga konvert() ishlating

Ikki narsaga qarang. Funksiya ikki marta chaqirildi, ogohlantirish — bir marta: bitta kod uchun deprecate bir marta xabar beradi, logni to'ldirmaydi. Va ogohlantirish natijalardan keyin chiqdi — Node uni asinxron yuboradi. Kodli ogohlantirish foydalanuvchiga uni aniq o'chirish imkonini beradi (--disable-warning=VALYUTA001).

Tekshirib ko'ring: CI'da testlar o'tadi, lekin logda 40 ta DeprecationWarning bor. Ularni qanday "majburiy" qilasiz?

Javob

Test buyrug'iga --throw-deprecation qo'shing (masalan NODE_OPTIONS=--throw-deprecation). Endi har eskirish xato bo'ladi va test yiqiladi — jamoa ularni tuzatishga majbur. Bir vaqtda hammasini tuzatib bo'lmasa, avval --trace-deprecation bilan manbalarni toping va ro'yxat tuzing.

4. --trace-gc: GC'ning har qadami

Garbage collection darsida GC'ning ikki turini ko'rgansiz: yosh avlod uchun tez Scavenge va butun heap uchun Mark-Compact. --trace-gc har GC'ni bir qator qilib stdout'ga yozadi. 300 000 obyekt yaratadigan dasturda biz olgan birinchi qator:

text
[4944:0000022EFE5DF000]       27 ms: Scavenge 4.8 5.8-bob -> 4.3 6.8-bob MB, pooled: 0 MB, 0.98 / 0.00 ms  (average mu = 1.000, current mu = 1.000) allocation failure;

Bo'laklab o'qiymiz:

Bo'lak Ma'nosi
[4944:…] PID va izolyat manzili
27 ms Jarayon boshidan o'tgan vaqt
Scavenge GC turi (yosh avlod)
4.8 5.8-bob -> 4.3 6.8-bob MB Ishlatilgan (ajratilgan) heap: oldin → keyin
0.98 / 0.00 ms GC qancha vaqt oldi
allocation failure Sabab: yangi obyektga joy qolmadi

Shu dasturda 60 ms ichida beshta Scavenge bo'ldi, oxirgisi 20.0 → 18.0 MB, 12.98 ms. Kanon o'lchovi (t49-diag.txt) ham xuddi shunday: 5 qator, birinchisi 4.8 dan 4.4 MB ga.

Nima uchun kerak? Memory leak darsidagi "arra tishi"ni raqam bilan ko'rish uchun: har Mark-Compact'dan keyingi "keyin" qiymati o'sib borsa — sizish. Va GC vaqti uchun: Mark-Compact yuzlab millisekund olsa, shu vaqtda server javob bermaydi. average mu (mutator utilization) — vaqtning qancha qismi sizning kodingizga qoldi; 1.000 — GC deyarli xalaqit bermadi.

Maslahat: --trace-gc chiqishi juda ko'p. Uni faylga yo'naltiring (node --trace-gc app.mjs > gc.log) va keyin faqat Mark-Compact qatorlarini qidiring.

5. diagnostics_channel: kutubxona ichiga oyna

5.1 Muammo

Siz HTTP so'rovlarni kuzatmoqchisiz: qaysi manzilga, qachon. fetch Node ichida, uning kodini o'zgartira olmaysiz. Har fetch chaqiruviga console.log qo'yish — kodni iflos qiladi va bog'liqliklardagi fetch larni ko'rmaysiz.

diagnostics_channel (diagnostika kanali) — nomli kanal: kutubxona unga xabar yuboradi (publish), kim xohlasa obuna bo'ladi (subscribe). Obunachi bo'lmasa, yuborish deyarli bepul. O'xshatish: radio. Radiostansiya efirga uzatadi; radiosi yoqilgan odam eshitadi, yoqilmaganlar uchun hech narsa o'zgarmaydi.

5.2 O'z kanalingiz

js
import diagnostics_channel from "node:diagnostics_channel";

// kutubxona tomoni: kanal yaratadi va xabar yuboradi
const kanal = diagnostics_channel.channel("valyuta:kurs");

function kursniOl(kod) {
  if (kanal.hasSubscribers) {
    kanal.publish({ kod, manba: "kesh" });
  }
  return 11903.15;
}

kursniOl("USD"); // obunachi yo'q — hech narsa yuborilmaydi

// ilova tomoni: kerak bo'lganda obuna bo'ladi
function kuzat(xabar, nom) {
  console.log(`${nom}:`, xabar);
}
diagnostics_channel.subscribe("valyuta:kurs", kuzat);
kursniOl("EUR");
diagnostics_channel.unsubscribe("valyuta:kurs", kuzat);
kursniOl("RUB");
console.log("tugadi");

Konsolda:

text
valyuta:kurs: { kod: 'EUR', manba: 'kesh' }
tugadi

Faqat EUR ko'rindi: USD paytida obunachi hali yo'q edi, RUB paytida — endi yo'q. hasSubscribers tekshiruvi xabar obyektini yaratishga ham pul sarflamaslik uchun.

Kanal nomi — kutubxona:hodisa ko'rinishida (kelishuv). Obunachi funksiya ikki argument oladi: xabar va kanal nomi. Bu EventEmitter ga o'xshaydi, lekin farqi bor: kanal global nom bo'yicha topiladi. Kutubxona va ilova bir-birini import qilishi shart emas.

5.3 Node'ning o'z kanallari

Node'ning ichki modullari ham kanallarga yozadi. fetch ni amalga oshiradigan undici — undici:request:create va boshqalar; http, net, child_process, worker_threads — o'z kanallari bilan (Node hujjatida ro'yxat bor). Biz fetch ni kuzatdik:

js
import diagnostics_channel from "node:diagnostics_channel";

const KANAL = "undici:request:create";
diagnostics_channel.subscribe(KANAL, ({ request }) => {
  const { method, origin, path } = request;
  console.log("so'rov:", method, origin + path);
});

try {
  await fetch("http://127.0.0.1:59999/kurs/USD");
} catch (xato) {
  console.log("xato:", xato.cause.code);
}

Biz ishga tushirdik (59999 portida hech narsa yo'q edi):

text
so'rov: GET http://127.0.0.1:59999/kurs/USD
xato: ECONNREFUSED

So'rov yaratilgani ulanishdan oldin ko'rindi. Biz fetch kodiga tegmadik. nocheck — natija tarmoqqa bog'liq: kompyuteringizda shu portda biror dastur bo'lsa, javob boshqacha bo'ladi. Built-in fetch darsidagi "bad port" tuzog'ini eslang: :9 port fetch uchun bloklangan.

Aynan shu mexanizm ustida APM vositalari (OpenTelemetry, Sentry, Datadog) ishlaydi: ular kodingizni o'zgartirmasdan har so'rov va so'rovlar vaqtini yig'adi.

5.4 Boshlanish, tugash va xato: tracingChannel

Bitta amalning boshlanishi, tugashi va xatosini kuzatish uchun tracingChannel bor — u bir nechta kanalni (start, end, error …) bitta nom ostida boshqaradi:

js
import diagnostics_channel from "node:diagnostics_channel";

const iz = diagnostics_channel.tracingChannel("valyuta:sorov");
iz.subscribe({
  start: (x) => console.log("start", x.kod),
  end: (x) => console.log("end", x.kod, x.result),
  error: (x) => console.log("error", x.kod, x.error.message),
});

function kurs(kod) {
  if (kod === "XYZ") throw new Error("noma'lum");
  return 1;
}

iz.traceSync(kurs, { kod: "USD" }, null, "USD");
try {
  iz.traceSync(kurs, { kod: "XYZ" }, null, "XYZ");
} catch {
  // xatoni chaqiruvchi o'zi hal qiladi
}

Konsolda:

text
start USD
end USD 1
start XYZ
error XYZ noma'lum
end XYZ undefined

traceSync(funksiya, kontekst, this, ...argumentlar) — funksiyani chaqiradi va kontekst obyektiga result yoki error qo'shadi. Xato bo'lsa ham end keladi — "amal tugadi, muvaffaqiyatsiz". Asinxron funksiya uchun tracePromise bor.

Tekshirib ko'ring: diagnostics_channel va oddiy console.log ning asosiy farqi nima?

Javob

console.log har doim yozadi va kodni o'zgartirishni talab qiladi. Kanal esa faqat obunachi bo'lsa ishlaydi (aks holda deyarli bepul) va kuzatuvchi kodni kutubxonaga emas, o'z ilovasiga yozadi. Kutubxona muallifi bir marta kanal qo'yadi — har foydalanuvchi o'zi xohlagan narsani yig'adi.

6. perf_hooks: vaqtni o'lchash

6.1 mark va measure

Performansni o'lchash darsida performance.now() va benchmark qoidalarini ko'rgansiz. User Timing API (performance.mark, performance.measure) brauzerda ham, Node'da ham bir xil:

js
performance.mark("boshi");
const kurslar = Array.from({ length: 50_000 }, (_, i) => i % 97);
kurslar.sort((a, b) => a - b);
performance.mark("oxiri");
const o = performance.measure("saralash", "boshi", "oxiri");
console.log(o.name, o.entryType, o.duration >= 0);
console.log(performance.getEntriesByType("mark").map((m) => m.name));

Konsolda:

text
saralash measure true
[ 'boshi', 'oxiri' ]

Bu blok saytda ham ishlaydi — «Ishga tushir» bilan brauzerda sinang. Davomiylikning o'zini chiqarmadik: u har safar boshqacha. mark — vaqt belgisi, measure — ikki belgi orasidagi masofa. Afzalligi performance.now() ayirmasidan: nomlangan yozuvlar yig'iladi va ularni bitta joydan o'qish mumkin.

6.2 PerformanceObserver va timerify

Node'da node:perf_hooks qo'shimcha beradi. PerformanceObserver — yangi yozuv paydo bo'lganda chaqiriladi. performance.timerify(f) — funksiyani o'raydi: har chaqiruvi avtomatik function turidagi yozuv bo'ladi.

js
import { performance, PerformanceObserver } from "node:perf_hooks";

function kurslarniSarala(n) {
  const kurslar = Array.from({ length: n }, (_, i) => (i * 7919) % n);
  return kurslar.sort((a, b) => a - b);
}

const kuzatuvchi = new PerformanceObserver((royxat) => {
  for (const y of royxat.getEntries()) {
    const ms = y.duration.toFixed(1);
    console.log(`${y.entryType} ${y.name}: ${ms} ms`);
  }
});
kuzatuvchi.observe({ entryTypes: ["measure", "function"] });

performance.mark("boshi");
kurslarniSarala(200_000);
performance.mark("oxiri");
performance.measure("saralash", "boshi", "oxiri");

const olchanadigan = performance.timerify(kurslarniSarala);
olchanadigan(100_000);
olchanadigan(400_000);

Biz ikki marta ishga tushirdik (Node 24.21.0, i5-12500H):

text
measure saralash: 60.3 ms
function kurslarniSarala: 30.6 ms
function kurslarniSarala: 143.1 ms

Ikkinchi safar: 58.6, 29.4, 127.9 ms. Raqamlar o'zgaradi — shuning uchun nocheck. Lekin nisbat barqaror: 4 baravar ko'p ma'lumot — ~4.5 baravar ko'p vaqt (saralash n·log n).

perf_hooks da yana monitorEventLoopDelay bor — event loop kechikishini o'lchaydi. Uni Event loop'ni bloklash darsida ishlatgansiz.

7. Qaysi vosita qachon

flowchart TD
  A["Muammo bor"] --> B{"Jarayon qulaydimi?"}
  B -- "ha" --> C["--report-on-fatalerror va --report-uncaught-exception"]
  B -- "yo'q" --> D{"Nima noto'g'ri?"}
  D -- "xotira o'sadi" --> E["--trace-gc, heap snapshot"]
  D -- "sekin" --> F["perf_hooks, --cpu-prof"]
  D -- "noma'lum ogohlantirish" --> G["--trace-warnings"]
  D -- "kutubxona ichi" --> H["diagnostics_channel"]

Nimaga qarang: birinchi savol — "qulaydimi". Qulasa, qolgan vositalar kech qoladi — hisobot bayroqlari oldindan yoqilgan bo'lishi kerak. Qolgan hollarda belgi bo'yicha tanlaysiz. CPU profiling va heap snapshot — oldingi ikki darsda.

8. CLI qadami: holat yo'q — tajriba

valyuta da yangi kod yo'q. U allaqachon eng kerakli diagnostikaga ega: util moduli darsida qo'shilgan NODE_DEBUG=valyuta. Biz yakuniy holatda ishga tushirdik (oflayn rejim):

text
VALYUTA 7304: so'rov { kesh: '…/kesh', api: undefined, sana: undefined, olish: { kutishMs: undefined, signal: AbortSignal { aborted: false }, urinishdan: [Function: urinishdan] }, offline: true, yangila: false }
VALYUTA 7304: manba fixture, 74 kurs
Ogohlantirish: offline rejim — saqlangan namuna kurslar (fixtures/) ishlatildi
2026-10-23 holatiga (fixture)
USD    1    11 903.15   -62.36  AQSH dollari

7304 — PID. Debug qatorlari stderr'ga ketadi, natija stdout'da toza qoladi.

Nega process.report va kanallar kirmadi? CLI ~100 ms yashaydi va xato bo'lsa o'zi aniq xabar va exit kod beradi (process obyekti darsidagi 0/1/2/130). Qulash hisoboti uzoq yashaydigan server uchun. Kanon tajribasi (t49-diag.txt) bu vositalarni alohida sinadi: hisobot bo'limlari, --trace-gc 5 qator, --trace-warnings stek bilan. Commit yo'q.

9. Ko'p uchraydigan xatolar

9.1 --report-dir papkasi yo'q

text
Failed to open Node.js report file: report.… directory: hisobot (errno: 2)

Node papka yaratmaydi. Ishga tushirish skriptida oldindan yarating (mkdir -p) va yozish huquqini tekshiring. Eng yomoni — bu xabar faqat qulash paytida chiqadi, ya'ni kech.

9.2 Hisobotni sirlar bilan ulashish

environmentVariables bo'limi — sirlar ro'yxati. Prodakshnda --report-exclude-env, ulashishdan oldin qidiruv.

9.3 Ogohlantirishni o'chirib qo'yish

--no-warnings yoki --no-deprecation "bezovta qiladi" deb qo'shiladi va keyin muhim xabar ham ko'rinmaydi. Aniq bittasini o'chirish kerak bo'lsa — --disable-warning=DEP0005 (kod bilan).

9.4 --report-on-signal Windows'da

Node yordam matni: Windows'da qo'llab-quvvatlanmaydi. Windows serverda hisobotni koddan (writeReport()) yoki xato bayroqlari bilan oling.

9.5 Bir martalik o'lchovga ishonish

timerify yoki measure bir marta 30 ms ko'rsatdi — bu raqam emas, taxmin. Biz ikki marta o'lchaganda 30.6 va 29.4 ms chiqdi. Qaror uchun bir necha o'lchov va mediana (Performansni o'lchash).

10. Mashqlar

Mashqlar kurs/mashqlar/24/49-diagnostika/ da.

1-mashq (oson): bo'sh joylarni to'ldiring

  • Hisobotni koddan olish: process.report.()
  • Heap tugaganda hisobot: --report-on-
  • Hisobotdan muhit o'zgaruvchilarini olib tashlash: --report-exclude-
  • Eskirish ogohlantirishi qayerdan kelganini ko'rish: --trace-
  • Funksiya vaqtini avtomatik o'lchash: performance.(f)
Yechim
  • getReport — JSON obyekt; writeReport() — faylga.
  • fatalerror — --report-dir papkasi oldindan bo'lishi shart.
  • env — environmentVariables bo'limi yo'qoladi.
  • deprecation — stek bilan; xatoga aylantirish — --throw-deprecation.
  • timerify — function turidagi yozuvlar PerformanceObserver ga keladi.

2-mashq (o'rta): hisobot xulosasi

hisobotXulosasi(r) funksiyasini yozing. U hisobot obyektidan qisqa xulosa qaytarsin: hodisa (header.event), sabab (header.trigger), heap ishlatilgani MB'da (javascriptHeap.usedMemory, bir xona aniqlikda) va muhit o'zgaruvchilaridan faqat nomlari sirga o'xshaganlari (KEY, SECRET, TOKEN, PASSWORD qatnashgan). Qiymatlarni hech qachon chiqarmang. Quyidagi namuna bilan sinang. Yordam: Object.keys va /KEY|SECRET|TOKEN|PASSWORD/i.test(nom) (RegExp asoslari).

js
const namuna = {
  header: { event: "Exception", trigger: "Exception" },
  javascriptHeap: { usedMemory: 4923984 },
  environmentVariables: {
    PATH: "C:/Windows",
    JWT_SECRET: "juda-maxfiy",
    VALYUTA_OFFLINE: "1",
    NPM_TOKEN: "npm_abc",
  },
};
Yechim
js
function hisobotXulosasi(r) {
  const env = r.environmentVariables ?? {};
  const sirlar = Object.keys(env).filter((nom) =>
    /KEY|SECRET|TOKEN|PASSWORD/i.test(nom),
  );
  const mb = r.javascriptHeap.usedMemory / 2 ** 20;
  return [
    `hodisa: ${r.header.event} (${r.header.trigger})`,
    `heap: ${mb.toFixed(1)} MB`,
    sirlar.length
      ? `DIQQAT, sirga o'xshash: ${sirlar.join(", ")}`
      : "sirga o'xshash o'zgaruvchi yo'q",
  ].join("\n");
}

const namuna = {
  header: { event: "Exception", trigger: "Exception" },
  javascriptHeap: { usedMemory: 4923984 },
  environmentVariables: {
    PATH: "C:/Windows",
    JWT_SECRET: "juda-maxfiy",
    VALYUTA_OFFLINE: "1",
    NPM_TOKEN: "npm_abc",
  },
};
console.log(hisobotXulosasi(namuna));
const envsiz = { ...namuna, environmentVariables: undefined };
console.log(hisobotXulosasi(envsiz));

Konsolda:

text
hodisa: Exception (Exception)
heap: 4.7 MB
DIQQAT, sirga o'xshash: JWT_SECRET, NPM_TOKEN
hodisa: Exception (Exception)
heap: 4.7 MB
sirga o'xshash o'zgaruvchi yo'q

Ikkinchi chaqiruv --report-exclude-env bilan olingan hisobotga teng: bo'lim yo'q, ?? {} buni ko'taradi. Bu funksiya ulashishdan oldingi tekshiruvni avtomatlashtiradi — faqat nomlarni ko'rsatadi, qiymatlarni emas.

3-mashq (qiyin): kanalli kutubxona

kursniOl(kod) asinxron funksiyasini yozing: 10 ms kutadi (new Promise((r) => setTimeout(r, 10))), XYZ uchun Error("noma'lum valyuta") tashlaydi, aks holda { kod, kurs: 11903.15 } qaytaradi. Uni tracingChannel("valyuta:kurs") ning tracePromise metodi bilan o'rang. Ilova tomonida asyncEnd va error hodisalariga obuna bo'lib, ok USD / xato XYZ: noma'lum valyuta deb chiqaring. USD va XYZ ni ketma-ket chaqiring (ikkinchisini try/catch bilan). Yordam: tracePromise(fn, kontekst, this, ...arg) — traceSync ning va'dali sherigi; natija kontekst.result da.

Yechim
js
import diagnostics_channel from "node:diagnostics_channel";

const iz = diagnostics_channel.tracingChannel("valyuta:kurs");

async function kursniOl(kod) {
  await new Promise((r) => setTimeout(r, 10));
  if (kod === "XYZ") throw new Error("noma'lum valyuta");
  return { kod, kurs: 11903.15 };
}
const kuzatilgan = (kod) =>
  iz.tracePromise(kursniOl, { kod }, null, kod);

iz.subscribe({
  asyncEnd: (x) => {
    if (!x.error) console.log("ok", x.result.kod);
  },
  error: (x) => console.log(`xato ${x.kod}: ${x.error.message}`),
});

await kuzatilgan("USD");
try {
  await kuzatilgan("XYZ");
} catch {
  console.log("chaqiruvchi ham xatoni oldi");
}

Konsolda:

text
ok USD
xato XYZ: noma'lum valyuta
chaqiruvchi ham xatoni oldi

Xato bo'lganda ham asyncEnd keladi — shuning uchun unda x.error ni tekshirdik. Kanal xatoni "yutib yubormaydi": chaqiruvchi uni baribir oladi. Kuzatuv faqat qaraydi, oqimni o'zgartirmaydi — diagnostika vositasidan aynan shu talab qilinadi.

4-mashq: CLI qadami — valyuta ning eskirish ogohlantirishi

Loyihangizda tajriba qiling (commit qilmang): src/index.ts ga eskiKonvert nomli eksport qo'shing — u konvert ni deprecate bilan o'rasin (kod VALYUTA001). Kichik skriptda import { eskiKonvert } from "./src/index.ts" qilib ikki marta chaqiring. Keyin uni --trace-deprecation va --throw-deprecation bilan ishga tushiring va chiqishlarni solishtiring.

Yechim

Kutiladigan manzara (darsdagi deprecate blokidagidek): oddiy ishga tushirishda ogohlantirish bir marta, (node:PID) [VALYUTA001] DeprecationWarning: … ko'rinishida; --trace-deprecation bilan uning ostida stek, bitta qatori sizning skriptingizga ishora qiladi; --throw-deprecation bilan DeprecationWarning xato sifatida tashlanadi va jarayon 1 bilan tugaydi. Biz sinaganda --throw-deprecation da ham ikkala natija avval chiqdi — ogohlantirish asinxron, xato undan keyin keladi. Tajribadan keyin o'zgarishni qaytaring: valyuta da eskirgan API yo'q.

11. Real ishda

  • Prodakshn sozlamasi: ko'p jamoalar servisni --report-on-fatalerror --report-uncaught-exception --report-exclude-env --report-dir=… bilan ishga tushiradi. Qulashdan keyin hisobot — birinchi qarash joyi.
  • OpenTelemetry: kuzatuv standarti. Uning Node instrumentatsiyalari diagnostics_channel ga obuna bo'lib, so'rovlar va baza chaqiruvlarini kodga tegmasdan yig'adi. Backend qismlarida loglar va kuzatuv mavzusida qaytamiz.
  • Kutubxona mualliflari: Fastify, undici, pg kabi paketlar o'z kanallarini e'lon qiladi. O'z kutubxonangizda ham kanal qo'yish — foydalanuvchilarga katta yordam.
  • Intervyu: "Prodakshnda debugger'siz nosozlikni qanday tahlil qilasiz?" — hisobot, loglar, trace bayroqlari, profil va heap snapshot, va ularni qachon yoqish kerakligi.

Xulosa

  • process.report — jarayonning JSON hisoboti; --report-on-fatalerror, --report-uncaught-exception uni qulash paytida yozadi.
  • --report-dir papkasi oldindan bo'lishi kerak; --report-on-signal Windows'da yo'q; sirlar uchun --report-exclude-env.
  • --trace-warnings va --trace-deprecation ogohlantirish manbasini ko'rsatadi; util.deprecate — o'z eskirish ogohlantirishingiz (bir marta, kod bilan).
  • --trace-gc qatori: GC turi, heap oldin → keyin, davomiylik va sabab.
  • diagnostics_channel — obunachi bo'lmasa bepul kuzatuv kanali; tracingChannel — start/end/error.
  • perf_hooks: mark/measure (brauzerda ham), PerformanceObserver, timerify.

Keyingi dars: Node'da CLI dastur anatomiyasi — shebang, bin, argumentlar, stdout va stderr, exit kodlar va quvurlar: valyuta misolida hamma qism bir joyda.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Node.js diagnostika: process.report, trace bayroqlari, diagnosticschannel va perfhooks — IlmHamroh