136 lines
2.7 KiB
Go
136 lines
2.7 KiB
Go
package metrics
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"git.openprivacy.ca/cwtch.im/tapir"
|
|
"git.openprivacy.ca/openprivacy/log"
|
|
"os"
|
|
"path"
|
|
"runtime"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
reportFile = "serverMonitorReport.txt"
|
|
)
|
|
|
|
type MessageCountFn func() int
|
|
|
|
// Monitors is a package of metrics for a Cwtch Server including message count, CPU, Mem, and conns
|
|
type Monitors struct {
|
|
MessageCounter Counter
|
|
Messages MonitorHistory
|
|
Memory MonitorHistory
|
|
ClientConns MonitorHistory
|
|
messageCountFn MessageCountFn
|
|
starttime time.Time
|
|
breakChannel chan bool
|
|
log bool
|
|
configDir string
|
|
running bool
|
|
lock sync.Mutex
|
|
}
|
|
|
|
func bToMb(b uint64) uint64 {
|
|
return b / 1024 / 1024
|
|
}
|
|
|
|
// Start initializes a Monitors's monitors
|
|
func (mp *Monitors) Start(ts tapir.Service, mcfn MessageCountFn, configDir string, doLogging bool) {
|
|
mp.log = doLogging
|
|
mp.configDir = configDir
|
|
mp.starttime = time.Now()
|
|
mp.breakChannel = make(chan bool)
|
|
mp.MessageCounter = NewCounter()
|
|
mp.messageCountFn = mcfn
|
|
|
|
mp.Messages = NewMonitorHistory(Count, Cumulative, func() (c float64) {
|
|
c = float64(mp.MessageCounter.Count())
|
|
mp.MessageCounter.Reset()
|
|
return
|
|
})
|
|
|
|
mp.Memory = NewMonitorHistory(MegaBytes, Average, func() float64 {
|
|
var m runtime.MemStats
|
|
runtime.ReadMemStats(&m)
|
|
return float64(bToMb(m.Sys))
|
|
})
|
|
|
|
mp.ClientConns = NewMonitorHistory(Count, Average, func() float64 { return float64(ts.Metrics().ConnectionCount) })
|
|
|
|
if mp.log {
|
|
go mp.run()
|
|
}
|
|
}
|
|
|
|
func (mp *Monitors) run() {
|
|
mp.running = true
|
|
for {
|
|
select {
|
|
case <-time.After(time.Minute):
|
|
mp.lock.Lock()
|
|
mp.report()
|
|
mp.lock.Unlock()
|
|
case <-mp.breakChannel:
|
|
mp.lock.Lock()
|
|
mp.running = false
|
|
mp.lock.Unlock()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func FormatDuration(ts time.Duration) string {
|
|
const (
|
|
Day = 24 * time.Hour
|
|
)
|
|
d := ts / Day
|
|
ts = ts % Day
|
|
h := ts / time.Hour
|
|
ts = ts % time.Hour
|
|
m := ts / time.Minute
|
|
return fmt.Sprintf("%dd%dh%dm", d, h, m)
|
|
}
|
|
|
|
func (mp *Monitors) report() {
|
|
f, err := os.Create(path.Join(mp.configDir, reportFile))
|
|
if err != nil {
|
|
log.Errorf("Could not open monitor reporting file: %v", err)
|
|
return
|
|
}
|
|
defer f.Close()
|
|
|
|
w := bufio.NewWriter(f)
|
|
|
|
fmt.Fprintf(w, "Uptime: %v \n", FormatDuration(time.Since(mp.starttime)))
|
|
fmt.Fprintf(w, "Total Messages: %v \n\n", mp.messageCountFn())
|
|
|
|
fmt.Fprintln(w, "Messages:")
|
|
mp.Messages.Report(w)
|
|
|
|
fmt.Fprintln(w, "\nClient Connections:")
|
|
mp.ClientConns.Report(w)
|
|
|
|
fmt.Fprintln(w, "\nSys Memory:")
|
|
mp.Memory.Report(w)
|
|
|
|
w.Flush()
|
|
}
|
|
|
|
// Stop stops all the monitors in a Monitors
|
|
func (mp *Monitors) Stop() {
|
|
mp.lock.Lock()
|
|
running := mp.running
|
|
mp.lock.Unlock()
|
|
if running {
|
|
if mp.log {
|
|
mp.breakChannel <- true
|
|
}
|
|
mp.Messages.Stop()
|
|
mp.Memory.Stop()
|
|
mp.ClientConns.Stop()
|
|
}
|
|
}
|