Fix Entry issue

This commit is contained in:
2025-09-06 03:21:36 +09:00
parent a24a0decb9
commit bcd0bee738
3 changed files with 207 additions and 7 deletions

166
monitor_app_errors.py Normal file
View File

@ -0,0 +1,166 @@
#!/usr/bin/env python3
"""
スマホアプリエラー監視ツール: リアルタイムで400エラーを監視
"""
import subprocess
import re
import time
from datetime import datetime
import json
def monitor_app_errors():
"""
スマホアプリの400エラーをリアルタイム監視
"""
print("🔍 スマホアプリエラー監視開始")
print("=" * 60)
print("Ctrl+C で停止")
print()
try:
# docker compose logs --follow で継続監視
process = subprocess.Popen(
['docker', 'compose', 'logs', '--follow', 'app'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1,
universal_newlines=True
)
error_patterns = {
'checkin_400': re.compile(r'Bad Request.*checkin_from_rogapp', re.I),
'member_400': re.compile(r'Bad Request.*members', re.I),
'team_400': re.compile(r'Bad Request.*teams', re.I),
'validation_error': re.compile(r'Validation error.*({.*})', re.I),
'checkin_start_error': re.compile(r'Team has not started yet.*team_name: \'([^\']+)\'.*cp_number: (\d+)', re.I),
'dart_request': re.compile(r'Dart/\d+\.\d+.*"([A-Z]+)\s+([^"]+)".*(\d{3})', re.I)
}
print(f"🎯 監視対象パターン:")
for name, pattern in error_patterns.items():
print(f"{name}")
print()
while True:
line = process.stdout.readline()
if not line:
break
timestamp = datetime.now().strftime("%H:%M:%S")
# Dartクライアントスマホアプリのリクエスト監視
dart_match = error_patterns['dart_request'].search(line)
if dart_match and 'Dart/' in line:
method = dart_match.group(1)
path = dart_match.group(2)
status = dart_match.group(3)
if status.startswith('4'): # 4xx エラー
print(f"❌ [{timestamp}] スマホアプリエラー: {method} {path} → HTTP {status}")
elif status.startswith('2'): # 2xx 成功
if any(keyword in path.lower() for keyword in ['checkin', 'teams', 'members']):
print(f"✅ [{timestamp}] スマホアプリ成功: {method} {path} → HTTP {status}")
# チェックインスタートエラー監視
start_error_match = error_patterns['checkin_start_error'].search(line)
if start_error_match:
team_name = start_error_match.group(1)
cp_number = start_error_match.group(2)
print(f"⚠️ [{timestamp}] チェックインエラー: チーム'{team_name}'がCP{cp_number}でスタート前チェックイン試行")
print(f" 💡 解決策: 先にstart_from_rogappでスタート処理が必要")
# バリデーションエラー監視
validation_match = error_patterns['validation_error'].search(line)
if validation_match:
try:
error_details = validation_match.group(1)
print(f"❌ [{timestamp}] バリデーションエラー: {error_details}")
if 'date_of_birth' in error_details:
print(f" 💡 date_of_birthフィールドの問題 - MemberCreationSerializerを確認")
except:
print(f"❌ [{timestamp}] バリデーションエラー詳細を解析できませんでした")
# 一般的な400エラー監視
for pattern_name, pattern in error_patterns.items():
if pattern_name in ['dart_request', 'checkin_start_error', 'validation_error']:
continue
if pattern.search(line):
print(f"❌ [{timestamp}] {pattern_name}: {line.strip()}")
except KeyboardInterrupt:
print(f"\n\n🛑 監視を停止しました")
process.terminate()
except Exception as e:
print(f"❌ 監視エラー: {e}")
if 'process' in locals():
process.terminate()
def analyze_current_issues():
"""
現在の問題を分析
"""
print("📊 現在の問題分析")
print("-" * 40)
try:
# 最近のエラーログを分析
result = subprocess.run(
['docker', 'compose', 'logs', '--tail=100', 'app'],
capture_output=True,
text=True
)
lines = result.stdout.split('\n')
# チェックインエラーの分析
checkin_errors = []
validation_errors = []
for line in lines:
if 'Team has not started yet' in line:
match = re.search(r'team_name: \'([^\']+)\'.*cp_number: (\d+)', line)
if match:
checkin_errors.append((match.group(1), match.group(2)))
if 'Validation error' in line and 'date_of_birth' in line:
validation_errors.append(line)
print(f"🔍 分析結果:")
print(f" • チェックインスタートエラー: {len(checkin_errors)}")
for team, cp in checkin_errors[-3:]: # 最新3件
print(f" - チーム'{team}' → CP{cp}")
print(f" • date_of_birthバリデーションエラー: {len(validation_errors)}")
if checkin_errors:
print(f"\n💡 推奨対策:")
print(f" 1. スマホアプリでスタート処理を実行")
print(f" 2. start_from_rogapp API の正常動作確認")
if validation_errors:
print(f" 3. MemberCreationSerializerの再確認")
except Exception as e:
print(f"❌ 分析エラー: {e}")
def main():
"""
メイン関数
"""
print("📱 スマホアプリエラー監視ツール")
print("=" * 60)
choice = input("選択してください:\n1. リアルタイム監視\n2. 現在の問題分析\n選択 (1/2): ")
if choice == "1":
monitor_app_errors()
elif choice == "2":
analyze_current_issues()
else:
print("無効な選択です")
if __name__ == "__main__":
main()

View File

@ -4,6 +4,7 @@ from django.contrib.auth import get_user_model
User = get_user_model() User = get_user_model()
import uuid import uuid
from datetime import datetime
from django.db import IntegrityError from django.db import IntegrityError
from django.conf import settings from django.conf import settings
from django.urls import reverse from django.urls import reverse
@ -851,12 +852,22 @@ class EntrySerializer(serializers.ModelSerializer):
def to_representation(self, instance): def to_representation(self, instance):
ret = super().to_representation(instance) ret = super().to_representation(instance)
ret['team'] = TeamSerializer(instance.team).data
ret['event'] = NewEvent2Serializer(instance.event).data # instance が辞書の場合(エラー時)は基本情報のみ返す
ret['category'] = NewCategorySerializer(instance.category).data if isinstance(instance, dict):
ret['owner'] = CustomUserSerializer(instance.owner).data return ret
# 正常な場合のみ関連オブジェクトを追加
if hasattr(instance, 'team') and instance.team:
ret['team'] = TeamSerializer(instance.team).data
if hasattr(instance, 'event') and instance.event:
ret['event'] = NewEvent2Serializer(instance.event).data
if hasattr(instance, 'category') and instance.category:
ret['category'] = NewCategorySerializer(instance.category).data
if hasattr(instance, 'owner') and instance.owner:
ret['owner'] = CustomUserSerializer(instance.owner).data
if isinstance(ret['date'], datetime): if isinstance(ret.get('date'), datetime):
ret['date'] = ret['date'].date().isoformat() ret['date'] = ret['date'].date().isoformat()
elif isinstance(ret['date'], date): elif isinstance(ret['date'], date):
ret['date'] = ret['date'].isoformat() ret['date'] = ret['date'].isoformat()

View File

@ -1748,7 +1748,11 @@ class EntryViewSet(viewsets.ModelViewSet):
else: else:
logger.info("External system registered successfully") logger.info("External system registered successfully")
except Exception as e: except Exception as e:
logger.exception(f"Error creating Entry: {str(e)}") logger.error(f"Error creating Entry: {e}")
if hasattr(e, 'message_dict'):
logger.error(f"Validation details: {e.message_dict}")
# perform_createで例外を発生させて、createメソッドでキャッチ
raise e
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
@ -1768,7 +1772,26 @@ class EntryViewSet(viewsets.ModelViewSet):
headers = self.get_success_headers(serializer.data) headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
except DjangoValidationError as e: except DjangoValidationError as e:
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST) # バリデーションエラーの詳細をログに記録
error_details = e.message_dict if hasattr(e, 'message_dict') else str(e)
logger.error(f"Entry validation error: {error_details}")
# ユーザーフレンドリーなエラーメッセージを作成
if '__all__' in error_details and '男性のみ参加可能' in str(error_details):
error_message = "選択されたカテゴリーは男性のみ参加可能です。適切なカテゴリーを選択してください。"
elif '__all__' in error_details and '女性のみ参加可能' in str(error_details):
error_message = "選択されたカテゴリーは女性のみ参加可能です。適切なカテゴリーを選択してください。"
else:
error_message = str(e)
return Response({"error": error_message}, status=status.HTTP_400_BAD_REQUEST)
except Exception as e:
# その他のエラー
logger.exception(f"Unexpected error creating Entry: {str(e)}")
return Response(
{"error": "エントリー作成中に予期しないエラーが発生しました。しばらく後に再試行してください。"},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
def register_team(self, zekken_number, event_code, team_name, category_name, password): def register_team(self, zekken_number, event_code, team_name, category_name, password):