mcpField
G
golang-samber-slog

golang-samber-slog

github.com/samber開発3.7k38.7k 回インストール6 日前に更新
リポジトリ

golang-samber-slog について

標準の slog.Handler インターフェースで構造化ログパイプラインを構築する samber/slog の Go パッケージを扱うスキルです。ハンドラーの合成、サンプリング、属性整形、HTTP ミドルウェア、バックエンドを説明します。

主な機能

  1. 01合成可能な slog ハンドラー
  2. 02ルーティング、ファンアウト、フェイルオーバー、プール
  3. 03ログ量を制御するサンプリング戦略
  4. 04属性整形と PII マスキング
  5. 05HTTP ミドルウェアとバックエンド

活用シーン

  1. 01エラーログを指定したハンドラーへ振り分け
  2. 02サンプリングによる反復ログの削減
  3. 03出力前の機密属性の除去
  4. 04HTTP ログへのリクエスト情報の追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-slog

インストール後、Claude Code で/golang-samber-slogを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
evals.json
references/
backend-handlers.md
http-middlewares.md
pipeline-patterns.md
sampling-strategies.md

詳細

Persona: Go ロギングアーキテクトです。すべてのレコードが適切なハンドラーを通るログパイプラインを設計します。サンプリングで早い段階にノイズを除去し、レコードがプロセスから出る前にフォーマッターで PII を取り除き、ルーターでエラーを Sentry に、情報ログを Loki に送ります。

samber/slog-**** — Go 向け構造化ログパイプライン

Go 1.21 以降向けの、合成可能な slog.Handler パッケージが 20 種類以上あります。3 つのコアパイプラインライブラリに加え、すべて標準の slog.Handler インターフェースを実装する HTTP ミドルウェアとバックエンドシンクを提供します。

公式リソース:

このスキルは網羅的ではありません。詳しくはライブラリのドキュメントとコード例を参照してください。

  • Go パッケージのドキュメント、シンボル、バージョン、インポーター、既知の脆弱性については、Context7 よりも優先して samber/cc-skills-golang@golang-pkg-go-dev スキル(godig)を参照してください。
  • 独自のコード内でこのライブラリの使い方(定義、呼び出し箇所、診断情報)を確認するには、samber/cc-skills-golang@golang-gopls スキル(gopls)を参照してください。
  • Context7 は、pkg.go.dev でインデックス化されていないドキュメントのフォールバックとして引き続き利用できます。

パイプラインモデル

samber/slog のすべてのパイプラインは、標準的な順序に従います。レコードは左から右へ流れます。最初にサンプリングを配置して早期にレコードを除外し、シンクに到達しないレコードの処理に CPU を浪費しないようにします。

record → [Sampling] → [Pipe: trace/PII] → [Router] → [Sinks]

順序が重要です。フォーマットの前にサンプリングすると CPU を節約できます。ルーティングの前にフォーマットすると、すべてのシンクにクリーンな属性が渡されます。順序を逆にすると、破棄されるレコードにも処理が行われ、無駄が生じます。

コアライブラリ

ライブラリ目的主なコンストラクター
slog-multiハンドラーの合成Fanout、Router、FirstMatch、Failover、Pool、Pipe
slog-samplingスループット制御UniformSamplingOption、ThresholdSamplingOption、AbsoluteSamplingOption、CustomSamplingOption
slog-formatter属性の変換PIIFormatter、ErrorFormatter、FormatByType[T]、FormatByKey、FlattenFormatterMiddleware

slog-multi — ハンドラーの合成

6 種類の合成パターンがあり、それぞれ異なるルーティングのニーズに対応します。

パターン動作レイテンシへの影響
Fanout(handlers...)すべてのハンドラーに順番にブロードキャストしますすべてのハンドラーのレイテンシの合計
Router().Add(h, predicate).Handler()条件に一致するすべてのハンドラーにルーティングします条件に一致するハンドラーの処理時間の合計
Router().Add(...).FirstMatch().Handler()最初に一致したハンドラーのみにルーティングします単一ハンドラーのレイテンシ
Failover()(handlers...)成功するまで順番に試行しますプライマリハンドラーのレイテンシ(正常時)
Pool()(handlers...)負荷分散し、各レコードを 1 つのハンドラーに送信します単一ハンドラーのレイテンシ
Pipe(middlewares...).Handler(sink)シンクの前にミドルウェアチェーンを実行しますミドルウェアのオーバーヘッド + シンク
// Route errors to Sentry, all logs to stdout
logger := slog.New(
    slogmulti.Router().
        Add(sentryHandler, slogmulti.LevelIs(slog.LevelError)).
        Add(slog.NewJSONHandler(os.Stdout, nil)).
        Handler(),
)

組み込みの述語:LevelIs、LevelIsNot、MessageIs、MessageIsNot、MessageContains、MessageNotContains、AttrValueIs、AttrKindIs。

各パターンの完全なコード例については、パイプラインパターンを参照してください。

slog-sampling — スループット制御

戦略動作最適な用途
Uniformすべてのレコードを一定の割合で破棄します開発環境/ステージング環境のノイズ低減
Threshold各間隔で最初の N 件を記録し、その後は割合 R でサンプリングします本番環境 — 初期の可視性を維持します
Absolute全体で各間隔あたり N 件のレコードに制限します厳格なコスト管理
Customユーザー関数が各レコードのサンプリング率を返しますレベルや時間に応じたルール

サンプリングはパイプラインで最も外側のハンドラーに MUST 配置します。フォーマット後に配置すると、破棄されるレコードにも CPU を無駄に使います。

// Threshold: log first 10 per 5s, then 10% — errors always pass through via Router
logger := slog.New(
    slogmulti.
        Pipe(slogsampling.ThresholdSamplingOption{
            Tick: 5 * time.Second, Threshold: 10, Rate: 0.1,
        }.NewMiddleware()).
        Handler(innerHandler),
)

マッチャーは、重複排除のために類似したレコードをグループ化します。MatchByLevel()、MatchByMessage()、MatchByLevelAndMessage()(デフォルト)、MatchBySource()、MatchByAttribute(groups, key) を使用できます。

戦略の比較と設定の詳細については、サンプリング戦略を参照してください。

slog-formatter — 属性の変換

Pipe ミドルウェアとして適用すると、すべての後続ハンドラーがクリーンな属性を受け取ります。

logger := slog.New(
    slogmulti.Pipe(slogformatter.NewFormatterMiddleware(
        slogformatter.PIIFormatter("user"),          // mask PII fields
        slogformatter.ErrorFormatter("error"),       // structured error info
        slogformatter.IPAddressFormatter("client"),  // mask IP addresses
    )).Handler(slog.NewJSONHandler(os.Stdout, nil)),
)

主なフォーマッター:PIIFormatter、ErrorFormatter、TimeFormatter、UnixTimestampFormatter、IPAddressFormatter、HTTPRequestFormatter、HTTPResponseFormatter。汎用フォーマッター:FormatByType[T]、FormatByKey、FormatByKind、FormatByGroup、FormatByGroupKey。FlattenFormatterMiddleware でネストされた属性をフラット化できます。

HTTP ミドルウェア

各フレームワークで一貫したパターンを使用します:router.Use(slogXXX.New(logger))。

利用可能なもの:slog-gin、slog-echo、slog-fiber、slog-chi、slog-http(net/http)。

いずれも、DefaultLevel、ClientErrorLevel、ServerErrorLevel、WithRequestBody、WithResponseBody、WithUserAgent、WithRequestID、WithTraceID、WithSpanID、Filters を含む Config 構造体を共有します。

// Gin with filters — skip health checks
router.Use(sloggin.NewWithConfig(logger, sloggin.Config{
    DefaultLevel:     slog.LevelInfo,
    ClientErrorLevel: slog.LevelWarn,
    ServerErrorLevel: slog.LevelError,
    WithRequestBody:  true,
    Filters: []sloggin.Filter{
        sloggin.IgnorePath("/health", "/metrics"),
    },
}))

フレームワーク固有の設定については、HTTP ミドルウェアを参照してください。

バックエンドシンク

いずれも Option{}.NewXxxHandler() コンストラクターパターンに従います。

カテゴリーパッケージ
クラウドslog-datadog、slog-sentry、slog-loki、slog-graylog
メッセージングslog-kafka、slog-fluentd、slog-logstash、slog-nats
通知slog-slack、slog-telegram、slog-webhook
ストレージslog-parquet
ブリッジslog-zap、slog-zerolog、slog-logrus

バッチハンドラーでは正常なシャットダウンが必要です — slog-datadog、slog-loki、slog-kafka、slog-parquet はレコードを内部でバッファリングします。シャットダウン時にフラッシュしてください(例:Datadog では handler.Stop(ctx)、Loki では lokiClient.Stop()、Kafka では writer.Close())。そうしないと、バッファー内のログが失われます。

設定例とシャットダウンのパターンについては、バックエンドハンドラーを参照してください。

よくある間違い

間違い問題が起きる理由修正方法
フォーマット後にサンプリングする破棄されるレコードのフォーマットにも CPU を無駄に使いますサンプリングを最も外側のハンドラーに配置します
多数の同期ハンドラーにファンアウトする呼び出し元がブロックされ、遅延はすべてのハンドラーの合計になります並行ディスパッチには Pool() を使用します
バッチハンドラーでシャットダウン時のフラッシュがないシャットダウン時にバッファー内のログが失われますdefer handler.Stop(ctx)(Datadog)、defer lokiClient.Stop()(Loki)、defer writer.Close()(Kafka)を指定します
デフォルト/キャッチオールハンドラーがないルーター一致しないレコードが通知なく破棄されます述語を指定しないハンドラーをキャッチオールとして追加します
HTTP ミドルウェアなしで AttrFromContext を使用するコンテキストに抽出対象のリクエスト属性がありません先に slog-gin/echo/fiber/chi ミドルウェアをインストールします
ミドルウェアなしで Pipe を使用するレコードごとのオーバーヘッドが加わるだけで、何も行いませんミドルウェアが不要なら Pipe() を削除します

パフォーマンスに関する警告

  • Fanout のレイテンシ = すべてのハンドラーのレイテンシの合計(逐次処理)。10ms のハンドラーが 5 つある場合、ログ呼び出しごとに 50ms かかります。Pool() を使うと、最大のレイテンシまで短縮できます
  • Pipe ミドルウェアはレコードごとに関数呼び出しのオーバーヘッドを追加します。チェーンは短く保ってください(ミドルウェア 2~4 個)
  • slog-formatterは属性を逐次処理するため、フォーマッターが多いと負荷が累積します。ホットパスで属性をフォーマットする場合は、代わりに型に slog.LogValuer を実装することをおすすめします
  • 本番環境にデプロイする前に、go test -bench でパイプラインをベンチマークしてください

診断: パイプラインのレコードごとの割り当てとレイテンシを測定し、チェーン内で最も多く割り当てを行うハンドラーを特定してください。

ベストプラクティス

  1. 最初にサンプリングし、次にフォーマットし、最後にルーティングする — この標準的な順序により、無駄な処理を最小限に抑え、すべてのシンクにクリーンなデータが渡るようにします
  2. 横断的な関心事には Pipe を使う — トレース ID の注入や PII のスクラブは、ハンドラーごとのロジックではなくミドルウェアに実装します
  3. slogmulti.NewHandleInlineHandler でパイプラインをテストする — 実際のシンクを使わずに、各段階に届くレコードを検証します
  4. AttrFromContext を使うと、HTTP ミドルウェアからリクエストスコープの属性をすべてのハンドラーに伝播できます
  5. ハンドラーごとに異なるレコード群が必要な場合は、Fanout より Router をおすすめします。Router は述語を評価し、一致しないハンドラーをスキップします

関連項目

  • → slog の基本(レベル、コンテキスト、ハンドラーの設定、移行)については、samber/cc-skills-golang@golang-observability スキルを参照してください
  • → ログに記録するか返すかのルールについては、samber/cc-skills-golang@golang-error-handling スキルを参照してください
  • → ログにおける PII の取り扱いについては、samber/cc-skills-golang@golang-security スキルを参照してください
  • → samber/oops を使った構造化エラーコンテキストについては、samber/cc-skills-golang@golang-samber-oops スキルを参照してください

samber/slog-* パッケージでバグや予期しない動作を見つけた場合は、該当するリポジトリ(例:slog-multi/issues、slog-sampling/issues)で issue を作成してください。

コメント