Files
2026-08-05 23:59:15 +08:00

142 lines
6.0 KiB
Python

from django.db import models
from django.conf import settings
class ApiRequestLog(models.Model):
timestamp = models.DateTimeField('请求时间', auto_now_add=True, db_index=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True, blank=True,
related_name='api_request_logs',
verbose_name='用户'
)
username = models.CharField('用户名', max_length=150, default='', blank=True)
ip_address = models.GenericIPAddressField('IP地址', null=True, blank=True, db_index=True)
user_agent = models.CharField('User-Agent', max_length=500, default='', blank=True)
method = models.CharField('HTTP方法', max_length=10, db_index=True)
path = models.CharField('请求路径', max_length=255, db_index=True)
query_string = models.TextField('查询参数', default='', blank=True)
request_body = models.TextField('请求体', default='', blank=True)
status_code = models.IntegerField('状态码', db_index=True)
response_size = models.IntegerField('响应大小(字节)', default=0)
duration_ms = models.FloatField('耗时(毫秒)', db_index=True)
app_name = models.CharField('应用模块', max_length=50, default='', blank=True, db_index=True)
is_error = models.BooleanField('是否错误', default=False, db_index=True)
class Meta:
verbose_name = 'API请求日志'
verbose_name_plural = 'API请求日志'
ordering = ['-timestamp']
indexes = [
models.Index(fields=['timestamp', '-duration_ms'], name='idx_request_time_duration'),
models.Index(fields=['status_code', 'timestamp'], name='idx_request_status_time'),
]
def __str__(self):
return f'{self.method} {self.path} - {self.status_code} ({self.duration_ms:.1f}ms)'
class ErrorLog(models.Model):
LEVEL_CHOICES = [
('DEBUG', 'DEBUG'),
('INFO', 'INFO'),
('WARNING', 'WARNING'),
('ERROR', 'ERROR'),
('CRITICAL', 'CRITICAL'),
]
timestamp = models.DateTimeField('发生时间', auto_now_add=True, db_index=True)
level = models.CharField('日志级别', max_length=20, choices=LEVEL_CHOICES, default='ERROR', db_index=True)
message = models.TextField('日志消息')
module = models.CharField('发生模块', max_length=100, default='', blank=True, db_index=True)
function = models.CharField('发生函数', max_length=100, default='', blank=True)
line_number = models.IntegerField('行号', null=True, blank=True)
exception_type = models.CharField('异常类型', max_length=200, default='', blank=True)
traceback = models.TextField('堆栈信息', default='', blank=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True, blank=True,
related_name='error_logs',
verbose_name='用户'
)
ip_address = models.GenericIPAddressField('IP地址', null=True, blank=True)
path = models.CharField('请求路径', max_length=255, default='', blank=True)
request_data = models.TextField('请求数据', default='', blank=True)
is_resolved = models.BooleanField('是否已处理', default=False, db_index=True)
resolved_at = models.DateTimeField('处理时间', null=True, blank=True)
hash_key = models.CharField('错误Hash', max_length=64, unique=True, db_index=True)
occurrence_count = models.IntegerField('出现次数', default=1)
class Meta:
verbose_name = '错误日志'
verbose_name_plural = '错误日志'
ordering = ['-timestamp']
def __str__(self):
return f'[{self.level}] {self.exception_type}: {self.message[:50]}'
class SystemEventLog(models.Model):
EVENT_TYPE_CHOICES = [
('login', '用户登录'),
('logout', '用户登出'),
('register', '用户注册'),
('password_reset', '密码重置'),
('password_change', '密码修改'),
('profile_update', '资料更新'),
('phone_bind', '手机绑定'),
('email_bind', '邮箱绑定'),
('avatar_upload', '头像上传'),
('checkin', '每日签到'),
('points_change', '积分变动'),
('coins_change', 'y币变动'),
('article_create', '文章创建'),
('article_update', '文章更新'),
('article_delete', '文章删除'),
('comment_create', '评论创建'),
('favorite_add', '收藏添加'),
('favorite_remove', '收藏取消'),
('blacklist_add', '拉黑用户'),
('blacklist_remove', '取消拉黑'),
('admin_action', '管理员操作'),
('system_error', '系统错误'),
('other', '其他'),
]
RESULT_CHOICES = [
('success', '成功'),
('failed', '失败'),
('partial', '部分成功'),
]
timestamp = models.DateTimeField('事件时间', auto_now_add=True, db_index=True)
event_type = models.CharField('事件类型', max_length=50, choices=EVENT_TYPE_CHOICES, db_index=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='system_event_logs',
verbose_name='操作用户'
)
target_user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True, blank=True,
related_name='targeted_event_logs',
verbose_name='目标用户'
)
description = models.CharField('描述', max_length=500, default='', blank=True)
metadata = models.JSONField('额外数据', default=dict, blank=True)
ip_address = models.GenericIPAddressField('IP地址', null=True, blank=True)
user_agent = models.CharField('User-Agent', max_length=500, default='', blank=True)
result = models.CharField('结果', max_length=20, choices=RESULT_CHOICES, default='success', db_index=True)
class Meta:
verbose_name = '系统事件日志'
verbose_name_plural = '系统事件日志'
ordering = ['-timestamp']
def __str__(self):
return f'{self.get_event_type_display()} - {self.user.username} ({self.get_result_display()})'