middleware.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. """
  2. 日志 django中间件
  3. """
  4. import json
  5. import logging
  6. from django.conf import settings
  7. from django.contrib.auth.models import AnonymousUser
  8. from django.http import HttpResponse, HttpResponseServerError
  9. from django.utils.deprecation import MiddlewareMixin
  10. from dvadmin.system.models import OperationLog
  11. from dvadmin.utils.request_util import get_request_user, get_request_ip, get_request_data, get_request_path, get_os, \
  12. get_browser, get_verbose_name
  13. class ApiLoggingMiddleware(MiddlewareMixin):
  14. """
  15. 用于记录API访问日志中间件
  16. """
  17. def __init__(self, get_response=None):
  18. super().__init__(get_response)
  19. self.enable = getattr(settings, 'API_LOG_ENABLE', None) or False
  20. self.methods = getattr(settings, 'API_LOG_METHODS', None) or set()
  21. self.operation_log_id = None
  22. @classmethod
  23. def __handle_request(cls, request):
  24. request.request_ip = get_request_ip(request)
  25. request.request_data = get_request_data(request)
  26. request.request_path = get_request_path(request)
  27. def __handle_response(self, request, response):
  28. # request_data,request_ip由PermissionInterfaceMiddleware中间件中添加的属性
  29. body = getattr(request, 'request_data', {})
  30. # 请求含有password则用*替换掉(暂时先用于所有接口的password请求参数)
  31. if isinstance(body, dict) and body.get('password', ''):
  32. body['password'] = '*' * len(body['password'])
  33. if not hasattr(response, 'data') or not isinstance(response.data, dict):
  34. response.data = {}
  35. try:
  36. if not response.data and response.content:
  37. content = json.loads(response.content.decode())
  38. response.data = content if isinstance(content, dict) else {}
  39. except Exception:
  40. return
  41. user = get_request_user(request)
  42. info = {
  43. 'request_ip': getattr(request, 'request_ip', 'unknown'),
  44. 'creator': user if not isinstance(user, AnonymousUser) else None,
  45. 'dept_belong_id': getattr(request.user, 'dept_id', None),
  46. 'request_method': request.method,
  47. 'request_path': request.request_path,
  48. 'request_body': body,
  49. 'response_code': response.data.get('code'),
  50. 'request_os': get_os(request),
  51. 'request_browser': get_browser(request),
  52. 'request_msg': request.session.get('request_msg'),
  53. 'status': True if response.data.get('code') in [2000, ] else False,
  54. 'json_result': {"code": response.data.get('code'), "msg": response.data.get('msg')},
  55. }
  56. operation_log, creat = OperationLog.objects.update_or_create(defaults=info, id=self.operation_log_id)
  57. if not operation_log.request_modular and settings.API_MODEL_MAP.get(request.request_path, None):
  58. operation_log.request_modular = settings.API_MODEL_MAP[request.request_path]
  59. operation_log.save()
  60. def process_view(self, request, view_func, view_args, view_kwargs):
  61. if hasattr(view_func, 'cls') and hasattr(view_func.cls, 'queryset'):
  62. if self.enable:
  63. if self.methods == 'ALL' or request.method in self.methods:
  64. log = OperationLog(request_modular=get_verbose_name(view_func.cls.queryset))
  65. log.save()
  66. self.operation_log_id = log.id
  67. return
  68. def process_request(self, request):
  69. self.__handle_request(request)
  70. def process_response(self, request, response):
  71. """
  72. 主要请求处理完之后记录
  73. :param request:
  74. :param response:
  75. :return:
  76. """
  77. if self.enable:
  78. if self.methods == 'ALL' or request.method in self.methods:
  79. self.__handle_response(request, response)
  80. return response
  81. logger = logging.getLogger("healthz")
  82. class HealthCheckMiddleware(object):
  83. """
  84. 存活检查中间件
  85. """
  86. def __init__(self, get_response):
  87. self.get_response = get_response
  88. # One-time configuration and initialization.
  89. def __call__(self, request):
  90. if request.method == "GET":
  91. if request.path == "/readiness":
  92. return self.readiness(request)
  93. elif request.path == "/healthz":
  94. return self.healthz(request)
  95. return self.get_response(request)
  96. def healthz(self, request):
  97. """
  98. Returns that the server is alive.
  99. """
  100. return HttpResponse("OK")
  101. def readiness(self, request):
  102. # Connect to each database and do a generic standard SQL query
  103. # that doesn't write any data and doesn't depend on any tables
  104. # being present.
  105. try:
  106. from django.db import connections
  107. for name in connections:
  108. cursor = connections[name].cursor()
  109. cursor.execute("SELECT 1;")
  110. row = cursor.fetchone()
  111. if row is None:
  112. return HttpResponseServerError("db: invalid response")
  113. except Exception as e:
  114. logger.exception(e)
  115. return HttpResponseServerError("db: cannot connect to database.")
  116. # Call get_stats() to connect to each memcached instance and get it's stats.
  117. # This can effectively check if each is online.
  118. try:
  119. from django.core.cache import caches
  120. from django.core.cache.backends.memcached import BaseMemcachedCache
  121. for cache in caches.all():
  122. if isinstance(cache, BaseMemcachedCache):
  123. stats = cache._cache.get_stats()
  124. if len(stats) != len(cache._servers):
  125. return HttpResponseServerError("cache: cannot connect to cache.")
  126. except Exception as e:
  127. logger.exception(e)
  128. return HttpResponseServerError("cache: cannot connect to cache.")
  129. return HttpResponse("OK")