package main
import (
"database/sql"
"encoding/json"
"fmt"
"io"
"math/rand"
"net/http"
_ "os"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
)
type Alert struct {
Receiver string `json:"receiver"`
Status string `json:"status"`
Alerts []Alerts `json:"alerts"`
}
type Alerts struct {
Status string `json:"status"`
Labels Labels `json:"labels"`
Annotations Annotations `json:"annotations"`
StartsAt string `json:"startsAt"`
EndsAt string `json:"endsAt"`
GeneratorURL string `json:"generatorURL"`
Fingerprint string `json:"fingerprint"`
}
type Labels struct {
Alertname string `json:"name"`
Device string `json:"device"`
FSType string `json:"fstype"`
Instance string `json:"instance"`
Job string `json:"job"`
MountPoint string `json:"mountpoint"`
Severity string `json:"severity"`
System string `json:"system"`
Yunyingshang string `json:"yunyingshang"`
Judian string `json:"judian"`
}
type Annotations struct {
Description string `json:"description"`
Summary string `json:"summary"`
}
type Alarm struct {
IP string
System string
ISP string
Desc string
Judian string
Summary string
}
func NewAlarm(value Alerts) Alarm {
isp := value.Labels.Yunyingshang
if len(isp) == 0 {
isp = "wa"
}
ip := strings.Split(value.Labels.Instance, ":")[0]
summary := value.Annotations.Summary
// desc := ip + summary
system := value.Labels.System
if len(system) == 0 {
system = "wa"
}
judian := value.Labels.Judian
if len(judian) == 0 {
judian = "wa"
}
return Alarm{
IP: ip,
System: system,
ISP: isp,
Judian: judian,
Summary: summary,
}
}
var onlyalartmID string
func generateAlarmID() (alarmID string) {
prefix := "wamaster"
dateStr := time.Now().Format("200601021504")
rand.Seed(time.Now().UnixNano())
randStr := strconv.Itoa(rand.Intn(9000) + 1000)
alarmID = prefix + dateStr + randStr
return
}
func insertAlertToDB(db *sql.DB, alert Alert) error {
// 查询是否存在相同的IP和summary的记录
queryCheck := `SELECT id FROM hookdata WHERE ip = ? AND summary = ?`
stmtCheck, err := db.Prepare(queryCheck)
if err != nil {
return err
}
defer stmtCheck.Close()
for _, value := range alert.Alerts {
onlyalartmID = generateAlarmID()
status := 1
alarm := NewAlarm(value)
// ipmiaoshu = alarm.IP + alarm.Desc
currentTime := time.Now().Format("2006-01-02 15:04:05") // 获取当前时间并格式化为字符串
var id string
err = stmtCheck.QueryRow(alarm.IP, alarm.Summary).Scan(&id)
if err == sql.ErrNoRows {
// 如果没有找到相同的记录,则插入新记录
queryInsert := `INSERT INTO hookdata (ip, status, alertid, system, isp, judian, summary, tuitime) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
stmtInsert, err := db.Prepare(queryInsert)
if err != nil {
return err
}
defer stmtInsert.Close()
_, err = stmtInsert.Exec(alarm.IP, status, onlyalartmID, alarm.System, alarm.ISP, alarm.Judian, alarm.Summary, currentTime)
if err != nil {
return err
}
} else if err != nil {
// 如果有其他错误,返回错误
return err
} else {
// 如果找到了相同的记录,则更新该记录
queryUpdate := `UPDATE hookdata SET status=1, tuitime=? WHERE id=?`
stmtUpdate, err := db.Prepare(queryUpdate)
if err != nil {
return err
}
defer stmtUpdate.Close()
_, err = stmtUpdate.Exec(currentTime, id)
if err != nil {
return err
}
}
}
return nil
}
// 每5分钟检查一下更新时间
func updateStatus(db *sql.DB) {
for {
query := `UPDATE hookdata SET status=0 WHERE TIMESTAMPDIFF(MINUTE, tuitime, NOW()) > 5`
_, err := db.Exec(query)
if err != nil {
fmt.Println("Error updating status:", err)
}
time.Sleep(5 * time.Minute) // 每5分钟执行一次更新操作
}
}
func main() {
fmt.Println(generateAlarmID())
// os.Exit(0)
r := gin.Default()
// 连接到MySQL数据库
db, err := sql.Open("mysql", "root:111111@tcp(localhost:3306)/alert")
if err != nil {
panic(err)
}
defer db.Close()
r.POST("/webhook", func(c *gin.Context) {
body, err := io.ReadAll(c.Request.Body)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无法读取请求体"})
return
}
var alert Alert
err = json.Unmarshal(body, &alert)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无法解析告警信息"})
return
}
//打印出告警信息进行调试
for _, value := range alert.Alerts {
onlyalartmID = generateAlarmID()
status := 0
alarm := NewAlarm(value)
// _ = InsertData(alarm)
// ipmiaoshu = alarm.IP + alarm.Desc
currentTime := time.Now().Format("2006-01-02 15:04:05") // 获取当前时间并格式化为字符串
fmt.Printf("ip: %s\nstatus: %v\nalertid: %s\nsystem: %s\nisp: %s\njudian: %s\nsummary: %s\ntuitime: %T\n", alarm.IP, status, onlyalartmID, alarm.System, alarm.ISP, alarm.Judian, alarm.Summary, currentTime)
}
// 将告警信息插入到数据库
err = insertAlertToDB(db, alert)
if err != nil {
fmt.Println(err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "无法将告警信息插入到数据库"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "告警已接收并存储到数据库"})
})
go updateStatus(db) // 启动一个协程来定期更新状态
r.Run(":8080") // 监听8080端口
}
go语言推告警判断
于 2024-09-11 21:34:17 首次发布