django - 如何在 Django 中记录请求和响应?

标签 django http logging django-rest-framework gunicorn

如何使用中间件在 Django 中记录我的所有请求和响应( header 和正文)?
我将 Django 2.2 与 Django rest 框架一起使用,所以有时请求和响应是原始 Django 类型,有时是 drf。
该应用程序在 gunicorn 后面提供。
我开发了中间件,但主要问题是我无法读取请求的正文两次,因为它给了我错误。

最佳答案

这是在数据库中记录请求的示例。
Note :这将在每个请求中额外访问一次数据库。
所以它会减慢响应时间。
模型.py

class Request(models.Model):
    endpoint = models.CharField(max_length=100, null=True) # The url the user requested
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) # User that made request, if authenticated
    response_code = models.PositiveSmallIntegerField() # Response status code
    method = models.CharField(max_length=10, null=True)  # Request method
    remote_address = models.CharField(max_length=20, null=True) # IP address of user
    exec_time = models.IntegerField(null=True) # Time taken to create the response
    date = models.DateTimeField(auto_now=True) # Date and time of request
    body_response = models.TextField() # Response data
    body_request = models.TextField() # Request data
中间件.py
class SaveRequest:
    def __init__(self, get_response):
        self.get_response = get_response

        # Filter to log all request to url's that start with any of the strings below.
        # With example below:
        # /example/test/ will be logged.
        # /other/ will not be logged.
        self.prefixs = [
            '/example'
        ]

    def __call__(self, request):
        _t = time.time() # Calculated execution time.
        response = self.get_response(request) # Get response from view function.
        _t = int((time.time() - _t)*1000)    

        # If the url does not start with on of the prefixes above, then return response and dont save log.
        # (Remove these two lines below to log everything)
        if not list(filter(request.get_full_path().startswith, self.prefixs)): 
            return response 

        # Create instance of our model and assign values
        request_log = Request(
            endpoint=request.get_full_path(),
            response_code=response.status_code,
            method=request.method,
            remote_address=self.get_client_ip(request),
            exec_time=_t,
            body_response=str(response.content),
            body_request=str(request.body)
        )

        # Assign user to log if it's not an anonymous user
        if not request.user.is_anonymous:
            request_log.user = request.user

        # Save log in db
        request_log.save() 
        return response

    # get clients ip address
    def get_client_ip(self, request):
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
        if x_forwarded_for:
            _ip = x_forwarded_for.split(',')[0]
        else:
            _ip = request.META.get('REMOTE_ADDR')
        return _ip
settings.py
# Activate the middleware in settings.py like this.
MIDDLEWARE = [
    ... # Django default middleware
    '<your_appname>.middleware.SaveRequest'
]

关于django - 如何在 Django 中记录请求和响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63077587/

相关文章:

python - 如何在单击按钮后禁用按钮并在登录过程完成后通过检查 django 中的服务器响应来启用它

java - 使用 .pem 文件在 java 中发送 https 请求

http - 这是一个格式正确的多部分/表单数据请求吗?

authentication - 检查用户是否已登录的最安全方法是什么?

go - 高并发下Go `net/http`的一些困惑

java - 在 Java Logging Framework 中关闭日志消息

python - Django模型: Reference foreign key table in __unicode__ function for admin

python - 如何在 django_admin_log 中启用 django rest api CRUD 操作的日志记录?

python - Django 属性错误 : object has not attribute 'forms'

api - Paypal TLS 1.2 和 .NET 3.5 兼容性