func New(name, disk string, sleep int, minfree float32, em *mail.Email, alarm time.Duration) monitors.Monitor { if alarm == 0 { alarm = Alarm } dm := &Disk{ MonitorBase: base.New(), name: name, disk: disk, close: make(chan bool), alertPeriode: alarm, email: em, monitoring: true, } dm.status = status.NewStatuses(name, em, definitions.LengthStatusHistory, status.NewStatus, dm.SendEvent, nil) go func() { for { select { case <-time.After(time.Duration(sleep) * time.Second): d, err := event.ProbeDisk(disk) if err != nil { dm.status.Log(status.Verbose, "DiskSpace failed with error: %v", e.Trace(e.Forward(err))) continue } percent := (float32(d.Free) / float32(d.Total)) * 100.0 if percent < minfree { if dm.alert.Before(time.Now()) { dm.alert = time.Now().Add(dm.alertPeriode) dm.status.LogAndEmail(status.Normal, "Disk limit ["+disk+"]", "Disk %v is %.4f%% free.", disk, round.RoundDec32(percent, 4)) } } else { if dm.alert.After(time.Now()) { dm.status.LogAndEmail(status.Normal, "Disk limit ["+disk+"]", "Disk %v is %.4f%% free.", disk, round.RoundDec32(percent, 4)) } dm.alert = time.Time{} } dm.SendEvent(d) case <-dm.close: break } } dm.status.Log(status.Normal, "Disk monitor stopped for %v.", name) }() return dm }
func Init(d *Daemon) (monitors.Monitor, error) { pid, err := util.ReadPidInt(d.PidFile) if err != nil && !e.Contains(err, "no such file or directory") { return nil, e.Forward(err) } if d.DaemonName == "" { return nil, e.New("empty daemon name") } if d.RestartCmd == "" { return nil, e.New("empty restart command") } if d.RestartArgs == nil { return nil, e.New("restart arguments is invalid") } if d.PidFile == "" { return nil, e.New("empty pid file") } if d.Sleep <= 0 { return nil, e.New("sleep is equal or less than zero") } if d.Tries < 0 { return nil, e.New("tries is equal or less than zero") } if d.Prio < 0 { return nil, e.New("prio have to be greater or equal to zero") } if d.Queue == nil { return nil, e.New("invalid queue") } if d.ExecTimeout <= 0 { return nil, e.New("exectution timeout is greater than zero") } d.MonitorBase = base.New() d.pid = pid d.killMonitor = make(chan bool) d.running = true d.status = status.NewStatuses(d.DaemonName, d.Email, definitions.LengthStatusHistory, status.NewStatus, d.SendEvent, nil) d.fswatcher, err = fsnotify.NewWatcher() if err != nil { return nil, e.Forward(err) } go func() { F: for { select { case ev := <-d.fswatcher.Event: if ev == nil { //watcher closed return } if ev.Name != d.PidFile { continue F } if ev.IsDelete() { d.pid = -1 } else if !(ev.IsCreate() && ev.IsModify()) { continue F } d.changePid() case err := <-d.fswatcher.Error: if err != nil { d.status.Log(status.Verbose, "Pid file %v watcher error: %v", d.PidFile, e.Trace(e.Forward(err))) } } } }() err = d.fswatcher.Watch(filepath.Dir(d.PidFile)) if err != nil { return nil, e.Push(err, e.New("invalid pid file %v", d.PidFile)) } d.monitor() return d, nil }
func Init(vs *VirtualServer) (monitors.Monitor, error) { if vs.VirtualServerName == "" { return nil, e.New("virtual server name empty") } if vs.PidFile == "" { return nil, e.New("pid file is requered") } if vs.RestartCmd == "" { return nil, e.New("empty restart command") } if vs.RestartArgs == nil { return nil, e.New("invalid restart command arguments") } if vs.MonitorUrl == nil { return nil, e.New("invalid monitor url") } if vs.Sleep <= 0 { return nil, e.New("sleep must be zero or greater value") } if vs.Tries < 0 { return nil, e.New("tries must be zero or greater value") } if vs.Email == nil { return nil, e.New("invalid email struct") } if vs.ForceKillCmd == "" { return nil, e.New("invalid force kill command") } if vs.ForceKillArgs == nil { return nil, e.New("invalid force kill arguments") } if vs.BeforeStartCmd == "" { return nil, e.New("invalid before star command") } if vs.BeforeStartArgs == nil { return nil, e.New("invalid before star arguments") } if vs.Prio < 0 { return nil, e.New("priority must be equal or greater than zero") } if vs.Queue == nil { return nil, e.New("invalid queue struct") } if vs.ExecTimeout <= 0 { return nil, e.New("exec timeout must be greater than zero") } vs.MonitorBase = base.New() vs.monitoring = true vs.close = make(chan bool) vs.status = status.NewStatuses(vs.VirtualServerName, vs.Email, definitions.LengthStatusHistory, status.NewStatus, vs.SendEvent, nil) st := status.NewStatuses(vs.VirtualServerName, vs.Email, definitions.LengthStatusHistory, status.NewStatus, nil, nil) vs.alive = &Alive{ Url: vs.MonitorUrl, Wait: vs.ConnWait, Tries: vs.ConnTries, Statuses: st, } vs.alive.Connect() go func() { events := vs.alive.Events() for { event := <-events if event == nil { return } st.Log(status.Normal, "Mensage from %v [%v]", event.Host(), event) } }() go func() { unmonitor := true tries := 0 F: for { select { case <-time.After(vs.Sleep): if vs.Tries != 0 && tries > vs.Tries+1 { vs.monitoring = false if unmonitor { vs.status.LogAndEmail(status.Normal, "Unmonitor server %v.", vs.VirtualServerName) unmonitor = false continue F } continue F } if vs.alive.Is() { tries = 0 vs.status.Log(status.Verbose, "%v server is running.", vs.VirtualServerName) continue F } tries++ vs.status.Log(status.Verbose, "Monitor: Alive for %v failed", vs.VirtualServerName) err := vs.SendToQueue(func() error { vs.status.Log(status.Verbose, "Restarting %v...", vs.VirtualServerName) err := vs.restart() if err != nil { vs.status.Log(status.Verbose, "Monitor failed to restart %v. Forcing restart.", vs.VirtualServerName) err := vs.forceRestart() if err != nil { vs.status.Log(status.Verbose, "Monitor failed to force restart %v. Giving up! Failed: %v", vs.VirtualServerName, e.Trace(e.Forward(err))) return e.Forward(err) } } return nil }) if err != nil { vs.status.Log(status.Verbose, "%v failed to send job to queue, error: %v", vs.VirtualServerName, e.Trace(e.Forward(err))) continue F } if !vs.alive.Is() { vs.SendToQueue(func() error { err = vs.forceRestart() if err != nil { vs.status.Log(status.Verbose, "Monitor failed to force restart %v. Giving up! Failed: %v", vs.VirtualServerName, e.Trace(e.Forward(err))) return e.Forward(err) } return nil }) } case <-vs.close: return } } }() return vs, nil }