Bu darsda nima bor
1–4-qismlar Observability’ni noldan quradi: nega kerak, uch ustun (logs/metrics/traces), har birining o‘rni va NestJS implementatsiya (strukturalangan log, Prometheus, correlation ID). 5–6-qismlar — distributed tracing (OpenTelemetry) va metrikani tizimli yig‘ish (RED/USE, SLI/SLO, alerting). 7-qism vositalar va amaliy qoidalar.
Nega kerak — taqsimlangan debug
Oddiy o‘xshatish: bitta xonada nimadir buzilsa, kirib ko‘rasiz. Lekin 50 xonali binoda, qorong‘ida, "biror joyda suv oqyapti" desa — har xonaga kirib tekshirib bo‘lmaydi. Sizga har xonadagi datchiklar, kameralar va suvning yo‘lini ko‘rsatuvchi xarita kerak.
Monolitda debug oson: bitta jarayon, bitta log, kirib grep qilasan. Lekin biz qurgan taqsimlangan tizimda (mikroservis — 1-mavzu) bitta so‘rov 5–6 xizmatdan o‘tadi.
Foydalanuvchi "checkout sekin ishlayapti" deydi. Lekin so‘rov Gateway → Auth → Katalog → Buyurtma → To‘lov → Bildirishnoma’dan o‘tadi. Qayerda sekinlashdi? Qaysi xizmat xato berdi? Har biriga alohida SSH qilib grep qilib bo‘lmaydi — bu imkonsiz.
Observability (kuzatuvchanlik) — tizimning tashqi chiqishlaridan (log, metrika, trace) uning ichki holatini tushunish qobiliyati. Bu shunchaki "monitoring" emas: monitoring oldindan bilingan muammolarni kuzatadi; observability esa oldindan bilinmagan savollarga javob berishga imkon beradi ("nega aynan shu foydalanuvchi so‘rovi sekin?").
Monitoring: "CPU 80%dan oshdimi?" — oldindan tayyorlangan savollar (known-unknowns). Observability: "nega seshanba kuni faqat mobil foydalanuvchilar uchun to‘lov sekinlashdi?" — yangi, kutilmagan savollar (unknown-unknowns). Taqsimlangan tizimda ikkinchisi hayotiy.
Asosiy g‘oya — 3 ustun
Observability uch "ustun"ga tayanadi — har biri boshqa savolga javob beradi:
- Logs (loglar): alohida hodisalar — "aynan shu lahzada nima bo‘ldi" (xato, muhim voqea). Diskret, batafsil.
- Metrics (metrikalar): vaqt bo‘yicha yig‘ilgan raqamlar — "qancha so‘rov, qancha xato, qanday kechikish". Arzon, dashboard va alert uchun.
- Traces (izlar): bitta so‘rovning boshidan oxirigacha yo‘li — "vaqt qayerda ketdi, qaysi xizmat muammoli". Taqsimlangan tizim uchun hal qiluvchi.
Metrikalar muammo borligini ko‘rsatadi ("xato darajasi oshdi"). Trace qayerdaligini topadi ("To‘lov xizmatida"). Log nima ekanligini aytadi ("DB ulanish timeout"). Uchtasi birga — to‘liq manzara.
Logs, Metrics, Traces — qachon
structured loggingHar ustunning o‘z o‘rni bor — ularni to‘g‘ri ishlatish muhim:
| Logs | Metrics | Traces | |
|---|---|---|---|
| Nima | Alohida hodisalar | Yig‘ilgan sonlar | Bitta so‘rov yo‘li |
| Savol | "Nima bo‘ldi?" | "Qancha / qanday tendensiya?" | "Vaqt qayerda ketdi?" |
| Hajm/narx | Katta (har hodisa) | Kichik (arzon) | O‘rta (sampling bilan) |
| Ishlatilishi | Debug, forensik | Dashboard, alert | Kechikish tahlili |
Strukturalangan log — eng muhim odat
console.log("Order 123 created for user 45") — bu matnni keyin filtrlash, qidirish qiyin. Millionlab qatorda "user 45 ning barcha xatolari"ni topib bo‘lmaydi.
Log JSON obyekt sifatida yozilsa — maydonlar bo‘yicha qidiriladi, filtrlanadi, agregatlanadi: { action: "order.created", userId: 45, orderId: 123, durationMs: 42 }. Loki/ELK’da userId=45 bo‘yicha bir zumda topasan.
NestJS implementatsiya
pino · prom-client · correlationNestJS’da uch ustunni amalga oshiramiz: strukturalangan log, Prometheus metrika va (keyingi bo‘limda) tracing.
1 · Correlation ID — hammani bog‘lovchi ip
// Correlation ID: har so'rovga noyob ID beriladi va servislar bo'ylab uzatiladi
@Injectable()
export class CorrelationMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const id = (req.headers["x-correlation-id"] as string) ?? randomUUID();
req["correlationId"] = id;
res.setHeader("x-correlation-id", id); // javobda ham qaytar
next();
}
}
2 · Strukturalangan log (nestjs-pino)
// Strukturalangan (JSON) log — nestjs-pino. correlationId bilan bog'lanadi
this.logger.info(
{
correlationId: req.correlationId,
userId: user.id,
action: "order.created",
orderId: order.id,
durationMs: 42,
},
"Order created",
);
// -> Loki/ELK'da correlationId bo'yicha butun so'rovning barcha loglarini topasan
3 · Prometheus metrika
// Metrika: har so'rov davomiyligini o'lchaymiz (prom-client)
const httpDuration = new Histogram({
name: "http_request_duration_seconds",
help: "HTTP request duration",
labelNames: ["method", "route", "status"], // kam kardinallik!
});
@Injectable()
export class MetricsInterceptor implements NestInterceptor {
intercept(ctx: ExecutionContext, next: CallHandler) {
const end = httpDuration.startTimer();
const req = ctx.switchToHttp().getRequest();
return next.handle().pipe(
tap(() => end({ method: req.method, route: req.route?.path, status: 200 })),
);
}
}
// GET /metrics -> Prometheus scrape qiladi -> Grafana dashboard
Metrika label’lariga kam turli qiymatli narsalarni qo‘y (method, route, status). Hech qachon userId yoki orderId kabi yuqori kardinalli qiymatni label qilma — Prometheus xotirasi portlaydi. Bunday narsalar log/trace’da bo‘lsin.
Distributed tracing va correlation ID
trace ID · OpenTelemetryTaqsimlangan tizim uchun eng qimmatli qurol — distributed tracing: bitta so‘rovning barcha xizmatlar bo‘ylab yo‘lini bir butun sifatida ko‘rish.
Qanday ishlaydi
Gateway (8-mavzu) so‘rovga trace ID beradi. Bu ID har xizmatga header orqali (W3C traceparent) uzatiladi. Har xizmat o‘z ishini span sifatida qo‘shadi. Natijada — so‘rovning to‘liq "sharshara" (waterfall) ko‘rinishi, har bosqichning vaqti bilan:
Buni qo‘lda yozmaysan — OpenTelemetry (OTel) standarti avtomatik qiladi: HTTP, Prisma, Redis chaqiruvlarini avtomatik instrument qilib, trace ID’ni servislar bo‘ylab tarqatadi:
// tracing.ts — ilova boshida ishga tushadi (OpenTelemetry)
const sdk = new NodeSDK({
traceExporter: new OTLPTraceExporter({ url: "http://jaeger:4318/v1/traces" }),
instrumentations: [getNodeAutoInstrumentations()], // HTTP, Prisma, Redis avtomatik
});
sdk.start();
// endi har so'rov trace ID oladi va span'lar servislar bo'ylab avtomatik tarqaladi
Trace ID (yoki correlation ID)ni har logga ham qo‘shsang — bitta so‘rov bo‘yicha trace’dagi sekin bosqichni ko‘rib, o‘sha bosqichning aniq log’iga o‘tasan. Uch ustun shunday bog‘lanadi.
RED/USE, SLI/SLO, alerting
golden signals · SLOMetrikalarni tasodifan emas, tizimli yig‘ish kerak. Buning uchun tayyor "usullar" bor — nimani o‘lchashni aytadi.
RED va USE usullari
| Usul | Nima uchun | Nimani o‘lchaydi |
|---|---|---|
| RED | Xizmatlar (so‘rov-asosli) | Rate (tezlik), Errors (xatolar), Duration (davomiylik) |
| USE | Resurslar (CPU, disk) | Utilization, Saturation, Errors |
Four golden signals (Google SRE): latency (kechikish), traffic (yuk), errors (xatolar), saturation (to‘lganlik). Bu to‘rttasini kuzatsang — tizim sog‘lig‘ining 90%ini ko‘rasan.
SLI, SLO, SLA
- SLI (indicator): o‘lchanadigan ko‘rsatkich — "so‘rovlarning 99%i 200ms’dan tez".
- SLO (objective): ichki maqsad — "99.9% so‘rov muvaffaqiyatli bo‘lsin".
- SLA (agreement): mijoz bilan rasmiy kelishuv (buzilsa — jarima/kompensatsiya).
Alert qo‘yishda: alomatga qo‘y ("foydalanuvchilar uchun kechikish 1s’dan oshdi"), sababga emas ("CPU 80%"). Chunki CPU yuqori bo‘lib, foydalanuvchi hech narsa sezmasligi mumkin — bu behuda alert. Foydalanuvchi og‘rig‘iga alert qo‘y. Alert fatigue (juda ko‘p behuda alert)dan qoch — aks holda muhimini o‘tkazib yuborasan.
Vositalar va amaliy qoidalar
Observability — incidentdan keyin emas, birinchi kundan qo‘yiladi (muammo chiqganda tayyor bo‘lishi kerak).
1. Uch ustunni birga qur: Prometheus + Grafana (metrika), Loki yoki ELK (log), Jaeger yoki Tempo (trace). OpenTelemetry — hammasini birlashtiruvchi ochiq standart (bitta instrumentatsiya, istalgan backend).
2. Correlation/trace ID’ni hamma joyda uzat — u uch ustunni bog‘laydi.
3. Strukturalangan log yoz (JSON), lekin ortiqcha log qilma (narx va shovqin — muhimlarini ko‘mib yuboradi).
4. Alert’ni alomatga (foydalanuvchi og‘rig‘i, SLO buzilishi) qo‘y, sababga emas.
5. Metrika kardinalligiga ehtiyot bo‘l — yuqori kardinalli label’lar Prometheus’ni cho‘ktiradi.
Boshlang‘ich uchun minimal to‘plam: strukturalangan log + correlation ID + asosiy RED metrikalari + golden signal alertlari. Tizim o‘sgan sari — distributed tracing (OTel) va SLO qo‘shasan. Hammasini birdan emas, bosqichma-bosqich.
Eslab qolish kerak bo‘lgan 5 jumla
- Observability = tizim chiqishlaridan uning ichki holatini tushunish. Taqsimlangan tizimda hayotiy (so‘rov ko‘p xizmatdan o‘tadi). Monitoring (known) ≠ observability (unknown savollar).
- Uch ustun: Logs (nima bo‘ldi — hodisalar), Metrics (qancha — yig‘ilgan sonlar), Traces (vaqt qayerda ketdi — so‘rov yo‘li).
- Log strukturalangan (JSON) bo‘lsin (qidiriladi); metrika kam kardinalli (kardinallikka ehtiyot); trace bitta so‘rovni servislar bo‘ylab ko‘rsatadi.
- Distributed tracing — trace ID gateway’da beriladi, header (W3C traceparent) orqali tarqaladi. OpenTelemetry avtomatik qiladi. Correlation ID uch ustunni bog‘laydi.
- Metrikani tizimli yig‘: RED (xizmat), USE (resurs), golden signals. SLI/SLO belgila; alert’ni alomatga (sababga emas) qo‘y.
Bu mavzuning Deep/Senior qatlami (OpenTelemetry collector/pipeline, sampling — head vs tail, context propagation ichki mexanikasi, kardinallik va metrika dizayni, SLO/error budget/burn-rate alerting, exemplars — metrika↔trace bog‘lash, log’ni masshtabda, continuous profiling) kerak bo‘lsa — ayting.
Yoki keyingi mavzu: “13-mavzu: Distributed Transactions” — taqsimlangan tizimda tranzaksiya (Saga).