Middleware logowania i identyfikatora żądania
Logowanie strukturalne i wstrzykiwanie identyfikatora śledzenia
Middleware logowania i identyfikatora żądania to bezpłatna lekcja Go Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Go Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Go Academy zawiera 4 lekcji w sumie.
Dlaczego rejestrowanie strukturalne?
Dzienniki w postaci zwykłego tekstu trudno analizować na dużą skalę. Rejestrowanie strukturalne (JSON lub key=value) pozwala agregatorom dzienników (Datadog, Loki, ELK) filtrować i korelować wpisy według pól.
Generowanie identyfikatora żądania
Generuj unikalny identyfikator dla każdego żądania (UUID lub ULID) w middleware i dołączaj go do nagłówka odpowiedzi oraz kontekstu:
func RequestID(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.Header.Get("X-Request-ID")
if id == "" { id = uuid.New().String() }
w.Header().Set("X-Request-ID", id)
ctx := context.WithValue(r.Context(), reqIDKey{}, id)
next.ServeHTTP(w, r.WithContext(ctx))
})
}Middleware rejestrowania z użyciem slog
W Go 1.21 dodano log/slog do rejestrowania strukturalnego. Używaj go w middleware:
func StructuredLogger(logger *slog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
cw := &captureWriter{ResponseWriter: w}
next.ServeHTTP(cw, r)
logger.Info("request",
"method", r.Method,
"path", r.URL.Path,
"status", cw.status,
"latency_ms", time.Since(start).Milliseconds(),
"request_id", r.Context().Value(reqIDKey{}),
)
})
}
}captureWriter
Opakuj ResponseWriter, aby przechwytywać kod statusu zapisany przez program obsługi:
type captureWriter struct {
http.ResponseWriter
status int
}
func (cw *captureWriter) WriteHeader(code int) {
cw.status = code
cw.ResponseWriter.WriteHeader(code)
}
func (cw *captureWriter) Status() int {
if cw.status == 0 { return http.StatusOK }
return cw.status
}Dodawanie identyfikatora żądania do każdego wpisu dziennika
Twórz dla każdego żądania logger potomny z wstępnie ustawionym identyfikatorem, a następnie przechowuj go w kontekście:
reqLogger := logger.With("request_id", id)
ctx := context.WithValue(r.Context(), loggerKey{}, reqLogger)Pobieranie loggera z kontekstu
Funkcja pomocnicza do pobierania loggera związanego z żądaniem z dowolnego programu obsługi lub serwisu:
func LoggerFromContext(ctx context.Context) *slog.Logger {
l, ok := ctx.Value(loggerKey{}).(*slog.Logger)
if !ok { return slog.Default() }
return l
}Poziomy rejestrowania
Używaj odpowiednich poziomów: Debug do szczegółowych informacji podczas programowania, Info do podsumowań żądań, Warn do anomalii, z których można się odzyskać, oraz Error do wymagających działania niepowodzeń. Nie rejestruj poufnych pól (tokenów, haseł).
Przedziały opóźnień
Uwzględniaj opóźnienie żądania w każdym wpisie dziennika. Agreguj je w przedziałach histogramu w systemie metryk (Prometheus), aby śledzić percentyle P50/P95/P99.
Identyfikatory korelacji w mikrousługach
Należy przekazywać nagłówek X-Request-ID z przychodzących żądań do wszystkich wychodzących wywołań HTTP i gRPC, aby umożliwić śledzenie rozproszone bez wdrażania pełnego systemu śledzenia.
Próbkowanie logów
W usługach o dużym ruchu należy próbkować logi debug/info (np. rejestrować na poziomie debug 1 na 100 żądań), aby zmniejszyć koszty przechowywania, zachowując kompletność logów błędów.
zap vs slog
zap (Uber) jest szybszy od slog w usługach o dużej przepustowości, ale wymaga większej ilości konfiguracji. slog należy do biblioteki standardowej, jest przenośny i wystarczający dla większości usług. Należy preferować slog, chyba że testy wydajności wykażą wąskie gardło.
Szybkie sprawdzenie
Dlaczego w middleware logującym potrzebny jest captureWriter?
Podsumowanie: logowanie i identyfikator żądania
Najważniejsze informacje:
- Generować/przekazywać X-Request-ID w middleware; przechowywać go w kontekście
- Używać slog do tworzenia logów strukturalnych z polami klucz-wartość
- captureWriter przechwytuje kod statusu na potrzeby logowania po wykonaniu handlera
- Przekazywać identyfikator korelacji do wszystkich wywołań usług niższych warstw
Często zadawane pytania
Czy lekcja „Middleware logowania i identyfikatora żądania” jest bezpłatna?
Tak — pełny tekst „Middleware logowania i identyfikatora żądania” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Go Academy, przejdź na CoddyKit PRO. Kurs Go Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Middleware logowania i identyfikatora żądania”?
Logowanie strukturalne i wstrzykiwanie identyfikatora śledzenia Ćwiczysz Go Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Go Academy?
Nie wymagamy żadnego doświadczenia. Go Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Middleware logowania i identyfikatora żądania”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Go Academy?
Tak. Każda lekcja Go Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Podstawy łańcucha middleware HTTP
- Middleware logowania i identyfikatora żądania
- Middleware uwierzytelniania i limitowania ruchu
- Middleware CORS i odzyskiwania po panic