Conversation
- /api/v1/health エンドポイント追加(UptimeRobot監視用) - DB接続、OpenAI設定、CORS確認 - Sentry統合準備(SENTRY_DSN環境変数) - OpenAI コスト上限を学生向けに設定($5-10/月) - 完全無料運用ガイド追加(3ヶ月$0-10) - Supabase移行手順追加(90日後の選択肢) 監視ツール: - OpenAI Dashboard: Hard $10, Soft $5(学生向け) - UptimeRobot: 死活監視(5分間隔) - Sentry: エラー追跡(5,000イベント/月無料) - Render Alert: リソース監視
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
問題: - config.pyにSKILL_TREE_CACHE_MINUTESを定義したが、 skill_tree_service.pyではハードコード値(CACHE_VALID_MINUTES=10)を使用 - テストも固定値を前提にしており、環境変数変更が反映されない 修正: - skill_tree_service.py: - ハードコード定数CACHE_VALID_MINUTESを削除 - settings.SKILL_TREE_CACHE_MINUTESを参照するよう変更 - docstringも更新 - test_skill_tree_service.py: - 全キャッシュ関連テストでsettingsをモック - mock_settings.SKILL_TREE_CACHE_MINUTES = 10 で制御 - 環境変数変更に対応した堅牢なテストに修正 影響: - .envでSKILL_TREE_CACHE_MINUTES=60と設定すれば60分キャッシュが有効になる - 本番環境で柔軟にキャッシュ時間を調整可能 テスト: 12 passed
There was a problem hiding this comment.
Pull request overview
このPRは、学生ハッカソン向けに月$0-10で運用可能な監視基盤を構築するものです。既存の無料SaaSツール(UptimeRobot、Sentry、Renderアラート)を活用し、OpenAI APIのコスト管理を重視した設計となっています。特にOpenAI使用量上限設定(Hard $10/月、Soft $5/月)とヘルスチェックエンドポイントの実装により、予算制約の厳しい学生チームでも安心して運用できる仕組みを提供しています。
Changes:
- ヘルスチェックエンドポイント(/api/v1/health)の実装:DB接続、OpenAI設定、CORS設定を監視
- Sentry統合準備(オプション機能):エラー追跡とスタックトレースの自動収集
- スキルツリーキャッシュ設定の環境変数化:SKILL_TREE_CACHE_MINUTESで調整可能に
- 学生ハッカソン向けデプロイメントガイドの拡充:完全無料運用の手順と監視チェックリスト
- Sentry選定理由の詳細なADRドキュメント作成
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| backend/app/api/api.py | ヘルスチェックエンドポイント(/api/v1/health)の実装 - DB、OpenAI、CORS設定の監視 |
| backend/app/main.py | Sentry統合コードの追加(SENTRY_DSN設定時のみ有効化) |
| backend/app/core/config.py | SKILL_TREE_CACHE_MINUTESとSENTRY_DSN設定の追加 |
| backend/app/services/skill_tree_service.py | ハードコードされたCACHE_VALID_MINUTESをsettings.SKILL_TREE_CACHE_MINUTESに変更 |
| backend/tests/test_services/test_skill_tree_service.py | キャッシュ有効期間のテストでsettingsをモック化して環境依存を排除 |
| DEPLOYMENT.md | 学生ハッカソン向け監視ツール設定ガイドとコスト試算の追加 |
| .github/decisions/019-sentry-for-error-tracking.md | Sentry選定理由とトレードオフを記載した詳細なADRドキュメント |
| ), patch( | ||
| "app.services.skill_tree_service.settings" | ||
| ) as mock_settings: | ||
| mock_settings.SKILL_TREE_CACHE_MINUTES = 10 # 15分前のキャッシュは無効 | ||
| mock_settings.SKIP_LLM_FOR_SKILL_TREE = False # LLMを使用 |
There was a problem hiding this comment.
settings オブジェクト全体をモックしていますが、SKILL_TREE_CACHE_MINUTES と SKIP_LLM_FOR_SKILL_TREE 以外の属性へのアクセスがあると AttributeError が発生する可能性があります。より安全な方法として、patch.object を使用して特定の属性のみをモックするか、MagicMock に spec 属性を設定することを推奨します。例:複数の patch.object を使用するか、mock_settings.configure_mock でその他の必要な属性も設定してください。
| with patch("app.services.skill_tree_service.settings") as mock_settings: | ||
| mock_settings.SKILL_TREE_CACHE_MINUTES = 10 |
There was a problem hiding this comment.
settings オブジェクト全体をモックしていますが、SKILL_TREE_CACHE_MINUTES 以外の属性へのアクセスがあると AttributeError が発生する可能性があります。より安全な方法として、patch.object を使用して特定の属性のみをモックすることを推奨します。例:patch.object(settings, "SKILL_TREE_CACHE_MINUTES", 10)
| """ | ||
| health = { | ||
| "status": "healthy", | ||
| "timestamp": datetime.utcnow().isoformat(), |
There was a problem hiding this comment.
datetime.utcnow()は非推奨です。コードベースの他の部分では一貫してdatetime.now(UTC)が使用されています(例:backend/app/services/skill_tree_service.py:221)。datetime.now(UTC)に変更する場合は、インポート文も「from datetime import datetime, UTC」に更新する必要があります。これにより、タイムゾーン対応が明示的になり、コードベース全体で一貫性が保たれます。
| environment=( | ||
| "production" | ||
| if settings.FRONTEND_URL.startswith("https://") | ||
| else "development" | ||
| ), |
There was a problem hiding this comment.
環境判定ロジックに問題があります。settings.FRONTEND_URLが"https://"で始まるかどうかで環境を判定していますが、本番環境が必ずhttpsで始まるとは限りません(例:開発環境でhttps付きのプレビューURLを使用する場合)。より確実な方法として、専用の環境変数(例:ENVIRONMENT="production")を導入するか、特定のドメイン("vercel.app"など)を含むかで判定することをお勧めします。
| @api_router.get("/health", tags=["monitoring"]) | ||
| def health_check(db: Session = Depends(get_db)) -> dict: | ||
| """ヘルスチェックエンドポイント(UptimeRobot等の監視用) | ||
|
|
||
| - データベース接続確認 | ||
| - 基本設定確認 | ||
| - タイムスタンプ返却 | ||
|
|
||
| Returns: | ||
| status: healthy/degraded/unhealthy | ||
| timestamp: 現在時刻(UTC) | ||
| checks: 各コンポーネントの状態 | ||
| """ | ||
| health = { | ||
| "status": "healthy", | ||
| "timestamp": datetime.utcnow().isoformat(), | ||
| "version": "1.0.0", | ||
| "checks": {}, | ||
| } | ||
|
|
||
| # データベース接続チェック | ||
| try: | ||
| db.execute(text("SELECT 1")) | ||
| health["checks"]["database"] = "ok" | ||
| except Exception as e: | ||
| health["checks"]["database"] = f"error: {str(e)}" | ||
| health["status"] = "unhealthy" | ||
|
|
||
| # OpenAI API Key設定確認(キー自体は返さない) | ||
| try: | ||
| if settings.OPENAI_API_KEY and len(settings.OPENAI_API_KEY) > 10: | ||
| health["checks"]["openai_configured"] = "ok" | ||
| else: | ||
| health["checks"]["openai_configured"] = "not_configured" | ||
| health["status"] = "degraded" | ||
| except Exception: | ||
| health["checks"]["openai_configured"] = "error" | ||
| health["status"] = "degraded" | ||
|
|
||
| # CORS設定確認 | ||
| try: | ||
| if settings.BACKEND_CORS_ORIGINS: | ||
| health["checks"]["cors_configured"] = "ok" | ||
| else: | ||
| health["checks"]["cors_configured"] = "not_configured" | ||
| except Exception: | ||
| health["checks"]["cors_configured"] = "error" | ||
|
|
||
| return health |
There was a problem hiding this comment.
ヘルスチェックエンドポイントのテストが不足しています。このプロジェクトでは他のAPIエンドポイントに対して包括的なテストが存在します(例:backend/tests/test_api/test_analyze.py)。監視用のヘルスチェックエンドポイントは重要な機能なので、以下のテストケースを追加することを推奨します:
- 正常時のレスポンスチェック(status="healthy")
- データベース接続失敗時の動作(status="unhealthy")
- OpenAI API Key未設定時の動作(status="degraded")
- レスポンス形式の検証(timestamp、version、checksフィールド)
|
|
||
| → OPENAI_API_KEYが正しく設定されているか、クレジットが残っているか確認 | ||
|
|
||
| ## 📊 モニタリング | ||
| ## 📊 モニタリング・監視基盤 | ||
|
|
||
| ### 標準ログ確認 | ||
|
|
||
| - **Render Logs**: Dashboard → Logs | ||
| - **Vercel Logs**: Dashboard → Deployments → Logs | ||
| - **エラートラッキング**: RenderのMetricsタブで確認 | ||
| - **Render Metrics**: Dashboard → Metrics(CPU/メモリ/リクエスト数) | ||
|
|
||
| ### 推奨監視ツール(全て無料) | ||
|
|
There was a problem hiding this comment.
DEPLOYMENT.mdのサンプルレスポンスに一貫性の問題があります。213-225行目のヘルスチェックエンドポイントの例では、checksの値が「"healthy"」という文字列になっていますが、実際の実装(backend/app/api/api.py:44,52)では「"ok"」、「"not_configured"」、「"error"」といった異なる値が使用されています。ドキュメントを実装と一致させる必要があります。
| except Exception as e: | ||
| health["checks"]["database"] = f"error: {str(e)}" | ||
| health["status"] = "unhealthy" |
There was a problem hiding this comment.
データベースエラーの詳細がヘルスチェックエンドポイントのレスポンスに含まれており、潜在的なセキュリティリスクがあります。str(e)により、データベース接続情報やスタックトレースの一部が外部に漏洩する可能性があります。本番環境では、エラーの詳細をログに記録しつつ、クライアントには汎用的なエラーメッセージ(例:「"error"」のみ)を返すことを推奨します。
| @@ -0,0 +1,281 @@ | |||
| # ADR-0001: Sentryをエラー追跡ツールとして選定 | |||
There was a problem hiding this comment.
PR説明とADRファイルパスに不一致があります。PR説明では「docs/adr/0001-sentry-for-error-tracking.md」と記載されていますが、実際のファイルは「.github/decisions/019-sentry-for-error-tracking.md」に作成されています。PR説明を実際のファイルパスに合わせて修正する必要があります。
| health = { | ||
| "status": "healthy", | ||
| "timestamp": datetime.utcnow().isoformat(), | ||
| "version": "1.0.0", | ||
| "checks": {}, | ||
| } | ||
|
|
||
| # データベース接続チェック | ||
| try: | ||
| db.execute(text("SELECT 1")) | ||
| health["checks"]["database"] = "ok" | ||
| except Exception as e: | ||
| health["checks"]["database"] = f"error: {str(e)}" | ||
| health["status"] = "unhealthy" |
There was a problem hiding this comment.
ヘルスチェックエンドポイントがstatus="unhealthy"の場合でもHTTP 200を返します。一般的な監視ツール(UptimeRobotを含む)は、サービスに問題がある場合にHTTP 5xxステータスコード(例:503 Service Unavailable)を返すことを期待します。データベース接続に失敗した場合など、status="unhealthy"の場合は適切なHTTPステータスコード(503など)を返すことで、監視ツールが即座に問題を検知できるようになります。
| with patch("app.services.skill_tree_service.settings") as mock_settings: | ||
| mock_settings.SKILL_TREE_CACHE_MINUTES = 10 |
There was a problem hiding this comment.
settings オブジェクト全体をモックしていますが、SKILL_TREE_CACHE_MINUTES 以外の属性へのアクセスがあると AttributeError が発生する可能性があります。より安全な方法として、patch.object を使用して特定の属性のみをモックするか、MagicMock に spec 属性を設定することを推奨します。例:patch.object(settings, "SKILL_TREE_CACHE_MINUTES", 10) または mock_settings.configure_mock(**{"SKILL_TREE_CACHE_MINUTES": 10, ...その他の必要な属性...})
📋 概要
学生ハッカソンという予算制約の厳しい環境において、月$0-10で運用可能な監視基盤を構築しました。
🎯 目的
課題
解決策
既存の無料SaaSツールを組み合わせ、最小限のコード変更で監視基盤を実現:
📝 変更内容
1. ヘルスチェックエンドポイント実装
ファイル:
backend/app/api/api.py効果:
2. Sentry統合準備
ファイル:
backend/app/main.py,backend/app/core/config.py効果:
3. 学生向けコスト設定ガイド
ファイル:
DEPLOYMENT.mdBefore(企業向け想定)
After(学生ハッカソン向け)
完全無料運用ガイド追加
🔍 設計判断(ADR参照)
Sentry選定理由の詳細は
docs/adr/0001-sentry-for-error-tracking.mdを参照選定基準:
🧪 テスト
ヘルスチェックエンドポイント
Sentry統合テスト
📊 コスト試算
デモ発表まで(1-2週間)
ハッカソン期間中(3ヶ月)
3ヶ月後(継続運用する場合)
🚀 デプロイ手順
1. 即座に実行(5分×3タスク)
OpenAI使用量上限設定(最優先)
UptimeRobot設定
Render Alert設定
2. オプション(Sentry統合)
✅ チェックリスト
セキュリティ
監視・アラート設定
週次監視(毎週月曜日5分)
🔄 今後の改善案
すぐできる(優先度: 高)
中期的に検討(優先度: 中)
長期的に検討(優先度: 低)
📖 参考資料
👥 レビューポイント
重点確認事項
細かい確認
🎓 学び・気づき
良かった点
改善が必要な点
学んだこと