|
@ -2,13 +2,16 @@ package consumers |
|
|
|
|
|
|
|
|
import ( |
|
|
import ( |
|
|
"encoding/json" |
|
|
"encoding/json" |
|
|
|
|
|
"fmt" |
|
|
"goInOut/adaptors" |
|
|
"goInOut/adaptors" |
|
|
"goInOut/consumers/SavoirTheme" |
|
|
"goInOut/consumers/SavoirTheme" |
|
|
"goInOut/dbOperate" |
|
|
"goInOut/dbOperate" |
|
|
"goInOut/dbOperate/_kafka" |
|
|
"goInOut/dbOperate/_kafka" |
|
|
"goInOut/models" |
|
|
"goInOut/models" |
|
|
|
|
|
"goInOut/monitors" |
|
|
"gopkg.in/yaml.v3" |
|
|
"gopkg.in/yaml.v3" |
|
|
"log" |
|
|
"log" |
|
|
|
|
|
"strings" |
|
|
"sync" |
|
|
"sync" |
|
|
"time" |
|
|
"time" |
|
|
) |
|
|
) |
|
@ -17,13 +20,16 @@ type consumerSavoirTheme struct { |
|
|
//数据缓存管道
|
|
|
//数据缓存管道
|
|
|
dataCache chan *models.EsTheme |
|
|
dataCache chan *models.EsTheme |
|
|
//具体配置
|
|
|
//具体配置
|
|
|
Info SavoirTheme.ConfigFile |
|
|
Info SavoirTheme.ConfigFile |
|
|
InKafka _kafka.KafkaHelper |
|
|
InKafka _kafka.KafkaHelper |
|
|
OutEs dbOperate.ESHelper |
|
|
OutEs dbOperate.ESHelper |
|
|
infoRedis *dbOperate.RedisHelper |
|
|
infoPg *dbOperate.DBHelper |
|
|
sinkMap sync.Map |
|
|
sinkMap sync.Map |
|
|
lock sync.Mutex |
|
|
lock sync.Mutex |
|
|
logTagId int |
|
|
logTagId int |
|
|
|
|
|
monitor *monitors.CommonMonitor |
|
|
|
|
|
//数据库配置信息
|
|
|
|
|
|
pgOffLineGaps []SavoirTheme.OffLineGap |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
func (the *consumerSavoirTheme) LoadConfigJson(cfgStr string) { |
|
|
func (the *consumerSavoirTheme) LoadConfigJson(cfgStr string) { |
|
@ -37,7 +43,7 @@ func (the *consumerSavoirTheme) LoadConfigJson(cfgStr string) { |
|
|
|
|
|
|
|
|
func (the *consumerSavoirTheme) Initial(cfg string) error { |
|
|
func (the *consumerSavoirTheme) Initial(cfg string) error { |
|
|
the.sinkMap = sync.Map{} |
|
|
the.sinkMap = sync.Map{} |
|
|
the.dataCache = make(chan *models.EsTheme, 500) |
|
|
the.dataCache = make(chan *models.EsTheme, 1000) |
|
|
|
|
|
|
|
|
the.LoadConfigJson(cfg) |
|
|
the.LoadConfigJson(cfg) |
|
|
err := the.inputInitial() |
|
|
err := the.inputInitial() |
|
@ -49,6 +55,11 @@ func (the *consumerSavoirTheme) Initial(cfg string) error { |
|
|
return err |
|
|
return err |
|
|
} |
|
|
} |
|
|
err = the.infoComponentInitial() |
|
|
err = the.infoComponentInitial() |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
return err |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err = the.monitorInitial() |
|
|
return err |
|
|
return err |
|
|
} |
|
|
} |
|
|
func (the *consumerSavoirTheme) inputInitial() error { |
|
|
func (the *consumerSavoirTheme) inputInitial() error { |
|
@ -78,12 +89,124 @@ func (the *consumerSavoirTheme) outputInitial() error { |
|
|
|
|
|
|
|
|
func (the *consumerSavoirTheme) infoComponentInitial() error { |
|
|
func (the *consumerSavoirTheme) infoComponentInitial() error { |
|
|
//数据出口
|
|
|
//数据出口
|
|
|
//addr := the.Info.OtherInfo..Redis.Address
|
|
|
pgConnStr := the.Info.QueryComponent.Pg.Connect |
|
|
//the.infoRedis = dbOperate.NewRedisHelper("", addr)
|
|
|
the.infoPg = dbOperate.NewDBHelper("postgres", pgConnStr) |
|
|
|
|
|
return nil |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (the *consumerSavoirTheme) monitorInitial() error { |
|
|
|
|
|
the.monitor = &monitors.CommonMonitor{ |
|
|
|
|
|
MonitorHelper: &monitors.MonitorHelper{}, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
the.monitor.Start() |
|
|
|
|
|
for taskName, cron := range the.Info.Monitor { |
|
|
|
|
|
switch taskName { |
|
|
|
|
|
case "cron": |
|
|
|
|
|
the.monitor.RegisterTask(cron, the.statisticsOffline) |
|
|
|
|
|
default: |
|
|
|
|
|
log.Printf("定时任务[%s],cron=[%s] 无匹配", taskName, cron) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return nil |
|
|
return nil |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (the *consumerSavoirTheme) statisticsOffline() { |
|
|
|
|
|
log.Printf("--> 定时任务 更新数据库 配置信息") |
|
|
|
|
|
sql := `SELECT off.*,s.name FROM "t_struct_factor_offlinegap" as off left join t_structure as s |
|
|
|
|
|
ON off.struct_id=s.id |
|
|
|
|
|
where off.is_open=true order by off.struct_id` |
|
|
|
|
|
err := the.infoPg.Query(&the.pgOffLineGaps, sql) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
log.Printf("查询数据库异常:err-> %s", err.Error()) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
log.Printf("当前共 %d条 启用配置", len(the.pgOffLineGaps)) |
|
|
|
|
|
|
|
|
|
|
|
//立即触发
|
|
|
|
|
|
the.judgeOffline() |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
func (the *consumerSavoirTheme) judgeOffline() { |
|
|
|
|
|
now := time.Now() |
|
|
|
|
|
for _, gap := range the.pgOffLineGaps { |
|
|
|
|
|
var alarmDetails []string |
|
|
|
|
|
if !gap.IsOpen { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
log.Printf("判断 s:%d,f:%d,durMin:%d", gap.StructId, gap.FactorId, gap.OfflineGap) |
|
|
|
|
|
queryStr := the.getESOfflineAlarmQueryStr(gap.StructId, gap.FactorId) |
|
|
|
|
|
allThemes, err := the.OutEs.SearchThemeData("savoir_last_theme", queryStr) |
|
|
|
|
|
if err != nil { |
|
|
|
|
|
log.Printf("查询es 异常") |
|
|
|
|
|
} |
|
|
|
|
|
log.Printf("查询相关测点数=%d", len(allThemes)) |
|
|
|
|
|
for _, theme := range allThemes { |
|
|
|
|
|
offlineMin := now.Sub(theme.CollectTime).Minutes() |
|
|
|
|
|
log.Printf("s:%d,f:%d,sensor:%d 离线%f min", gap.StructId, gap.FactorId, theme.Sensor, offlineMin) |
|
|
|
|
|
if offlineMin > float64(gap.OfflineGap) { |
|
|
|
|
|
msg := fmt.Sprintf("测点[%s]离线%f min > %d min", theme.SensorName, offlineMin, gap.OfflineGap) |
|
|
|
|
|
log.Printf("----- > %s", msg) |
|
|
|
|
|
alarmDetails = append(alarmDetails, msg) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
prefix := "offline-" |
|
|
|
|
|
sourceId := prefix + fmt.Sprintf("%d-%d", gap.StructId, gap.FactorId) |
|
|
|
|
|
if len(alarmDetails) > 0 { |
|
|
|
|
|
alarmMsg := models.KafkaAlarm{ |
|
|
|
|
|
MessageMode: "AlarmGeneration", |
|
|
|
|
|
StructureId: gap.StructId, |
|
|
|
|
|
StructureName: gap.StructName, |
|
|
|
|
|
SourceId: sourceId, |
|
|
|
|
|
SourceName: gap.StructName, |
|
|
|
|
|
AlarmTypeCode: "8004", |
|
|
|
|
|
AlarmCode: "80040001", |
|
|
|
|
|
Content: strings.Join(alarmDetails, ","), |
|
|
|
|
|
Time: time.Now().Format("2006-01-02T15:04:05+0800"), |
|
|
|
|
|
SourceTypeId: 1, // 0:DTU, 1:传感器, 2:测点
|
|
|
|
|
|
Sponsor: "goInOut_savoirTheme", |
|
|
|
|
|
Extras: nil, |
|
|
|
|
|
SubDevices: nil, |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
payload, _ := json.Marshal(alarmMsg) |
|
|
|
|
|
the.InKafka.Publish("savoir_alarm", payload) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (the *consumerSavoirTheme) getESOfflineAlarmQueryStr(structId, factorId int) string { |
|
|
|
|
|
|
|
|
|
|
|
esQuery := fmt.Sprintf(` |
|
|
|
|
|
{ |
|
|
|
|
|
"query": { |
|
|
|
|
|
"bool": { |
|
|
|
|
|
"must": [ |
|
|
|
|
|
{ |
|
|
|
|
|
"term": { |
|
|
|
|
|
"structure": { |
|
|
|
|
|
"value": %d |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
"term": { |
|
|
|
|
|
"factor": { |
|
|
|
|
|
"value": %d |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
] |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
`, structId, factorId) |
|
|
|
|
|
return esQuery |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
func (the *consumerSavoirTheme) sinkTask() { |
|
|
func (the *consumerSavoirTheme) sinkTask() { |
|
|
intervalSec := the.Info.IoConfig.Out.Es.Interval |
|
|
intervalSec := the.Info.IoConfig.Out.Es.Interval |
|
|
ticker := time.NewTicker(time.Duration(intervalSec) * time.Second) |
|
|
ticker := time.NewTicker(time.Duration(intervalSec) * time.Second) |
|
|