diff --git a/README.md b/README.md index f73fbdf..906c707 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
LOGO designed by 熊大 .

-    +   

:trollface: 哪吒监控 一站式轻监控轻运维系统。支持系统状态、HTTP(SSL 证书变更、即将到期、到期)、TCP、Ping 监控报警,计划任务和在线终端。

@@ -144,8 +144,8 @@ URL 里面也可放置占位符,请求时会进行简单的字符串替换。 - cycle_interval 每隔多少个周期单位(例如,周期单位为天,该值为 7,则代表每隔 7 天统计一次) - cycle_unit 统计周期单位,默认`hour`,可选(`hour`, `day`, `week`, `month`, `year`) - min/max、cover、ignore 参考基本规则配置 -- 示例: ID 为 3 的机器(ignore 里面定义)的每月 15 号计费的出站月流量 1T 报警 `[{"type":"transfer_out_cycle","max":1000000000000,"cycle_start":"2021-07-15T08:00:00Z","cycle_interval":1,"cycle_unit":"month","cover":1,"ignore":{"3":true}}]` - [![7QKaUx.md.png](https://s4.ax1x.com/2022/01/13/7QKaUx.md.png)](https://imgtu.com/i/7QKaUx) +- 示例: ID 为 3 的机器(ignore 里面定义)的每月 15 号计费的出站月流量 1T 报警 `[{"type":"transfer_out_cycle","max":1000000000000,"cycle_start":"2022-01-11T08:00:00.00+08:00","cycle_interval":1,"cycle_unit":"month","cover":1,"ignore":{"3":true}}]` + ![7QKaUx.md.png](https://s4.ax1x.com/2022/01/13/7QKaUx.md.png) diff --git a/cmd/dashboard/controller/controller.go b/cmd/dashboard/controller/controller.go index 4c3d797..1b8dbc0 100644 --- a/cmd/dashboard/controller/controller.go +++ b/cmd/dashboard/controller/controller.go @@ -13,6 +13,7 @@ import ( "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" + "github.com/naiba/nezha/model" "github.com/naiba/nezha/pkg/mygin" "github.com/naiba/nezha/service/singleton" ) @@ -27,7 +28,7 @@ func ServeWeb(port uint) *http.Server { r.Use(mygin.RecordPath) r.SetFuncMap(template.FuncMap{ "tf": func(t time.Time) string { - return t.Format("2006年1月2号 15:04:05") + return t.In(model.Loc).Format("2006年1月2号 15:04:05") }, "len": func(slice []interface{}) string { return strconv.Itoa(len(slice)) @@ -39,7 +40,7 @@ func ServeWeb(port uint) *http.Server { return template.HTML(`<` + s + `>`) // #nosec }, "stf": func(s uint64) string { - return time.Unix(int64(s), 0).Format("2006年1月2号 15:04") + return time.Unix(int64(s), 0).In(model.Loc).Format("2006年1月2号 15:04") }, "sf": func(duration uint64) string { return time.Duration(time.Duration(duration) * time.Second).String() diff --git a/cmd/dashboard/controller/member_api.go b/cmd/dashboard/controller/member_api.go index 9422253..f9298da 100644 --- a/cmd/dashboard/controller/member_api.go +++ b/cmd/dashboard/controller/member_api.go @@ -440,9 +440,24 @@ func (ma *memberAPI) addOrEditAlertRule(c *gin.Context) { err = errors.New("至少定义一条规则") } else { for i := 0; i < len(r.Rules); i++ { - if !r.Rules[i].IsTransferDurationRule() && r.Rules[i].Duration < 3 { - err = errors.New("错误:Duration 至少为 3") - break + if !r.Rules[i].IsTransferDurationRule() { + if r.Rules[i].Duration < 3 { + err = errors.New("错误:Duration 至少为 3") + break + } + } else { + if r.Rules[i].CycleInterval < 1 { + err = errors.New("错误: cycle_interval 至少为 1") + break + } + if r.Rules[i].CycleStart == nil { + err = errors.New("错误: cycle_start 未设置") + break + } + if r.Rules[i].CycleStart.After(time.Now()) { + err = errors.New("错误: cycle_start 是个未来值") + break + } } } } diff --git a/go.mod b/go.mod index d400650..000b0f8 100644 --- a/go.mod +++ b/go.mod @@ -13,10 +13,10 @@ require ( github.com/go-ping/ping v0.0.0-20211130115550-779d1e919534 github.com/golang/protobuf v1.5.2 github.com/google/go-github v17.0.0+incompatible - github.com/gorilla/websocket v1.4.2 + github.com/gorilla/websocket v1.5.0 github.com/hashicorp/go-uuid v1.0.2 github.com/iamacarpet/go-winpty v1.0.2 - github.com/ory/graceful v0.1.1 + github.com/ory/graceful v0.1.2 github.com/p14yground/go-github-selfupdate v0.0.0-20220205132106-76a6d59b925b github.com/patrickmn/go-cache v2.1.0+incompatible github.com/robfig/cron/v3 v3.0.1 @@ -24,13 +24,13 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.10.1 github.com/stretchr/testify v1.7.0 - golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 + golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b google.golang.org/grpc v1.44.0 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v2 v2.4.0 - gorm.io/driver/sqlite v1.2.6 - gorm.io/gorm v1.22.5 + gorm.io/driver/sqlite v1.3.1 + gorm.io/gorm v1.23.1 ) require ( diff --git a/go.sum b/go.sum index a094382..dcbc280 100644 --- a/go.sum +++ b/go.sum @@ -241,8 +241,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= @@ -284,7 +284,6 @@ github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7V github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -364,8 +363,8 @@ github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAl github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/ory/graceful v0.1.1 h1:zx+8tDObLPrG+7Tc8jKYlXsqWnLtOQA1IZ/FAAKHMXU= -github.com/ory/graceful v0.1.1/go.mod h1:zqu70l95WrKHF4AZ6tXHvAqAvpY6M7g6ttaAVcMm7KU= +github.com/ory/graceful v0.1.2 h1:ErCFGuO0T6IHMQ9Fu9GKjIaRbNCrKDX/WdHDwM/mAlY= +github.com/ory/graceful v0.1.2/go.mod h1:4zFz687IAF7oNHHiB586U4iL+/4aV09o/PYLE34t2bA= github.com/p14yground/go-github-selfupdate v0.0.0-20220205132106-76a6d59b925b h1:RdYnjYaMiGP+6j4mcGnYeTasmOASC3grb8AVrW0GI7o= github.com/p14yground/go-github-selfupdate v0.0.0-20220205132106-76a6d59b925b/go.mod h1:u+UXObeNk8HBmfbGG5nBf/PZxw3N8uwpvsQsd40DL4I= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -486,8 +485,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838 h1:71vQrMauZZhcTVK6KdYM+rklehEEwb3E+ZhaE5jrPrE= -golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -587,8 +586,9 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b h1:clP8eMhB30EHdc0bd2Twtq6kgU7yl5ub2cQLSdrv1Dg= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -930,11 +930,10 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4= -gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY= -gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU= -gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= +gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= +gorm.io/gorm v1.23.1 h1:aj5IlhDzEPsoIyOPtTRVI+SyaN1u6k613sbt4pwbxG0= +gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/model/common.go b/model/common.go index 05ac8a7..1596b38 100644 --- a/model/common.go +++ b/model/common.go @@ -6,6 +6,16 @@ const CtxKeyAuthorizedUser = "ckau" const CacheKeyOauth2State = "p:a:state" +var Loc *time.Location + +func init() { + var err error + Loc, err = time.LoadLocation("Asia/Shanghai") + if err != nil { + panic(err) + } +} + type Common struct { ID uint64 `gorm:"primary_key"` CreatedAt time.Time `sql:"index"` diff --git a/model/rule.go b/model/rule.go index e8a3acd..bcec64c 100644 --- a/model/rule.go +++ b/model/rule.go @@ -23,9 +23,9 @@ type Rule struct { Type string `json:"type,omitempty"` Min float64 `json:"min,omitempty"` // 最小阈值 (百分比、字节 kb ÷ 1024) Max float64 `json:"max,omitempty"` // 最大阈值 (百分比、字节 kb ÷ 1024) - CycleStart time.Time `json:"cycle_start,omitempty"` // 流量统计的开始时间 + CycleStart *time.Time `json:"cycle_start,omitempty"` // 流量统计的开始时间 CycleInterval uint64 `json:"cycle_interval,omitempty"` // 流量统计周期 - CycleUnit string `json:"cycle_unit,omitempty"` // 流量统计周期单位,默认hour,可选(hour, day, week, month, year) + CycleUnit string `json:"cycle_unit,omitempty"` // 流量统计周期单位,默认hour,可选(hour, day, week, month, year) Duration uint64 `json:"duration,omitempty"` // 持续时间 (秒) Cover uint64 `json:"cover,omitempty"` // 覆盖范围 RuleCoverAll/IgnoreAll Ignore map[uint64]bool `json:"ignore,omitempty"` // 覆盖范围的排除 @@ -166,7 +166,7 @@ func (rule Rule) IsTransferDurationRule() bool { func (rule Rule) GetTransferDurationStart() time.Time { // Accept uppercase and lowercase unit := strings.ToLower(rule.CycleUnit) - startTime := rule.CycleStart + startTime := *rule.CycleStart var nextTime time.Time switch unit { case "year": @@ -182,10 +182,10 @@ func (rule Rule) GetTransferDurationStart() time.Time { nextTime = nextTime.AddDate(0, int(rule.CycleInterval), 0) } case "week": - nextTime = startTime.AddDate(0, 0, 7 * int(rule.CycleInterval)) + nextTime = startTime.AddDate(0, 0, 7*int(rule.CycleInterval)) for time.Now().After(nextTime) { startTime = nextTime - nextTime = nextTime.AddDate(0, 0, 7 * int(rule.CycleInterval)) + nextTime = nextTime.AddDate(0, 0, 7*int(rule.CycleInterval)) } case "day": nextTime = startTime.AddDate(0, 0, int(rule.CycleInterval)) @@ -205,7 +205,7 @@ func (rule Rule) GetTransferDurationStart() time.Time { func (rule Rule) GetTransferDurationEnd() time.Time { // Accept uppercase and lowercase unit := strings.ToLower(rule.CycleUnit) - startTime := rule.CycleStart + startTime := *rule.CycleStart var nextTime time.Time switch unit { case "year": @@ -221,10 +221,10 @@ func (rule Rule) GetTransferDurationEnd() time.Time { nextTime = nextTime.AddDate(0, int(rule.CycleInterval), 0) } case "week": - nextTime = startTime.AddDate(0, 0, 7 * int(rule.CycleInterval)) + nextTime = startTime.AddDate(0, 0, 7*int(rule.CycleInterval)) for time.Now().After(nextTime) { startTime = nextTime - nextTime = nextTime.AddDate(0, 0, 7 * int(rule.CycleInterval)) + nextTime = nextTime.AddDate(0, 0, 7*int(rule.CycleInterval)) } case "day": nextTime = startTime.AddDate(0, 0, int(rule.CycleInterval)) @@ -236,7 +236,7 @@ func (rule Rule) GetTransferDurationEnd() time.Time { // For hour unit or not set. interval := 3600 * int64(rule.CycleInterval) startTime = time.Unix(rule.CycleStart.Unix()+(time.Now().Unix()-rule.CycleStart.Unix())/interval*interval, 0) - nextTime = time.Unix(startTime.Unix() + interval, 0) + nextTime = time.Unix(startTime.Unix()+interval, 0) } return nextTime diff --git a/service/singleton/singleton.go b/service/singleton/singleton.go index 198dc26..beaedca 100644 --- a/service/singleton/singleton.go +++ b/service/singleton/singleton.go @@ -14,7 +14,7 @@ import ( pb "github.com/naiba/nezha/proto" ) -var Version = "v0.12.10" // !!记得修改 README 中的 badge 版本!! +var Version = "v0.12.11" // !!记得修改 README 中的 badge 版本!! var ( Conf *model.Config