The smallest watchdog on earth. Tiny, monitoring-plugins compatible monitoring with a status page. https://cloud.docker.com/repository/docker/momar/chihuahua/general
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

100 lines
3.1 KiB

package chihuahua
import (
"github.com/antonmedv/expr"
"github.com/rs/zerolog/log"
"strings"
)
type verification struct {
previousState CheckResult
times uint
}
var verifications = map[*Check]*verification{}
var verificationsPerNotifier = map[string]map[*Check]*verification{}
func (chk *Check) Notify(cfg *Config, previousState CheckResult) {
if previousState.Details == "Waiting for first check..." {
previousState.Status = StatusOk
}
if chk.Verify > 0 {
if _, ok := verifications[chk]; ok {
if verifications[chk].previousState.Status == chk.Result.Status {
// switched back to original state, ignoring
delete(verifications, chk)
return
}
verifications[chk].times++
if verifications[chk].times < chk.Verify {
// not yet verified often enough, waiting for next check
return
}
// verified often enough, will fall through to the notifications
previousState = verifications[chk].previousState
delete(verifications, chk)
} else if previousState.Status != chk.Result.Status {
// first time something changed, waiting for next check
verifications[chk] = &verification{
previousState: previousState,
times: 0,
}
return
} else {
// no reason to worry - there's no verification running, and the check didn't change
return
}
} else if previousState.Status == chk.Result.Status {
// no reason to worry - the check didn't change
return
}
if chk.Notifiers == nil {
log.Info().Str("check", strings.Join(chk.FullID(), "/")).Str("status", chk.Result.Status.String()).Msg("notifying everyone due to status change")
for notifier := range cfg.Notifiers {
cfg.Notifiers[notifier].Notify(cfg, notifier, chk, previousState)
}
return
}
log.Info().Str("check", strings.Join(chk.FullID(), "/")).Interface("notifiers", chk.Notifiers).Str("status", chk.Result.Status.String()).Msg("notifying due to status change")
for _, notifier := range chk.Notifiers {
if _, ok := cfg.Notifiers[notifier]; !ok {
if !cfg.Silent {
log.Error().Str("notifier", notifier).Msg("Notifier doesn't exist")
}
continue // TODO: we need to check somewhere in the config if the notifiers exist?!
}
cfg.Notifiers[notifier].Notify(cfg, notifier, chk, previousState)
}
}
func (c NotifierConfig) Notify(cfg *Config, notifier string, chk *Check, previousState CheckResult) {
if accept := c.Filter(*chk, previousState); accept {
c.Notifier.Notify(cfg, *chk, previousState)
}
}
func (c NotifierConfig) Filter(check Check, previousResult CheckResult) (bool) {
accept := true
if c.Filters != nil {
for i, f := range c.Filters {
r, err := expr.Run(f.If, map[string]interface{}{
"Check": check,
"PreviousResult": previousResult,
"OK": StatusOk,
"WARNING": StatusWarning,
"CRITICAL": StatusCritical,
"UNKNOWN": StatusUnknown,
})
log.Trace().Interface("result", r).Str("filter", f.If.Disassemble()).Msg("Executed filter expression")
if err == nil && r == true {
if f.Accept != nil {
accept = *f.Accept
}
} else if err != nil {
log.Error().Err(err).Str("filter", f.If.Disassemble()).Msgf("Couldn't execute filter %d", i)
}
}
}
return accept
}