✈️

Go 1.25 FlightRecorder 徹底解説 ✈️

に公開

はじめに

Go 1.25 で runtime/trace パッケージに FlightRecorder が新設されました。これは、プロセスの実行トレースをリングバッファに常時保持し、必要なタイミングで直近数秒‐数十秒のスナップショットを切り出せる “フライトレコーダ” 型の計測機構です。従来の trace.Start は長時間有効化すると巨大なファイルを生成するため実運用では扱いづらい面がありましたが、FlightRecorder により 常時オンで低負荷問題発生時のみ保存 という実用的な運用が可能になりました。

本記事では FlightRecorder のアーキテクチャ、API 仕様、導入手順、および現場での活用パターンを詳説します。Go ランタイムの可観測性を高めたいエンジニアの方はぜひ参考にしてください。


FlightRecorder とは

  • リングバッファ でトレースイベントを保持し続ける。
  • メモリ上限 (MaxBytes) と保持期間 (MinAge) を超えた世代から自動破棄。
  • 必要に応じて WriteTo(io.Writer)スナップショット を取得。
  • go tool trace / gotraceui で従来のトレースと 同フォーマット で解析可能。

背景

  1. 短時間だけ発生するレイテンシ・負荷スパイク は再現が難しい。
  2. 常時 trace.Start を有効にするとディスク I/O とストレージ消費が無視できない。
  3. FlightRecorder はメモリリングバッファ方式でこれらの課題を解決。

既存 trace.Start との比較

項目 FlightRecorder trace.Start
起動形態 プロセス起動後いつでも Start() 任意タイミングで trace.Start(w)
データ保持 メモリリングバッファ ファイル or メモリバッファに逐次書込
オーバーヘッド I/O なし、CPU は同等 I/O コスト大 (長時間)
保存対象 直近 N 秒のみ 呼び出し~停止まで全量
主要ユースケース 障害時の直前分析 再現可能なワークロードの全期間解析

API 概観

import "runtime/trace"

cfg := trace.FlightRecorderConfig{
    MinAge:   5 * time.Second, // 最低保持期間
    MaxBytes: 20 << 20,        // 20 MiB 上限
}
fr := trace.NewFlightRecorder(cfg)

if err := fr.Start(); err != nil {
    log.Fatalf("flight recorder: %v", err)
}
defer fr.Stop()

// 異常検知時にスナップショットをファイルに書き込み
if latency > threshold {
    f, _ := os.Create("trace_`date +%s`.out")
    fr.WriteTo(f)
    f.Close()
}

主な型・メソッド

シンボル 概要
FlightRecorderConfig MinAge, MaxBytes を保持する設定構造体
NewFlightRecorder(cfg) Recorder を生成 (未開始状態)
(*FlightRecorder) Start/Stop 計測開始・停止。複数回開始可
(*FlightRecorder) Enabled() 起動中かどうかを返す
(*FlightRecorder) WriteTo(w) スナップショットを io.Writer へ出力

利用シナリオ別サンプル

1. API レイテンシが閾値を超えたら自動ダンプ

middleware := func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        if d := time.Since(start); d > 200*time.Millisecond {
            if fr.Enabled() {
                f, _ := os.Create("latency_trace_" + time.Now().Format("20060102_150405") + ".out")
                _ = fr.WriteTo(f)
                f.Close()
            }
        }
    })
}

2. panic / SIGTERM 時

func main() {
    defer func() {
        if r := recover(); r != nil {
            fr.WriteTo(os.Stderr)
            panic(r) // 伝播
        }
    }()

    sig := make(chan os.Signal, 1)
    signal.Notify(sig, syscall.SIGTERM)
    go func() {
        <-sig
        fr.WriteTo(os.Stderr)
        os.Exit(1)
    }()

    // アプリ本体
}

まとめ

  • FlightRecorder は 低負荷・常時オン のトレースリングバッファ。
  • レイテンシ異常やpanicなど異常事態の分析用途に最適。

参考リンク

Discussion