From 202fdd1da6d90ff6668cbecda37cb96e4f2af69b Mon Sep 17 00:00:00 2001 From: Gituser143 Date: Fri, 7 Aug 2020 18:41:08 +0530 Subject: [PATCH 1/6] Made Memory chart dimesnions dynamic --- src/display/general/init.go | 1 + src/display/general/overallGraphs.go | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/display/general/init.go b/src/display/general/init.go index 31ea11c3..2677f74b 100644 --- a/src/display/general/init.go +++ b/src/display/general/init.go @@ -104,6 +104,7 @@ func (page *MainPage) InitGeneral(numCores int) { ui.NewRow(0.34, page.DiskChart), ) + // Get Terminal Dimensions w, h := ui.TerminalDimensions() page.Grid.SetRect(w/2, 0, w, h) } diff --git a/src/display/general/overallGraphs.go b/src/display/general/overallGraphs.go index b99fea65..2cbdf6b8 100644 --- a/src/display/general/overallGraphs.go +++ b/src/display/general/overallGraphs.go @@ -155,9 +155,15 @@ func RenderCharts(endChannel chan os.Signal, ui.Clear() height := int(h / numCores) - heightOffset := h - (height * numCores) // There's some extra empty space left + heightOffset := h - (height * numCores) + + // Adjust Grid dimensions myPage.Grid.SetRect(w/2, 0, w, h-heightOffset) + // Adjust Memory Bar graph values + myPage.MemoryChart.BarGap = ((w / 2) - (4 * myPage.MemoryChart.BarWidth)) / 4 + + // Adjust CPU Gauge dimensions if isCPUSet { for i := 0; i < numCores; i++ { myPage.CPUCharts[i].SetRect(0, i*height, w/2, (i+1)*height) From aca71555feaac82de8d59a0e1929b40b63f7cdc0 Mon Sep 17 00:00:00 2001 From: MadhavJivrajani Date: Fri, 7 Aug 2020 20:13:49 +0530 Subject: [PATCH 2/6] added binary installation instruction in README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index b07dea05..2b8c8967 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,13 @@ Using go get: go get -u github.com/pesos/grofer ``` +As an executable: +``` +curl -sSL https://github.com/pesos/grofer/releases/download//grofer --output grofer +chmod +x grofer +``` +For system wide usage, install `grofer` to a location on `$PATH`, e.g. `/usr/local/bin` + Building from source: ``` From 3f5cf9a35ed412b7eaa20fd94948d8a0256f5971 Mon Sep 17 00:00:00 2001 From: Gituser143 Date: Fri, 7 Aug 2020 21:51:04 +0530 Subject: [PATCH 3/6] Made data transfer through single channel. Fixes #2 --- cmd/root.go | 10 ++- src/display/general/overallGraphs.go | 104 +++++++++++++-------------- src/general/generalStats.go | 16 ++--- src/general/printStats.go | 39 +++++++--- src/utils/data.go | 9 +++ 5 files changed, 101 insertions(+), 77 deletions(-) create mode 100644 src/utils/data.go diff --git a/cmd/root.go b/cmd/root.go index 01edb022..5f6e916d 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -26,6 +26,7 @@ import ( overallGraph "github.com/pesos/grofer/src/display/general" "github.com/pesos/grofer/src/general" + "github.com/pesos/grofer/src/utils" ) const ( @@ -47,15 +48,12 @@ var rootCmd = &cobra.Command{ var wg sync.WaitGroup endChannel := make(chan os.Signal, 1) - memChannel := make(chan []float64, 1) - cpuChannel := make(chan []float64, 1) - diskChannel := make(chan [][]string, 1) - netChannel := make(chan map[string][]float64, 1) + dataChannel := make(chan utils.DataStats, 1) wg.Add(2) - go general.GlobalStats(endChannel, cpuChannel, memChannel, diskChannel, netChannel, overallRefreshRate, &wg) - go overallGraph.RenderCharts(endChannel, memChannel, cpuChannel, diskChannel, netChannel, overallRefreshRate, &wg) + go general.GlobalStats(endChannel, dataChannel, overallRefreshRate, &wg) + go overallGraph.RenderCharts(endChannel, dataChannel, overallRefreshRate, &wg) wg.Wait() diff --git a/src/display/general/overallGraphs.go b/src/display/general/overallGraphs.go index 2cbdf6b8..3bcc7eb2 100644 --- a/src/display/general/overallGraphs.go +++ b/src/display/general/overallGraphs.go @@ -26,6 +26,7 @@ import ( "time" ui "github.com/gizak/termui/v3" + "github.com/pesos/grofer/src/utils" ) var isCPUSet = false @@ -34,10 +35,7 @@ var run = true // RenderCharts handles plotting graphs and charts for system stats in general. func RenderCharts(endChannel chan os.Signal, - memChannel chan []float64, - cpuChannel chan []float64, - diskChannel chan [][]string, - netChannel chan map[string][]float64, + dataChannel chan utils.DataStats, refreshRate int32, wg *sync.WaitGroup) { @@ -80,73 +78,71 @@ func RenderCharts(endChannel chan os.Signal, pause() } - case data := <-memChannel: // Update memory values + case data := <-dataChannel: if run { - myPage.MemoryChart.Data = data - } + switch data.FieldSet { - case data := <-diskChannel: // Update disk values - if run { - myPage.DiskChart.Rows = data - } - - case data := <-netChannel: // Update network stats & render braille plots - if run { - - var curBytesRecv, curBytesSent float64 + case "CPU": // Update CPU stats + for index, rate := range data.CpuStats { + myPage.CPUCharts[index].Title = " CPU " + strconv.Itoa(index) + " " + myPage.CPUCharts[index].Percent = int(rate) + } - for _, netInterface := range data { - curBytesRecv += netInterface[1] - curBytesSent += netInterface[0] - } + case "MEM": // Update Memory stats + myPage.MemoryChart.Data = data.MemStats - var recentBytesRecv, recentBytesSent float64 + case "DISK": // Update Disk stats + myPage.DiskChart.Rows = data.DiskStats - if totalBytesRecv != 0 { - recentBytesRecv = curBytesRecv - totalBytesRecv - recentBytesSent = curBytesSent - totalBytesSent + case "NET": // Update Network stats + var curBytesRecv, curBytesSent float64 - if int(recentBytesRecv) < 0 { - recentBytesRecv = 0 - } - if int(recentBytesSent) < 0 { - recentBytesSent = 0 + for _, netInterface := range data.NetStats { + curBytesRecv += netInterface[1] + curBytesSent += netInterface[0] } - ipData = ipData[1:] - opData = opData[1:] + var recentBytesRecv, recentBytesSent float64 - ipData = append(ipData, recentBytesRecv) - opData = append(opData, recentBytesSent) - } + if totalBytesRecv != 0 { + recentBytesRecv = curBytesRecv - totalBytesRecv + recentBytesSent = curBytesSent - totalBytesSent - totalBytesRecv = curBytesRecv - totalBytesSent = curBytesSent + if int(recentBytesRecv) < 0 { + recentBytesRecv = 0 + } + if int(recentBytesSent) < 0 { + recentBytesSent = 0 + } - titles := make([]string, 2) + ipData = ipData[1:] + opData = opData[1:] - for i := 0; i < 2; i++ { - if i == 0 { - titles[i] = fmt.Sprintf("[Total RX](fg:red): %5.1f %s\n", totalBytesRecv/1024, "mB") - } else { - titles[i] = fmt.Sprintf("\n[Total TX](fg:green): %5.1f %s", totalBytesSent/1024, "mB") + ipData = append(ipData, recentBytesRecv) + opData = append(opData, recentBytesSent) } - } + totalBytesRecv = curBytesRecv + totalBytesSent = curBytesSent - myPage.NetPara.Text = titles[0] + titles[1] + titles := make([]string, 2) - temp := [][]float64{} - temp = append(temp, ipData) - temp = append(temp, opData) - myPage.NetworkChart.Data = temp - } + for i := 0; i < 2; i++ { + if i == 0 { + titles[i] = fmt.Sprintf("[Total RX](fg:red): %5.1f %s\n", totalBytesRecv/1024, "mB") + } else { + titles[i] = fmt.Sprintf("\n[Total TX](fg:green): %5.1f %s", totalBytesSent/1024, "mB") + } + + } + + myPage.NetPara.Text = titles[0] + titles[1] + + temp := [][]float64{} + temp = append(temp, ipData) + temp = append(temp, opData) + myPage.NetworkChart.Data = temp - case cpu_data := <-cpuChannel: // Update Gauge map with newer values - if run { - for index, rate := range cpu_data { - myPage.CPUCharts[index].Title = " CPU " + strconv.Itoa(index) + " " - myPage.CPUCharts[index].Percent = int(rate) } } diff --git a/src/general/generalStats.go b/src/general/generalStats.go index 155f6ab2..bd04b70d 100644 --- a/src/general/generalStats.go +++ b/src/general/generalStats.go @@ -19,15 +19,13 @@ import ( "os" "sync" "time" + + "github.com/pesos/grofer/src/utils" ) // GlobalStats gets stats about the mem and the CPUs and prints it. func GlobalStats(endChannel chan os.Signal, - cpuChannel chan []float64, - memChannel chan []float64, - diskChannel chan [][]string, - netChannel chan map[string][]float64, - refreshRate int32, + dataChannel chan utils.DataStats, refreshRate int32, wg *sync.WaitGroup) { for { @@ -38,10 +36,10 @@ func GlobalStats(endChannel chan os.Signal, default: // Get Memory and CPU rates per core periodically - go PrintCPURates(cpuChannel) - go PrintMemRates(memChannel) - go PrintDiskRates(diskChannel) - PrintNetRates(netChannel) + go PrintCPURates(dataChannel) + go PrintMemRates(dataChannel) + go PrintDiskRates(dataChannel) + PrintNetRates(dataChannel) time.Sleep(time.Duration(refreshRate) * time.Millisecond) } } diff --git a/src/general/printStats.go b/src/general/printStats.go index 6124822e..bcefeea3 100644 --- a/src/general/printStats.go +++ b/src/general/printStats.go @@ -22,6 +22,7 @@ import ( "strings" "time" + "github.com/pesos/grofer/src/utils" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/disk" "github.com/shirou/gopsutil/mem" @@ -34,26 +35,36 @@ func roundOff(num uint64) float64 { } // PrintCPURates print the cpu rates -func PrintCPURates(cpuChannel chan []float64) { +func PrintCPURates(cpuChannel chan utils.DataStats) { cpuRates, err := cpu.Percent(time.Second, true) if err != nil { log.Fatal(err) } - cpuChannel <- cpuRates + data := utils.DataStats{ + CpuStats: cpuRates, + FieldSet: "CPU", + } + cpuChannel <- data } // PrintMemRates prints stats about the memory -func PrintMemRates(dataChannel chan []float64) { +func PrintMemRates(dataChannel chan utils.DataStats) { memory, err := mem.VirtualMemory() if err != nil { log.Fatal(err) } - data := []float64{roundOff(memory.Total), roundOff(memory.Available), roundOff(memory.Used), roundOff(memory.Free)} + memRates := []float64{roundOff(memory.Total), roundOff(memory.Available), roundOff(memory.Used), roundOff(memory.Free)} + + data := utils.DataStats{ + MemStats: memRates, + FieldSet: "MEM", + } + dataChannel <- data } -func PrintDiskRates(dataChannel chan [][]string) { +func PrintDiskRates(dataChannel chan utils.DataStats) { var partitions []disk.PartitionStat var err error @@ -83,10 +94,16 @@ func PrintDiskRates(dataChannel chan [][]string) { } } - dataChannel <- rows + + data := utils.DataStats{ + DiskStats: rows, + FieldSet: "DISK", + } + + dataChannel <- data } -func PrintNetRates(dataChannel chan map[string][]float64) { +func PrintNetRates(dataChannel chan utils.DataStats) { netStats, err := net.IOCounters(false) if err != nil { log.Fatal(err) @@ -96,5 +113,11 @@ func PrintNetRates(dataChannel chan map[string][]float64) { nic := []float64{float64(IOStat.BytesSent) / (1024), float64(IOStat.BytesRecv) / (1024)} IO[IOStat.Name] = nic } - dataChannel <- IO + + data := utils.DataStats{ + NetStats: IO, + FieldSet: "NET", + } + + dataChannel <- data } diff --git a/src/utils/data.go b/src/utils/data.go new file mode 100644 index 00000000..695ef6eb --- /dev/null +++ b/src/utils/data.go @@ -0,0 +1,9 @@ +package utils + +type DataStats struct { + CpuStats []float64 + MemStats []float64 + DiskStats [][]string + NetStats map[string][]float64 + FieldSet string +} From 706e0079ff1c38604f633eb90416e6fec567a6eb Mon Sep 17 00:00:00 2001 From: Gituser143 Date: Fri, 7 Aug 2020 22:01:12 +0530 Subject: [PATCH 4/6] Fix oops and add license --- src/utils/data.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/utils/data.go b/src/utils/data.go index 695ef6eb..a82e7015 100644 --- a/src/utils/data.go +++ b/src/utils/data.go @@ -1,3 +1,19 @@ +/* +Copyright © 2020 The PES Open Source Team pesos@pes.edu + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + package utils type DataStats struct { From d180514eec177f93b631bda78cd692e4b802ea54 Mon Sep 17 00:00:00 2001 From: MadhavJivrajani Date: Sat, 8 Aug 2020 10:31:57 +0530 Subject: [PATCH 5/6] added export command --- cmd/export.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 cmd/export.go diff --git a/cmd/export.go b/cmd/export.go new file mode 100644 index 00000000..54885d06 --- /dev/null +++ b/cmd/export.go @@ -0,0 +1,51 @@ +/* +Copyright © 2020 The PES Open Source Team pesos@pes.edu + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +// exportCmd represents the export command +var exportCmd = &cobra.Command{ + Use: "export", + Short: "A brief description of your command", + Long: `A longer description that spans multiple lines and likely contains examples +and usage of using your command. For example: + +Cobra is a CLI library for Go that empowers applications. +This application is a tool to generate the needed files +to quickly create a Cobra application.`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println("export called") + }, +} + +func init() { + rootCmd.AddCommand(exportCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // exportCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // exportCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} From c360279c2c67cd7db204ac3c0418e78295b487f0 Mon Sep 17 00:00:00 2001 From: Bhargav SNV <44526455+Gituser143@users.noreply.github.com> Date: Sat, 8 Aug 2020 16:38:04 +0530 Subject: [PATCH 6/6] Delete export.go --- cmd/export.go | 51 --------------------------------------------------- 1 file changed, 51 deletions(-) delete mode 100644 cmd/export.go diff --git a/cmd/export.go b/cmd/export.go deleted file mode 100644 index 54885d06..00000000 --- a/cmd/export.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright © 2020 The PES Open Source Team pesos@pes.edu - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -package cmd - -import ( - "fmt" - - "github.com/spf13/cobra" -) - -// exportCmd represents the export command -var exportCmd = &cobra.Command{ - Use: "export", - Short: "A brief description of your command", - Long: `A longer description that spans multiple lines and likely contains examples -and usage of using your command. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("export called") - }, -} - -func init() { - rootCmd.AddCommand(exportCmd) - - // Here you will define your flags and configuration settings. - - // Cobra supports Persistent Flags which will work for this command - // and all subcommands, e.g.: - // exportCmd.PersistentFlags().String("foo", "", "A help for foo") - - // Cobra supports local flags which will only run when this command - // is called directly, e.g.: - // exportCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -}