How to log all errors related to an API request in Django Rest Framework along with multiple fields in a CSV file?

I want to log any type of error that occurs during an API request in Django Rest Framework into a CSV file, including the error message along with additional details like username, user ip, url, etc. I also want to capture errors that occur before reaching the view (e.g., errors related to JWT). I tried using middleware for this, but the issue was that some responses were not rendered correctly, and even after manually rendering, they still resulted in errors. I would appreciate it if you could suggest a solution.

The code below is the middleware I tried to use. I don't have an issue with logging errors that occur inside the view because if I only wanted to log errors within the view, I could use decorators or create a custom APIView. However, what I'm looking for is a way to log any type of error, even those that occur outside the view.

class ErrorLogMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
        self.filename = settings.ERROR_LOG_PATH
        self.fieldnames = ["Username", "IP", "User Agent", "Date/Time", "Time Interval", "Query", "Message", "URL"]

    def __call__(self, request):
        if not exists(self.filename):
            with open(self.filename, "a", newline="", encoding="utf-8") as csvfile:
                writer = DictWriter(csvfile, fieldnames=self.fieldnames)
                writer.writeheader()

        before = time()
        try:
            response = self.get_response(request)

            if response.status_code != 200:
                if hasattr(response, "render"):
                    if not response.is_rendered:
                        response.render()

                error = None
                if hasattr(response, "data"):
                    error = response.data
                else:
                    html_content = response.content.decode("utf-8")
                    error = html_content.split("</title>")[0].split("<title>")[1]

                self.submit_error(request, before, error)

            return response

        except Exception as e:
            self.submit_error(request, before, e)
            return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    def submit_error(self, request, before, error):
        after = time()
        query = ""

        for dic in connection.queries:
            query += f"{dic['sql']}\n"

        new_error_log = {
            "Username": request.user.username,
            "IP": get_user_ip(request),
            "User Agent": request.META.get("HTTP_USER_AGENT"),
            "Date/Time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            "Time Interval": after - before,
            "Query": query,
            "Message": str(error),
            "URL": request.get_full_path()
        }

        with open(self.filename, "a", newline="", encoding="utf-8") as csvfile:
            writer = DictWriter(csvfile, fieldnames=self.fieldnames)
            writer.writerow(new_error_log)

error: The response content must be rendered before it can be accessed

Вернуться на верх