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()})'