Skip to content

デバッグ方法

Published: at 23:20

デバッグガイド

システム構成

🔧 環境設定

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 タブ

Network タブ

Application タブ

2. React Query DevTools

ブラウザ右下の React Query アイコンをクリックして以下を確認:

3. デバッグページの活用

作成したデバッグページにアクセス: http://localhost:3003/ja/debug

確認できる項目:

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 ドキュメントを確認:

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. リクエストフローの追跡

  1. フロントエンド: ブラウザの Network タブで API リクエストを確認
  2. プロキシ: API プロキシのログでリクエスト/レスポンスを確認
  3. バックエンド: Docker logs で API サーバーのログを確認

2. エラーの特定手順

  1. エラーの発生場所を特定

    • フロントエンド: Console でエラーメッセージを確認
    • バックエンド: Docker logs でスタックトレースを確認
  2. データの流れを追跡

    • リクエストデータの確認
    • レスポンスデータの確認
    • 中間処理での変換を確認
  3. 認証の確認

    • Firebase トークンの有効性
    • 権限チェックの結果

3. パフォーマンスの監視

# APIレスポンス時間の確認
docker-compose logs api | grep "INFO"

# リクエスト数の確認
docker-compose logs api | grep "GET\|POST\|PUT\|DELETE"

🛠️ 推奨デバッグツール

フロントエンド

バックエンド

統合ツール

🚨 よくある問題と対処法

1. API 通信エラー

症状: Network タブで 500 エラーが発生 対処法:

  1. バックエンドのログを確認: docker-compose logs api
  2. 認証トークンを確認: Application タブで Cookie を確認
  3. プロキシログを確認: フロントエンドのコンソールログを確認

2. 認証エラー

症状: 401 Unauthorized エラー 対処法:

  1. Firebase トークンの有効期限を確認
  2. 認証フローのログを確認
  3. Cookie の idToken を確認

3. データベース接続エラー

症状: Firestore への接続に失敗 対処法:

  1. credentials.json の存在を確認
  2. 環境変数の設定を確認
  3. Firebase プロジェクトの権限を確認

📝 デバッグ時のベストプラクティス

  1. ログレベルの使い分け

    • ERROR: システムエラー
    • WARN: 警告
    • INFO: 一般的な情報
    • DEBUG: 詳細なデバッグ情報
  2. 構造化されたログ

    logger.info(f"API呼び出し: method={method}, path={path}, user_id={user_id}")
  3. エラーハンドリング

    • 例外を適切にキャッチ
    • ユーザーフレンドリーなエラーメッセージ
    • 詳細なログ出力
  4. テスト駆動開発

    • 単体テストでデバッグ
    • 統合テストでフローテスト
    • 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

このガイドを参考に、効率的なデバッグを行い、問題の早期発見と解決を実現してください。