diff --git a/internal/models/alert.go b/internal/models/alert.go index ea52eb5..2480c96 100644 --- a/internal/models/alert.go +++ b/internal/models/alert.go @@ -2,19 +2,20 @@ package models // AlertRecord 告警记录 type AlertRecord struct { - ID int64 `gorm:"primaryKey;autoIncrement" json:"id"` // 记录ID - AgentID string `gorm:"index" json:"agentId"` // 探针ID - AgentName string `json:"agentName"` // 探针名称 - AlertType string `json:"alertType"` // 告警类型: cpu, memory, disk, network - Message string `json:"message"` // 告警消息 - Threshold float64 `json:"threshold"` // 告警阈值 - ActualValue float64 `json:"actualValue"` // 实际值 - Level string `json:"level"` // 告警级别: info, warning, critical - Status string `json:"status"` // 状态: firing(告警中), resolved(已恢复) - FiredAt int64 `gorm:"index" json:"firedAt"` // 触发时间(时间戳毫秒) - ResolvedAt int64 `json:"resolvedAt,omitempty"` // 恢复时间(时间戳毫秒) - CreatedAt int64 `json:"createdAt"` // 创建时间(时间戳毫秒) - UpdatedAt int64 `json:"updatedAt" gorm:"autoUpdateTime:milli"` // 更新时间(时间戳毫秒) + ID int64 `gorm:"primaryKey;autoIncrement" json:"id"` // 记录ID + AgentID string `gorm:"index" json:"agentId"` // 探针ID + AgentName string `json:"agentName"` // 探针名称 + AlertType string `json:"alertType"` // 告警类型: cpu, memory, disk, network + Message string `json:"message"` // 告警消息 + Threshold float64 `json:"threshold"` // 告警阈值 + ActualValue float64 `json:"actualValue"` // 告警触发时的实际值 + ResolvedValue float64 `json:"resolvedValue,omitempty"` // 恢复时的实际值 + Level string `json:"level"` // 告警级别: info, warning, critical + Status string `json:"status"` // 状态: firing(告警中), resolved(已恢复) + FiredAt int64 `gorm:"index" json:"firedAt"` // 触发时间(时间戳毫秒) + ResolvedAt int64 `json:"resolvedAt,omitempty"` // 恢复时间(时间戳毫秒) + CreatedAt int64 `json:"createdAt"` // 创建时间(时间戳毫秒) + UpdatedAt int64 `json:"updatedAt" gorm:"autoUpdateTime:milli"` // 更新时间(时间戳毫秒) } func (AlertRecord) TableName() string { diff --git a/internal/service/alert_service.go b/internal/service/alert_service.go index 5200856..7fa69c4 100644 --- a/internal/service/alert_service.go +++ b/internal/service/alert_service.go @@ -226,6 +226,7 @@ func (s *AlertService) resolveAlert(ctx context.Context, config *models.AlertCon } else { now := time.Now().UnixMilli() existingRecord.Status = "resolved" + existingRecord.ResolvedValue = state.Value existingRecord.ResolvedAt = now existingRecord.UpdatedAt = now @@ -517,7 +518,7 @@ func (s *AlertService) resolveCertAlert(ctx context.Context, config *models.Aler } else if existingRecord != nil && existingRecord.Status == "firing" { now := time.Now().UnixMilli() existingRecord.Status = "resolved" - existingRecord.ActualValue = certDaysLeft + existingRecord.ResolvedValue = certDaysLeft existingRecord.ResolvedAt = now existingRecord.UpdatedAt = now @@ -680,6 +681,7 @@ func (s *AlertService) resolveServiceDownAlert(ctx context.Context, config *mode } else if existingRecord != nil && existingRecord.Status == "firing" { now := time.Now().UnixMilli() existingRecord.Status = "resolved" + existingRecord.ResolvedValue = 0 // 服务已恢复在线 existingRecord.ResolvedAt = now existingRecord.UpdatedAt = now @@ -818,6 +820,7 @@ func (s *AlertService) resolveAgentOfflineAlert(ctx context.Context, config *mod } else if existingRecord != nil && existingRecord.Status == "firing" { now := time.Now().UnixMilli() existingRecord.Status = "resolved" + existingRecord.ResolvedValue = 0 // 探针已恢复在线 existingRecord.ResolvedAt = now existingRecord.UpdatedAt = now diff --git a/internal/service/notifier.go b/internal/service/notifier.go index 2182384..91ce2cb 100644 --- a/internal/service/notifier.go +++ b/internal/service/notifier.go @@ -282,8 +282,20 @@ func (n *Notifier) buildResolvedMessage( fmt.Sprintf("告警类型: %s", record.AlertType), } + // 显示告警值和恢复值的对比 if metadata.ShowActual { - lines = append(lines, fmt.Sprintf("当前值: %.2f%s", record.ActualValue, metadata.ValueUnit)) + // 对于服务下线和探针离线,恢复值为0时显示"已在线" + if (record.AlertType == "service" || record.AlertType == "agent_offline") && record.ResolvedValue == 0 { + lines = append(lines, + fmt.Sprintf("告警值: %.2f%s", record.ActualValue, metadata.ValueUnit), + "恢复状态: 已在线", + ) + } else { + lines = append(lines, + fmt.Sprintf("告警值: %.2f%s", record.ActualValue, metadata.ValueUnit), + fmt.Sprintf("恢复值: %.2f%s", record.ResolvedValue, metadata.ValueUnit), + ) + } } lines = append(lines, @@ -632,6 +644,8 @@ func (n *Notifier) buildCustomBody(agent *models.Agent, record *models.AlertReco v = fmt.Sprintf("%.2f", record.Threshold) case "alert.actualValue": v = fmt.Sprintf("%.2f", record.ActualValue) + case "alert.resolvedValue": + v = fmt.Sprintf("%.2f", record.ResolvedValue) case "alert.firedAt": // 格式化的触发时间 (使用系统时区,Docker 中设置为 Asia/Shanghai) v = utils.FormatTimestamp(record.FiredAt) diff --git a/web/src/admin/pages/AlertRecords/index.tsx b/web/src/admin/pages/AlertRecords/index.tsx index d0b1146..8de0308 100644 --- a/web/src/admin/pages/AlertRecords/index.tsx +++ b/web/src/admin/pages/AlertRecords/index.tsx @@ -184,7 +184,7 @@ const AlertRecordList = () => { }, }, { - title: '实际值', + title: '告警值', dataIndex: 'actualValue', width: 100, render: (_, record) => { @@ -200,6 +200,27 @@ const AlertRecordList = () => { return `${record.actualValue.toFixed(2)}%`; }, }, + { + title: '恢复值', + dataIndex: 'resolvedValue', + width: 100, + render: (_, record) => { + // 只有已恢复的告警才显示恢复值 + if (record.status !== 'resolved' || record.resolvedValue === undefined) { + return '-'; + } + if (record.alertType === 'network') { + return `${record.resolvedValue.toFixed(2)} MB/s`; + } + if (record.alertType === 'cert') { + return `${record.resolvedValue.toFixed(0)} 天`; + } + if (record.alertType === 'service' || record.alertType === 'agent_offline') { + return record.resolvedValue === 0 ? '已在线' : `${record.resolvedValue.toFixed(0)} 秒`; + } + return `${record.resolvedValue.toFixed(2)}%`; + }, + }, { title: '告警级别', dataIndex: 'level', @@ -286,6 +307,9 @@ const AlertRecordList = () => { pageSizeOptions: ['10', '20', '50', '100'], showTotal: (total) => `共 ${total} 条`, }} + scroll={{ + x: 'max-content' + }} onChange={handleTableChange} /> diff --git a/web/src/types/index.ts b/web/src/types/index.ts index 33eed43..eeaad9e 100644 --- a/web/src/types/index.ts +++ b/web/src/types/index.ts @@ -496,6 +496,7 @@ export interface AlertRecord { message: string; threshold: number; actualValue: number; + resolvedValue?: number; level: string; status: string; firedAt: number;