-
Notifications
You must be signed in to change notification settings - Fork 2.8k
feat: log management #3189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: log management #3189
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # coding=utf-8 | ||
| """ | ||
| @project: MaxKB | ||
| @Author:虎虎 | ||
| @file: log.py | ||
| @date:2025/6/4 14:13 | ||
| @desc: | ||
| """ | ||
|
|
||
| from system_manage.models.log_management import Log | ||
|
|
||
|
|
||
| def _get_ip_address(request): | ||
| """ | ||
| 获取ip地址 | ||
| @param request: | ||
| @return: | ||
| """ | ||
| x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') | ||
| if x_forwarded_for: | ||
| ip = x_forwarded_for.split(',')[0] | ||
| else: | ||
| ip = request.META.get('REMOTE_ADDR') | ||
| return ip | ||
|
|
||
|
|
||
| def _get_user(request): | ||
| """ | ||
| 获取用户 | ||
| @param request: | ||
| @return: | ||
| """ | ||
| user = request.user | ||
| if user is None: | ||
| return { | ||
|
|
||
| } | ||
| return { | ||
| "id": str(user.id), | ||
| "email": user.email, | ||
| "phone": user.phone, | ||
| "nick_name": user.nick_name, | ||
| "username": user.username, | ||
| "role": user.role, | ||
| } | ||
|
|
||
|
|
||
| def _get_details(request): | ||
| path = request.path | ||
| body = request.data | ||
| query = request.query_params | ||
| return { | ||
| 'path': path, | ||
| 'body': body, | ||
| 'query': query | ||
| } | ||
|
|
||
|
|
||
| def log(menu: str, operate, get_user=_get_user, get_ip_address=_get_ip_address, get_details=_get_details, | ||
| get_operation_object=None): | ||
| """ | ||
| 记录审计日志 | ||
| @param menu: 操作菜单 str | ||
| @param operate: 操作 str|func 如果是一个函数 入参将是一个request 响应为str def operate(request): return "操作菜单" | ||
| @param get_user: 获取用户 | ||
| @param get_ip_address:获取IP地址 | ||
| @param get_details: 获取执行详情 | ||
| @param get_operation_object: 获取操作对象 | ||
| @return: | ||
| """ | ||
|
|
||
| def inner(func): | ||
| def run(view, request, **kwargs): | ||
| status = 200 | ||
| operation_object = {} | ||
| try: | ||
| if get_operation_object is not None: | ||
| operation_object = get_operation_object(request, kwargs) | ||
| except Exception as e: | ||
| pass | ||
| try: | ||
| return func(view, request, **kwargs) | ||
| except Exception as e: | ||
| status = 500 | ||
| raise e | ||
| finally: | ||
| ip = get_ip_address(request) | ||
| user = get_user(request) | ||
| details = get_details(request) | ||
| _operate = operate | ||
| if callable(operate): | ||
| _operate = operate(request) | ||
| # 插入审计日志 | ||
| Log(menu=menu, operate=_operate, user=user, status=status, ip_address=ip, details=details, | ||
| operation_object=operation_object).save() | ||
|
|
||
| return run | ||
|
|
||
| return inner | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| # Generated by Django 5.2 on 2025-06-04 06:17 | ||
|
|
||
| import common.encoder.encoder | ||
| import uuid | ||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
|
|
||
| dependencies = [ | ||
| ('system_manage', '0003_workspaceuserresourcepermission_and_more'), | ||
| ] | ||
|
|
||
| operations = [ | ||
| migrations.CreateModel( | ||
| name='Log', | ||
| fields=[ | ||
| ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')), | ||
| ('update_time', models.DateTimeField(auto_now=True, verbose_name='修改时间')), | ||
| ('id', models.UUIDField(default=uuid.uuid1, editable=False, primary_key=True, serialize=False, verbose_name='主键id')), | ||
| ('menu', models.CharField(max_length=128, verbose_name='操作菜单')), | ||
| ('operate', models.CharField(max_length=128, verbose_name='操作')), | ||
| ('operation_object', models.JSONField(default=dict, encoder=common.encoder.encoder.SystemEncoder, verbose_name='操作对象')), | ||
| ('user', models.JSONField(default=dict, verbose_name='用户信息')), | ||
| ('status', models.IntegerField(verbose_name='状态')), | ||
| ('ip_address', models.CharField(max_length=128, verbose_name='ip地址')), | ||
| ('details', models.JSONField(default=dict, encoder=common.encoder.encoder.SystemEncoder, verbose_name='详情')), | ||
| ], | ||
| options={ | ||
| 'db_table': 'log', | ||
| }, | ||
| ), | ||
| ] | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are no significant issues with the provided code snippet for creating a migration to introduce a new
Overall, the migration looks clean and straightforward, suitable for adding a logging system to your Django application. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,3 +8,4 @@ | |
| """ | ||
| from .workspace_user_permission import * | ||
| from .system_setting import * | ||
| from .log_management import * | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| # coding=utf-8 | ||
| """ | ||
| @project: MaxKB | ||
| @Author:虎虎 | ||
| @file: log_management.py | ||
| @date:2025/6/4 14:15 | ||
| @desc: | ||
| """ | ||
| import uuid | ||
|
|
||
| from django.db import models | ||
|
|
||
| from common.encoder.encoder import SystemEncoder | ||
| from common.mixins.app_model_mixin import AppModelMixin | ||
|
|
||
|
|
||
| class Log(AppModelMixin): | ||
| """ | ||
| 审计日志 | ||
| """ | ||
| id = models.UUIDField(primary_key=True, max_length=128, default=uuid.uuid1, editable=False, verbose_name="主键id") | ||
|
|
||
| menu = models.CharField(max_length=128, verbose_name="操作菜单") | ||
|
|
||
| operate = models.CharField(max_length=128, verbose_name="操作") | ||
|
|
||
| operation_object = models.JSONField(verbose_name="操作对象", default=dict, encoder=SystemEncoder) | ||
|
|
||
| user = models.JSONField(verbose_name="用户信息", default=dict) | ||
|
|
||
| status = models.IntegerField(verbose_name="状态") | ||
|
|
||
| ip_address = models.CharField(max_length=128, verbose_name="ip地址") | ||
|
|
||
| details = models.JSONField(verbose_name="详情", default=dict, encoder=SystemEncoder) | ||
|
|
||
| class Meta: | ||
| db_table = "log" | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are several potential improvements and corrections needed in this Python code:
Here’s an updated version of your code with these changes: # coding=utf-8
"""
@project: MaxKB
@Author:虎虎
@file: log_management.py
@date:2025/6/4 14:15
@desc:
"""
import uuid
from django.conf import settings
from django.db import models
from common.encoder.encoder import SystemEncoder
from common.mixins.app_model_mixin import AppModelMixin
class Log(AppModelMixin):
"""
审计日志
"""
# Explicitly specify UUID type
id = models.UUIDField(primary_key=True, max_length=128)
# Define char fields properly
menu = models.CharField(max_length=settings.MAX_LENGTH_MENU, verbose_name="操作菜单")
operate = models.CharField(max_length=settings.MAX_LENGTH_OPERATE, verbose_name="操作")
# Initialize JSON fields properly
operation_object = models.JSONField(verbose_name="操作对象", default={}, encoder=SystemEncoder)
user = models.JSONField(verbose_name="用户信息", default={})
status = models.IntegerField(verbose_name="状态")
ip_address = models.CharField(max_length=settings.MAX_LENGTH_IP_ADDRESS, verbose_name="ip地址")
details = models.JSONField(verbose_name="详情", default={}, encoder=SystemEncoder)
class Meta:
db_table = "log"Key Changes:
Additional Recommendations:
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review and Suggestions
1. Function Definitions
_get_ip_address,_get_user,log) should be at the top of the file to ensure readability.2. Class Imports
Logfromsystem_manage.models.log_managementis correctly imported and available in this module scope.3. Method Decorators
The decorator pattern used in the
runfunction can be made more concise using Python'sfunctools.wraps.Remove duplicate variable names like
request. For examplerequestcan be simply referred to asview.request.4. String Formatting
Use formatted string literals (f-strings) instead of concatenation for cleaner code.
Example: Replace
"操作菜单"with{operate}if it's supposed to display the result of executing theoperatefunction.5. Error Handling
function(view, request, **kwargs)even when wrapped by another try-except block.6. Comments for Clarity
get_operation_objectraises an error.7. Return Statements
8. Logging Structure
9. Security Considerations
Final Revised Code:
Key Changes Made: