Request Logging & Correlation IDs
So'rovlarni loglash va correlation ID'lar
Bemorga kasalxonaga kelganda BILAKUZUK (wristband) taqib qo'yishadi — undagi RAQAM orqali laboratoriya, rentgen, dorixona — HAR BIR bo'lim bir xil BEMORNING ma'lumotlarini bir-biriga ULAY oladi, garchi ular BUTUNLAY boshqa xonalarda ishlasa ham. Correlation ID — API'da xuddi shu "bilakuzuk": har bir so'rovga BIRINCHI qadamda beriladigan noyob identifikator, va so'rov qaysi handler, middleware yoki ("Distributed Tracing Basics" darsidagi kabi) qaysi MIKROSERVISGA o'tmasin, LOG yozuvlarida BIR XIL ID orqali kuzatiladi.
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
)
type ctxKey string
const correlationIDKey ctxKey = "correlationID"
var counter int
// nextCorrelationID — HAR BIR yangi so'rov uchun noyob identifikator yaratadi
func nextCorrelationID() string {
counter++
return fmt.Sprintf("req-%d", counter)
}
// loggingMiddleware — HAR BIR so'rovga correlation ID biriktiradi va uni LOGGA yozadi
func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id := r.Header.Get("X-Correlation-ID")
if id == "" {
id = nextCorrelationID()
}
ctx := context.WithValue(r.Context(), correlationIDKey, id)
w.Header().Set("X-Correlation-ID", id)
fmt.Printf("[%s] %s %s\n", id, r.Method, r.URL.Path)
next(w, r.WithContext(ctx))
}
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /books/{id}", loggingMiddleware(func(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(correlationIDKey)
fmt.Fprintf(w, "handler ichida correlation ID: %s", id)
}))
req1 := httptest.NewRequest("GET", "/books/1", nil)
rec1 := httptest.NewRecorder()
mux.ServeHTTP(rec1, req1)
fmt.Println(rec1.Body.String())
req2 := httptest.NewRequest("GET", "/books/2", nil)
req2.Header.Set("X-Correlation-ID", "upstream-req-99")
rec2 := httptest.NewRecorder()
mux.ServeHTTP(rec2, req2)
fmt.Println(rec2.Body.String())
}context.WithValue ("Context Basics" darsini eslang) — correlation ID'ni HANDLER zanjiri bo'ylab, EXPLICIT parametr sifatida uzatmasdan, context.Context ICHIDA "yashirincha" olib o'tadi. Ikkinchi so'rovda X-Correlation-ID: upstream-req-99 sarlavhasi ALLAQACHON BERILGAN — bu HAQIQIY mikroservis arxitekturasida yuz beradigan holat: bitta so'rov BOSHQA servisdan kelayotganda, o'sha servis O'ZINING correlation ID'sini uzatadi, va biz uni YANGISI bilan almashtirmasdan, DAVOM ettiramiz.
Natijada: BIRINCHI so'rov o'zining req-1 ID'sini avtomatik OLADI, IKKINCHI so'rov esa yuqoridan kelgan upstream-req-99 ID'sini SAQLAB QOLADI. Agar keyinchalik ANIQ shu so'rov bilan bog'liq xatoni LOGLARDAN qidirish kerak bo'lsa, BITTA ID orqali BUTUN so'rov "hayoti"ni KUZATISH mumkin.
>_ Exercise
Log qatoriga JAVOB statusini ham qo'shing.
- •statusRecorder struct'ini yozing: http.ResponseWriter'ni EMBED qiling, qo'shimcha status int maydoni bilan
- •statusRecorder uchun WriteHeader(status int) metodini OVERRIDE qiling: status'ni saqlab, so'ng ICHKI ResponseWriter'ning WriteHeader'ini chaqiring
- •loggingMiddleware'ni o'zgartiring: next'ni CHAQIRISHDAN OLDIN emas, next TUGAGANDAN KEYIN, statusRecorder.status bilan birga LOGGA yozing
- •id="1" (200 qaytaradigan) va id="99" (404 qaytaradigan) uchun so'rov yuboring — log qatorlari to'g'ri statusni ko'rsatishi kerak
Stuck? Reveal a hint to help you.
Key Takeaway
Key Takeaway:
Correlation ID — har bir so'rovni context orqali BOSHIDAN OXIRIGACHA kuzatib boradigan noyob identifikator; ResponseWriter'ni EMBED qilib status kodni "ushlab qolish" — middleware'da javobning YAKUNIY natijasini LOGLASH uchun standart naqsh.
NEXT UP
Content Negotiation
$ go run main.go
Kodingizni ishga tushiring