mirror of
https://github.com/nezhahq/nezha.git
synced 2025-01-22 20:58:14 -05:00
Compare commits
5 Commits
87e01a532e
...
0ba6fde027
Author | SHA1 | Date | |
---|---|---|---|
|
0ba6fde027 | ||
|
33115bb221 | ||
|
0c0143170d | ||
|
85818c2630 | ||
|
b876909a8a |
@ -62,10 +62,10 @@ add your theme to [service/singleton/frontend-templates.yaml](service/singleton/
|
|||||||
<a href="https://github.com/liuyanxi975" title="刘颜溪"><img src="https://avatars.githubusercontent.com/u/24417037?v=4" width="50;" alt="刘颜溪"/></a>
|
<a href="https://github.com/liuyanxi975" title="刘颜溪"><img src="https://avatars.githubusercontent.com/u/24417037?v=4" width="50;" alt="刘颜溪"/></a>
|
||||||
<a href="https://github.com/CosmosZ-code" title="CosmosZ-code"><img src="https://avatars.githubusercontent.com/u/81398224?v=4" width="50;" alt="CosmosZ-code"/></a>
|
<a href="https://github.com/CosmosZ-code" title="CosmosZ-code"><img src="https://avatars.githubusercontent.com/u/81398224?v=4" width="50;" alt="CosmosZ-code"/></a>
|
||||||
<a href="https://github.com/lvgj-stack" title="Ko no dio"><img src="https://avatars.githubusercontent.com/u/38449861?v=4" width="50;" alt="Ko no dio"/></a>
|
<a href="https://github.com/lvgj-stack" title="Ko no dio"><img src="https://avatars.githubusercontent.com/u/38449861?v=4" width="50;" alt="Ko no dio"/></a>
|
||||||
|
<a href="https://github.com/weblate" title="Weblate (bot)"><img src="https://avatars.githubusercontent.com/u/1607653?v=4" width="50;" alt="Weblate (bot)"/></a>
|
||||||
<a href="https://github.com/hhhkkk520" title="Kris"><img src="https://avatars.githubusercontent.com/u/52115472?v=4" width="50;" alt="Kris"/></a>
|
<a href="https://github.com/hhhkkk520" title="Kris"><img src="https://avatars.githubusercontent.com/u/52115472?v=4" width="50;" alt="Kris"/></a>
|
||||||
<a href="https://github.com/1ridic" title="1ridic"><img src="https://avatars.githubusercontent.com/u/88495501?v=4" width="50;" alt="1ridic"/></a>
|
<a href="https://github.com/1ridic" title="1ridic"><img src="https://avatars.githubusercontent.com/u/88495501?v=4" width="50;" alt="1ridic"/></a>
|
||||||
<a href="https://github.com/Mmx233" title="Mmx"><img src="https://avatars.githubusercontent.com/u/36563672?v=4" width="50;" alt="Mmx"/></a>
|
<a href="https://github.com/Mmx233" title="Mmx"><img src="https://avatars.githubusercontent.com/u/36563672?v=4" width="50;" alt="Mmx"/></a>
|
||||||
<a href="https://github.com/weblate" title="Weblate (bot)"><img src="https://avatars.githubusercontent.com/u/1607653?v=4" width="50;" alt="Weblate (bot)"/></a>
|
|
||||||
<a href="https://github.com/rootmelo92118" title="rootmelo92118"><img src="https://avatars.githubusercontent.com/u/32770959?v=4" width="50;" alt="rootmelo92118"/></a>
|
<a href="https://github.com/rootmelo92118" title="rootmelo92118"><img src="https://avatars.githubusercontent.com/u/32770959?v=4" width="50;" alt="rootmelo92118"/></a>
|
||||||
<a href="https://github.com/Moraxyc" title="Moraxyc"><img src="https://avatars.githubusercontent.com/u/69713071?v=4" width="50;" alt="Moraxyc"/></a>
|
<a href="https://github.com/Moraxyc" title="Moraxyc"><img src="https://avatars.githubusercontent.com/u/69713071?v=4" width="50;" alt="Moraxyc"/></a>
|
||||||
<a href="https://github.com/zhucaidan" title="zhucaidan"><img src="https://avatars.githubusercontent.com/u/47970938?v=4" width="50;" alt="zhucaidan"/></a>
|
<a href="https://github.com/zhucaidan" title="zhucaidan"><img src="https://avatars.githubusercontent.com/u/47970938?v=4" width="50;" alt="zhucaidan"/></a>
|
||||||
|
@ -168,7 +168,7 @@ func updateNotificationGroup(c *gin.Context) (any, error) {
|
|||||||
ngf.Notifications = slices.Compact(ngf.Notifications)
|
ngf.Notifications = slices.Compact(ngf.Notifications)
|
||||||
|
|
||||||
var count int64
|
var count int64
|
||||||
if err := singleton.DB.Model(&model.Server{}).Where("id in (?)", ngf.Notifications).Count(&count).Error; err != nil {
|
if err := singleton.DB.Model(&model.Notification{}).Where("id in (?)", ngf.Notifications).Count(&count).Error; err != nil {
|
||||||
return nil, newGormError("%v", err)
|
return nil, newGormError("%v", err)
|
||||||
}
|
}
|
||||||
if count != int64(len(ngf.Notifications)) {
|
if count != int64(len(ngf.Notifications)) {
|
||||||
|
@ -62,13 +62,9 @@ func (r *AlertRule) Enabled() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Snapshot 对传入的Server进行该报警规则下所有type的检查 返回每项检查结果
|
// Snapshot 对传入的Server进行该报警规则下所有type的检查 返回每项检查结果
|
||||||
func (r *AlertRule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB, role uint8) []bool {
|
func (r *AlertRule) Snapshot(cycleTransferStats *CycleTransferStats, server *Server, db *gorm.DB) []bool {
|
||||||
point := make([]bool, len(r.Rules))
|
point := make([]bool, len(r.Rules))
|
||||||
|
|
||||||
if r.UserID != server.UserID && role != RoleAdmin {
|
|
||||||
return point
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, rule := range r.Rules {
|
for i, rule := range r.Rules {
|
||||||
point[i] = rule.Snapshot(cycleTransferStats, server, db)
|
point[i] = rule.Snapshot(cycleTransferStats, server, db)
|
||||||
}
|
}
|
||||||
@ -79,17 +75,15 @@ func (r *AlertRule) Snapshot(cycleTransferStats *CycleTransferStats, server *Ser
|
|||||||
func (r *AlertRule) Check(points [][]bool) (maxDuration int, passed bool) {
|
func (r *AlertRule) Check(points [][]bool) (maxDuration int, passed bool) {
|
||||||
failCount := 0 // 检查未通过的个数
|
failCount := 0 // 检查未通过的个数
|
||||||
|
|
||||||
for i, rule := range r.Rules {
|
for ruleId, rule := range r.Rules {
|
||||||
if rule.IsTransferDurationRule() {
|
if rule.IsTransferDurationRule() {
|
||||||
// 循环区间流量报警
|
// 循环区间流量报警
|
||||||
if maxDuration < 1 {
|
if maxDuration < 1 {
|
||||||
maxDuration = 1
|
maxDuration = 1
|
||||||
}
|
}
|
||||||
for j := len(points[i]) - 1; j >= 0; j-- {
|
// 只要最后一次检查超出了规则范围 就认为检查未通过
|
||||||
if !points[i][j] {
|
if len(points) > 0 && !points[len(points)-1][ruleId] {
|
||||||
failCount++
|
failCount++
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 常规报警
|
// 常规报警
|
||||||
@ -100,21 +94,20 @@ func (r *AlertRule) Check(points [][]bool) (maxDuration int, passed bool) {
|
|||||||
if len(points) < duration {
|
if len(points) < duration {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
total, fail := 0.0, 0.0
|
total, fail := 0.0, 0.0
|
||||||
for j := len(points) - duration; j < len(points); j++ {
|
for timeTick := len(points) - duration; timeTick < len(points); timeTick++ {
|
||||||
total++
|
total++
|
||||||
if !points[j][i] {
|
if !points[timeTick][ruleId] {
|
||||||
fail++
|
fail++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 当70%以上的采样点未通过规则判断时 才认为当前检查未通过
|
// 当70%以上的采样点未通过规则判断时 才认为当前检查未通过
|
||||||
if fail/total > 0.7 {
|
if fail/total > 0.7 {
|
||||||
failCount++
|
failCount++
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 仅当所有检查均未通过时 返回false
|
|
||||||
|
// 仅当所有检查均未通过时 才触发告警
|
||||||
return maxDuration, failCount != len(r.Rules)
|
return maxDuration, failCount != len(r.Rules)
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
@ -8,16 +8,16 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-12-22 11:55+0800\n"
|
"POT-Creation-Date: 2024-12-22 11:55+0800\n"
|
||||||
"PO-Revision-Date: 2024-12-17 04:52+0000\n"
|
"PO-Revision-Date: 2024-12-26 06:06+0000\n"
|
||||||
"Last-Translator: UUBulb <uub@kuzu.uk>\n"
|
"Last-Translator: UUBulb <uub@kuzu.uk>\n"
|
||||||
"Language-Team: German <https://hosted.weblate.org/projects/nezha/nezha-"
|
"Language-Team: German <https://hosted.weblate.org/projects/nezha/"
|
||||||
"dashboard/de/>\n"
|
"nezha-dashboard/de/>\n"
|
||||||
"Language: de_DE\n"
|
"Language: de_DE\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
"X-Generator: Weblate 5.9\n"
|
"X-Generator: Weblate 5.10-dev\n"
|
||||||
|
|
||||||
#: cmd/dashboard/controller/alertrule.go:103
|
#: cmd/dashboard/controller/alertrule.go:103
|
||||||
#, c-format
|
#, c-format
|
||||||
@ -51,7 +51,7 @@ msgstr "benachrichtigungs ID %d existiert nicht"
|
|||||||
#: cmd/dashboard/controller/service.go:370
|
#: cmd/dashboard/controller/service.go:370
|
||||||
#: cmd/dashboard/controller/terminal.go:41
|
#: cmd/dashboard/controller/terminal.go:41
|
||||||
msgid "permission denied"
|
msgid "permission denied"
|
||||||
msgstr ""
|
msgstr "zugriff verweigert"
|
||||||
|
|
||||||
#: cmd/dashboard/controller/alertrule.go:183
|
#: cmd/dashboard/controller/alertrule.go:183
|
||||||
msgid "duration need to be at least 3"
|
msgid "duration need to be at least 3"
|
||||||
@ -153,7 +153,7 @@ msgstr "service ID %d existiert nicht"
|
|||||||
|
|
||||||
#: cmd/dashboard/controller/user.go:58
|
#: cmd/dashboard/controller/user.go:58
|
||||||
msgid "incorrect password"
|
msgid "incorrect password"
|
||||||
msgstr ""
|
msgstr "falsches passwort"
|
||||||
|
|
||||||
#: cmd/dashboard/controller/user.go:110
|
#: cmd/dashboard/controller/user.go:110
|
||||||
msgid "password length must be greater than 6"
|
msgid "password length must be greater than 6"
|
||||||
@ -165,7 +165,7 @@ msgstr "benutzername darf nicht leer sein"
|
|||||||
|
|
||||||
#: cmd/dashboard/controller/user.go:152
|
#: cmd/dashboard/controller/user.go:152
|
||||||
msgid "can't delete yourself"
|
msgid "can't delete yourself"
|
||||||
msgstr ""
|
msgstr "du kannst dich selbst nicht löschen"
|
||||||
|
|
||||||
#: service/rpc/io_stream.go:128
|
#: service/rpc/io_stream.go:128
|
||||||
msgid "timeout: no connection established"
|
msgid "timeout: no connection established"
|
||||||
@ -269,4 +269,4 @@ msgstr "Unten"
|
|||||||
|
|
||||||
#: service/singleton/user.go:53
|
#: service/singleton/user.go:53
|
||||||
msgid "user id not specified"
|
msgid "user id not specified"
|
||||||
msgstr ""
|
msgstr "benutzer-id nicht angegeben"
|
||||||
|
Binary file not shown.
@ -8,16 +8,16 @@ msgstr ""
|
|||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-12-22 11:55+0800\n"
|
"POT-Creation-Date: 2024-12-22 11:55+0800\n"
|
||||||
"PO-Revision-Date: 2024-12-17 04:52+0000\n"
|
"PO-Revision-Date: 2024-12-26 06:07+0000\n"
|
||||||
"Last-Translator: UUBulb <uub@kuzu.uk>\n"
|
"Last-Translator: UUBulb <uub@kuzu.uk>\n"
|
||||||
"Language-Team: Spanish <https://hosted.weblate.org/projects/nezha/nezha-"
|
"Language-Team: Spanish <https://hosted.weblate.org/projects/nezha/"
|
||||||
"dashboard/es/>\n"
|
"nezha-dashboard/es/>\n"
|
||||||
"Language: es_ES\n"
|
"Language: es_ES\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
"X-Generator: Weblate 5.9\n"
|
"X-Generator: Weblate 5.10-dev\n"
|
||||||
|
|
||||||
#: cmd/dashboard/controller/alertrule.go:103
|
#: cmd/dashboard/controller/alertrule.go:103
|
||||||
#, c-format
|
#, c-format
|
||||||
@ -51,7 +51,7 @@ msgstr "el ID de alerta %d no existe"
|
|||||||
#: cmd/dashboard/controller/service.go:370
|
#: cmd/dashboard/controller/service.go:370
|
||||||
#: cmd/dashboard/controller/terminal.go:41
|
#: cmd/dashboard/controller/terminal.go:41
|
||||||
msgid "permission denied"
|
msgid "permission denied"
|
||||||
msgstr ""
|
msgstr "permiso denegado"
|
||||||
|
|
||||||
#: cmd/dashboard/controller/alertrule.go:183
|
#: cmd/dashboard/controller/alertrule.go:183
|
||||||
msgid "duration need to be at least 3"
|
msgid "duration need to be at least 3"
|
||||||
@ -153,7 +153,7 @@ msgstr "el ID de servicio %d no existe"
|
|||||||
|
|
||||||
#: cmd/dashboard/controller/user.go:58
|
#: cmd/dashboard/controller/user.go:58
|
||||||
msgid "incorrect password"
|
msgid "incorrect password"
|
||||||
msgstr ""
|
msgstr "contraseña incorrecta"
|
||||||
|
|
||||||
#: cmd/dashboard/controller/user.go:110
|
#: cmd/dashboard/controller/user.go:110
|
||||||
msgid "password length must be greater than 6"
|
msgid "password length must be greater than 6"
|
||||||
@ -165,7 +165,7 @@ msgstr "el nombre de usuario no puede estar vacío"
|
|||||||
|
|
||||||
#: cmd/dashboard/controller/user.go:152
|
#: cmd/dashboard/controller/user.go:152
|
||||||
msgid "can't delete yourself"
|
msgid "can't delete yourself"
|
||||||
msgstr ""
|
msgstr "no puedes eliminarte a ti mismo"
|
||||||
|
|
||||||
#: service/rpc/io_stream.go:128
|
#: service/rpc/io_stream.go:128
|
||||||
msgid "timeout: no connection established"
|
msgid "timeout: no connection established"
|
||||||
@ -274,4 +274,4 @@ msgstr "Fallo"
|
|||||||
|
|
||||||
#: service/singleton/user.go:53
|
#: service/singleton/user.go:53
|
||||||
msgid "user id not specified"
|
msgid "user id not specified"
|
||||||
msgstr ""
|
msgstr "id de usuario no especificado"
|
||||||
|
@ -38,7 +38,7 @@ func (a *authHandler) Check(ctx context.Context) (uint64, error) {
|
|||||||
|
|
||||||
singleton.UserLock.RLock()
|
singleton.UserLock.RLock()
|
||||||
userId, ok := singleton.AgentSecretToUserId[clientSecret]
|
userId, ok := singleton.AgentSecretToUserId[clientSecret]
|
||||||
if !ok && clientSecret != singleton.Conf.AgentSecretKey {
|
if !ok {
|
||||||
singleton.UserLock.RUnlock()
|
singleton.UserLock.RUnlock()
|
||||||
model.BlockIP(singleton.DB, ip, model.WAFBlockReasonTypeAgentAuthFail, model.BlockIDgRPC)
|
model.BlockIP(singleton.DB, ip, model.WAFBlockReasonTypeAgentAuthFail, model.BlockIDgRPC)
|
||||||
return 0, status.Error(codes.Unauthenticated, "客户端认证失败")
|
return 0, status.Error(codes.Unauthenticated, "客户端认证失败")
|
||||||
|
@ -26,7 +26,7 @@ type NotificationHistory struct {
|
|||||||
var (
|
var (
|
||||||
AlertsLock sync.RWMutex
|
AlertsLock sync.RWMutex
|
||||||
Alerts []*model.AlertRule
|
Alerts []*model.AlertRule
|
||||||
alertsStore map[uint64]map[uint64][][]bool // [alert_id][server_id] -> 对应报警规则的检查结果
|
alertsStore map[uint64]map[uint64][][]bool // [alert_id][server_id] -> [timeTick][ruleId] 时间点对应的rule的检查结果
|
||||||
alertsPrevState map[uint64]map[uint64]uint8 // [alert_id][server_id] -> 对应报警规则的上一次报警状态
|
alertsPrevState map[uint64]map[uint64]uint8 // [alert_id][server_id] -> 对应报警规则的上一次报警状态
|
||||||
AlertsCycleTransferStatsStore map[uint64]*model.CycleTransferStats // [alert_id] -> 对应报警规则的周期流量统计
|
AlertsCycleTransferStatsStore map[uint64]*model.CycleTransferStats // [alert_id] -> 对应报警规则的周期流量统计
|
||||||
)
|
)
|
||||||
@ -151,8 +151,11 @@ func checkStatus() {
|
|||||||
role = u.Role
|
role = u.Role
|
||||||
}
|
}
|
||||||
UserLock.RUnlock()
|
UserLock.RUnlock()
|
||||||
|
if alert.UserID != server.UserID && role != model.RoleAdmin {
|
||||||
|
continue
|
||||||
|
}
|
||||||
alertsStore[alert.ID][server.ID] = append(alertsStore[alert.
|
alertsStore[alert.ID][server.ID] = append(alertsStore[alert.
|
||||||
ID][server.ID], alert.Snapshot(AlertsCycleTransferStatsStore[alert.ID], server, DB, role))
|
ID][server.ID], alert.Snapshot(AlertsCycleTransferStatsStore[alert.ID], server, DB))
|
||||||
// 发送通知,分为触发报警和恢复通知
|
// 发送通知,分为触发报警和恢复通知
|
||||||
max, passed := alert.Check(alertsStore[alert.ID][server.ID])
|
max, passed := alert.Check(alertsStore[alert.ID][server.ID])
|
||||||
// 保存当前服务器状态信息
|
// 保存当前服务器状态信息
|
||||||
|
@ -2,14 +2,14 @@
|
|||||||
name: "OfficialAdmin"
|
name: "OfficialAdmin"
|
||||||
repository: "https://github.com/nezhahq/admin-frontend"
|
repository: "https://github.com/nezhahq/admin-frontend"
|
||||||
author: "nezhahq"
|
author: "nezhahq"
|
||||||
version: "v1.4.3"
|
version: "v1.4.4"
|
||||||
isadmin: true
|
isadmin: true
|
||||||
isofficial: true
|
isofficial: true
|
||||||
- path: "user-dist"
|
- path: "user-dist"
|
||||||
name: "Official"
|
name: "Official"
|
||||||
repository: "https://github.com/hamster1963/nezha-dash-v1"
|
repository: "https://github.com/hamster1963/nezha-dash-v1"
|
||||||
author: "hamster1963"
|
author: "hamster1963"
|
||||||
version: "v1.9.3"
|
version: "v1.10.3"
|
||||||
isofficial: true
|
isofficial: true
|
||||||
- path: "nazhua-dist"
|
- path: "nazhua-dist"
|
||||||
name: "Nazhua"
|
name: "Nazhua"
|
||||||
|
@ -21,6 +21,13 @@ func initUser() {
|
|||||||
var users []model.User
|
var users []model.User
|
||||||
DB.Find(&users)
|
DB.Find(&users)
|
||||||
|
|
||||||
|
// for backward compatibility
|
||||||
|
UserInfoMap[0] = model.UserInfo{
|
||||||
|
Role: model.RoleAdmin,
|
||||||
|
AgentSecret: Conf.AgentSecretKey,
|
||||||
|
}
|
||||||
|
AgentSecretToUserId[Conf.AgentSecretKey] = 0
|
||||||
|
|
||||||
for _, u := range users {
|
for _, u := range users {
|
||||||
UserInfoMap[u.ID] = model.UserInfo{
|
UserInfoMap[u.ID] = model.UserInfo{
|
||||||
Role: u.Role,
|
Role: u.Role,
|
||||||
|
Loading…
Reference in New Issue
Block a user