log.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # -*- coding: utf-8 -*-
  2. # @Author : YY
  3. from datetime import datetime
  4. from functools import wraps
  5. from typing import Any, Callable
  6. from werkzeug.exceptions import HTTPException
  7. from flask import Response, request
  8. from pydantic import BaseModel
  9. from ruoyi_common.domain.entity import LoginUser
  10. from ruoyi_common.domain.enum import BusinessStatus, BusinessType,OperatorType
  11. from ruoyi_common.utils import IpUtil
  12. from ruoyi_common.utils import security_util as SecurityUtil
  13. from ruoyi_common.base.signal import log_signal
  14. from ruoyi_common.utils.base import DescriptUtil
  15. from ruoyi_framework.asyncsched.manager import TaskManager
  16. from ruoyi_framework.asyncsched.task import record_operlog
  17. from ruoyi_system.domain.entity import SysOperLog
  18. class Log:
  19. def __init__(self,
  20. title:str,
  21. business_type:BusinessType=BusinessType.OTHER,
  22. operator_type:BusinessType=OperatorType.MANAGE,
  23. is_save_request_data:bool=True,
  24. is_save_response_data:bool=True
  25. ):
  26. self.title = title
  27. self.business_type = business_type
  28. self.operator_type = operator_type
  29. self.is_save_request_data = is_save_request_data
  30. self.is_save_response_data = is_save_response_data
  31. self._oper_log = SysOperLog()
  32. self._oper_log.title = self.title
  33. self._oper_log.business_type = self.business_type.value
  34. self._oper_log.operator_type = self.operator_type.value
  35. def __call__(self, func) -> Callable:
  36. raw_func = DescriptUtil.get_raw(func)
  37. log_signal.connect_via(sender=raw_func)(self.on_event)
  38. @wraps(func)
  39. def wrapper(*args: Any, **kwargs: Any) -> Any:
  40. rv = func(*args, **kwargs)
  41. return rv
  42. return wrapper
  43. def on_event(self, sender, **kwargs):
  44. '''
  45. 监听信号
  46. Args:
  47. sender: 信号发送者
  48. **kwargs: 信号消息
  49. '''
  50. message = kwargs.get('message')
  51. self.handle_request(sender)
  52. self.handle_login_user()
  53. if isinstance(message, HTTPException):
  54. self.handle_exception(message)
  55. else:
  56. self.handle_response(message)
  57. TaskManager.execute(record_operlog,self._oper_log)
  58. def handle_exception(self, e:Exception):
  59. '''
  60. 处理异常
  61. Args:
  62. e(Exception): 异常
  63. '''
  64. self._oper_log.status = BusinessStatus.FAIL.value
  65. self._oper_log.error_msg = str(e)[:2000]
  66. def handle_login_user(self):
  67. '''
  68. 处理登录用户
  69. Args:
  70. login_user(LoginUser): 登录用户
  71. '''
  72. self._oper_log.status = BusinessStatus.SUCCESS.value
  73. login_user:LoginUser = SecurityUtil.get_login_user()
  74. if login_user:
  75. self._oper_log.oper_name = login_user.user_name
  76. def handle_request(self, func):
  77. '''
  78. 处理请求参数
  79. Args:
  80. func: 被装饰的函数
  81. '''
  82. if self.is_save_request_data:
  83. json_param = request.get_data(as_text=True)
  84. self._oper_log.oper_ip = IpUtil.get_ip()
  85. self._oper_log.oper_param = json_param[:2000] if json_param else ""
  86. self._oper_log.request_method = request.method
  87. self._oper_log.oper_url = request.path
  88. self._oper_log.method = "{}.{}".format(func.__module__, func.__name__)
  89. self._oper_log.oper_time = datetime.now()
  90. def handle_response(self, response:Response|BaseModel):
  91. '''
  92. 处理响应参数
  93. Args:
  94. response(Response|BaseModel): 响应参数
  95. '''
  96. if self.is_save_response_data:
  97. if isinstance(response, BaseModel):
  98. self._oper_log.json_result = response.model_dump_json(exclude_none=True)[:2000]
  99. elif isinstance(response, Response):
  100. print("handle_response response: {}".format(response))
  101. json_result = response.get_data(as_text=False)
  102. if json_result:
  103. self._oper_log.json_result = json_result[:2000]