💬 update notification text [skip ci]
This commit is contained in:
		
							parent
							
								
									cc5d8da952
								
							
						
					
					
						commit
						36432e31b2
					
				@ -14,7 +14,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
\>> QQ 交流群:872069346 **加群要求:已搭建好哪吒监控 & 有 2+ 服务器, 机器人自动审核**
 | 
					\>> QQ 交流群:872069346 **加群要求:已搭建好哪吒监控 & 有 2+ 服务器, 机器人自动审核**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
\>> [Use Cases | 我们的用户](https://www.google.com/search?q=%22powered+by+%E5%93%AA%E5%90%92%E7%9B%91%E6%8E%A7%22+OR+%22powered+by+Nezha+Monitoring%22&filter=0) (Google)
 | 
					\>> [Use Cases | 我们的用户](https://www.google.com/search?q=%22powered+by+Nezha+Monitoring%22+OR+%22powered+by+%E5%93%AA%E5%90%92%E7%9B%91%E6%8E%A7%22) (Google)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| Default Theme                                                                                 | DayNight [@JackieSung](https://github.com/JackieSung4ev)                                               | hotaru                                                                     |
 | 
					| Default Theme                                                                                 | DayNight [@JackieSung](https://github.com/JackieSung4ev)                                               | hotaru                                                                     |
 | 
				
			||||||
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
 | 
					| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
 | 
				
			||||||
 | 
				
			|||||||
@ -87,7 +87,7 @@ var funcMap = template.FuncMap{
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"tf": func(t time.Time) string {
 | 
						"tf": func(t time.Time) string {
 | 
				
			||||||
		return t.In(singleton.Loc).Format("2006年1月2号 15:04:05")
 | 
							return t.In(singleton.Loc).Format("02/01/2006 15:04:05")
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"len": func(slice []interface{}) string {
 | 
						"len": func(slice []interface{}) string {
 | 
				
			||||||
		return strconv.Itoa(len(slice))
 | 
							return strconv.Itoa(len(slice))
 | 
				
			||||||
@ -99,7 +99,7 @@ var funcMap = template.FuncMap{
 | 
				
			|||||||
		return template.HTML(`<` + s + `>`) // #nosec
 | 
							return template.HTML(`<` + s + `>`) // #nosec
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"stf": func(s uint64) string {
 | 
						"stf": func(s uint64) string {
 | 
				
			||||||
		return time.Unix(int64(s), 0).In(singleton.Loc).Format("2006年1月2号 15:04")
 | 
							return time.Unix(int64(s), 0).In(singleton.Loc).Format("02/01/2006 15:04")
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"sf": func(duration uint64) string {
 | 
						"sf": func(duration uint64) string {
 | 
				
			||||||
		return time.Duration(time.Duration(duration) * time.Second).String()
 | 
							return time.Duration(time.Duration(duration) * time.Second).String()
 | 
				
			||||||
@ -151,7 +151,7 @@ var funcMap = template.FuncMap{
 | 
				
			|||||||
	"dayBefore": func(i int) string {
 | 
						"dayBefore": func(i int) string {
 | 
				
			||||||
		year, month, day := time.Now().Date()
 | 
							year, month, day := time.Now().Date()
 | 
				
			||||||
		today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
 | 
							today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
 | 
				
			||||||
		return today.AddDate(0, 0, i-29).Format("1月2号")
 | 
							return today.AddDate(0, 0, i-29).Format("02/01")
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"className": func(percent float32) string {
 | 
						"className": func(percent float32) string {
 | 
				
			||||||
		if percent == 0 {
 | 
							if percent == 0 {
 | 
				
			||||||
@ -165,16 +165,7 @@ var funcMap = template.FuncMap{
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return "danger"
 | 
							return "danger"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"statusName": func(percent float32) string {
 | 
						"statusName": func(val float32) string {
 | 
				
			||||||
		if percent == 0 {
 | 
							return singleton.StatusCodeToString(singleton.GetStatusCode(val))
 | 
				
			||||||
			return "无数据"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if percent > 95 {
 | 
					 | 
				
			||||||
			return "良好"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if percent > 80 {
 | 
					 | 
				
			||||||
			return "低可用"
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return "故障"
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24
									
								
								resource/l10n/zh-CN.toml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								resource/l10n/zh-CN.toml
									
									
									
									
										vendored
									
									
								
							@ -489,3 +489,27 @@ other = "报警规则"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[NotificationMethod]
 | 
					[NotificationMethod]
 | 
				
			||||||
other = "通知方式"
 | 
					other = "通知方式"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Incident]
 | 
				
			||||||
 | 
					other = "故障"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Resolved]
 | 
				
			||||||
 | 
					other = "恢复"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[StatusNoData]
 | 
				
			||||||
 | 
					other = "无数据"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[StatusGood]
 | 
				
			||||||
 | 
					other = "良好"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[StatusLowAvailability]
 | 
				
			||||||
 | 
					other = "低可用"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[ScheduledTaskExecutedSuccessfully]
 | 
				
			||||||
 | 
					other = "任务成功"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[ScheduledTaskExecutedFailed]
 | 
				
			||||||
 | 
					other = "任务失败"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[IPChanged]
 | 
				
			||||||
 | 
					other = "IP变更"
 | 
				
			||||||
 | 
				
			|||||||
@ -3,9 +3,11 @@ package rpc
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"github.com/jinzhu/copier"
 | 
					 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/jinzhu/copier"
 | 
				
			||||||
 | 
						"github.com/nicksnyder/go-i18n/v2/i18n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/naiba/nezha/model"
 | 
						"github.com/naiba/nezha/model"
 | 
				
			||||||
	pb "github.com/naiba/nezha/proto"
 | 
						pb "github.com/naiba/nezha/proto"
 | 
				
			||||||
	"github.com/naiba/nezha/service/singleton"
 | 
						"github.com/naiba/nezha/service/singleton"
 | 
				
			||||||
@ -33,10 +35,18 @@ func (s *NezhaHandler) ReportTask(c context.Context, r *pb.TaskResult) (*pb.Rece
 | 
				
			|||||||
			curServer := model.Server{}
 | 
								curServer := model.Server{}
 | 
				
			||||||
			copier.Copy(&curServer, singleton.ServerList[clientID])
 | 
								copier.Copy(&curServer, singleton.ServerList[clientID])
 | 
				
			||||||
			if cr.PushSuccessful && r.GetSuccessful() {
 | 
								if cr.PushSuccessful && r.GetSuccessful() {
 | 
				
			||||||
				singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[任务成功] %s ,服务器:%s,日志:\n%s", cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false, &curServer)
 | 
									singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[%s] %s, %s\n%s", singleton.Localizer.MustLocalize(
 | 
				
			||||||
 | 
										&i18n.LocalizeConfig{
 | 
				
			||||||
 | 
											MessageID: "ScheduledTaskExecutedSuccessfully",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false, &curServer)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if !r.GetSuccessful() {
 | 
								if !r.GetSuccessful() {
 | 
				
			||||||
				singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[任务失败] %s ,服务器:%s,日志:\n%s", cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false, &curServer)
 | 
									singleton.SendNotification(cr.NotificationTag, fmt.Sprintf("[%s] %s, %s\n%s", singleton.Localizer.MustLocalize(
 | 
				
			||||||
 | 
										&i18n.LocalizeConfig{
 | 
				
			||||||
 | 
											MessageID: "ScheduledTaskExecutedFailed",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									), cr.Name, singleton.ServerList[clientID].Name, r.GetData()), false, &curServer)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			singleton.DB.Model(cr).Updates(model.Cron{
 | 
								singleton.DB.Model(cr).Updates(model.Cron{
 | 
				
			||||||
				LastExecutedAt: time.Now().Add(time.Second * -1 * time.Duration(r.GetDelay())),
 | 
									LastExecutedAt: time.Now().Add(time.Second * -1 * time.Duration(r.GetDelay())),
 | 
				
			||||||
@ -108,7 +118,10 @@ func (s *NezhaHandler) ReportSystemInfo(c context.Context, r *pb.Host) (*pb.Rece
 | 
				
			|||||||
		host.IP != "" &&
 | 
							host.IP != "" &&
 | 
				
			||||||
		singleton.ServerList[clientID].Host.IP != host.IP {
 | 
							singleton.ServerList[clientID].Host.IP != host.IP {
 | 
				
			||||||
		singleton.SendNotification(singleton.Conf.IPChangeNotificationTag, fmt.Sprintf(
 | 
							singleton.SendNotification(singleton.Conf.IPChangeNotificationTag, fmt.Sprintf(
 | 
				
			||||||
			"[IP变更] %s ,旧IP:%s,新IP:%s。",
 | 
								"[%s] %s, %s => %s",
 | 
				
			||||||
 | 
								singleton.Localizer.MustLocalize(&i18n.LocalizeConfig{
 | 
				
			||||||
 | 
									MessageID: "IPChanged",
 | 
				
			||||||
 | 
								}),
 | 
				
			||||||
			singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].Host.IP), singleton.IPDesensitize(host.IP)), true)
 | 
								singleton.ServerList[clientID].Name, singleton.IPDesensitize(singleton.ServerList[clientID].Host.IP), singleton.IPDesensitize(host.IP)), true)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2,11 +2,13 @@ package singleton
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"github.com/jinzhu/copier"
 | 
					 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/jinzhu/copier"
 | 
				
			||||||
 | 
						"github.com/nicksnyder/go-i18n/v2/i18n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/naiba/nezha/model"
 | 
						"github.com/naiba/nezha/model"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -153,11 +155,15 @@ func checkStatus() {
 | 
				
			|||||||
			copier.Copy(&curServer, server)
 | 
								copier.Copy(&curServer, server)
 | 
				
			||||||
			if !passed {
 | 
								if !passed {
 | 
				
			||||||
				alertsPrevState[alert.ID][server.ID] = _RuleCheckFail
 | 
									alertsPrevState[alert.ID][server.ID] = _RuleCheckFail
 | 
				
			||||||
				message := fmt.Sprintf("[主机故障] %s(%s) 规则:%s", server.Name, IPDesensitize(server.Host.IP), alert.Name)
 | 
									message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
 | 
				
			||||||
 | 
										MessageID: "Incident",
 | 
				
			||||||
 | 
									}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
 | 
				
			||||||
				go SendNotification(alert.NotificationTag, message, true, &curServer)
 | 
									go SendNotification(alert.NotificationTag, message, true, &curServer)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				if alertsPrevState[alert.ID][server.ID] == _RuleCheckFail {
 | 
									if alertsPrevState[alert.ID][server.ID] == _RuleCheckFail {
 | 
				
			||||||
					message := fmt.Sprintf("[主机恢复] %s(%s) 规则:%s", server.Name, IPDesensitize(server.Host.IP), alert.Name)
 | 
										message := fmt.Sprintf("[%s] %s(%s) %s", Localizer.MustLocalize(&i18n.LocalizeConfig{
 | 
				
			||||||
 | 
											MessageID: "Resolved",
 | 
				
			||||||
 | 
										}), server.Name, IPDesensitize(server.Host.IP), alert.Name)
 | 
				
			||||||
					go SendNotification(alert.NotificationTag, message, true, &curServer)
 | 
										go SendNotification(alert.NotificationTag, message, true, &curServer)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				alertsPrevState[alert.ID][server.ID] = _RuleCheckPass
 | 
									alertsPrevState[alert.ID][server.ID] = _RuleCheckPass
 | 
				
			||||||
 | 
				
			|||||||
@ -10,11 +10,11 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/naiba/nezha/model"
 | 
						"github.com/naiba/nezha/model"
 | 
				
			||||||
	pb "github.com/naiba/nezha/proto"
 | 
						pb "github.com/naiba/nezha/proto"
 | 
				
			||||||
 | 
						"github.com/nicksnyder/go-i18n/v2/i18n"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	_CurrentStatusSize = 30 // 统计 15 分钟内的数据为当前状态
 | 
						_CurrentStatusSize = 30 // 统计 15 分钟内的数据为当前状态
 | 
				
			||||||
	_StatusOk          = "良好"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var ServiceSentinelShared *ServiceSentinel
 | 
					var ServiceSentinelShared *ServiceSentinel
 | 
				
			||||||
@ -39,7 +39,7 @@ func NewServiceSentinel(serviceSentinelDispatchBus chan<- model.Monitor) {
 | 
				
			|||||||
		serviceCurrentStatusIndex:           make(map[uint64]int),
 | 
							serviceCurrentStatusIndex:           make(map[uint64]int),
 | 
				
			||||||
		serviceCurrentStatusData:            make(map[uint64][]model.MonitorHistory),
 | 
							serviceCurrentStatusData:            make(map[uint64][]model.MonitorHistory),
 | 
				
			||||||
		latestDate:                          make(map[uint64]string),
 | 
							latestDate:                          make(map[uint64]string),
 | 
				
			||||||
		lastStatus:                          make(map[uint64]string),
 | 
							lastStatus:                          make(map[uint64]int),
 | 
				
			||||||
		serviceResponseDataStoreCurrentUp:   make(map[uint64]uint64),
 | 
							serviceResponseDataStoreCurrentUp:   make(map[uint64]uint64),
 | 
				
			||||||
		serviceResponseDataStoreCurrentDown: make(map[uint64]uint64),
 | 
							serviceResponseDataStoreCurrentDown: make(map[uint64]uint64),
 | 
				
			||||||
		monitors:                            make(map[uint64]*model.Monitor),
 | 
							monitors:                            make(map[uint64]*model.Monitor),
 | 
				
			||||||
@ -97,7 +97,7 @@ type ServiceSentinel struct {
 | 
				
			|||||||
	serviceCurrentStatusIndex           map[uint64]int                    // [monitor_id] -> 该监控ID对应的 serviceCurrentStatusData 的最新索引下标
 | 
						serviceCurrentStatusIndex           map[uint64]int                    // [monitor_id] -> 该监控ID对应的 serviceCurrentStatusData 的最新索引下标
 | 
				
			||||||
	serviceCurrentStatusData            map[uint64][]model.MonitorHistory // [monitor_id] -> []model.MonitorHistory
 | 
						serviceCurrentStatusData            map[uint64][]model.MonitorHistory // [monitor_id] -> []model.MonitorHistory
 | 
				
			||||||
	latestDate                          map[uint64]string                 // 最近一次更新时间
 | 
						latestDate                          map[uint64]string                 // 最近一次更新时间
 | 
				
			||||||
	lastStatus                          map[uint64]string
 | 
						lastStatus                          map[uint64]int
 | 
				
			||||||
	serviceResponseDataStoreCurrentUp   map[uint64]uint64         // [monitor_id] -> 当前服务在线计数
 | 
						serviceResponseDataStoreCurrentUp   map[uint64]uint64         // [monitor_id] -> 当前服务在线计数
 | 
				
			||||||
	serviceResponseDataStoreCurrentDown map[uint64]uint64         // [monitor_id] -> 当前服务离线计数
 | 
						serviceResponseDataStoreCurrentDown map[uint64]uint64         // [monitor_id] -> 当前服务离线计数
 | 
				
			||||||
	monitors                            map[uint64]*model.Monitor // [monitor_id] -> model.Monitor
 | 
						monitors                            map[uint64]*model.Monitor // [monitor_id] -> model.Monitor
 | 
				
			||||||
@ -277,20 +277,6 @@ func (ss *ServiceSentinel) LoadStats() map[uint64]*model.ServiceItemResponse {
 | 
				
			|||||||
	return ss.monthlyStatus
 | 
						return ss.monthlyStatus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getStateStr 根据服务在线率返回对应的状态字符串
 | 
					 | 
				
			||||||
func getStateStr(percent uint64) string {
 | 
					 | 
				
			||||||
	if percent == 0 {
 | 
					 | 
				
			||||||
		return "无数据"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if percent > 95 {
 | 
					 | 
				
			||||||
		return _StatusOk
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if percent > 80 {
 | 
					 | 
				
			||||||
		return "低可用"
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return "故障"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// worker 服务监控的实际工作流程
 | 
					// worker 服务监控的实际工作流程
 | 
				
			||||||
func (ss *ServiceSentinel) worker() {
 | 
					func (ss *ServiceSentinel) worker() {
 | 
				
			||||||
	// 从服务状态汇报管道获取汇报的服务数据
 | 
						// 从服务状态汇报管道获取汇报的服务数据
 | 
				
			||||||
@ -321,7 +307,7 @@ func (ss *ServiceSentinel) worker() {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ss.serviceStatusToday[mh.MonitorID].Down++
 | 
								ss.serviceStatusToday[mh.MonitorID].Down++
 | 
				
			||||||
			ServerLock.RLock()
 | 
								ServerLock.RLock()
 | 
				
			||||||
			log.Println("NEZHA>> 服务故障上报:", ss.monitors[mh.MonitorID].Target, "上报者:", ServerList[r.Reporter].Name, "错误信息:", mh.Data)
 | 
								log.Println("NEZHA>> Services Incident:", ss.monitors[mh.MonitorID].Target, "Reporter:", ServerList[r.Reporter].Name, "Error:", mh.Data)
 | 
				
			||||||
			ServerLock.RUnlock()
 | 
								ServerLock.RUnlock()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// 写入当前数据
 | 
							// 写入当前数据
 | 
				
			||||||
@ -343,25 +329,25 @@ func (ss *ServiceSentinel) worker() {
 | 
				
			|||||||
		if ss.serviceResponseDataStoreCurrentDown[mh.MonitorID]+ss.serviceResponseDataStoreCurrentUp[mh.MonitorID] > 0 {
 | 
							if ss.serviceResponseDataStoreCurrentDown[mh.MonitorID]+ss.serviceResponseDataStoreCurrentUp[mh.MonitorID] > 0 {
 | 
				
			||||||
			upPercent = ss.serviceResponseDataStoreCurrentUp[mh.MonitorID] * 100 / (ss.serviceResponseDataStoreCurrentDown[mh.MonitorID] + ss.serviceResponseDataStoreCurrentUp[mh.MonitorID])
 | 
								upPercent = ss.serviceResponseDataStoreCurrentUp[mh.MonitorID] * 100 / (ss.serviceResponseDataStoreCurrentDown[mh.MonitorID] + ss.serviceResponseDataStoreCurrentUp[mh.MonitorID])
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		stateStr := getStateStr(upPercent)
 | 
							stateCode := GetStatusCode(upPercent)
 | 
				
			||||||
		// 数据持久化
 | 
							// 数据持久化
 | 
				
			||||||
		if ss.serviceCurrentStatusIndex[mh.MonitorID] == _CurrentStatusSize {
 | 
							if ss.serviceCurrentStatusIndex[mh.MonitorID] == _CurrentStatusSize {
 | 
				
			||||||
			ss.serviceCurrentStatusIndex[mh.MonitorID] = 0
 | 
								ss.serviceCurrentStatusIndex[mh.MonitorID] = 0
 | 
				
			||||||
			if err := DB.Create(&model.MonitorHistory{
 | 
								if err := DB.Create(&model.MonitorHistory{
 | 
				
			||||||
				MonitorID:  mh.MonitorID,
 | 
									MonitorID:  mh.MonitorID,
 | 
				
			||||||
				Delay:      ss.serviceStatusToday[mh.MonitorID].Delay,
 | 
									Delay:      ss.serviceStatusToday[mh.MonitorID].Delay,
 | 
				
			||||||
				Successful: stateStr == _StatusOk,
 | 
									Successful: stateCode == StatusGood,
 | 
				
			||||||
				Data:       mh.Data,
 | 
									Data:       mh.Data,
 | 
				
			||||||
			}).Error; err != nil {
 | 
								}).Error; err != nil {
 | 
				
			||||||
				log.Println("NEZHA>> 服务监控数据持久化失败:", err)
 | 
									log.Println("NEZHA>> 服务监控数据持久化失败:", err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if stateStr == "故障" || stateStr != ss.lastStatus[mh.MonitorID] {
 | 
							if stateCode == StatusDown || stateCode != ss.lastStatus[mh.MonitorID] {
 | 
				
			||||||
			ss.monitorsLock.RLock()
 | 
								ss.monitorsLock.RLock()
 | 
				
			||||||
			isNeedSendNotification := (ss.lastStatus[mh.MonitorID] != "" || stateStr == "故障") && ss.monitors[mh.MonitorID].Notify
 | 
								isNeedSendNotification := (ss.lastStatus[mh.MonitorID] != 0 || stateCode == StatusDown) && ss.monitors[mh.MonitorID].Notify
 | 
				
			||||||
			ss.lastStatus[mh.MonitorID] = stateStr
 | 
								ss.lastStatus[mh.MonitorID] = stateCode
 | 
				
			||||||
			if isNeedSendNotification {
 | 
								if isNeedSendNotification {
 | 
				
			||||||
				go SendNotification(ss.monitors[mh.MonitorID].NotificationTag, fmt.Sprintf("[服务%s] %s", stateStr, ss.monitors[mh.MonitorID].Name), true)
 | 
									go SendNotification(ss.monitors[mh.MonitorID].NotificationTag, fmt.Sprintf("[%s] %s", StatusCodeToString(stateCode), ss.monitors[mh.MonitorID].Name), true)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			ss.monitorsLock.RUnlock()
 | 
								ss.monitorsLock.RUnlock()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -385,7 +371,7 @@ func (ss *ServiceSentinel) worker() {
 | 
				
			|||||||
				// 证书过期提醒
 | 
									// 证书过期提醒
 | 
				
			||||||
				if expiresNew.Before(time.Now().AddDate(0, 0, 7)) {
 | 
									if expiresNew.Before(time.Now().AddDate(0, 0, 7)) {
 | 
				
			||||||
					errMsg = fmt.Sprintf(
 | 
										errMsg = fmt.Sprintf(
 | 
				
			||||||
						"SSL证书将在七天内过期,过期时间:%s。",
 | 
											"The SSL certificate will expire within seven days. Expiration time: %s",
 | 
				
			||||||
						expiresNew.Format("2006-01-02 15:04:05"))
 | 
											expiresNew.Format("2006-01-02 15:04:05"))
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// 证书变更提醒
 | 
									// 证书变更提醒
 | 
				
			||||||
@ -397,7 +383,7 @@ func (ss *ServiceSentinel) worker() {
 | 
				
			|||||||
				if oldCert[0] != newCert[0] && !expiresNew.Equal(expiresOld) {
 | 
									if oldCert[0] != newCert[0] && !expiresNew.Equal(expiresOld) {
 | 
				
			||||||
					ss.sslCertCache[mh.MonitorID] = mh.Data
 | 
										ss.sslCertCache[mh.MonitorID] = mh.Data
 | 
				
			||||||
					errMsg = fmt.Sprintf(
 | 
										errMsg = fmt.Sprintf(
 | 
				
			||||||
						"SSL证书变更,旧:%s, %s 过期;新:%s, %s 过期。",
 | 
											"SSL certificate changed, old: %s, %s expired; new: %s, %s expired.",
 | 
				
			||||||
						oldCert[0], expiresOld.Format("2006-01-02 15:04:05"), newCert[0], expiresNew.Format("2006-01-02 15:04:05"))
 | 
											oldCert[0], expiresOld.Format("2006-01-02 15:04:05"), newCert[0], expiresNew.Format("2006-01-02 15:04:05"))
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -411,3 +397,39 @@ func (ss *ServiceSentinel) worker() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						_ = iota
 | 
				
			||||||
 | 
						StatusNoData
 | 
				
			||||||
 | 
						StatusGood
 | 
				
			||||||
 | 
						StatusLowAvailability
 | 
				
			||||||
 | 
						StatusDown
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetStatusCode[T float32 | uint64](percent T) int {
 | 
				
			||||||
 | 
						if percent == 0 {
 | 
				
			||||||
 | 
							return StatusNoData
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if percent > 95 {
 | 
				
			||||||
 | 
							return StatusGood
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if percent > 80 {
 | 
				
			||||||
 | 
							return StatusLowAvailability
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return StatusDown
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func StatusCodeToString(statusCode int) string {
 | 
				
			||||||
 | 
						switch statusCode {
 | 
				
			||||||
 | 
						case StatusNoData:
 | 
				
			||||||
 | 
							return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusNoData"})
 | 
				
			||||||
 | 
						case StatusGood:
 | 
				
			||||||
 | 
							return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusGood"})
 | 
				
			||||||
 | 
						case StatusLowAvailability:
 | 
				
			||||||
 | 
							return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusLowAvailability"})
 | 
				
			||||||
 | 
						case StatusDown:
 | 
				
			||||||
 | 
							return Localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "StatusDown"})
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user