デバッグガイド
システム構成
- フロントエンド: Next.js + React Query + Firebase 認証 + Material-UI
- バックエンド: FastAPI + Firebase Admin SDK + Firestore
- 開発環境: Docker Compose
- 通信: API プロキシ経由でバックエンドとの通信
- ポート: フロントエンド(3003)、バックエンド(8008)
🔧 環境設定
Docker 環境の起動
# 開発環境の起動
docker-compose up
# バックグラウンドで起動
docker-compose up -d
# 特定のサービスのみ起動
docker-compose up front
docker-compose up api
コンテナの再起動
# 新しいパッケージを反映させる場合
docker-compose down && docker-compose up -d
# 個別のコンテナを再起動
docker-compose restart front
docker-compose restart api
🖥️ フロントエンド(Next.js)のデバッグ方法
1. ブラウザの開発者ツール
アクセス方法: F12 または右クリック → 「検証」
Console タブ
-
JavaScript エラーやログを確認
-
既存のデバッグログを活用:
// 認証情報のログ console.log("ログイン成功:", user, "IDトークン:", idToken); // API通信のログ console.log("🔍 [API Proxy] GET /api/proxy/users"); console.log("✅ [API Proxy] Success response:", data); // エラーログ console.error("❌ [API Proxy] Backend error:", errorBody);
Network タブ
- API 通信を監視
- リクエスト/レスポンスの詳細を確認
- 通信エラーの原因を特定
Application タブ
- Cookie、localStorage、sessionStorage の確認
- Firebase 認証トークンの確認
2. React Query DevTools
ブラウザ右下の React Query アイコンをクリックして以下を確認:
- クエリの状態(loading、error、success)
- キャッシュされたデータ
- クエリの実行履歴
- リアルタイムでのデータ変更
3. デバッグページの活用
作成したデバッグページにアクセス: http://localhost:3003/ja/debug
確認できる項目:
- 環境変数(NEXTPUBLIC*)
- API 接続テスト
- ブラウザ情報
4. コンソールログでのデバッグ
コンポーネントレベルでのデバッグ
// useEffect でのデバッグ
useEffect(() => {
console.log("コンポーネント状態:", { users, isLoading, isError });
}, [users, isLoading, isError]);
// 条件付きデバッグ
if (process.env.NODE_ENV === "development") {
console.log("デバッグ情報:", debugData);
}
エラーハンドリングのデバッグ
// try-catch でのエラーキャッチ
try {
const response = await api.call();
} catch (error) {
console.error("APIエラー:", error);
// 詳細なエラー情報を確認
console.error("エラー詳細:", error.response?.data);
}
5. API プロキシのデバッグ
front/src/lib/apiHelper.ts に詳細なログが実装済み:
// リクエスト情報
console.log(`🔍 [API Proxy] ${method} ${backendUrl}`);
// リクエストボディ
console.log(`📝 [API Proxy] Request body:`, body);
// 認証ヘッダー
console.log(`🔑 [API Proxy] Authorization header present`);
// レスポンス
console.log(`📡 [API Proxy] Response status: ${response.status}`);
console.log(`✅ [API Proxy] Success response:`, data);
// エラー
console.error(`❌ [API Proxy] Backend error:`, errorBody);
🐍 Python API(FastAPI)のデバッグ方法
1. Docker 環境でのログ確認
基本的なログコマンド
# 全てのログを確認
docker-compose logs
# 特定のサービスのログを確認
docker-compose logs api
docker-compose logs front
# リアルタイムでログを監視
docker-compose logs -f api
# 最新50行のログを確認
docker-compose logs --tail=50 api
# 特定の時間範囲のログを確認
docker-compose logs --since="2024-01-01T00:00:00" api
2. FastAPI の自動リロード機能
開発環境では --reload フラグが有効になっており、コードを変更すると自動的にサーバーが再起動されます。
# run_fastapi.sh の内容
python -m uvicorn app:app --reload --port 8080
3. Python でのデバッグログ追加
基本的なログ出力
# 現在の実装例(functions/user_controller/base.py)
def check_admin(self, user_id: str = Depends(authenticate_user)) -> bool:
try:
user = self.get_user(user_id)
return user.is_admin
except Exception as e:
print(e) # 基本的なエラーログ
raise e
改善されたログ実装の例
import logging
from datetime import datetime
# ロガーの設定
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def check_admin(self, user_id: str = Depends(authenticate_user)) -> bool:
try:
logger.info(f"管理者チェック開始: user_id={user_id}")
user = self.get_user(user_id)
if user is None:
logger.warning(f"ユーザーが見つかりません: user_id={user_id}")
return False
logger.info(f"管理者チェック結果: user_id={user_id}, is_admin={user.is_admin}")
return user.is_admin
except Exception as e:
logger.error(f"管理者チェックエラー: user_id={user_id}, error={str(e)}")
raise e
4. HTTPException によるエラーハンドリング
from fastapi import HTTPException
# 現在の実装例
def get_badge(self, badge_id: str | None) -> Badge:
if not badge_id:
raise HTTPException(status_code=400, detail="badge_idが指定されていません。")
# ... 処理続行
5. FastAPI の自動ドキュメント機能
開発中の API ドキュメントを確認:
- Swagger UI:
http://localhost:8008/docs - ReDoc:
http://localhost:8008/redoc
6. Pytest でのテスト実行
# コンテナ内でのテスト実行
docker-compose exec api pytest tests/
# 特定のテストファイルを実行
docker-compose exec api pytest tests/test_endpoints.py
# 詳細な出力でテスト実行
docker-compose exec api pytest tests/ -v
# テストカバレッジを確認
docker-compose exec api pytest tests/ --cov=.
7. Firebase 認証のデバッグ
# 認証関連のデバッグ(functions/user_controller/auth.py)
def authenticate_user(token: str = Depends(oauth2_scheme)) -> str:
try:
print(f"認証開始: token={token[:20]}...") # トークンの一部のみ表示
decoded_token: dict = auth.verify_id_token(token, app=settings.firebase_app)
user_id = decoded_token.get("uid", None)
print(f"認証成功: user_id={user_id}")
return user_id
except FirebaseError as e:
print(f"認証エラー: {str(e)}")
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid authentication credentials",
headers={"WWW-Authenticate": "Bearer"},
)
8. Firestore クエリのデバッグ
# Firestore操作のデバッグ例
def get_user(self, user_id: str) -> User | None:
print(f"ユーザー取得開始: user_id={user_id}")
user_snapshot = self._get_user_snapshot(user_id)
if not user_snapshot.exists:
print(f"ユーザーが存在しません: user_id={user_id}")
return None
user_data = user_snapshot.to_dict()
print(f"ユーザーデータ取得成功: user_id={user_id}, data={user_data}")
return User(**user_data)
9. 環境変数のデバッグ
# 環境変数の確認
import os
from config import settings
print(f"PROJECT_ID: {settings.project_id}")
print(f"NEXT_URL: {settings.next_url}")
print(f"Firebase App: {settings.firebase_app}")
🔄 統合デバッグ方法
1. リクエストフローの追跡
- フロントエンド: ブラウザの Network タブで API リクエストを確認
- プロキシ: API プロキシのログでリクエスト/レスポンスを確認
- バックエンド: Docker logs で API サーバーのログを確認
2. エラーの特定手順
-
エラーの発生場所を特定
- フロントエンド: Console でエラーメッセージを確認
- バックエンド: Docker logs でスタックトレースを確認
-
データの流れを追跡
- リクエストデータの確認
- レスポンスデータの確認
- 中間処理での変換を確認
-
認証の確認
- Firebase トークンの有効性
- 権限チェックの結果
3. パフォーマンスの監視
# APIレスポンス時間の確認
docker-compose logs api | grep "INFO"
# リクエスト数の確認
docker-compose logs api | grep "GET\|POST\|PUT\|DELETE"
🛠️ 推奨デバッグツール
フロントエンド
- React Developer Tools: React コンポーネントの状態確認
- Redux DevTools: 状態管理のデバッグ
- React Query DevTools: データフェッチングの監視
バックエンド
- FastAPI docs: API 仕様の確認
- Firestore コンソール: データベースの状態確認
- Firebase Authentication: 認証状態の確認
統合ツール
- Postman: API エンドポイントの直接テスト
- curl: コマンドラインでの API テスト
🚨 よくある問題と対処法
1. API 通信エラー
症状: Network タブで 500 エラーが発生 対処法:
- バックエンドのログを確認:
docker-compose logs api - 認証トークンを確認: Application タブで Cookie を確認
- プロキシログを確認: フロントエンドのコンソールログを確認
2. 認証エラー
症状: 401 Unauthorized エラー 対処法:
- Firebase トークンの有効期限を確認
- 認証フローのログを確認
- Cookie の idToken を確認
3. データベース接続エラー
症状: Firestore への接続に失敗 対処法:
- credentials.json の存在を確認
- 環境変数の設定を確認
- Firebase プロジェクトの権限を確認
📝 デバッグ時のベストプラクティス
-
ログレベルの使い分け
- ERROR: システムエラー
- WARN: 警告
- INFO: 一般的な情報
- DEBUG: 詳細なデバッグ情報
-
構造化されたログ
logger.info(f"API呼び出し: method={method}, path={path}, user_id={user_id}") -
エラーハンドリング
- 例外を適切にキャッチ
- ユーザーフレンドリーなエラーメッセージ
- 詳細なログ出力
-
テスト駆動開発
- 単体テストでデバッグ
- 統合テストでフローテスト
- E2E テストでユーザー体験のテスト
🔍 アドバンスドデバッグ
1. プロファイリング
import cProfile
import pstats
def profile_function():
profiler = cProfile.Profile()
profiler.enable()
# 処理実行
profiler.disable()
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(10)
2. メモリ使用量の監視
import psutil
import os
def get_memory_usage():
process = psutil.Process(os.getpid())
memory_info = process.memory_info()
return f"Memory: {memory_info.rss / 1024 / 1024:.2f} MB"
3. 非同期処理のデバッグ
import asyncio
import logging
async def debug_async_function():
logger = logging.getLogger(__name__)
logger.info("非同期処理開始")
try:
result = await some_async_operation()
logger.info(f"非同期処理成功: {result}")
return result
except Exception as e:
logger.error(f"非同期処理エラー: {str(e)}")
raise
このガイドを参考に、効率的なデバッグを行い、問題の早期発見と解決を実現してください。