|
|
|
|
@ -0,0 +1,81 @@
|
|
|
|
|
import logging
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
from ipware import get_client_ip # 用于获取客户端IP地址
|
|
|
|
|
from user_agents import parse # 用于解析用户代理字符串
|
|
|
|
|
|
|
|
|
|
# 从blog应用导入Elasticsearch相关配置和管理器
|
|
|
|
|
from blog.documents import ELASTICSEARCH_ENABLED, ElaspedTimeDocumentManager
|
|
|
|
|
|
|
|
|
|
# 获取当前模块的日志记录器
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class OnlineMiddleware(object):
|
|
|
|
|
"""
|
|
|
|
|
在线用户中间件类
|
|
|
|
|
功能:记录页面渲染时间、用户访问信息,并在页面中显示加载时间
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, get_response=None):
|
|
|
|
|
"""
|
|
|
|
|
初始化中间件
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
get_response: Django框架提供的获取响应的方法
|
|
|
|
|
"""
|
|
|
|
|
self.get_response = get_response
|
|
|
|
|
super().__init__()
|
|
|
|
|
|
|
|
|
|
def __call__(self, request):
|
|
|
|
|
''' 主要处理逻辑:计算和记录页面渲染时间 '''
|
|
|
|
|
|
|
|
|
|
# 记录请求开始处理的时间戳
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
|
|
|
|
# 调用后续中间件和视图函数,获取最终的HTTP响应对象
|
|
|
|
|
response = self.get_response(request)
|
|
|
|
|
|
|
|
|
|
# 从请求的META信息中获取用户代理字符串,如果不存在则使用空字符串
|
|
|
|
|
http_user_agent = request.META.get('HTTP_USER_AGENT', '')
|
|
|
|
|
|
|
|
|
|
# 获取客户端IP地址,ip是真实IP,第二个返回值可能是代理IP(这里用_忽略)
|
|
|
|
|
ip, _ = get_client_ip(request)
|
|
|
|
|
|
|
|
|
|
# 解析用户代理字符串,获取浏览器、设备等信息
|
|
|
|
|
user_agent = parse(http_user_agent)
|
|
|
|
|
|
|
|
|
|
# 检查响应是否为流式响应(如文件下载),非流式响应才进行处理
|
|
|
|
|
if not response.streaming:
|
|
|
|
|
try:
|
|
|
|
|
# 计算从请求开始到响应生成的总耗时(单位:秒)
|
|
|
|
|
cast_time = time.time() - start_time
|
|
|
|
|
|
|
|
|
|
# 如果Elasticsearch功能已启用,记录详细的访问信息
|
|
|
|
|
if ELASTICSEARCH_ENABLED:
|
|
|
|
|
# 将耗时从秒转换为毫秒,并保留2位小数
|
|
|
|
|
time_taken = round((cast_time) * 1000, 2)
|
|
|
|
|
# 获取请求的URL路径
|
|
|
|
|
url = request.path
|
|
|
|
|
# 延迟导入,避免循环依赖
|
|
|
|
|
from django.utils import timezone
|
|
|
|
|
# 创建Elasticsearch文档记录访问信息
|
|
|
|
|
ElaspedTimeDocumentManager.create(
|
|
|
|
|
url=url, # 访问的URL路径
|
|
|
|
|
time_taken=time_taken, # 页面渲染耗时(毫秒)
|
|
|
|
|
log_datetime=timezone.now(), # 记录创建的时间戳
|
|
|
|
|
useragent=user_agent, # 解析后的用户代理对象
|
|
|
|
|
ip=ip) # 客户端IP地址
|
|
|
|
|
|
|
|
|
|
# 在响应内容中替换占位符为实际的加载时间
|
|
|
|
|
# 将耗时转换为字符串,取前5位(避免过长),然后编码为字节
|
|
|
|
|
# 替换模板中的<!!LOAD_TIMES!!>占位符
|
|
|
|
|
response.content = response.content.replace(
|
|
|
|
|
b'<!!LOAD_TIMES!!>', str.encode(str(cast_time)[:5]))
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
# 捕获并记录处理过程中可能出现的任何异常
|
|
|
|
|
logger.error("Error OnlineMiddleware: %s" % e)
|
|
|
|
|
|
|
|
|
|
# 返回处理后的响应对象
|
|
|
|
|
return response
|