ロギングとリクエストIDのミドルウェア
構造化ロギングとトレースIDの注入
「ロギングとリクエストIDのミドルウェア」はCoddyKit上の無料Go Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはGo Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Go Academyコースには全4レッスンが含まれています。
構造化ロギングを使う理由
プレーンテキストのログは、大規模な環境では解析が困難です。構造化ロギング(JSONまたはkey=value)を使用すると、ログアグリゲーター(Datadog、Loki、ELK)でフィールドごとにエントリをフィルタリングし、関連付けられます。
リクエストIDの生成
ミドルウェアでリクエストごとに一意のID(UUIDまたはULID)を生成し、レスポンスヘッダーとコンテキストに追加します。
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))
})
}slogを使用したロギングミドルウェア
Go 1.21では、構造化ロギングのためにlog/slogが追加されました。ミドルウェア内で使用します。
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
ResponseWriterをラップして、ハンドラーが書き込んだステータスコードを取得します。
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
}すべてのログ行にリクエストIDを追加する
あらかじめIDを設定したリクエストごとの子ロガーを作成し、それをコンテキストに保存します。
reqLogger := logger.With("request_id", id)
ctx := context.WithValue(r.Context(), loggerKey{}, reqLogger)コンテキストからロガーを取得する
任意のハンドラーやサービスからリクエスト単位のロガーを取得するヘルパーです。
func LoggerFromContext(ctx context.Context) *slog.Logger {
l, ok := ctx.Value(loggerKey{}).(*slog.Logger)
if !ok { return slog.Default() }
return l
}ログレベル
適切なレベルを使用します。Debugは開発時の詳細なログ、Infoはリクエストの概要、Warnは復旧可能な異常、Errorは対処が必要な失敗に使用します。機密性の高いフィールド(トークンやパスワード)は記録しないでください。
レイテンシバケット
すべてのログ行にリクエストのレイテンシを含めます。メトリクスシステム(Prometheus)でヒストグラムバケットに集計し、P50/P95/P99パーセンタイルを追跡します。
マイクロサービスにおける相関 ID
分散トレーシングシステム全体を導入しなくても分散トレーシングを可能にするため、受信リクエストの X-Request-ID ヘッダーを、すべての送信 HTTP および gRPC 呼び出しに転送します。
ログサンプリング
トラフィックの多いサービスでは、デバッグログや情報ログをサンプリングします(例:debug レベルで 100 リクエストに 1 件だけ記録します)。これにより、エラーログを完全に保持しながらストレージコストを削減できます。
zap と slog の比較
zap(Uber)はスループットの高いサービスでは slog より高速ですが、セットアップがより複雑です。slog は標準ライブラリで移植性があり、ほとんどのサービスには十分です。ベンチマークでボトルネックが確認されない限り、slog を優先してください。
確認問題
ロギングミドルウェアで captureWriter が必要なのはなぜですか?
まとめ: ロギングとリクエスト ID
重要なポイント:
- ミドルウェアで X-Request-ID を生成または転送し、context に保存する
- キーと値のフィールドを持つ構造化ログには slog を使用する
- captureWriter でステータスコードを捕捉し、ハンドラー処理後のログ記録に利用する
- 相関 ID をすべての下流呼び出しに転送する
AI チューターと学ぶ Go — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 51
- レッスン
- 203
よくある質問
「ロギングとリクエストIDのミドルウェア」レッスンは無料ですか?
はい。「ロギングとリクエストIDのミドルウェア」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Go Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Go Academyコースには全4レッスンが含まれています。
「ロギングとリクエストIDのミドルウェア」で何を学びますか?
構造化ロギングとトレースIDの注入 ブラウザで直接実行するハンズオンコードでGo Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Go Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのGo Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「ロギングとリクエストIDのミドルウェア」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このGo Academyレッスンでコードを書いて実行できますか?
はい。すべてのGo Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- HTTPミドルウェアチェーンの基本
- ロギングとリクエストIDのミドルウェア
- 認証とレート制限のミドルウェア
- CORSとパニックリカバリーのミドルウェア