kappanhang/statuslog.go
2020-10-28 18:03:35 +01:00

122 lines
2.3 KiB
Go

package main
import (
"fmt"
"sync"
"time"
)
type statusLogStruct struct {
ticker *time.Ticker
stopChan chan bool
stopFinishedChan chan bool
mutex sync.Mutex
line string
startTime time.Time
rttLatency time.Duration
audioTimeDiff time.Duration
}
var statusLog statusLogStruct
func (s *statusLogStruct) reportRTTLatency(l time.Duration) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.rttLatency = l
}
func (s *statusLogStruct) reportServerAudioTime(t time.Time) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.audioTimeDiff = time.Since(t)
}
func (s *statusLogStruct) print() {
s.mutex.Lock()
defer s.mutex.Unlock()
if s.isRealtimeInternal() {
log.printLineClear()
fmt.Print(s.line)
} else {
log.Print(s.line)
}
}
func (s *statusLogStruct) update() {
s.mutex.Lock()
defer s.mutex.Unlock()
up, down, lost, retransmits := netstat.get()
var debugStr string
if verboseLog {
debugStr = fmt.Sprint(" adiff ", s.audioTimeDiff.Milliseconds(), "ms")
}
s.line = fmt.Sprint("up ", time.Since(s.startTime).Round(time.Second),
" rtt ", s.rttLatency.Milliseconds(), "ms up ",
netstat.formatByteCount(up), "/s down ",
netstat.formatByteCount(down), "/s retx ", retransmits, " /1m lost ", lost, " /1m", debugStr)
if s.isRealtimeInternal() {
s.line = fmt.Sprint(time.Now().Format("2006-01-02T15:04:05.000Z0700"), " ", s.line, "\r")
}
}
func (s *statusLogStruct) loop() {
for {
select {
case <-s.ticker.C:
s.update()
s.print()
case <-s.stopChan:
s.stopFinishedChan <- true
return
}
}
}
func (s *statusLogStruct) isRealtimeInternal() bool {
return statusLogInterval < time.Second
}
func (s *statusLogStruct) isRealtime() bool {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.ticker != nil && s.isRealtimeInternal()
}
func (s *statusLogStruct) isActive() bool {
s.mutex.Lock()
defer s.mutex.Unlock()
return s.ticker != nil
}
func (s *statusLogStruct) startPeriodicPrint() {
s.mutex.Lock()
defer s.mutex.Unlock()
s.startTime = time.Now()
s.stopChan = make(chan bool)
s.stopFinishedChan = make(chan bool)
s.ticker = time.NewTicker(statusLogInterval)
go s.loop()
}
func (s *statusLogStruct) stopPeriodicPrint() {
if !s.isActive() {
return
}
s.ticker.Stop()
s.ticker = nil
s.stopChan <- true
<-s.stopFinishedChan
}