// function to check query list, try to init them and build query, and exit with // displaying relevant errors, if any func (e *Env) checkAndExit() { var err bool var err2 error var errcount uint32 if len(g_queryList) == 0 { eslog.Warning("%s : No query added, %d", os.Args[0]) errcount++ } for k, v := range g_queryList { eslog.Info("%s : initiating...", k) err = v.SetQueryConfig(config.G_Config.ManualConfig.List) if err { eslog.Error("%s : failed to get config", k) errcount++ continue } _, err2 = v.BuildQuery() if err2 != nil { eslog.Error("%s : error while building query, %s", k, err2.Error()) errcount++ } //test scheduler and sender schedule := new(scheduler) send := new(sender) schedInfo, ok := e.queries[strings.ToLower(k)] if ok { if errinit := schedule.initScheduler(&schedInfo); errinit != nil { eslog.Error("%s : error in schedule info, %s", k, errinit.Error()) errcount++ } } else { eslog.Error("%s : error while getting query info in yaml", k) errcount++ } if err2 = send.initSender(&schedInfo); err2 != nil { eslog.Error("%s : error while getting query information, %s", k, err2.Error()) errcount++ } } if errcount > 0 { eslog.Warning("%s : Detected %d errors", os.Args[0], errcount) } else { eslog.Info("%s : Everything is ok !", os.Args[0]) } os.Exit(0) }
func (a *autoQuery) SetQueryConfig(c config.ManualQueryList) bool { //autoqueries don't need the manualquery list, parameter stay unused info, ok := config.G_Config.Config.QueryList[a.name] if !ok { eslog.Error("%s : failed to get query configuration", a.name) return true } a.actionList = info.Actions.List if len(a.actionList) == 0 { eslog.Warning("%s : No action defined", a.name) } for _, val := range a.actionList { //loop to initialize the actions switch val { case "email": if len(info.Actions.Email.To) == 0 { eslog.Error("%s : No recipients defined for email action", a.name) return true } a.initMailerForAutoQuery(&info) case "slack": if len(info.Actions.Slack.Channel) == 0 { eslog.Error("%s : No channels defined for slack action", a.name) return true } a.initSlackForAutoQuery(info.Actions.Slack) } } a.limit = info.Query.Limit a.queryInfo = &info.Query return false }
// function that handles the life of each query func launchQuery(c queries.Query, name string, env *Env) { schedule := new(scheduler) retries := getMaxRetries() send := new(sender) stats := queryStats{true, false, retries, 0, "None"} var query elastic.Query //query initiation eslog.Info("%s : getting query configuration", name) c.SetQueryConfig(config.G_Config.ManualConfig.List) query, err := c.BuildQuery() if err != nil { eslog.Error("%s : failed to build query, %s", name, err.Error()) stats.IsUp = false if isServer() { go collectorUpdate(stats, name) } return } //scheduler and sender initiation schedInfo, ok := env.queries[strings.ToLower(name)] if ok { schedule.initScheduler(&schedInfo) } else { schedule.initSchedulerDefault() } err = send.initSender(&schedInfo) if err != nil { eslog.Error("%s : initSender failed, %s", name, err.Error()) stats.IsUp = false if isServer() { go collectorUpdate(stats, name) } return } eslog.Info("%s : Starting...", name) //loop forever for { //try to send request. If fails, continue while decreasing attempts, or //die if retries reach 0. env.semaphore <- struct{}{} results, err := send.SendRequest(env.client, query) <-env.semaphore if err != nil { eslog.Error(err.Error()) stats.Tries -= 1 if stats.Tries == 0 { eslog.Error("%s : max attempts reached, stopping query", name) stats.IsUp = false if isServer() { go collectorUpdate(stats, name) } return } else { //retry after schedule eslog.Warning("%s : failed to connect, number of attempts left : %d", name, stats.Tries) if isServer() { go collectorUpdate(stats, name) } schedule.wait() continue } } // interpet the results, if any if results != nil && results.Hits != nil && results.Hits.TotalHits > 0 { //request succeeded, restart attempts stats.Tries = getMaxRetries() eslog.Warning("%s : found a total of %d results", name, results.Hits.TotalHits) yes := c.CheckCondition(results) if yes { //condition is verified. Should we enter alert status ? if !schedule.isAlertOnlyOnce || (schedule.isAlertOnlyOnce && !schedule.alertState) { eslog.Alert("%s : Action triggered", name) c.DoAction(results) schedule.alertState = true stats.AlertStatus = true stats.LastAlert = time.Now().Format(TIMELAYOUT) stats.NbAlerts++ } } else if !yes { //condition not verified. Exiting alert status, triggering onAlertEnd() if necessary if schedule.alertState == true && schedule.isAlertEndMsg == true { c.OnAlertEnd() } schedule.alertState = false stats.AlertStatus = false } } else { // no results found eslog.Info("%s : no result found", name) if schedule.alertState == true && schedule.isAlertEndMsg == true { c.OnAlertEnd() } schedule.alertState = false stats.AlertStatus = false } //update the stats and display them, if necessary if isServer() { go collectorUpdate(stats, name) } //wait, and do it again schedule.wait() } }