package metrics import ( "bufio" "fmt" "git.openprivacy.ca/openprivacy/libricochet-go/application" "github.com/struCoder/pidusage" "log" "os" "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 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(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() } func (mp *Monitors) log() { for { select { case <-time.After(time.Minute): messageMinutes := mp.Messages.Minutes() cpuMinutes := mp.CPU.Minutes() memoryMinutes := mp.Memory.Minutes() 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.Fprintf(w, "Started: %v\n\n", mp.starttime) 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.ClientConns.Stop() }