2025-07-31 21:21:45 +08:00
|
|
|
from django.db import models
|
|
|
|
|
from django.utils import timezone
|
|
|
|
|
|
2025-09-07 16:47:12 +08:00
|
|
|
# 引入loguru库用于日志记录
|
|
|
|
|
try:
|
|
|
|
|
from loguru import logger
|
|
|
|
|
except ImportError:
|
|
|
|
|
import logging
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
class ServiceGroup(models.Model):
|
|
|
|
|
name = models.CharField(max_length=100, unique=True, verbose_name="服务分组")
|
|
|
|
|
description = models.TextField(blank=True, null=True, verbose_name="描述")
|
2025-07-31 21:21:45 +08:00
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return self.name
|
|
|
|
|
|
|
|
|
|
class Meta:
|
2025-09-07 16:47:12 +08:00
|
|
|
verbose_name = '服务分组'
|
|
|
|
|
verbose_name_plural = '服务分组'
|
|
|
|
|
|
|
|
|
|
class Service(models.Model):
|
|
|
|
|
STATUS_CHOICES = [
|
|
|
|
|
('UP', '正常'),
|
|
|
|
|
('DOWN', '故障'),
|
|
|
|
|
('UNKNOWN', '未知'),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
name = models.CharField(max_length=200, verbose_name="服务名称")
|
|
|
|
|
group = models.ForeignKey(ServiceGroup, on_delete=models.CASCADE, related_name='services', verbose_name="所属分组")
|
|
|
|
|
host = models.CharField(max_length=255, verbose_name="主机/IP")
|
|
|
|
|
port = models.PositiveIntegerField(null=True, blank=True, verbose_name="端口(可选)")
|
|
|
|
|
check_type = models.CharField(max_length=50, default='ping', choices=[
|
|
|
|
|
('ping', 'Ping检测'),
|
|
|
|
|
('tcp', 'TCP端口检测'),
|
|
|
|
|
('http', 'HTTP请求'),
|
|
|
|
|
('custom', '自定义脚本'),
|
|
|
|
|
], verbose_name="检测类型")
|
|
|
|
|
description = models.TextField(blank=True, null=True, verbose_name="描述")
|
|
|
|
|
is_active = models.BooleanField(default=True, verbose_name="是否启用监控")
|
|
|
|
|
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return f"{self.name} ({self.host})"
|
|
|
|
|
|
2025-09-07 19:51:04 +08:00
|
|
|
def get_latest_status(self):
|
|
|
|
|
"""获取最新状态"""
|
|
|
|
|
latest_record = self.records.first()
|
|
|
|
|
if latest_record:
|
|
|
|
|
return latest_record.status
|
|
|
|
|
return 'UNKNOWN'
|
|
|
|
|
|
|
|
|
|
def get_latest_check_time(self):
|
|
|
|
|
"""获取最新检测时间"""
|
|
|
|
|
latest_record = self.records.first()
|
|
|
|
|
if latest_record:
|
|
|
|
|
return latest_record.checked_at
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def get_latest_response_time(self):
|
|
|
|
|
"""获取最新响应时间"""
|
|
|
|
|
latest_record = self.records.first()
|
|
|
|
|
if latest_record:
|
|
|
|
|
return latest_record.response_time
|
|
|
|
|
return None
|
|
|
|
|
|
2025-09-07 16:47:12 +08:00
|
|
|
class Meta:
|
|
|
|
|
verbose_name = '服务'
|
|
|
|
|
verbose_name_plural = '服务'
|
|
|
|
|
|
|
|
|
|
class ServiceCheckRecord(models.Model):
|
|
|
|
|
service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name='records')
|
|
|
|
|
status = models.CharField(max_length=10, choices=Service.STATUS_CHOICES, verbose_name="状态")
|
|
|
|
|
response_time = models.FloatField(null=True, blank=True, verbose_name="响应时间(ms)")
|
|
|
|
|
message = models.TextField(blank=True, null=True, verbose_name="返回信息/错误原因")
|
|
|
|
|
checked_at = models.DateTimeField(default=timezone.now, verbose_name="检测时间")
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
ordering = ['-checked_at']
|
|
|
|
|
verbose_name = '服务检测记录'
|
|
|
|
|
verbose_name_plural = '服务检测记录'
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
return f"{self.service.name} - {self.status} at {self.checked_at}"
|
|
|
|
|
|
|
|
|
|
def save(self, *args, **kwargs):
|
|
|
|
|
logger.info(f"保存服务检测记录: {self.service.name}, 状态: {self.status}, 响应时间: {self.response_time}ms")
|
|
|
|
|
super().save(*args, **kwargs)
|