fiber-logging-and-project-structure について
Go Fiber アプリケーションを開発する人向けのコーディングスキルです。プロジェクト構成、ログ、ミドルウェア、設定、エラー処理を扱い、HTTP ハンドラーとビジネスロジックの分離や、リクエストコンテキストと機密情報の管理を重視します。
主な機能
- 01標準的な Go 構成の指針
- 02構造化ログとリクエスト ID
- 03ミドルウェア登録順の推奨
- 04型付き環境設定
- 05一貫した HTTP エラー処理
活用シーン
- 01規約に沿った Fiber コードのレビュー
- 02Fiber アプリケーション構成の計画
- 03ビジネスロジック分離のためのハンドラー改修
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ oimiragieo/ agent-studio --skill fiber-logging-and-project-structureインストール後、Claude Code で/fiber-logging-and-project-structureを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
commands/fiber-logging-and-project-structure.mdhooks/post-execute.cjspre-execute.cjsreferences/research-requirements.mdrules/fiber-logging-and-project-structure.mdschemas/input.schema.jsonoutput.schema.jsonscripts/main.cjstemplates/implementation-template.md詳細
Fiber のロギングとプロジェクト構成スキル
Fiber のロギングとプロジェクト構成を専門とするコーディング規約のエキスパートです。 確立されたガイドラインとベストプラクティスを適用し、開発者がより良いコードを書けるよう支援します。 - ガイドラインへの準拠状況についてコードをレビューする - ベストプラクティスに基づいて改善案を提案する - 特定のパターンが推奨される理由を説明する - 規約を満たすようにコードをリファクタリングする Go Fiber のコードをレビューまたは記述する際は、以下のガイドラインを適用してください。プロジェクト構成(標準的な Go レイアウト)
- すべての Fiber アプリケーションを、
cmd/<appname>/main.go(エントリーポイント)、internal/(非公開パッケージ)、pkg/(再利用可能なパッケージ)、api/(ハンドラー/ルート)、config/(設定用構造体)を使って構成します。 - ビジネスロジックを
cmd/に置かないでください。main.goは初期化(ミドルウェアの登録、サーバーの起動、DB への接続)のみにします。 - ルートハンドラーとビジネスロジックを分離します。HTTP 関連の処理には
api/handler/、ドメインロジックにはinternal/service/、データアクセスにはinternal/repository/を使います。
ロギング
- 構造化ロギングを使用します(Fiber では
zerologを推奨します)。本番環境のハンドラーでfmt.Printlnや標準ライブラリのlogを使用しないでください。 - Fiber 組み込みのロガーミドルウェアを早い段階(すべてのルートより前)に登録します:
app.Use(logger.New())。 - Fiber v3 のロガーミドルウェアは、
github.com/gofiber/fiber/v3/middleware/loggerからインポートします。 - ミドルウェアで
ctx.Locals("requestID", uuid.New())を使って相関 ID を追加し、すべてのログエントリーに含めます。 - 機密フィールド(パスワード、トークン、PII)をログに記録しないでください。フィールド単位のマスキング、または許可リストを使用します。
ミドルウェアの登録順序
- グローバルミドルウェアはルートより前に登録します:ロガー → RequestID → CORS → RateLimiter → Auth → Routes。
app.Use()で登録したミドルウェアは、それ以降のすべてのルートに適用されます。配置が重要です。- ルート固有のミドルウェアは、
app.Get("/path", authMiddleware, handler)の第 2 引数として適用します。
環境設定
- 起動時に
viper、envconfig、またはgodotenvで設定を読み込みます。ハンドラー内のあちこちでos.Getenv()を読み取らないでください。 - 型付きの設定用構造体を定義します:
type Config struct { Port string \env:"PORT" envDefault:"3000"` }`。 - 必須変数をすべて記載した
.env.exampleを用意します。.envファイルをコミットしないでください。 - 必須設定が不足している場合は、速やかに処理を中断します。必須の環境変数がない場合は、起動時に panic または
log.Fatalを使用します。
エラー処理
- HTTP エラーの場合、ハンドラーから
fiber.NewError(fiber.StatusBadRequest, "message")を返します。 app.Config().ErrorHandlerを使ってグローバルエラーハンドラーを設定し、一貫した JSON エラーレスポンスを生成します。- 本番環境のエラーレスポンスに、内部エラーの詳細やスタックトレースを含めないでください。
import ( "log" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/fiber/v2/middleware/requestid" "myapp/internal/config" "myapp/api/routes" )
func main() { cfg := config.Load() // typed config, fails fast on missing vars
app := fiber.New(fiber.Config{
ErrorHandler: func(c *fiber.Ctx, err error) error {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
},
})
// Middleware: register BEFORE routes
app.Use(requestid.New())
app.Use(logger.New(logger.Config{
Format: "${time} ${method} ${path} ${status} ${latency}\n",
}))
routes.Register(app) // all routes in internal/api/routes/
log.Fatal(app.Listen(cfg.Port))
}
// internal/config/config.go — typed config type Config struct { Port string `env:"PORT" envDefault:":3000"` DBUrl string `env:"DATABASE_URL,required"` }
</examples>
## 絶対遵守事項
1. **必ず**構造化ロギング(JSON 出力の zerolog または logrus)を使用します。本番環境の Fiber アプリケーションで `fmt.Println` や `log.Printf` を使用しないでください。非構造化ログはログ集約ツールで解析できません。
2. **絶対に**ルートハンドラーにビジネスロジックを置かないでください。必ずサービス/コントローラーレイヤーを呼び出します。ルートハンドラーは HTTP 関連の処理(解析、検証、レスポンスの書き込み)のみを担当します。
3. **必ず**リクエストスコープの値(ユーザー ID、トレース ID)には Fiber の `ctx.Locals()` を使用します。グローバル変数や関数パラメーターで、呼び出しスタックの下位にリクエストスコープのデータを渡さないでください。
4. **絶対に**機密性の高い設定をコードに直接コミットしないでください。`.env.example` テンプレートとともに `envconfig`、`viper`、または環境変数を使用します。読み込んだシークレットをログに出力してはいけません。
5. **必ず**プロジェクトを `cmd/`、`internal/`、`pkg/` の規約に沿って構成します。すべてのコードをルートパッケージに置く Fiber プロジェクトは、規模が大きくなると保守できなくなります。
## アンチパターン
| アンチパターン | 問題点 | 正しい方法 |
| ------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| Fiber のハンドラーでのログ記録に `fmt.Println` を使う | 構造化されておらず、ログレベルも相関 ID もなく、ログ集約を妨げます | zerolog または logrus で `zap.String("key", value)` の構造化フィールドを使います |
| ルートハンドラーにビジネスロジックを置く | ロジックがテストも再利用もできなくなり、HTTP 層とドメインが密結合します | サービス層に移し、ハンドラーからサービスメソッドを呼び出してレスポンスを整形します |
| リクエストコンテキストにグローバル状態を使う | 同時リクエストが互いのコンテキストを上書きし、競合状態が発生します | リクエストスコープのデータにはすべて `ctx.Locals("key", value)` を使います |
| 設定値をハードコードする | 環境ごとのデプロイができず、認証情報がソース履歴に残ります | `.env.example` とともに `envconfig` または `viper` を使い、実際の値は決してコミットしません |
| プロジェクトのルートにすべてのファイルを置く | 公開 API と内部 API を分離できず、パッケージのインポート循環が発生します | 標準的な Go のレイアウトを使います:`cmd/`、`internal/`、`pkg/`、`api/` |
## メモリープロトコル(必須)
**開始前:**
```bash
cat .claude/context/memory/learnings.md
完了後: 新たに見つかったパターンや例外を記録してください。
中断を想定してください:コンテキストがリセットされることがあります。メモリーに記録されていなければ、実行されていないものとします。