forked from cwtch.im/cwtch
Merge branch 'server-metrics' of dan/cwtch into master
This commit is contained in:
commit
e0396c6c8e
|
@ -1,6 +1,9 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
@ -46,7 +49,21 @@ func (c *counter) GetStarttime() time.Time {
|
|||
return c.startTime
|
||||
}
|
||||
|
||||
// MonitorType controls how the monitor will report itself
|
||||
type MonitorType int
|
||||
|
||||
const (
|
||||
// Count indicates the monitor should report in interger format
|
||||
Count MonitorType = iota
|
||||
// Percent indicates the monitor should report in decimal format with 2 places
|
||||
Percent
|
||||
// MegaBytes indicates the monitor should transform the raw number into MBs
|
||||
MegaBytes
|
||||
)
|
||||
|
||||
type monitorHistory struct {
|
||||
monitorType MonitorType
|
||||
|
||||
starttime time.Time
|
||||
perMinutePerHour [60]float64
|
||||
timeLastHourRotate time.Time
|
||||
|
@ -74,11 +91,13 @@ type MonitorHistory interface {
|
|||
Days() []float64
|
||||
Weeks() []float64
|
||||
Months() []float64
|
||||
|
||||
Report(w *bufio.Writer)
|
||||
}
|
||||
|
||||
// NewMonitorHistory returns a new MonitorHistory with starttime of time.Now and Started running with supplied monitor
|
||||
func NewMonitorHistory(monitor func() float64) MonitorHistory {
|
||||
mh := &monitorHistory{starttime: time.Now(), monitor: monitor, breakChannel: make(chan bool)}
|
||||
func NewMonitorHistory(t MonitorType, monitor func() float64) MonitorHistory {
|
||||
mh := &monitorHistory{monitorType: t, starttime: time.Now(), monitor: monitor, breakChannel: make(chan bool)}
|
||||
mh.Start()
|
||||
return mh
|
||||
}
|
||||
|
@ -118,6 +137,30 @@ func (mh *monitorHistory) Months() []float64 {
|
|||
return mh.returnCopy(mh.perMonthForYear[:])
|
||||
}
|
||||
|
||||
func (mh *monitorHistory) Report(w *bufio.Writer) {
|
||||
fmt.Fprintln(w, "Minutes:", reportLine(mh.monitorType, mh.perMinutePerHour[:]))
|
||||
fmt.Fprintln(w, "Hours: ", reportLine(mh.monitorType, mh.perHourForDay[:]))
|
||||
fmt.Fprintln(w, "Days: ", reportLine(mh.monitorType, mh.perDayForWeek[:]))
|
||||
fmt.Fprintln(w, "Weeks: ", reportLine(mh.monitorType, mh.perWeekForMonth[:]))
|
||||
fmt.Fprintln(w, "Months: ", reportLine(mh.monitorType, mh.perMonthForYear[:]))
|
||||
}
|
||||
|
||||
func reportLine(t MonitorType, array []float64) string {
|
||||
switch t {
|
||||
case Count:
|
||||
return strings.Trim(strings.Join(strings.Fields(fmt.Sprint(array)), " "), "[]")
|
||||
case Percent:
|
||||
return strings.Trim(strings.Join(strings.Fields(fmt.Sprintf("%.2f", array)), " "), "[]")
|
||||
case MegaBytes:
|
||||
mbs := make([]int, len(array))
|
||||
for i, b := range array {
|
||||
mbs[i] = int(b) / 1024 / 1024
|
||||
}
|
||||
return strings.Trim(strings.Join(strings.Fields(fmt.Sprintf("%d", mbs)), "MBs "), "[]") + "MBs"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (mh *monitorHistory) returnCopy(slice []float64) []float64 {
|
||||
retSlice := make([]float64, len(slice))
|
||||
mh.lock.Lock()
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"git.openprivacy.ca/openprivacy/libricochet-go/application"
|
||||
"github.com/struCoder/pidusage"
|
||||
"log"
|
||||
|
@ -8,24 +10,30 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
reportFile = "serverMonitorReport.txt"
|
||||
)
|
||||
|
||||
// Monitors is a package of metrics for a Cwtch Server including message count, CPU, Mem, and conns
|
||||
type Monitors struct {
|
||||
MessageCounter Counter
|
||||
Messages MonitorHistory
|
||||
CPU MonitorHistory
|
||||
Memory MonitorHistory
|
||||
ClientListenConns MonitorHistory
|
||||
breakChannel chan bool
|
||||
MessageCounter Counter
|
||||
Messages MonitorHistory
|
||||
CPU MonitorHistory
|
||||
Memory MonitorHistory
|
||||
ClientConns MonitorHistory
|
||||
starttime time.Time
|
||||
breakChannel chan bool
|
||||
}
|
||||
|
||||
// Start initializes a Monitors's monitors
|
||||
func (mp *Monitors) Start(ra *application.RicochetApplication) {
|
||||
mp.starttime = time.Now()
|
||||
mp.breakChannel = make(chan bool)
|
||||
mp.MessageCounter = NewCounter()
|
||||
mp.Messages = NewMonitorHistory(func() (c float64) { c = float64(mp.MessageCounter.Count()); mp.MessageCounter.Reset(); return })
|
||||
mp.CPU = NewMonitorHistory(func() float64 { sysInfo, _ := pidusage.GetStat(os.Getpid()); return float64(sysInfo.CPU) })
|
||||
mp.Memory = NewMonitorHistory(func() float64 { sysInfo, _ := pidusage.GetStat(os.Getpid()); return float64(sysInfo.Memory) })
|
||||
mp.ClientListenConns = NewMonitorHistory(func() float64 { return float64(ra.ConnectionCount()) })
|
||||
mp.Messages = NewMonitorHistory(Count, func() (c float64) { c = float64(mp.MessageCounter.Count()); mp.MessageCounter.Reset(); return })
|
||||
mp.CPU = NewMonitorHistory(Percent, func() float64 { sysInfo, _ := pidusage.GetStat(os.Getpid()); return float64(sysInfo.CPU) })
|
||||
mp.Memory = NewMonitorHistory(MegaBytes, func() float64 { sysInfo, _ := pidusage.GetStat(os.Getpid()); return float64(sysInfo.Memory) })
|
||||
mp.ClientConns = NewMonitorHistory(Count, func() float64 { return float64(ra.ConnectionCount()) })
|
||||
|
||||
// Todo: replace with proper reporting
|
||||
go mp.log()
|
||||
|
@ -38,19 +46,48 @@ func (mp *Monitors) log() {
|
|||
messageMinutes := mp.Messages.Minutes()
|
||||
cpuMinutes := mp.CPU.Minutes()
|
||||
memoryMinutes := mp.Memory.Minutes()
|
||||
listenConnsMinutes := mp.ClientListenConns.Minutes()
|
||||
log.Printf("METRICS: Messages: %.0f ClientListenConns: %.0f CPU: %.2f Memory: %.0f\n", messageMinutes[0], listenConnsMinutes[0], cpuMinutes[0], memoryMinutes[0])
|
||||
listenConnsMinutes := mp.ClientConns.Minutes()
|
||||
log.Printf("METRICS: Messages: %.0f ClientConns: %.0f CPU: %.2f Memory: %.0fMBs\n", messageMinutes[0], listenConnsMinutes[0], cpuMinutes[0], memoryMinutes[0]/1024/1024)
|
||||
mp.report()
|
||||
case <-mp.breakChannel:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (mp *Monitors) report() {
|
||||
f, err := os.Create(reportFile)
|
||||
if err != nil {
|
||||
log.Println("ERROR: Could not open monitor reporting file: ", err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
fmt.Fprintln(w, "Started: ", mp.starttime, "\n")
|
||||
|
||||
fmt.Fprintln(w, "Messages:")
|
||||
mp.Messages.Report(w)
|
||||
|
||||
fmt.Fprintln(w, "\nClient Connections:")
|
||||
mp.ClientConns.Report(w)
|
||||
|
||||
fmt.Fprintln(w, "\nCPU:")
|
||||
mp.CPU.Report(w)
|
||||
|
||||
fmt.Fprintln(w, "\nMemory:")
|
||||
mp.Memory.Report(w)
|
||||
|
||||
w.Flush()
|
||||
|
||||
}
|
||||
|
||||
// Stop stops all the monitors in a Monitors
|
||||
func (mp *Monitors) Stop() {
|
||||
mp.breakChannel <- true
|
||||
mp.Messages.Stop()
|
||||
mp.CPU.Stop()
|
||||
mp.Memory.Stop()
|
||||
mp.ClientListenConns.Stop()
|
||||
mp.ClientConns.Stop()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue