[Python] Django记录请求和响应信息的日志装饰器

1. Django记录请求和响应信息的日志装饰器

写一个Django记录请求和响应信息的日志装饰器,接收请求时,记录请求的请求地址、请求方法、请求路径、请求信息,返回状态码、返回内容长度。

from functools import wraps

def http_logger(logger):
    def logging_decorator(func):
        @wraps(func)
        def wrapped_function(*args, **kwargs):
            request = args[0]
            response = func(*args, **kwargs)
            logger.info(f'Received Request: {request.META["REMOTE_ADDR"]} {request.method} "{request.META["PATH_INFO"]}'
                        f'{request.META["QUERY_STRING"]} {request.META["SERVER_PROTOCOL"]}" {response.status_code} {len(response.content)}')
            return response
        return wrapped_function
    return logging_decorator

2. 使用日志装饰器

日志logger可以使用python自带的logging模块创建的logger。也可以使用后文的logging代码。

from Log.logging import Logger
from Log.logging import http_logger
logger = Logger()

@http_logger(logger=logger)
def index_handler(request):
    return render(request, 'index.html')

访问输出结果如下:

2020-12-07 17:11:20,099  [logging.py 18] : Received Request: 127.0.0.1 GET "/ HTTP/1.1" 200 858

3. 单例日志模块

使用方式参考__main__

"""
我们的目的是借助单例模式,只生成一个logger。
当日志文件已经存在时,默认以追加方式写入。
"""
import logging
import os
import time
import sys

class SingletonType(type):
    _instances = {}
    
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonType, cls).__call__(*args, **kwargs)
        return cls._instances[cls]
    

class Logger(metaclass=SingletonType):
    def __new__(cls, log_file=None, file_output=True, standard_output=True):
        """
        1. Logger的__new__只在创建第一个实例的时候被调用。
        2. 我们要返回的不是Logger类实例,而是使用内置logging模块创建的实例。
        """
        # 日志文件的路径
        if log_file is None:
            # 文件的当前目录
            current_path = os.path.dirname(os.path.realpath(__file__))
            current_time = time.strftime("%Y-%m-%d-%H%M%S", time.localtime())
            log_file = os.path.join(current_path, 'log_output', f'{current_time}.txt')
            os.makedirs(os.path.dirname(log_file), exist_ok=True)

        cls.logger = logging.getLogger(__name__)
        formater = logging.Formatter('%(asctime)s  [%(filename)s %(lineno)s] : %(message)s')
        # 如果既不使用标准输出,也不使用日志文件输出,则选择标准输出
        if not file_output and not standard_output:
            standard_output = True
        if standard_output:
            # 标准输出
            standard_out = logging.StreamHandler(sys.stdout)
            standard_out.setFormatter(formater)
            cls.logger.addHandler(standard_out)    # 添加标准输出
        if file_output:
            # 日志文件输出
            file_out = logging.FileHandler(log_file)
            file_out.setFormatter(formater)
            cls.logger.addHandler(file_out)    # 添加文件输出
            cls.logger.setLevel(logging.INFO)
        return cls.logger


if __name__ == '__main__':
    logger = Logger("Logger1",standard_output=True, file_output=True)  # 只第一个名称有效
    logger2 = Logger("Logger2")	# 因为是单例模式,logger2其实都是logger1
    logger3 = Logger("Logger3")	# 因为是单例模式,logger3其实都是logger1
    logger.info("This is a info")
    print(logger is logger2, logger2 is logger3)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值