261 lines
8.1 KiB
Go
261 lines
8.1 KiB
Go
package controller
|
||
|
||
import (
|
||
"encoding/json"
|
||
"net/http"
|
||
"strconv"
|
||
"time"
|
||
|
||
"ezops/model"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// 告警静默规则 CRUD(AlertHandler 方法接收者) // Logan.Li
|
||
|
||
// CreateSilenceRequest 创建静默规则请求
|
||
type CreateSilenceRequest struct {
|
||
Name string `json:"name" binding:"required"`
|
||
Description string `json:"description"`
|
||
RuleIDs []uint `json:"rule_ids"`
|
||
TargetIDs []uint `json:"target_ids"`
|
||
Matchers []model.AlertSilenceMatcher `json:"matchers"`
|
||
SilenceType string `json:"silence_type"`
|
||
StartTime string `json:"start_time"`
|
||
EndTime string `json:"end_time" binding:"required"`
|
||
Weekdays []int `json:"weekdays"`
|
||
Status *int `json:"status"`
|
||
}
|
||
|
||
// UpdateSilenceRequest 更新静默规则请求
|
||
type UpdateSilenceRequest struct {
|
||
Name string `json:"name"`
|
||
Description string `json:"description"`
|
||
RuleIDs []uint `json:"rule_ids"`
|
||
TargetIDs []uint `json:"target_ids"`
|
||
Matchers []model.AlertSilenceMatcher `json:"matchers"`
|
||
SilenceType string `json:"silence_type"`
|
||
StartTime string `json:"start_time"`
|
||
EndTime string `json:"end_time"`
|
||
Weekdays []int `json:"weekdays"`
|
||
Status *int `json:"status"`
|
||
}
|
||
|
||
// ListSilences GET /alerts/silences
|
||
func (h *AlertHandler) ListSilences(c *gin.Context) {
|
||
var silences []model.AlertSilence
|
||
query := h.db.Order("created_at DESC")
|
||
|
||
if status := c.Query("status"); status != "" {
|
||
if status == "active" {
|
||
now := time.Now()
|
||
query = query.Where("status = ? AND start_time <= ? AND end_time >= ?", 1, now, now)
|
||
} else if s, err := strconv.Atoi(status); err == nil {
|
||
query = query.Where("status = ?", s)
|
||
}
|
||
}
|
||
|
||
query.Find(&silences)
|
||
|
||
// 解析 JSON 字段为前端友好的格式
|
||
type SilenceWithParsed struct {
|
||
model.AlertSilence
|
||
RuleIDList []uint `json:"rule_id_list"`
|
||
TargetIDList []uint `json:"target_id_list"`
|
||
MatcherList []model.AlertSilenceMatcher `json:"matcher_list"`
|
||
WeekdayList []int `json:"weekday_list"`
|
||
IsActive bool `json:"is_active"`
|
||
}
|
||
|
||
var result []SilenceWithParsed
|
||
now := time.Now()
|
||
for _, s := range silences {
|
||
item := SilenceWithParsed{AlertSilence: s}
|
||
if s.RuleIDs != "" {
|
||
json.Unmarshal([]byte(s.RuleIDs), &item.RuleIDList)
|
||
}
|
||
if s.TargetIDs != "" {
|
||
json.Unmarshal([]byte(s.TargetIDs), &item.TargetIDList)
|
||
}
|
||
if s.Matchers != "" {
|
||
json.Unmarshal([]byte(s.Matchers), &item.MatcherList)
|
||
}
|
||
if s.Weekdays != "" {
|
||
json.Unmarshal([]byte(s.Weekdays), &item.WeekdayList)
|
||
}
|
||
item.IsActive = s.Status == 1 && now.After(s.StartTime) && now.Before(s.EndTime)
|
||
result = append(result, item)
|
||
}
|
||
|
||
c.JSON(http.StatusOK, model.Response{
|
||
Code: 200,
|
||
Message: "success",
|
||
Data: model.ListResponse{List: result, Total: int64(len(result))},
|
||
})
|
||
}
|
||
|
||
// CreateSilence POST /alerts/silences
|
||
func (h *AlertHandler) CreateSilence(c *gin.Context) {
|
||
var req CreateSilenceRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "请求参数错误: " + err.Error()})
|
||
return
|
||
}
|
||
|
||
silenceType := model.AlertSilenceOneTime
|
||
if req.SilenceType != "" {
|
||
silenceType = model.AlertSilenceType(req.SilenceType)
|
||
}
|
||
|
||
// 解析时间
|
||
var startTime, endTime time.Time
|
||
var err error
|
||
if req.StartTime != "" {
|
||
startTime, err = time.Parse(time.RFC3339, req.StartTime)
|
||
if err != nil {
|
||
startTime, err = time.ParseInLocation("2006-01-02 15:04:05", req.StartTime, time.Local)
|
||
if err != nil {
|
||
startTime = time.Now()
|
||
}
|
||
}
|
||
} else {
|
||
startTime = time.Now()
|
||
}
|
||
|
||
endTime, err = time.Parse(time.RFC3339, req.EndTime)
|
||
if err != nil {
|
||
endTime, err = time.ParseInLocation("2006-01-02 15:04:05", req.EndTime, time.Local)
|
||
if err != nil {
|
||
c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "结束时间格式错误"})
|
||
return
|
||
}
|
||
}
|
||
|
||
ruleIDsJSON, _ := json.Marshal(req.RuleIDs)
|
||
targetIDsJSON, _ := json.Marshal(req.TargetIDs)
|
||
matchersJSON, _ := json.Marshal(req.Matchers)
|
||
weekdaysJSON, _ := json.Marshal(req.Weekdays)
|
||
|
||
silence := model.AlertSilence{
|
||
Name: req.Name,
|
||
Description: req.Description,
|
||
RuleIDs: string(ruleIDsJSON),
|
||
TargetIDs: string(targetIDsJSON),
|
||
Matchers: string(matchersJSON),
|
||
SilenceType: silenceType,
|
||
StartTime: startTime,
|
||
EndTime: endTime,
|
||
Weekdays: string(weekdaysJSON),
|
||
Status: 1,
|
||
}
|
||
|
||
// 获取创建人 ID
|
||
if userID, exists := c.Get("userID"); exists {
|
||
if uid, ok := userID.(uint); ok {
|
||
silence.CreatedBy = uid
|
||
}
|
||
}
|
||
|
||
if err := h.db.Create(&silence).Error; err != nil {
|
||
c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "创建失败: " + err.Error()})
|
||
return
|
||
}
|
||
|
||
c.JSON(http.StatusOK, model.Response{Code: 200, Message: "创建成功", Data: silence})
|
||
}
|
||
|
||
// UpdateSilence PUT /alerts/silences/:id
|
||
func (h *AlertHandler) UpdateSilence(c *gin.Context) {
|
||
id, _ := strconv.Atoi(c.Param("id"))
|
||
var req UpdateSilenceRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, model.Response{Code: 400, Message: "请求参数错误"})
|
||
return
|
||
}
|
||
|
||
var silence model.AlertSilence
|
||
if err := h.db.First(&silence, id).Error; err != nil {
|
||
c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "静默规则不存在"})
|
||
return
|
||
}
|
||
|
||
updates := map[string]interface{}{}
|
||
if req.Name != "" {
|
||
updates["name"] = req.Name
|
||
}
|
||
if req.Description != "" {
|
||
updates["description"] = req.Description
|
||
}
|
||
if req.SilenceType != "" {
|
||
updates["silence_type"] = req.SilenceType
|
||
}
|
||
if len(req.RuleIDs) > 0 || req.RuleIDs != nil {
|
||
ruleIDsJSON, _ := json.Marshal(req.RuleIDs)
|
||
updates["rule_ids"] = string(ruleIDsJSON)
|
||
}
|
||
if len(req.TargetIDs) > 0 || req.TargetIDs != nil {
|
||
targetIDsJSON, _ := json.Marshal(req.TargetIDs)
|
||
updates["target_ids"] = string(targetIDsJSON)
|
||
}
|
||
if len(req.Matchers) > 0 || req.Matchers != nil {
|
||
matchersJSON, _ := json.Marshal(req.Matchers)
|
||
updates["matchers"] = string(matchersJSON)
|
||
}
|
||
if len(req.Weekdays) > 0 || req.Weekdays != nil {
|
||
weekdaysJSON, _ := json.Marshal(req.Weekdays)
|
||
updates["weekdays"] = string(weekdaysJSON)
|
||
}
|
||
if req.StartTime != "" {
|
||
if st, err := time.Parse(time.RFC3339, req.StartTime); err == nil {
|
||
updates["start_time"] = st
|
||
} else if st, err := time.ParseInLocation("2006-01-02 15:04:05", req.StartTime, time.Local); err == nil {
|
||
updates["start_time"] = st
|
||
}
|
||
}
|
||
if req.EndTime != "" {
|
||
if et, err := time.Parse(time.RFC3339, req.EndTime); err == nil {
|
||
updates["end_time"] = et
|
||
} else if et, err := time.ParseInLocation("2006-01-02 15:04:05", req.EndTime, time.Local); err == nil {
|
||
updates["end_time"] = et
|
||
}
|
||
}
|
||
if req.Status != nil {
|
||
updates["status"] = *req.Status
|
||
}
|
||
|
||
h.db.Model(&silence).Updates(updates)
|
||
h.db.First(&silence, id)
|
||
|
||
c.JSON(http.StatusOK, model.Response{Code: 200, Message: "更新成功", Data: silence})
|
||
}
|
||
|
||
// DeleteSilence DELETE /alerts/silences/:id
|
||
func (h *AlertHandler) DeleteSilence(c *gin.Context) {
|
||
id, _ := strconv.Atoi(c.Param("id"))
|
||
if err := h.db.Delete(&model.AlertSilence{}, id).Error; err != nil {
|
||
c.JSON(http.StatusInternalServerError, model.Response{Code: 500, Message: "删除失败"})
|
||
return
|
||
}
|
||
c.JSON(http.StatusOK, model.Response{Code: 200, Message: "删除成功"})
|
||
}
|
||
|
||
// ToggleSilence POST /alerts/silences/:id/toggle
|
||
func (h *AlertHandler) ToggleSilence(c *gin.Context) {
|
||
id, _ := strconv.Atoi(c.Param("id"))
|
||
var silence model.AlertSilence
|
||
if err := h.db.First(&silence, id).Error; err != nil {
|
||
c.JSON(http.StatusNotFound, model.Response{Code: 404, Message: "静默规则不存在"})
|
||
return
|
||
}
|
||
|
||
newStatus := 0
|
||
if silence.Status == 0 {
|
||
newStatus = 1
|
||
}
|
||
|
||
h.db.Model(&silence).Update("status", newStatus)
|
||
h.db.First(&silence, id)
|
||
|
||
c.JSON(http.StatusOK, model.Response{Code: 200, Message: "切换成功", Data: silence})
|
||
}
|