|
- package memsto
-
- import (
- "fmt"
- "sync"
- "time"
-
- "github.com/ccfos/nightingale/v6/dumper"
- "github.com/ccfos/nightingale/v6/models"
- "github.com/ccfos/nightingale/v6/pkg/ctx"
-
- "github.com/pkg/errors"
- "github.com/toolkits/pkg/logger"
- )
-
- type AlertSubscribeCacheType struct {
- statTotal int64
- statLastUpdated int64
- ctx *ctx.Context
- stats *Stats
-
- sync.RWMutex
- subs map[int64][]*models.AlertSubscribe
- }
-
- func NewAlertSubscribeCache(ctx *ctx.Context, stats *Stats) *AlertSubscribeCacheType {
- asc := &AlertSubscribeCacheType{
- statTotal: -1,
- statLastUpdated: -1,
- ctx: ctx,
- stats: stats,
- subs: make(map[int64][]*models.AlertSubscribe),
- }
- asc.SyncAlertSubscribes()
- return asc
- }
-
- func (c *AlertSubscribeCacheType) Reset() {
- c.Lock()
- defer c.Unlock()
-
- c.statTotal = -1
- c.statLastUpdated = -1
- c.subs = make(map[int64][]*models.AlertSubscribe)
- }
-
- func (c *AlertSubscribeCacheType) StatChanged(total, lastUpdated int64) bool {
- if c.statTotal == total && c.statLastUpdated == lastUpdated {
- return false
- }
-
- return true
- }
-
- func (c *AlertSubscribeCacheType) Set(m map[int64][]*models.AlertSubscribe, total, lastUpdated int64) {
- c.Lock()
- c.subs = m
- c.Unlock()
-
- // only one goroutine used, so no need lock
- c.statTotal = total
- c.statLastUpdated = lastUpdated
- }
-
- func (c *AlertSubscribeCacheType) Get(ruleId int64) ([]*models.AlertSubscribe, bool) {
- c.RLock()
- defer c.RUnlock()
-
- lst, has := c.subs[ruleId]
- return lst, has
- }
-
- func (c *AlertSubscribeCacheType) GetAll() []*models.AlertSubscribe {
- c.RLock()
- defer c.RUnlock()
- var ret []*models.AlertSubscribe
- for _, v := range c.subs {
- ret = append(ret, v...)
- }
- return ret
- }
-
- func (c *AlertSubscribeCacheType) GetStructs(ruleId int64) []models.AlertSubscribe {
- c.RLock()
- defer c.RUnlock()
-
- lst, has := c.subs[ruleId]
- if !has {
- return []models.AlertSubscribe{}
- }
-
- ret := make([]models.AlertSubscribe, len(lst))
- for i := 0; i < len(lst); i++ {
- ret[i] = *lst[i]
- }
-
- return ret
- }
-
- func (c *AlertSubscribeCacheType) SyncAlertSubscribes() {
- err := c.syncAlertSubscribes()
- if err != nil {
- fmt.Println("failed to sync alert subscribes:", err)
- exit(1)
- }
-
- go c.loopSyncAlertSubscribes()
- }
-
- func (c *AlertSubscribeCacheType) loopSyncAlertSubscribes() {
- duration := time.Duration(9000) * time.Millisecond
- for {
- time.Sleep(duration)
- if err := c.syncAlertSubscribes(); err != nil {
- logger.Warning("failed to sync alert subscribes:", err)
- }
- }
- }
-
- func (c *AlertSubscribeCacheType) syncAlertSubscribes() error {
- start := time.Now()
- stat, err := models.AlertSubscribeStatistics(c.ctx)
- if err != nil {
- dumper.PutSyncRecord("alert_subscribes", start.Unix(), -1, -1, "failed to query statistics: "+err.Error())
- return errors.WithMessage(err, "failed to exec AlertSubscribeStatistics")
- }
-
- if !c.StatChanged(stat.Total, stat.LastUpdated) {
- c.stats.GaugeCronDuration.WithLabelValues("sync_alert_subscribes").Set(0)
- c.stats.GaugeSyncNumber.WithLabelValues("sync_alert_subscribes").Set(0)
- dumper.PutSyncRecord("alert_subscribes", start.Unix(), -1, -1, "not changed")
- return nil
- }
-
- lst, err := models.AlertSubscribeGetsAll(c.ctx)
- if err != nil {
- dumper.PutSyncRecord("alert_subscribes", start.Unix(), -1, -1, "failed to query records: "+err.Error())
- return errors.WithMessage(err, "failed to exec AlertSubscribeGetsAll")
- }
-
- subs := make(map[int64][]*models.AlertSubscribe)
-
- for i := 0; i < len(lst); i++ {
- err = lst[i].Parse()
- if err != nil {
- logger.Warningf("failed to parse alert subscribe, id: %d", lst[i].Id)
- continue
- }
-
- err = lst[i].DB2FE()
- if err != nil {
- logger.Warningf("failed to db2fe alert subscribe, id: %d", lst[i].Id)
- continue
- }
-
- err = lst[i].FillDatasourceIds(c.ctx)
- if err != nil {
- logger.Warningf("failed to fill datasource ids, id: %d", lst[i].Id)
- continue
- }
-
- subs[lst[i].RuleId] = append(subs[lst[i].RuleId], lst[i])
- }
-
- c.Set(subs, stat.Total, stat.LastUpdated)
-
- ms := time.Since(start).Milliseconds()
- c.stats.GaugeCronDuration.WithLabelValues("sync_alert_subscribes").Set(float64(ms))
- c.stats.GaugeSyncNumber.WithLabelValues("sync_alert_subscribes").Set(float64(len(lst)))
- logger.Infof("timer: sync subscribes done, cost: %dms, number: %d", ms, len(lst))
- dumper.PutSyncRecord("alert_subscribes", start.Unix(), ms, len(lst), "success")
-
- return nil
- }
|