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()
import uuid
from datetime import datetime
from django.db import IntegrityError
from django.conf import settings
from django.urls import reverse
@ -851,12 +852,22 @@ class EntrySerializer(serializers.ModelSerializer):
def to_representation(self, instance):
ret = super().to_representation(instance)
ret['team'] = TeamSerializer(instance.team).data
ret['event'] = NewEvent2Serializer(instance.event).data
ret['category'] = NewCategorySerializer(instance.category).data
ret['owner'] = CustomUserSerializer(instance.owner).data
if isinstance(ret['date'], datetime):
# instance が辞書の場合(エラー時)は基本情報のみ返す
if isinstance(instance, dict):
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.get('date'), datetime):
ret['date'] = ret['date'].date().isoformat()
elif isinstance(ret['date'], date):
ret['date'] = ret['date'].isoformat()

View File

@ -1748,7 +1748,11 @@ class EntryViewSet(viewsets.ModelViewSet):
else:
logger.info("External system registered successfully")
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):
@ -1768,7 +1772,26 @@ class EntryViewSet(viewsets.ModelViewSet):
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
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):