package model import ( "time" ) // ============================================ // SiteTask 拨测任务 // ============================================ // SiteTaskType 拨测任务类型 type SiteTaskType string const ( SiteTaskTypeHTTP SiteTaskType = "http" // HTTP/HTTPS Web 拨测 SiteTaskTypeSSL SiteTaskType = "ssl" // SSL/TLS 证书拨测 SiteTaskTypeTCP SiteTaskType = "tcp" // TCP拨测 SiteTaskTypePing SiteTaskType = "ping" // ICMP Ping拨测 SiteTaskTypeDNS SiteTaskType = "dns" // DNS拨测 SiteTaskTypeUDP SiteTaskType = "udp" // UDP拨测 SiteTaskTypeFTP SiteTaskType = "ftp" // FTP拨测 SiteTaskTypeSMTP SiteTaskType = "smtp" // SMTP拨测 SiteTaskTypeTraceroute SiteTaskType = "traceroute" // 路由追踪 ) // SiteTaskMethod HTTP请求方法 type SiteTaskMethod string const ( SiteTaskMethodGET SiteTaskMethod = "GET" SiteTaskMethodPOST SiteTaskMethod = "POST" SiteTaskMethodHEAD SiteTaskMethod = "HEAD" ) // SiteTaskStatus 拨测任务状态 type SiteTaskStatus string const ( SiteTaskStatusRunning SiteTaskStatus = "running" // 运行中 SiteTaskStatusPaused SiteTaskStatus = "paused" // 已暂停 SiteTaskStatusError SiteTaskStatus = "error" // 异常 ) // SiteTask 站点拨测任务表 // 定义对网站、服务等进行主动拨测的任务配置 type SiteTask struct { ID uint `gorm:"primaryKey;autoIncrement;comment:主键ID" json:"id"` Name string `gorm:"type:varchar(128);not null;comment:任务名称" json:"name"` URL string `gorm:"type:varchar(512);not null;comment:拨测URL/地址" json:"url"` TaskType SiteTaskType `gorm:"type:varchar(16);not null;comment:拨测类型" json:"task_type"` Method SiteTaskMethod `gorm:"type:varchar(8);default:'GET';comment:HTTP方法" json:"method"` // HTTP 拨测配置 Headers string `gorm:"type:text;comment:请求头JSON" json:"headers,omitempty"` Body string `gorm:"type:text;comment:请求体" json:"body,omitempty"` Timeout int `gorm:"default:10;comment:超时时间(秒)" json:"timeout"` FollowRedirect bool `gorm:"default:true;comment:是否跟随重定向" json:"follow_redirect"` VerifySSL bool `gorm:"default:true;comment:是否验证SSL证书" json:"verify_ssl"` // 期望响应配置 ExpectedStatus int `gorm:"default:200;comment:期望状态码" json:"expected_status"` ExpectedContent string `gorm:"type:text;comment:期望响应内容(支持正则)" json:"expected_content,omitempty"` ExpectedLength int `gorm:"default:0;comment:期望响应长度(0表示不检查)" json:"expected_length"` // 执行配置 Frequency int `gorm:"default:60;comment:拨测频率(秒)" json:"frequency"` Nodes string `gorm:"type:varchar(256);comment:执行节点列表JSON" json:"nodes,omitempty"` // DNS 配置 DNSResolver string `gorm:"type:varchar(64);comment:DNS解析服务器" json:"dns_resolver,omitempty"` // 状态 Status SiteTaskStatus `gorm:"type:varchar(16);default:'running';comment:任务状态" json:"status"` LastResult string `gorm:"type:varchar(16);comment:最近结果: success/fail" json:"last_result,omitempty"` LastCheckAt *time.Time `gorm:"comment:最近检查时间" json:"last_check_at,omitempty"` SuccessRate float64 `gorm:"type:decimal(5,2);default:100.00;comment:成功率(%)" json:"success_rate"` AvgResponse float64 `gorm:"comment:平均响应时间(ms)" json:"avg_response,omitempty"` Description string `gorm:"type:varchar(256);comment:描述" json:"description,omitempty"` CreatedBy uint `gorm:"index;comment:创建人ID" json:"created_by"` CreatedAt time.Time `gorm:"not null;comment:创建时间" json:"created_at"` UpdatedAt time.Time `gorm:"not null;comment:更新时间" json:"updated_at"` DeletedAt *time.Time `gorm:"index;comment:删除时间" json:"deleted_at,omitempty"` // ── 内容监控(Content Monitor)──────────────────────────────── // 区别于"可用性拨测":服务活着但返回内容变了,这里负责发现。 // Logan.Li ContentCheckMode string `gorm:"type:varchar(8);default:'off';comment:内容检查模式 off/text/json" json:"content_check_mode"` // ContentPaths JSON 模式要参与比对字段的 JSONPath,如 ["$.data.status","$.data.ips"] ContentPaths string `gorm:"type:text;comment:JSONPath字段列表(JSON数组)" json:"content_paths,omitempty"` // ContentIgnoreRules 忽略规则:文本按正则替换为空,避免时间戳/nonce 造成误报 ContentIgnoreRules string `gorm:"type:text;comment:忽略规则(JSON数组,正则)" json:"content_ignore_rules,omitempty"` // ContentMinLength 小于该长度判为"采集异常"而非"内容变更",防止错误页误报 ContentMinLength int `gorm:"default:0;comment:最小有效长度(字节)" json:"content_min_length"` // ContentConfirmTimes 连续 N 次不一致才判定变更,抑制抖动 ContentConfirmTimes int `gorm:"default:2;comment:连续确认次数" json:"content_confirm_times"` // ContentSortLines 纯文本是否排序后比对(顺序无关的清单类接口应开启) ContentSortLines bool `gorm:"default:false;comment:文本排序后比对" json:"content_sort_lines"` // CurrentBaselineID 当前生效的基线版本 CurrentBaselineID uint `gorm:"default:0;comment:当前基线ID" json:"current_baseline_id"` // PendingChangeCount 待确认的变更次数(用于防抖计数) PendingChangeCount int `gorm:"default:0;comment:连续变更计数" json:"pending_change_count"` // 关联关系 Results []SiteResult `gorm:"foreignKey:TaskID" json:"results,omitempty"` Alerts []SiteAlert `gorm:"foreignKey:TaskID" json:"alerts,omitempty"` } // TableName 指定表名 func (SiteTask) TableName() string { return "monitor_site_tasks" } // ============================================ // SiteResult 拨测结果 // ============================================ // SiteResultStatus 拨测结果状态 type SiteResultStatus string const ( SiteResultSuccess SiteResultStatus = "success" // 成功 SiteResultFail SiteResultStatus = "fail" // 失败 SiteResultTimeout SiteResultStatus = "timeout" // 超时 ) // SiteResult 拨测结果表 // 存储每次拨测的详细结果数据 type SiteResult struct { ID uint `gorm:"primaryKey;autoIncrement;comment:主键ID" json:"id"` TaskID uint `gorm:"not null;index:idx_task_time;comment:任务ID" json:"task_id"` Status SiteResultStatus `gorm:"type:varchar(16);not null;comment:结果状态" json:"status"` HTTPStatusCode int `gorm:"comment:HTTP状态码" json:"http_status_code,omitempty"` // 时间指标 DNSTime float64 `gorm:"comment:DNS解析时间(ms)" json:"dns_time,omitempty"` ConnectTime float64 `gorm:"comment:连接时间(ms)" json:"connect_time,omitempty"` TLSTime float64 `gorm:"comment:TLS握手时间(ms)" json:"tls_time,omitempty"` TTFB float64 `gorm:"comment:首字节时间(ms)" json:"ttfb,omitempty"` ResponseTime float64 `gorm:"comment:响应时间(ms)" json:"response_time,omitempty"` TotalTime float64 `gorm:"not null;comment:总耗时(ms)" json:"total_time"` // 响应信息 ResponseSize int `gorm:"comment:响应大小(bytes)" json:"response_size,omitempty"` ResponseBody string `gorm:"type:text;comment:响应内容摘要" json:"response_body,omitempty"` // 网络信息 RemoteIP string `gorm:"type:varchar(64);comment:远端IP" json:"remote_ip,omitempty"` LocalNode string `gorm:"type:varchar(64);comment:执行节点" json:"local_node,omitempty"` // 错误信息 ErrorMessage string `gorm:"type:text;comment:错误信息" json:"error_message,omitempty"` ErrorDetail string `gorm:"type:text;comment:错误详情" json:"error_detail,omitempty"` // SSL 证书信息 SSLCertExpiry *time.Time `gorm:"comment:SSL证书过期时间" json:"ssl_cert_expiry,omitempty"` SSLCertIssuer string `gorm:"type:varchar(256);comment:SSL证书签发者" json:"ssl_cert_issuer,omitempty"` SSLCertSubject string `gorm:"type:varchar(256);comment:SSL证书主题" json:"ssl_cert_subject,omitempty"` SSLDaysRemaining int `gorm:"comment:SSL证书剩余天数" json:"ssl_days_remaining,omitempty"` // 检查内容匹配 ContentMatch bool `gorm:"comment:内容匹配结果" json:"content_match,omitempty"` // 时间戳 CheckedAt time.Time `gorm:"not null;index:idx_task_time;comment:拨测时间" json:"checked_at"` CreatedAt time.Time `gorm:"not null;comment:创建时间" json:"created_at"` // 关联关系 Task *SiteTask `gorm:"foreignKey:TaskID" json:"task,omitempty"` } // TableName 指定表名 func (SiteResult) TableName() string { return "monitor_site_results" } // ============================================ // SiteAlert 拨测告警 // ============================================ // SiteAlertStatus 拨测告警状态 type SiteAlertStatus string const ( SiteAlertStatusActive SiteAlertStatus = "active" // 活跃 SiteAlertStatusResolved SiteAlertStatus = "resolved" // 已恢复 SiteAlertStatusMuted SiteAlertStatus = "muted" // 已静默 ) // SiteAlertSeverity 拨测告警级别 type SiteAlertSeverity string const ( SiteAlertCritical SiteAlertSeverity = "critical" // 严重 SiteAlertWarning SiteAlertSeverity = "warning" // 警告 SiteAlertInfo SiteAlertSeverity = "info" // 通知 ) // SiteAlert 拨测告警表 // 记录拨测任务触发的告警事件 type SiteAlert struct { ID uint `gorm:"primaryKey;autoIncrement;comment:主键ID" json:"id"` TaskID uint `gorm:"not null;index;comment:任务ID" json:"task_id"` Severity SiteAlertSeverity `gorm:"type:varchar(16);not null;comment:告警级别" json:"severity"` Status SiteAlertStatus `gorm:"type:varchar(16);default:'active';index;comment:告警状态" json:"status"` Title string `gorm:"type:varchar(256);not null;comment:告警标题" json:"title"` Message string `gorm:"type:text;comment:告警详情" json:"message,omitempty"` // 触发条件 TriggerType string `gorm:"type:varchar(32);comment:触发类型: timeout/status_error/response_time/ssl_expiry" json:"trigger_type"` TriggerValue string `gorm:"type:varchar(128);comment:触发值" json:"trigger_value,omitempty"` Threshold float64 `gorm:"comment:阈值" json:"threshold,omitempty"` // 响应信息 ResponseTime float64 `gorm:"comment:响应时间(ms)" json:"response_time,omitempty"` HTTPStatus int `gorm:"comment:HTTP状态码" json:"http_status,omitempty"` ErrorMessage string `gorm:"type:text;comment:错误信息" json:"error_message,omitempty"` // 状态变化 StartedAt time.Time `gorm:"not null;comment:告警开始时间" json:"started_at"` ResolvedAt *time.Time `gorm:"comment:告警恢复时间" json:"resolved_at,omitempty"` Duration int `gorm:"comment:持续时间(秒)" json:"duration,omitempty"` NotifyCount int `gorm:"default:0;comment:通知次数" json:"notify_count"` LastNotifyAt *time.Time `gorm:"comment:最近通知时间" json:"last_notify_at,omitempty"` Acknowledged bool `gorm:"default:false;comment:是否已确认" json:"acknowledged"` AcknowledgedBy uint `gorm:"comment:确认人ID" json:"acknowledged_by,omitempty"` AcknowledgedAt *time.Time `gorm:"comment:确认时间" json:"acknowledged_at,omitempty"` CreatedAt time.Time `gorm:"not null;comment:创建时间" json:"created_at"` UpdatedAt time.Time `gorm:"not null;comment:更新时间" json:"updated_at"` // 关联关系 Task *SiteTask `gorm:"foreignKey:TaskID" json:"task,omitempty"` } // TableName 指定表名 func (SiteAlert) TableName() string { return "monitor_site_alerts" } // SiteTaskCreateRequest 拨测任务创建请求 type SiteTaskCreateRequest struct { Name string `json:"name" binding:"required,max=128"` URL string `json:"url" binding:"required,max=512,url"` TaskType SiteTaskType `json:"task_type" binding:"required"` Method SiteTaskMethod `json:"method"` Headers string `json:"headers"` Body string `json:"body"` Timeout int `json:"timeout"` FollowRedirect bool `json:"follow_redirect"` VerifySSL bool `json:"verify_ssl"` ExpectedStatus int `json:"expected_status"` ExpectedContent string `json:"expected_content"` ExpectedLength int `json:"expected_length"` Frequency int `json:"frequency"` Nodes []string `json:"nodes"` DNSResolver string `json:"dns_resolver"` Description string `json:"description"` } // SiteTaskUpdateRequest 拨测任务更新请求 type SiteTaskUpdateRequest struct { Name string `json:"name" binding:"max=128"` URL string `json:"url" binding:"max=512,url"` Method SiteTaskMethod `json:"method"` Headers string `json:"headers"` Body string `json:"body"` Timeout int `json:"timeout"` FollowRedirect bool `json:"follow_redirect"` VerifySSL bool `json:"verify_ssl"` ExpectedStatus int `json:"expected_status"` ExpectedContent string `json:"expected_content"` Frequency int `json:"frequency"` Nodes []string `json:"nodes"` Status SiteTaskStatus `json:"status"` Description string `json:"description"` } // SiteTaskStatistics 拨测任务统计 type SiteTaskStatistics struct { TaskID uint `json:"task_id"` TotalChecks int64 `json:"total_checks"` SuccessCount int64 `json:"success_count"` FailCount int64 `json:"fail_count"` TimeoutCount int64 `json:"timeout_count"` SuccessRate float64 `json:"success_rate"` AvgResponseTime float64 `json:"avg_response_time"` MinResponseTime float64 `json:"min_response_time"` MaxResponseTime float64 `json:"max_response_time"` Last24hUptime float64 `json:"last_24h_uptime"` Last7dUptime float64 `json:"last_7d_uptime"` Last30dUptime float64 `json:"last_30d_uptime"` } // SiteResultQuery 拨测结果查询参数 type SiteResultQuery struct { TaskID uint `json:"task_id" form:"task_id"` Status string `json:"status" form:"status"` StartTime int64 `json:"start_time" form:"start_time"` EndTime int64 `json:"end_time" form:"end_time"` Limit int `json:"limit" form:"limit"` Offset int `json:"offset" form:"offset"` } // ============================================ // 内容监控:基线版本 + 变更记录 // ============================================ // SiteBaseline 内容基线(一个任务的多版本快照)。 // // 首次采集自动建立 v1(source=auto),之后每次"接受新基线"新增一版(source=manual)。 // 保留完整规范化内容,用于并排 diff 与回溯。 // Logan.Li type SiteBaseline struct { ID uint `gorm:"primaryKey;autoIncrement" json:"id"` TaskID uint `gorm:"not null;index:idx_baseline_task;comment:任务ID" json:"task_id"` Version int `gorm:"not null;comment:版本号(从1递增)" json:"version"` ContentHash string `gorm:"type:varchar(64);not null;comment:规范化内容sha256" json:"content_hash"` ContentText string `gorm:"type:longtext;comment:规范化后的内容快照" json:"content_text,omitempty"` Source string `gorm:"type:varchar(16);default:'auto';comment:来源 auto/manual" json:"source"` AcceptedBy string `gorm:"type:varchar(128);comment:确认人" json:"accepted_by"` Note string `gorm:"type:varchar(512);comment:备注" json:"note"` CreatedAt time.Time `gorm:"not null;comment:创建时间" json:"created_at"` } // TableName 指定表名 // Logan.Li func (SiteBaseline) TableName() string { return "monitor_site_baselines" } // SiteContentChange 内容变更记录。 // // Status 流转:pending(已发现,待处理)→ accepted(接受为新基线)/ ignored(误报忽略)。 // DiffPayload 存结构化差异,前端并排视图直接渲染。 // Logan.Li type SiteContentChange struct { ID uint `gorm:"primaryKey;autoIncrement" json:"id"` TaskID uint `gorm:"not null;index:idx_change_task" json:"task_id"` FromBaselineID uint `gorm:"not null;comment:变更前基线" json:"from_baseline_id"` FromVersion int `gorm:"comment:变更前版本号" json:"from_version"` ContentHash string `gorm:"type:varchar(64);comment:新内容hash" json:"content_hash"` ContentText string `gorm:"type:longtext;comment:新内容快照" json:"content_text,omitempty"` DiffType string `gorm:"type:varchar(16);comment:text_line/json_field" json:"diff_type"` DiffPayload string `gorm:"type:longtext;comment:结构化diff(JSON)" json:"diff_payload,omitempty"` Status string `gorm:"type:varchar(16);default:'pending';index;comment:状态" json:"status"` HandledBy string `gorm:"type:varchar(128);comment:处理人" json:"handled_by,omitempty"` DetectedAt time.Time `gorm:"not null;comment:发现时间" json:"detected_at"` HandledAt *time.Time `json:"handled_at,omitempty"` } // TableName 指定表名 // Logan.Li func (SiteContentChange) TableName() string { return "monitor_site_content_changes" } // 内容变更状态常量 // Logan.Li const ( ContentChangePending = "pending" ContentChangeAccepted = "accepted" ContentChangeIgnored = "ignored" )