feat: Implement centralized error capture and handling with new middleware, services, and API endpoints, and add new admin and statistics API views.

This commit is contained in:
pacnpal
2026-01-02 15:55:42 -05:00
parent 1adba1b804
commit 95700c7d7b
43 changed files with 2477 additions and 158 deletions

View File

@@ -43,6 +43,7 @@ from apps.api.v1.serializers.accounts import (
UserPreferencesSerializer,
UserStatisticsSerializer,
)
from apps.core.utils import capture_and_log
from apps.lists.models import UserList
# Set up logging
@@ -198,16 +199,13 @@ def delete_user_preserve_submissions(request, user_id):
)
except Exception as e:
# Log the error for debugging
logger.error(
f"Error deleting user {user_id} by admin {request.user.username}: {str(e)}",
extra={
"admin_user": request.user.username,
"target_user_id": user_id,
"detail": str(e),
"action": "user_deletion_error",
},
exc_info=True,
# Capture error to dashboard
capture_and_log(
e,
f'Delete user {user_id} by admin {request.user.username}',
source='api',
request=request,
severity='high',
)
return Response(
@@ -333,7 +331,7 @@ def save_avatar_image(request):
)
except Exception as api_error:
logger.error(f"Error fetching image from Cloudflare API: {str(api_error)}", exc_info=True)
capture_and_log(api_error, 'Fetch image from Cloudflare API', source='api', request=request)
return Response(
{"detail": f"Failed to fetch image from Cloudflare: {str(api_error)}"},
status=status.HTTP_400_BAD_REQUEST,
@@ -357,7 +355,7 @@ def save_avatar_image(request):
service.delete_image(old_avatar)
logger.info(f"Successfully deleted old avatar from Cloudflare: {old_avatar.cloudflare_id}")
except Exception as e:
logger.error(f"Failed to delete old avatar from Cloudflare: {str(e)}")
capture_and_log(e, 'Delete old avatar from Cloudflare', source='api', request=request, severity='low')
# Continue with database deletion even if Cloudflare deletion fails
old_avatar.delete()
@@ -390,7 +388,7 @@ def save_avatar_image(request):
)
except Exception as e:
logger.error(f"Error saving avatar image: {str(e)}", exc_info=True)
capture_and_log(e, 'Save avatar image', source='api', request=request)
return Response(
{"detail": f"Failed to save avatar: {str(e)}"},
status=status.HTTP_400_BAD_REQUEST,
@@ -441,7 +439,7 @@ def delete_avatar(request):
service.delete_image(avatar_to_delete)
logger.info(f"Successfully deleted avatar from Cloudflare: {avatar_to_delete.cloudflare_id}")
except Exception as e:
logger.error(f"Failed to delete avatar from Cloudflare: {str(e)}")
capture_and_log(e, 'Delete avatar from Cloudflare', source='api', request=request, severity='low')
# Continue with database deletion even if Cloudflare deletion fails
avatar_to_delete.delete()
@@ -550,16 +548,13 @@ def request_account_deletion(request):
status=status.HTTP_400_BAD_REQUEST,
)
except Exception as e:
# Log the error for debugging
logger.error(
f"Error creating deletion request for user {request.user.username} (ID: {request.user.user_id}): {str(e)}",
extra={
"user": request.user.username,
"user_id": request.user.user_id,
"detail": str(e),
"action": "self_deletion_error",
},
exc_info=True,
# Capture error to dashboard
capture_and_log(
e,
f'Create deletion request for user {request.user.username}',
source='api',
request=request,
severity='high',
)
return Response(
@@ -1547,7 +1542,7 @@ def export_user_data(request):
export_data = UserExportService.export_user_data(request.user)
return Response(export_data, status=status.HTTP_200_OK)
except Exception as e:
logger.error(f"Error exporting data for user {request.user.id}: {e}", exc_info=True)
capture_and_log(e, 'Export user data', source='api', request=request)
return Response({"detail": "Failed to generate data export"}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)