pass test: QQ(webhook)

This commit is contained in:
LollipopKit 2023-03-17 20:54:51 +08:00
parent e94353e8df
commit 6a489a3b17
6 changed files with 75 additions and 92 deletions

View File

@ -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,

View File

@ -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":

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -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())
}
}