// package topic_stat -- небольшая статистика топика package topic_stat import ( "fmt" "sync" "p78git.ddns.net/svi/gobus/api/netapi" "p78git.ddns.net/svi/gobus/pkg/alias" "p78git.ddns.net/svi/gobus/pkg/types" ) // TopicStat -- небольшая статистика топика type TopicStat struct { countMsg int // Количество прокрученных сообщений countTraff int // Счётчик прокрученного траффика countErr int // Количество ошибок топика topicName alias.TopicName // Имя топика size int // Размер топика block sync.RWMutex } // NewTopicStat -- возвращает статистику топика func NewTopicStat(msg *netapi.TopicMsg) (*TopicStat, error) { { // Предусловия if msg == nil { return nil, fmt.Errorf("NewTopicStat(): TopicMsg==nil") } if msg.Topic == "" { return nil, fmt.Errorf("NewTopicStat(): topicName is empty") } } sf := &TopicStat{ topicName: alias.TopicName(msg.Topic), } _ = types.ITopicStat(sf) return sf, nil } // Size -- возвращает текущий размер топика func (sf *TopicStat) Size() int { sf.block.RLock() defer sf.block.RUnlock() return sf.size } // CountTraff -- возвращает количество траффика пропущенного через топик func (sf *TopicStat) CountTraff() int { sf.block.RLock() defer sf.block.RUnlock() return sf.countTraff } // CountMsg -- возвращает количество сообщений пропущенных через топик func (sf *TopicStat) CountMsg() int { sf.block.RLock() defer sf.block.RUnlock() return sf.countMsg } // CountErr -- возвращает количество ошибок счётчика func (sf *TopicStat) CountErr() int { sf.block.RLock() defer sf.block.RUnlock() return sf.countErr } // Name -- возвращает имя топика func (sf *TopicStat) Name() alias.TopicName { return sf.topicName } const ( lenHelper = 24 // Длина UUID и номера источника ) // Update -- обновляет статистику func (sf *TopicStat) Update(msg *netapi.TopicMsg) error { sf.block.Lock() defer sf.block.Unlock() sf.countMsg++ if msg == nil { sf.countErr++ return fmt.Errorf("TopicStat.Update(): TopicMsg==nil") } if err := sf.check(msg); err != nil { sf.countErr++ return fmt.Errorf("TopicStat.Update(): in check msg, err=\n\t%w", err) } sf.size = len(msg.BinMsg) + len(sf.topicName) + lenHelper sf.countTraff += sf.size return nil } // Проверяет под блокировкой верхнего уровня правильность сообщения func (sf *TopicStat) check(msg *netapi.TopicMsg) error { if msg.Topic != string(sf.topicName) { return fmt.Errorf("TopicStat.check(): msg.Topic(%q)!=%q", msg.Topic, sf.topicName) } if len(msg.StrUuid) != 20 { return fmt.Errorf("TopicStat.check(): len msg.StrUuuid(%v)!=20", len(msg.StrUuid)) } return nil }