go-common/app/admin/main/videoup/service/monitor.go
2019-04-22 18:49:16 +08:00

279 lines
7.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package service
import (
"context"
"go-common/app/admin/main/videoup/model/archive"
"go-common/app/admin/main/videoup/model/manager"
"go-common/app/admin/main/videoup/model/monitor"
"go-common/library/log"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
)
// MonitorResult 获取监控业务的统计结果列表
func (s *Service) MonitorResult(c context.Context, p *monitor.RuleResultParams) (res []*monitor.RuleResultData, err error) {
var (
rules []*monitor.Rule
mUser *manager.User
)
res = []*monitor.RuleResultData{}
if rules, err = s.monitor.GetRules(c, p.Type, p.Business, true); err != nil {
return
}
for _, v := range rules {
var stats *monitor.Stats
if stats, err = s.MonitorStats(c, v); err != nil {
return
}
if mUser, err = s.mng.User(c, v.UID); err != nil {
mUser = &manager.User{
ID: v.UID,
}
err = nil
}
tmp := &monitor.RuleResultData{
Stats: stats,
User: mUser,
Rule: v,
}
res = append(res, tmp)
}
return
}
// MonitorStats 根据business和rule获取统计结果
func (s *Service) MonitorStats(c context.Context, rule *monitor.Rule) (stats *monitor.Stats, err error) {
var (
qualiKeys []string //符合条件的统计redis key
)
qualiKeys, err = s.RuleQualifiedKeys(c, rule)
//根据符合条件的redis key qualiKeys获取数据
stats = &monitor.Stats{}
for _, k := range qualiKeys {
var res *monitor.Stats
if res, err = s.monitor.StatsResult(c, k, rule.RuleConf); err != nil {
return
}
stats.TotalCount += res.TotalCount
stats.MoniCount += res.MoniCount
if res.MaxTime > stats.MaxTime {
stats.MaxTime = res.MaxTime
}
}
return
}
// MonitorRuleUpdate 更新监控规则
func (s *Service) MonitorRuleUpdate(c context.Context, rule *monitor.Rule) (err error) {
rule.CTime = time.Now().Format("2006-01-02 15:04:05")
err = s.monitor.SetRule(c, rule)
return
}
// RuleQualifiedKeys 获取监控业务中符合监控条件的Redis key
func (s *Service) RuleQualifiedKeys(c context.Context, rule *monitor.Rule) (qualiKeys []string, err error) {
var (
allKeys []string //当前业务的所有统计redis key
//qualiKeys []string //符合条件的统计redis key
prefix string //当前业务redis 可以前缀
keyConf *monitor.KeyConf //当前业务redis key 的字段配置信息
moniCdt = rule.RuleConf.MoniCdt //当前业务中,需要统计的条件
ok bool
)
qualiKeys = []string{}
if keyConf, ok = monitor.RedisKeyConf[rule.Business]; !ok {
err = errors.New("Business Not Exists")
return
}
prefix, allKeys, err = s.monitor.BusStatsKeys(c, rule.Business)
kFields := keyConf.KFields //Redis key中的字段
for _, fullK := range allKeys {
k := strings.Replace(fullK, prefix, "", 1) //去掉redis key 中的前缀monitor_stats_{business}_
ks := strings.Split(k, "_") //redis key 的切割,格式:%d_%d
if len(ks) != len(kFields) { //KFields中的字段数必须与redis key中数量一致
err = errors.New("KeyConf 中 KFields 的字段配置错误")
return
}
//把满足条件的Redis key找出来
qualified := true //当前key是否满足条件
i := -1
for kf := range kFields {
i++
var (
fv int64
)
fv, err = strconv.ParseInt(ks[i], 10, 64) //Redis key 中第i位的值
if err != nil {
return
}
if _, ok = moniCdt[kf]; !ok {
err = errors.New("配置的 moniCdt 中不存在: " + kf)
return
}
switch moniCdt[kf].Comp {
case monitor.CompE:
if fv != moniCdt[kf].Value {
qualified = false
}
case monitor.CompNE:
if fv == moniCdt[kf].Value {
qualified = false
}
case monitor.CompGET:
if fv < moniCdt[kf].Value {
qualified = false
}
case monitor.CompLET:
if fv > moniCdt[kf].Value {
qualified = false
}
case monitor.CompGT:
if fv <= moniCdt[kf].Value {
qualified = false
}
case monitor.CompLT:
if fv >= moniCdt[kf].Value {
qualified = false
}
default:
err = errors.New("配置的 MoniCdt 中 comparison 不合法: " + moniCdt[kf].Comp)
return
}
}
if qualified {
qualiKeys = append(qualiKeys, fullK)
}
}
return
}
// MoniStayOids 获取监控范围内滞留的oids
func (s *Service) MoniStayOids(c context.Context, tp, bid int8, id int64) (total int, oidMap map[int64]int, qualiKeys []string, err error) {
var (
rule *monitor.Rule
)
if rule, err = s.monitor.GetRule(c, tp, bid, id); err != nil {
return
}
//查找符合条件的统计redis key
if qualiKeys, err = s.RuleQualifiedKeys(c, rule); err != nil {
return
}
oidMap, total, err = s.monitor.StayOids(c, rule, qualiKeys)
log.Info("MoniStayOids(%d,%d,%d) oidMap(%v)", tp, bid, id, oidMap)
return
}
// MonitorStayOids 获取监控范围内滞留的oids
func (s *Service) MonitorStayOids(c context.Context, id int64) (oidMap map[int64]int, err error) {
return s.data.MonitorOids(c, id)
}
// MonitorNotifyResult 获取达到了报警阀值的数据
func (s *Service) MonitorNotifyResult(c context.Context) (res []*monitor.RuleResultData, err error) {
var (
rules []*monitor.Rule
stats *monitor.Stats
)
res = []*monitor.RuleResultData{}
if rules, err = s.monitor.GetAllRules(c, false); err != nil {
log.Error("MonitorNotifyCheck() error(%v)", err)
return
}
for _, v := range rules {
if v.Business == monitor.BusVideo {
s.MonitorCheckVideoStatus(c, v.Type, v.ID)
}
if stats, err = s.MonitorStats(c, v); err != nil {
log.Error("MonitorNotifyCheck() error(%v)", err)
err = nil
continue
}
notify := true
//暂时只有time、count这两个报警条件
if _, ok := v.RuleConf.NotifyCdt["time"]; ok {
threshold := v.RuleConf.NotifyCdt["time"].Value
comp := v.RuleConf.NotifyCdt["time"].Comp
switch comp {
case monitor.CompGT:
if int64(stats.MaxTime) < threshold {
notify = false
}
case monitor.CompLT:
if int64(stats.MaxTime) > threshold {
notify = false
}
}
}
if _, ok := v.RuleConf.NotifyCdt["count"]; ok {
threshold := v.RuleConf.NotifyCdt["count"].Value
comp := v.RuleConf.NotifyCdt["count"].Comp
switch comp {
case monitor.CompGT:
if int64(stats.MoniCount) < threshold {
notify = false
}
case monitor.CompLT:
if int64(stats.MoniCount) > threshold {
notify = false
}
}
}
if notify {
tmp := &monitor.RuleResultData{
Stats: stats,
Rule: v,
}
res = append(res, tmp)
}
}
return
}
// MonitorCheckVideoStatus 检查视频的稿件状态,如果是-100则剔除SortedSet的数据
func (s *Service) MonitorCheckVideoStatus(c context.Context, tp int8, id int64) (err error) {
var (
vidMap map[int64]int
vidAidMap map[int64]int64
arcStates map[int64]int
vids, aids []int64
bid = monitor.BusVideo
keys []string
)
if _, vidMap, keys, err = s.MoniStayOids(c, tp, bid, id); err != nil {
log.Error("s.MoniStayOids(%d,%d,%d) error(%v)", tp, bid, id, err)
return
}
for vid := range vidMap {
vids = append(vids, vid)
}
if vidAidMap, err = s.arc.VideoAidMap(c, vids); err != nil {
log.Error("s.VideoAidMap(%d) error(%v)", vids, err)
return
}
for _, aid := range vidAidMap {
aids = append(aids, aid)
}
if arcStates, err = s.arc.ArcStateMap(c, aids); err != nil {
log.Error("s.ArcStateMap(%d) error(%v)", aids, err)
return
}
for vid, aid := range vidAidMap {
if _, ok := arcStates[aid]; !ok {
continue
}
if arcStates[aid] != int(archive.StateForbidUpDelete) && arcStates[aid] != int(archive.StateForbidLock) && arcStates[aid] != int(archive.StateForbidRecycle) {
continue
}
for _, k := range keys {
if err = s.monitor.RemMonitorStats(c, k, vid); err != nil {
log.Error("s.monitor.RemMonitorStats(%s,%d) error(%v)", k, vid, err)
}
}
}
return
}