sync from local backup
This commit is contained in:
+141
@@ -0,0 +1,141 @@
|
||||
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()})'
|
||||
Reference in New Issue
Block a user