mirror of
https://github.com/lollipopkit/server_box_monitor.git
synced 2025-01-09 04:10:01 +08:00
pass test: QQ
(webhook)
This commit is contained in:
parent
e94353e8df
commit
6a489a3b17
@ -15,21 +15,14 @@ var (
|
||||
|
||||
type AppConfig struct {
|
||||
Version int `json:"version"`
|
||||
Interval `json:"interval"`
|
||||
// Such as "300ms", "-1.5h" or "2h45m".
|
||||
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
||||
// Values less than 1 minute are not allowed.
|
||||
Interval string`json:"interval"`
|
||||
Rules []Rule `json:"rules"`
|
||||
Pushes []Push `json:"pushes"`
|
||||
}
|
||||
|
||||
// Such as "300ms", "-1.5h" or "2h45m".
|
||||
// Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
||||
type Interval struct {
|
||||
// interval for running the script to get status
|
||||
// Values greater than 10 or less than 3 will be ignored
|
||||
Run string `json:"run"`
|
||||
// interval for pushing the status
|
||||
Push string `json:"push"`
|
||||
}
|
||||
|
||||
func ReadAppConfig() error {
|
||||
if !utils.Exist(res.AppConfigPath) {
|
||||
configBytes, err := json.MarshalIndent(DefaultappConfig, "", "\t")
|
||||
@ -60,23 +53,22 @@ func ReadAppConfig() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (ac *AppConfig) GetRunInterval() time.Duration {
|
||||
d, err := time.ParseDuration(ac.Interval.Run)
|
||||
func GetInterval() time.Duration {
|
||||
ac := DefaultappConfig
|
||||
if Config != nil {
|
||||
ac = Config
|
||||
}
|
||||
d, err := time.ParseDuration(ac.Interval)
|
||||
if err == nil {
|
||||
if d < res.DefaultInterval {
|
||||
utils.Warn("[CONFIG] interval is too short, use default interval: 1m")
|
||||
return res.DefaultInterval
|
||||
}
|
||||
return d
|
||||
}
|
||||
utils.Warn("[CONFIG] parse interval failed: %v, use default interval: 5s", err)
|
||||
return time.Second * 5
|
||||
utils.Warn("[CONFIG] parse interval failed: %v, use default interval: 1m", err)
|
||||
return res.DefaultInterval
|
||||
}
|
||||
func (ac *AppConfig) GetPushInterval() time.Duration {
|
||||
d, err := time.ParseDuration(ac.Interval.Push)
|
||||
if err == nil {
|
||||
return d
|
||||
}
|
||||
utils.Warn("[CONFIG] parse interval failed: %v, use default interval: 5m", err)
|
||||
return time.Minute * 5
|
||||
}
|
||||
|
||||
|
||||
var (
|
||||
defaultWekhookBody = map[string]interface{}{
|
||||
@ -92,7 +84,7 @@ var (
|
||||
Url: "http://localhost:5700",
|
||||
Headers: map[string]string{
|
||||
"Content-Type": "application/json",
|
||||
"Auhorization": "Bearer YOUR_SECRET",
|
||||
"Authorization": "Bearer YOUR_SECRET",
|
||||
},
|
||||
Method: "POST",
|
||||
Body: defaultWekhookBodyBytes,
|
||||
@ -109,7 +101,7 @@ var (
|
||||
|
||||
DefaultappConfig = &AppConfig{
|
||||
Version: 1,
|
||||
Interval: Interval{Run: "5s", Push: "5m"},
|
||||
Interval: "3m",
|
||||
Rules: []Rule{
|
||||
{
|
||||
MonitorType: MonitorTypeCPU,
|
||||
|
@ -37,22 +37,22 @@ func (p *Push) GetIface() (PushIface, error) {
|
||||
return nil, errors.New("unknown push type")
|
||||
}
|
||||
|
||||
func (p *Push) Push(args []*PushFormatArgs) error {
|
||||
func (p *Push) Push(args []*PushPair) error {
|
||||
iface, err := p.GetIface()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, code, err := iface.push(args)
|
||||
if p.SuccessCode != 0 && code != p.SuccessCode {
|
||||
return fmt.Errorf("[PUSH] failed, code: %d, resp: %s", code, string(resp))
|
||||
return fmt.Errorf("code: %d, resp: %s", code, string(resp))
|
||||
}
|
||||
if p.SuccessBodyRegex != "" {
|
||||
reg, err := regexp.Compile(p.SuccessBodyRegex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("[PUSH] compile regex failed: %s", err.Error())
|
||||
return fmt.Errorf("compile regex failed: %s", err.Error())
|
||||
}
|
||||
if !reg.Match(resp) {
|
||||
return fmt.Errorf("[PUSH] failed, resp: %s", string(resp))
|
||||
return fmt.Errorf("resp: %s", string(resp))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@ -74,12 +74,12 @@ func (p *Push) Id() string {
|
||||
|
||||
// {{key}} {{value}}
|
||||
type PushFormat string
|
||||
type PushFormatArgs struct {
|
||||
type PushPair struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
func (pf PushFormat) String(args []*PushFormatArgs) string {
|
||||
func (pf PushFormat) String(args []*PushPair) string {
|
||||
ss := []string{}
|
||||
for _, arg := range args {
|
||||
s := string(pf)
|
||||
@ -98,7 +98,7 @@ const (
|
||||
)
|
||||
|
||||
type PushIface interface {
|
||||
push([]*PushFormatArgs) ([]byte, int, error)
|
||||
push([]*PushPair) ([]byte, int, error)
|
||||
}
|
||||
|
||||
type PushIOS struct {
|
||||
@ -108,7 +108,7 @@ type PushIOS struct {
|
||||
Content PushFormat `json:"content"`
|
||||
}
|
||||
|
||||
func (p PushIOS) push(args []*PushFormatArgs) ([]byte, int, error) {
|
||||
func (p PushIOS) push(args []*PushPair) ([]byte, int, error) {
|
||||
title := p.Title.String(args)
|
||||
content := p.Content.String(args)
|
||||
func (a,b string){}(title, content)
|
||||
@ -123,7 +123,7 @@ type PushWebhook struct {
|
||||
Body json.RawMessage `json:"body"`
|
||||
}
|
||||
|
||||
func (p PushWebhook) push(args []*PushFormatArgs) ([]byte, int, error) {
|
||||
func (p PushWebhook) push(args []*PushPair) ([]byte, int, error) {
|
||||
body := PushFormat(p.Body).String(args)
|
||||
switch p.Method {
|
||||
case "GET":
|
||||
|
@ -34,7 +34,7 @@ type Rule struct {
|
||||
func (r *Rule) Id() string {
|
||||
return fmt.Sprintf("[%s %s %s]", r.MonitorType, r.Threshold, r.Matcher)
|
||||
}
|
||||
func (r *Rule) ShouldNotify(s *Status) (bool, *PushFormatArgs, error) {
|
||||
func (r *Rule) ShouldNotify(s *Status) (bool, *PushPair, error) {
|
||||
t, err := ParseToThreshold(r.Threshold)
|
||||
if err != nil {
|
||||
return false, nil, errors.Join(ErrInvalidRule, err)
|
||||
@ -57,7 +57,7 @@ func (r *Rule) ShouldNotify(s *Status) (bool, *PushFormatArgs, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Rule) shouldNotifyCPU(ss []CPUStatus, t *Threshold) (bool, *PushFormatArgs, error) {
|
||||
func (r *Rule) shouldNotifyCPU(ss []CPUStatus, t *Threshold) (bool, *PushPair, error) {
|
||||
if len(ss) == 0 {
|
||||
// utils.Warn("cpu is not valid, skip this rule")
|
||||
return false, nil, nil
|
||||
@ -90,7 +90,7 @@ func (r *Rule) shouldNotifyCPU(ss []CPUStatus, t *Threshold) (bool, *PushFormatA
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: fmt.Sprintf("cpu%d", idx),
|
||||
Value: fmt.Sprintf("%.2f%%", usedPercent),
|
||||
}, nil
|
||||
@ -98,7 +98,7 @@ func (r *Rule) shouldNotifyCPU(ss []CPUStatus, t *Threshold) (bool, *PushFormatA
|
||||
return false, nil, errors.Join(ErrInvalidRule, fmt.Errorf("invalid threshold type for cpu: %s", t.ThresholdType.Name()))
|
||||
}
|
||||
}
|
||||
func (r *Rule) shouldNotifyMemory(s *MemStatus, t *Threshold) (bool, *PushFormatArgs, error) {
|
||||
func (r *Rule) shouldNotifyMemory(s *MemStatus, t *Threshold) (bool, *PushPair, error) {
|
||||
if s == nil {
|
||||
// utils.Warn("memory is not valid, skip this rule")
|
||||
return false, nil, nil
|
||||
@ -125,7 +125,7 @@ func (r *Rule) shouldNotifyMemory(s *MemStatus, t *Threshold) (bool, *PushFormat
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher + "of Memory",
|
||||
Value: size.String(),
|
||||
}, nil
|
||||
@ -134,7 +134,7 @@ func (r *Rule) shouldNotifyMemory(s *MemStatus, t *Threshold) (bool, *PushFormat
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher + "of Memory",
|
||||
Value: fmt.Sprintf("%.2f%%", percent*100),
|
||||
}, nil
|
||||
@ -142,7 +142,7 @@ func (r *Rule) shouldNotifyMemory(s *MemStatus, t *Threshold) (bool, *PushFormat
|
||||
return false, nil, errors.Join(ErrInvalidRule, fmt.Errorf("invalid threshold type for memory: %s", t.ThresholdType.Name()))
|
||||
}
|
||||
}
|
||||
func (r *Rule) shouldNotifySwap(s *SwapStatus, t *Threshold) (bool, *PushFormatArgs, error) {
|
||||
func (r *Rule) shouldNotifySwap(s *SwapStatus, t *Threshold) (bool, *PushPair, error) {
|
||||
if s == nil {
|
||||
// utils.Warn("swap is not valid, skip this rule")
|
||||
return false, nil, nil
|
||||
@ -166,7 +166,7 @@ func (r *Rule) shouldNotifySwap(s *SwapStatus, t *Threshold) (bool, *PushFormatA
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher + "of Swap",
|
||||
Value: size.String(),
|
||||
}, nil
|
||||
@ -175,7 +175,7 @@ func (r *Rule) shouldNotifySwap(s *SwapStatus, t *Threshold) (bool, *PushFormatA
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher + "of Swap",
|
||||
Value: fmt.Sprintf("%.2f%%", percent*100),
|
||||
}, nil
|
||||
@ -183,7 +183,7 @@ func (r *Rule) shouldNotifySwap(s *SwapStatus, t *Threshold) (bool, *PushFormatA
|
||||
return false, nil, errors.Join(ErrInvalidRule, fmt.Errorf("invalid threshold type for swap: %s", t.ThresholdType.Name()))
|
||||
}
|
||||
}
|
||||
func (r *Rule) shouldNotifyDisk(s []DiskStatus, t *Threshold) (bool, *PushFormatArgs, error) {
|
||||
func (r *Rule) shouldNotifyDisk(s []DiskStatus, t *Threshold) (bool, *PushPair, error) {
|
||||
if len(s) == 0 {
|
||||
// utils.Warn("disk is not valid, skip this rule")
|
||||
return false, nil, nil
|
||||
@ -207,7 +207,7 @@ func (r *Rule) shouldNotifyDisk(s []DiskStatus, t *Threshold) (bool, *PushFormat
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher,
|
||||
Value: disk.Used.String(),
|
||||
}, nil
|
||||
@ -216,7 +216,7 @@ func (r *Rule) shouldNotifyDisk(s []DiskStatus, t *Threshold) (bool, *PushFormat
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher,
|
||||
Value: fmt.Sprintf("%.2f%%", disk.UsedPercent),
|
||||
}, nil
|
||||
@ -224,7 +224,7 @@ func (r *Rule) shouldNotifyDisk(s []DiskStatus, t *Threshold) (bool, *PushFormat
|
||||
return false, nil, errors.Join(ErrInvalidRule, fmt.Errorf("invalid threshold type for disk: %s", t.ThresholdType.Name()))
|
||||
}
|
||||
}
|
||||
func (r *Rule) shouldNotifyNetwork(s []NetworkStatus, t *Threshold) (bool, *PushFormatArgs, error) {
|
||||
func (r *Rule) shouldNotifyNetwork(s []NetworkStatus, t *Threshold) (bool, *PushPair, error) {
|
||||
if len(s) == 0 {
|
||||
// utils.Warn("network is not valid, skip this rule")
|
||||
return false, nil, nil
|
||||
@ -273,7 +273,7 @@ func (r *Rule) shouldNotifyNetwork(s []NetworkStatus, t *Threshold) (bool, *Push
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher,
|
||||
Value: speed.String(),
|
||||
}, nil
|
||||
@ -289,7 +289,7 @@ func (r *Rule) shouldNotifyNetwork(s []NetworkStatus, t *Threshold) (bool, *Push
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher,
|
||||
Value: size.String(),
|
||||
}, nil
|
||||
@ -298,7 +298,7 @@ func (r *Rule) shouldNotifyNetwork(s []NetworkStatus, t *Threshold) (bool, *Push
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Rule) shouldNotifyTemperature(s []TemperatureStatus, t *Threshold) (bool, *PushFormatArgs, error) {
|
||||
func (r *Rule) shouldNotifyTemperature(s []TemperatureStatus, t *Threshold) (bool, *PushPair, error) {
|
||||
if len(s) == 0 {
|
||||
// utils.Warn("temperature is not valid, skip this rule")
|
||||
return false, nil, nil
|
||||
@ -323,7 +323,7 @@ func (r *Rule) shouldNotifyTemperature(s []TemperatureStatus, t *Threshold) (boo
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return ok, &PushFormatArgs{
|
||||
return ok, &PushPair{
|
||||
Key: r.Matcher,
|
||||
Value: fmt.Sprintf("%.2f°C", temp.Value),
|
||||
}, nil
|
||||
|
@ -108,14 +108,14 @@ func (ns *NetworkStatus) TransmitSpeed() (Size, error) {
|
||||
return 0, ErrNotReady
|
||||
}
|
||||
diff := ns.TimeSequence.New.Transmit - ns.TimeSequence.Old.Transmit
|
||||
return diff / Size(Config.GetRunInterval()), nil
|
||||
return diff / Size(GetInterval()), nil
|
||||
}
|
||||
func (ns *NetworkStatus) ReceiveSpeed() (Size, error) {
|
||||
if ns.TimeSequence.New == nil || ns.TimeSequence.Old == nil {
|
||||
return 0, ErrNotReady
|
||||
}
|
||||
diff := ns.TimeSequence.New.Receive - ns.TimeSequence.Old.Receive
|
||||
return diff / Size(Config.GetRunInterval()), nil
|
||||
return diff / Size(GetInterval()), nil
|
||||
}
|
||||
|
||||
func RefreshStatus() error {
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"embed"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/lollipopkit/server_box_monitor/utils"
|
||||
)
|
||||
@ -27,6 +28,10 @@ var (
|
||||
AppConfigPath = filepath.Join(ServerBoxDirPath, AppConfigFileName)
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultInterval = time.Second * 5
|
||||
)
|
||||
|
||||
func init() {
|
||||
if !utils.Exist(ServerBoxDirPath) {
|
||||
err := os.MkdirAll(ServerBoxDirPath, 0755)
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
pushArgs = []*model.PushFormatArgs{}
|
||||
pushArgsLock = new(sync.RWMutex)
|
||||
pushPairs = []*model.PushPair{}
|
||||
pushPairsLock = new(sync.RWMutex)
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -31,19 +31,18 @@ func init() {
|
||||
|
||||
func Start() {
|
||||
go Run()
|
||||
go Push()
|
||||
// 阻塞主线程
|
||||
select {}
|
||||
}
|
||||
|
||||
func Run() {
|
||||
err := model.ReadAppConfig()
|
||||
if err != nil {
|
||||
utils.Error("[CONFIG] Read app config error: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for {
|
||||
err := model.ReadAppConfig()
|
||||
if err != nil {
|
||||
time.Sleep(model.DefaultappConfig.GetRunInterval())
|
||||
continue
|
||||
}
|
||||
|
||||
err = model.RefreshStatus()
|
||||
status := model.GetStatus()
|
||||
if err != nil {
|
||||
@ -52,54 +51,41 @@ func Run() {
|
||||
}
|
||||
|
||||
for _, rule := range model.Config.Rules {
|
||||
notify, arg, err := rule.ShouldNotify(status)
|
||||
notify, pushPair, err := rule.ShouldNotify(status)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), "not ready") {
|
||||
utils.Warn("[RULE] %s error: %v", rule.Id(), err)
|
||||
}
|
||||
}
|
||||
|
||||
if notify && arg != nil {
|
||||
pushArgsLock.Lock()
|
||||
pushArgs = append(pushArgs, arg)
|
||||
pushArgsLock.Unlock()
|
||||
if notify && pushPair != nil {
|
||||
pushPairsLock.Lock()
|
||||
pushPairs = append(pushPairs, pushPair)
|
||||
pushPairsLock.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
// utils.Info("[STATUS] refreshed, %d to push", len(pushArgs))
|
||||
SLEEP:
|
||||
time.Sleep(model.Config.GetRunInterval())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
func Push() {
|
||||
for {
|
||||
err := model.ReadAppConfig()
|
||||
if err != nil {
|
||||
time.Sleep(model.DefaultappConfig.GetRunInterval())
|
||||
continue
|
||||
if len(pushPairs) == 0 {
|
||||
goto SLEEP
|
||||
}
|
||||
|
||||
if len(pushArgs) == 0 {
|
||||
time.Sleep(model.Config.GetPushInterval())
|
||||
continue
|
||||
}
|
||||
utils.Info("[STATUS] refreshed, %d to push", len(pushPairs))
|
||||
|
||||
pushPairsLock.RLock()
|
||||
for _, push := range model.Config.Pushes {
|
||||
pushArgsLock.RLock()
|
||||
err := push.Push(pushArgs)
|
||||
pushArgsLock.RUnlock()
|
||||
err := push.Push(pushPairs)
|
||||
if err != nil {
|
||||
utils.Warn("[PUSH] %s error: %v", push.Id(), err)
|
||||
continue
|
||||
}
|
||||
utils.Success("[PUSH] %s success", push.Id())
|
||||
}
|
||||
pushArgsLock.Lock()
|
||||
pushArgs = []*model.PushFormatArgs{}
|
||||
pushArgsLock.Unlock()
|
||||
pushPairsLock.RUnlock()
|
||||
|
||||
time.Sleep(model.Config.GetPushInterval())
|
||||
pushPairsLock.Lock()
|
||||
pushPairs = []*model.PushPair{}
|
||||
pushPairsLock.Unlock()
|
||||
SLEEP:
|
||||
time.Sleep(model.GetInterval())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user