From ec17948fe45e22fd8388e34c6a32be7a70fb4969 Mon Sep 17 00:00:00 2001 From: naiba Date: Wed, 20 Jan 2021 19:24:59 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=90=8E=E5=8F=B0=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E5=A4=87=E6=B3=A8=20close=20#72?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 17 +--- cmd/dashboard/controller/common_page.go | 91 +++++++++++-------- cmd/dashboard/controller/member_api.go | 2 + cmd/dashboard/controller/oauth2.go | 4 +- model/common.go | 3 +- model/server.go | 5 +- resource/template/component/server.html | 8 +- resource/template/dashboard/monitor.html | 2 +- resource/template/dashboard/notification.html | 4 +- resource/template/dashboard/server.html | 6 +- resource/template/theme-default/service.html | 2 +- service/dao/dao.go | 5 +- 12 files changed, 83 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index d1b3145..b14e688 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # 哪吒面板 -系统状态监控报警;API(SSL证书变更、即将到期、到期)/TCP端口存活/PING 监控;计划任务可以定时在Agent上执行命令(备份、重启、What ever you want);极省资源,64M 服务器也能装 agent。 +![dashboard](https://img.shields.io/badge/管理面板-v0.3.2-brightgreen) ![agent](https://img.shields.io/badge/Agent-v0.3.1-brightgreen) + +系统状态监控报警、API(SSL证书变更、即将到期、到期)/TCP端口存活/PING 监控、计划任务(可以定时在Agent上执行命令,备份、重启、What ever you want)、极省资源,64M 服务器也能装 agent。 | 首页截图1 | 首页截图2 | | ---- | ---- | @@ -207,16 +209,3 @@ URL 里面也可放置占位符,请求时会进行简单的字符串替换。 - [哪吒面板,一个便携服务器状态监控面板搭建教程,不想拥有一个自己的探针吗?](https://haoduck.com/644.html) - [哪吒面板:小鸡们的最佳探针](https://www.zhujizixun.com/2843.html) *(已过时)* - [>>更多教程](https://www.google.com/search?q=%22%E5%93%AA%E5%90%92%E9%9D%A2%E6%9D%BF%22+%22%E6%95%99%E7%A8%8B%22) (Google) - -## 变更日志 - -只保留最后一次更新导致必须更新面板的说明。 - -- `agent 0.3.1` - - - 0.3.0 的更新的一个问题导致 Windows 用户的 Agent 无法自动更新,需要下载 0.3.1 或更新的 release 手动替换掉二进制文件。 - - 增加了对 mips(路由器) 的支持,在 release 处下载后手动配置 - -- `dashboard 0.3.0` `agent 0.3.0` **重大更新** - - 增加了定时任务功能,可以定时在 Agent 上执行脚本(应用于定期备份、重启服务等计划运维场景) diff --git a/cmd/dashboard/controller/common_page.go b/cmd/dashboard/controller/common_page.go index 751834e..c6396c9 100644 --- a/cmd/dashboard/controller/common_page.go +++ b/cmd/dashboard/controller/common_page.go @@ -1,6 +1,7 @@ package controller import ( + "log" "net/http" "time" @@ -36,51 +37,65 @@ type ServiceItem struct { } func (p *commonPage) service(c *gin.Context) { - var ms []model.Monitor - dao.DB.Find(&ms) - year, month, day := time.Now().Date() - today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) - var mhs []model.MonitorHistory - dao.DB.Where("created_at >= ?", today.AddDate(0, 0, -29)).Find(&mhs) + var msm map[uint64]*ServiceItem - msm := make(map[uint64]*ServiceItem) - for i := 0; i < len(ms); i++ { - msm[ms[i].ID] = &ServiceItem{ - Monitor: ms[i], - Delay: &[30]float32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Up: &[30]int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - Down: &[30]int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + var cached bool + if _, has := c.Get(model.CtxKeyAuthorizedUser); !has { + data, has := dao.Cache.Get(model.CacheKeyServicePage) + if has { + log.Println("use cache") + msm = data.(map[uint64]*ServiceItem) + cached = true } } - // 整合数据 - todayStatus := make(map[uint64][]bool) - for i := 0; i < len(mhs); i++ { - dayIndex := 29 - if mhs[i].CreatedAt.Before(today) { - dayIndex = 28 - (int(today.Sub(mhs[i].CreatedAt).Hours()) / 24) - } else { - todayStatus[mhs[i].MonitorID] = append(todayStatus[mhs[i].MonitorID], mhs[i].Successful) - } - if mhs[i].Successful { - msm[mhs[i].MonitorID].TotalUp++ - msm[mhs[i].MonitorID].Delay[dayIndex] = (msm[mhs[i].MonitorID].Delay[dayIndex]*float32(msm[mhs[i].MonitorID].Up[dayIndex]) + mhs[i].Delay) / float32(msm[mhs[i].MonitorID].Up[dayIndex]+1) - msm[mhs[i].MonitorID].Up[dayIndex]++ - } else { - msm[mhs[i].MonitorID].TotalDown++ - msm[mhs[i].MonitorID].Down[dayIndex]++ - } - } + if !cached { + msm = make(map[uint64]*ServiceItem) + var ms []model.Monitor + dao.DB.Find(&ms) + year, month, day := time.Now().Date() + today := time.Date(year, month, day, 0, 0, 0, 0, time.Local) + var mhs []model.MonitorHistory + dao.DB.Where("created_at >= ?", today.AddDate(0, 0, -29)).Find(&mhs) - // 当日最后 20 个采样作为当前状态 - for _, m := range msm { - for i := len(todayStatus[m.Monitor.ID]) - 1; i >= 0 && i >= (len(todayStatus[m.Monitor.ID])-1-20); i-- { - if todayStatus[m.Monitor.ID][i] { - m.CurrentUp++ - } else { - m.CurrentDown++ + for i := 0; i < len(ms); i++ { + msm[ms[i].ID] = &ServiceItem{ + Monitor: ms[i], + Delay: &[30]float32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Up: &[30]int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + Down: &[30]int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, } } + // 整合数据 + todayStatus := make(map[uint64][]bool) + for i := 0; i < len(mhs); i++ { + dayIndex := 29 + if mhs[i].CreatedAt.Before(today) { + dayIndex = 28 - (int(today.Sub(mhs[i].CreatedAt).Hours()) / 24) + } else { + todayStatus[mhs[i].MonitorID] = append(todayStatus[mhs[i].MonitorID], mhs[i].Successful) + } + if mhs[i].Successful { + msm[mhs[i].MonitorID].TotalUp++ + msm[mhs[i].MonitorID].Delay[dayIndex] = (msm[mhs[i].MonitorID].Delay[dayIndex]*float32(msm[mhs[i].MonitorID].Up[dayIndex]) + mhs[i].Delay) / float32(msm[mhs[i].MonitorID].Up[dayIndex]+1) + msm[mhs[i].MonitorID].Up[dayIndex]++ + } else { + msm[mhs[i].MonitorID].TotalDown++ + msm[mhs[i].MonitorID].Down[dayIndex]++ + } + } + // 当日最后 20 个采样作为当前状态 + for _, m := range msm { + for i := len(todayStatus[m.Monitor.ID]) - 1; i >= 0 && i >= (len(todayStatus[m.Monitor.ID])-1-20); i-- { + if todayStatus[m.Monitor.ID][i] { + m.CurrentUp++ + } else { + m.CurrentDown++ + } + } + } + // 未登录人员缓存十分钟 + dao.Cache.Set(model.CacheKeyServicePage, msm, time.Minute*10) } c.HTML(http.StatusOK, "theme-"+dao.Conf.Site.Theme+"/service", mygin.CommonEnvironment(c, gin.H{ diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go index 11d934d..cfe334d 100644 --- a/cmd/dashboard/controller/member_api.go +++ b/cmd/dashboard/controller/member_api.go @@ -108,6 +108,7 @@ type serverForm struct { DisplayIndex int Secret string Tag string + Note string } func (ma *memberAPI) addOrEditServer(c *gin.Context) { @@ -122,6 +123,7 @@ func (ma *memberAPI) addOrEditServer(c *gin.Context) { s.DisplayIndex = sf.DisplayIndex s.ID = sf.ID s.Tag = sf.Tag + s.Note = sf.Note if sf.ID == 0 { s.Secret = utils.MD5(fmt.Sprintf("%s%s%d", time.Now(), sf.Name, admin.ID)) s.Secret = s.Secret[:10] diff --git a/cmd/dashboard/controller/oauth2.go b/cmd/dashboard/controller/oauth2.go index a97ec6f..e342920 100644 --- a/cmd/dashboard/controller/oauth2.go +++ b/cmd/dashboard/controller/oauth2.go @@ -28,14 +28,14 @@ func (oa *oauth2controller) serve() { func (oa *oauth2controller) login(c *gin.Context) { state := utils.RandStringBytesMaskImprSrcUnsafe(6) - dao.Cache.Set(fmt.Sprintf("%s%s", model.CtxKeyOauth2State, c.ClientIP()), state, 0) + dao.Cache.Set(fmt.Sprintf("%s%s", model.CacheKeyOauth2State, c.ClientIP()), state, 0) url := oa.oauth2Config.AuthCodeURL(state, oauth2.AccessTypeOnline) c.Redirect(http.StatusFound, url) } func (oa *oauth2controller) callback(c *gin.Context) { // 验证登录跳转时的 State - state, ok := dao.Cache.Get(fmt.Sprintf("%s%s", model.CtxKeyOauth2State, c.ClientIP())) + state, ok := dao.Cache.Get(fmt.Sprintf("%s%s", model.CacheKeyOauth2State, c.ClientIP())) if !ok || state.(string) != c.Query("state") { mygin.ShowErrorPage(c, mygin.ErrInfo{ Code: http.StatusBadRequest, diff --git a/model/common.go b/model/common.go index e2cb6fb..ef4736b 100644 --- a/model/common.go +++ b/model/common.go @@ -4,7 +4,8 @@ import "time" const CtxKeyAuthorizedUser = "ckau" -const CtxKeyOauth2State = "cko2s" +const CacheKeyOauth2State = "p:a:state" +const CacheKeyServicePage = "p:c:service" type Common struct { ID uint64 `gorm:"primary_key"` diff --git a/model/server.go b/model/server.go index e7d3de1..8d65296 100644 --- a/model/server.go +++ b/model/server.go @@ -11,8 +11,9 @@ import ( type Server struct { Common Name string - Tag string + Tag string // 分组名 Secret string `json:"-"` + Note string `json:"-"` // 管理员可见备注 DisplayIndex int // 展示权重,越大越靠前 Host *Host `gorm:"-"` @@ -24,5 +25,5 @@ type Server struct { } func (s Server) Marshal() template.JS { - return template.JS(fmt.Sprintf(`{"ID":%d,"Name":"%s","Secret":"%s"}`, s.ID, s.Name, s.Secret)) + return template.JS(fmt.Sprintf(`{"ID":%d,"Name":"%s","Secret":"%s","DisplayIndex":%d,"Tag":"%s","Note":"%s"}`, s.ID, s.Name, s.Secret, s.DisplayIndex, s.Tag, s.Note)) } diff --git a/resource/template/component/server.html b/resource/template/component/server.html index 9a73595..e333796 100644 --- a/resource/template/component/server.html +++ b/resource/template/component/server.html @@ -9,8 +9,8 @@
- - + +
@@ -20,6 +20,10 @@
+
+ + +
diff --git a/resource/template/dashboard/monitor.html b/resource/template/dashboard/monitor.html index ff94cec..68856ae 100644 --- a/resource/template/dashboard/monitor.html +++ b/resource/template/dashboard/monitor.html @@ -41,7 +41,7 @@
diff --git a/resource/template/dashboard/notification.html b/resource/template/dashboard/notification.html index b9698b6..e1fd832 100644 --- a/resource/template/dashboard/notification.html +++ b/resource/template/dashboard/notification.html @@ -34,7 +34,7 @@ @@ -74,7 +74,7 @@ diff --git a/resource/template/dashboard/server.html b/resource/template/dashboard/server.html index 3acc2a6..b2061d2 100644 --- a/resource/template/dashboard/server.html +++ b/resource/template/dashboard/server.html @@ -15,10 +15,11 @@ 权重 备注 - 标签 + 分组 IP ID 密钥 + 隐藏备注 管理 @@ -31,6 +32,7 @@ {{$server.Host.IP}} {{$server.ID}} {{$server.Secret}} + {{$server.Note}}
diff --git a/resource/template/theme-default/service.html b/resource/template/theme-default/service.html index d3d67ac..5a910bd 100644 --- a/resource/template/theme-default/service.html +++ b/resource/template/theme-default/service.html @@ -26,7 +26,7 @@ {{range $i,$d := $service.Delay}}
+ data-tooltip="{{dayBefore $i}},在线率:{{float32f (div (index $service.Up $i) (add (index $service.Up $i) (index $service.Down $i)))}}%,平均延迟:{{float32f $d}}ms">
{{end}} diff --git a/service/dao/dao.go b/service/dao/dao.go index 7df19a6..9165cd2 100644 --- a/service/dao/dao.go +++ b/service/dao/dao.go @@ -34,7 +34,7 @@ var CronLock sync.RWMutex var Crons map[uint64]*model.Cron var Cron *cron.Cron -var Version = "v0.3.1" +var Version = "v0.3.2" func ReSortServer() { ServerLock.RLock() @@ -48,6 +48,9 @@ func ReSortServer() { } sort.SliceStable(SortedServerList, func(i, j int) bool { + if SortedServerList[i].DisplayIndex == SortedServerList[j].DisplayIndex { + return SortedServerList[i].ID < SortedServerList[i].ID + } return SortedServerList[i].DisplayIndex > SortedServerList[j].DisplayIndex }) }