Django日志中要包括主机名、客户端IP

需求:

    分布式运行项目时,要日志记录中跟踪源IP地址与运行主机,以便更好的通过日志快速定位分析问题。

不借助django日志场景:

# 可以通过添加自定义日志过滤器和格式化程序来实现这一点,该过滤器和格式化程序将主机名放入日志消息中
import logging, platform

class HostnameFilter(logging.Filter):
    hostname = platform.node()   # 获取主机名
    def filter(self, record):
        record.hostname = HostnameFilter.hostname
        return True

handler = logging.StreamHandler()
handler.addFilter(HostnameFilter())
handler.setFormatter(logging.Formatter('%(asctime)s %(hostname)s: %(message)s', datefmt='%b %d %H:%M:%S'))
logger = logging.getLogger()
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.info('Hello, world!')

借助django日志场景:

1、自定义中间件

# 自定义中间件
import threading
import logging
import socket

try:
    from django.utils.deprecation import MiddlewareMixin
except ImportError:
    MiddlewareMixin = object
local = threading.local()

class RequestLogFilter(logging.Filter):
    """
    日志过滤器,将当前请求线程的request信息保存到日志的record上下文
    record带有formater需要的信息。
    """
    def filter(self, record):
        record.hostname =  getattr(local, 'hostname', None)   # 主机名称
        record.dest_ip =  getattr(local, 'dest_ip', None)     # 服务器IP
        record.username = getattr(local, 'username', None)    # 用户
        record.source_ip = getattr(local, 'source_ip', None)  # 客户端IP
        return True

class RequestLogMiddleware(MiddlewareMixin):
    """
    将request的信息记录在当前的请求线程上。
    """
    def process_request(self, request):
        local.hostname = socket.gethostname()
        local.dest_ip = socket.gethostbyname(local.hostname)
        local.username = request.user
        x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '')
        if x_forwarded_for:
            source_ip = x_forwarded_for.split(',')[0]   # 所以这里是真实的ip
        else:
            source_ip = request.META.get('REMOTE_ADDR') # 这里获得代理ip
        local.source_ip = source_ip

    def process_response(self, request, response):
        return response

2、settings.py   

 MIDDLEWARE新增中间件  ''firmware_manage.middlewares.RequestLogMiddleware'

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'firmware_manage.middlewares.RequestLogMiddleware',  # 自定义中间件 firmware_manage是app
]

# 日志文件配置
LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,    # 是否禁用已经存在的日志器
    'formatters': {                      # 日志信息显示的格式
        'verbose': {'format': '[%(asctime)s %(levelname)s [%(module)s:%(lineno)d] [%(process)d:%(threadName)s] %(message)s'},
        'simple':  {'format': '%(asctime)s %(levelname)s [%(module)s:%(lineno)d] %(message)s'},
        'complex': {'format': '[%(hostname)s source_ip:%(source_ip)s] [%(asctime)s %(levelname)s [%(module)s:%(lineno)d] [%(process)d:%(threadName)s] %(message)s'},
    },
    'filters': {
        'new_add': {
            '()': 'firmware_manage.middlewares.RequestLogFilter',
        },
    },
    'handlers': {          # 日志处理方法
        'console': {      # 向终端中输出日志
            'level': 'INFO',
            'filters': ['new_add'],
            'class': 'logging.StreamHandler',
            'formatter': 'complex'
        },
    },
    'loggers': {
        'django': {      # 定义了一个名为django的日志器
            'handlers': ['console'],              # 可以同时向终端与文件中输出日志
            'level': 'INFO',                      # 日志器接收的最低日志级别
            'propagate': False,                   # 是否继承父类的log信息,0:否 1:是
        },
    }
}

3、视图函数使用

import logging
logger = logging.getLogger("django")

@require_POST
def get_tasks(request):
    """
    func:
        任务管理页搜索
    """
    logger.info("in get tasks...")
    data = json.loads(request.body)

4、测试结果

非k8s部署,日志中携带主机名、客户端IP:
k8s部署,日志中携带运行的deployment、客户端IP:

参考:

        https://www.cnpython.com/qa/296606   Python日志如何在日志中跟踪主机名?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值