diff --git a/check/check_ping.go b/check/check_ping.go index 5ed266c..fb3b36a 100644 --- a/check/check_ping.go +++ b/check/check_ping.go @@ -65,7 +65,7 @@ func (c *CheckPing) Check(debuglvl int) error { } } - if debuglvl > 0 { + if debuglvl > 1 { fmt.Printf("Packet loss: %.f%%\n", stats.PacketLoss) fmt.Printf("Max RTT: %s\n", stats.MaxRtt.String()) fmt.Printf("Max Configured RTT: %s\n", c.MaxRTT.String()) diff --git a/config/config.go b/config/config.go index 4ab5ea4..e137870 100644 --- a/config/config.go +++ b/config/config.go @@ -3,6 +3,8 @@ package config import ( "alrm/alarm" "fmt" + "runtime" + "strconv" "time" ) @@ -10,12 +12,15 @@ type Config struct { Groups map[string]*Group Alarms map[string]alarm.Alarm Interval time.Duration + Threads int } func NewConfig() *Config { return &Config{ // Default check interval, 30 seconds Interval: time.Second * 30, + // Default number of threads, use local CPU count + Threads: runtime.NumCPU(), } } @@ -61,6 +66,16 @@ func (c *Config) SetInterval(val string) error { return nil } +func (c *Config) SetThreads(val string) error { + threads, err := strconv.Atoi(val) + if err != nil { + return err + } + + c.Threads = threads + return nil +} + func ReadConfig(fn string, debuglvl int) (*Config, error) { parser := &Parser{DebugLevel: debuglvl} config, err := parser.Parse(fn) diff --git a/config/parser.go b/config/parser.go index 3c79b56..2fcbc9a 100644 --- a/config/parser.go +++ b/config/parser.go @@ -63,6 +63,14 @@ func (p *Parser) Parse(fn string) (*Config, error) { switch key { case "interval": err := config.SetInterval(value) + if err != nil { + return nil, fmt.Errorf( + "invalid duration for interval in %s, line %d: \"%s\"", + fn, tok.Line(), value, + ) + } + case "threads": + err := config.SetThreads(value) if err != nil { return nil, fmt.Errorf( "invalid number for interval in %s, line %d: \"%s\"", diff --git a/main.go b/main.go index 64ee4cc..9b4f984 100644 --- a/main.go +++ b/main.go @@ -109,6 +109,19 @@ func main() { } fmt.Printf("check successful\n") + case "server": + cfg, err := config.ReadConfig(*cfgPath, *debuglvl) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err.Error()) + os.Exit(1) + } + + err = startServer(cfg, *debuglvl) + if err != nil { + fmt.Fprintf(os.Stderr, "%s\n", err.Error()) + os.Exit(1) + } + case "help", "": printUsage() @@ -127,4 +140,5 @@ func printUsage() { fmt.Printf(" verify configuration: %s [args] config\n", os.Args[0]) fmt.Printf(" run a check manually: %s [args] check \n", os.Args[0]) fmt.Printf(" test an alarm: %s [args] alarm \n", os.Args[0]) + fmt.Printf(" start server (forground): %s [args] server\n", os.Args[0]) } diff --git a/server.go b/server.go new file mode 100644 index 0000000..00004ff --- /dev/null +++ b/server.go @@ -0,0 +1,44 @@ +package main + +import ( + "alrm/check" + "alrm/config" + "fmt" + "time" +) + +func startServer(cfg *config.Config, debuglvl int) error { + ch := make(chan check.Check, cfg.Threads) + for i := 0; i < cfg.Threads; i++ { + go worker(ch, debuglvl) + } + + t := time.NewTicker(cfg.Interval) + defer t.Stop() + for { + select { + case r := <-t.C: + if debuglvl > 0 { + fmt.Printf("Interval check at %s\n", r) + } + for _, g := range cfg.Groups { + for _, h := range g.Hosts { + for _, c := range h.Checks { + ch <- c + } + } + } + } + } + return nil +} + +func worker(ch chan check.Check, debuglvl int) { + for { + chk := <-ch + err := chk.Check(debuglvl) + if err != nil { + fmt.Printf("Check error: %s\n", err) + } + } +}