Skip to content

Commit

Permalink
merge readme
Browse files Browse the repository at this point in the history
  • Loading branch information
cha87de committed Nov 2, 2018
2 parents 74ddaed + a0e22db commit 76f8b53
Show file tree
Hide file tree
Showing 13 changed files with 160 additions and 13 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,19 @@ A more detailed list, including all metrics is available here at [./docs/README.
## kvmtop with InfluxDB

kvmtop can be used as a monitoring agent to send data to an InfluxDB instance: kvmtop transmits JSON data via TCP to logstash, while logstash writes to InfluxDB. More detailes are available at [https://github.com/cha87de/kvmtop-datasink/](https://github.com/cha87de/kvmtop-datasink/).
<<<<<<< HEAD
=======

```
kvmtop-datasink
+-----------------------------------------------------+
| |
+------------ | +------------+ +------------+ +-----------+ |
| | | | | | | | | |
| kvmtop +---> | | logstash +---> | influxdb +---> | grafana | |
| | | | | | | | | |
+------------ | +------------+ +------------+ +-----------+ |
| |
+-----------------------------------------------------+
```
>>>>>>> master
4 changes: 3 additions & 1 deletion cmd/kvmtop/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ func initializeFlags() {

// Parse parameters
if _, err := parser.Parse(); err != nil {
fmt.Printf("Error parsing flags: %s", err)
code := 1
if fe, ok := err.(*flags.Error); ok {
if fe.Type == flags.ErrHelp {
code = 0
}
}
if code != 0 {
fmt.Printf("Error parsing flags: %s", err)
}
os.Exit(code)
}

Expand Down
9 changes: 9 additions & 0 deletions cmd/kvmtop/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/signal"
"runtime/debug"
"syscall"

"github.com/cha87de/kvmtop/config"
Expand All @@ -16,6 +17,14 @@ var version = "devbuild"

func main() {

// catch panics
defer func() {
if r := recover(); r != nil {
debug.PrintStack()
shutdown(1)
}
}()

// handle flags
initializeFlags()
if config.Options.Version {
Expand Down
8 changes: 7 additions & 1 deletion collectors/cpucollector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ func (collector *Collector) Collect() {
func (collector *Collector) Print() models.Printable {
hostFields := []string{
"cpu_cores",
"cpu_meanfreq",
"cpu_curfreq",
}
if config.Options.Verbose {
hostFields = append(hostFields,
"cpu_minfreq",
"cpu_maxfreq",
)
}
domainFields := []string{
"cpu_cores",
Expand Down
33 changes: 24 additions & 9 deletions collectors/cpucollector/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,47 @@ package cpucollector

import (
"github.com/cha87de/kvmtop/collectors"
"github.com/cha87de/kvmtop/config"
"github.com/cha87de/kvmtop/models"

"github.com/cha87de/kvmtop/util"
"gonum.org/v1/gonum/stat"
)

func cpuLookupHost(host *models.Host) {
cpuinfo := util.GetProcCpuinfo()
cpuinfo := util.GetSysCPU()

// calculate average MHz
coreFrequencies := []float64{}
// calculate average of current cpu frequency
coreFreqMin := []float64{}
coreFreqMax := []float64{}
coreFreqCurrent := []float64{}
for _, c := range cpuinfo {
coreFrequencies = append(coreFrequencies, float64(c.CPUMhz))
// convert kHz to MHz
coreFreqMin = append(coreFreqMin, float64(c.MinFreq/1000))
coreFreqMax = append(coreFreqMax, float64(c.MaxFreq/1000))
coreFreqCurrent = append(coreFreqCurrent, float64(c.CurFreq/1000))
}
freqMean := stat.Mean(coreFrequencies, nil)
host.AddMetricMeasurement("cpu_meanfreq", models.CreateMeasurement(freqMean))
coreFreqMinMean := stat.Mean(coreFreqMin, nil)
host.AddMetricMeasurement("cpu_minfreq", models.CreateMeasurement(coreFreqMinMean))
coreFreqMaxMean := stat.Mean(coreFreqMax, nil)
host.AddMetricMeasurement("cpu_maxfreq", models.CreateMeasurement(coreFreqMaxMean))
coreFreqCurMean := stat.Mean(coreFreqCurrent, nil)
host.AddMetricMeasurement("cpu_curfreq", models.CreateMeasurement(coreFreqCurMean))

cores := len(coreFrequencies)
cores := len(coreFreqCurrent)
host.AddMetricMeasurement("cpu_cores", models.CreateMeasurement(uint64(cores)))
}

func cpuPrintHost(host *models.Host) []string {
cpuMeanfreq := collectors.GetMetricFloat64(host.Measurable, "cpu_meanfreq", 0)
cpuMinfreq := collectors.GetMetricFloat64(host.Measurable, "cpu_minfreq", 0)
cpuMaxfreq := collectors.GetMetricFloat64(host.Measurable, "cpu_maxfreq", 0)
cpuCurfreq := collectors.GetMetricFloat64(host.Measurable, "cpu_curfreq", 0)
cpuCores := collectors.GetMetricUint64(host.Measurable, "cpu_cores", 0)

// put results together
result := append([]string{cpuCores}, cpuMeanfreq)
result := append([]string{cpuCores}, cpuCurfreq)
if config.Options.Verbose {
result = append(result, cpuMinfreq, cpuMaxfreq)
}
return result
}
1 change: 1 addition & 0 deletions collectors/netcollector/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (collector *Collector) Print() models.Printable {
hostFields := []string{
"net_host_receivedBytes",
"net_host_transmittedBytes",
"net_host_speed",
}
domainFields := []string{
"net_receivedBytes",
Expand Down
3 changes: 3 additions & 0 deletions collectors/netcollector/hostCollect.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package netcollector

import (
"fmt"

"github.com/cha87de/kvmtop/models"
"github.com/cha87de/kvmtop/util"
)

func hostCollect(host *models.Host) {
// get stats from net/dev for host interfaces
ifs := host.GetMetricStringArray("net_host_ifs")
fmt.Printf("ifs: %+v\n", ifs)
statsSum := util.ProcNetDev{}
for _, devname := range ifs {
devStats := util.GetProcNetDev(0, devname)
Expand Down
6 changes: 6 additions & 0 deletions collectors/netcollector/hostLookup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package netcollector
import (
"fmt"

"github.com/cha87de/kvmtop/config"
"github.com/cha87de/kvmtop/connector"
"github.com/cha87de/kvmtop/models"
"github.com/cha87de/kvmtop/util"
libvirt "github.com/libvirt/libvirt-go"
libvirtxml "github.com/libvirt/libvirt-go-xml"
)
Expand All @@ -13,6 +15,10 @@ func hostLookup(host *models.Host) {
bridges := getHostBridges()
newMeasurementInterfaces := models.CreateMeasurement(bridges)
host.AddMetricMeasurement("net_host_ifs", newMeasurementInterfaces)

speed := util.GetSysNetSpeed(config.Options.NetworkDevice)
newMeasurementSpeed := models.CreateMeasurement(uint64(speed.Value))
host.AddMetricMeasurement("net_host_speed", newMeasurementSpeed)
}

func getHostBridges() []string {
Expand Down
4 changes: 3 additions & 1 deletion collectors/netcollector/hostPrint.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ func hostPrint(host *models.Host) []string {
transmittedCarrier := collectors.GetMetricDiffUint64(host.Measurable, "net_host_TransmittedCarrier", true)
transmittedCompressed := collectors.GetMetricDiffUint64(host.Measurable, "net_host_TransmittedCompressed", true)

result := append([]string{receivedBytes}, transmittedBytes)
speed := collectors.GetMetricUint64(host.Measurable, "net_host_speed", 0)

result := append([]string{receivedBytes}, transmittedBytes, speed)
if config.Options.Verbose {
result = append(result, receivedPackets, receivedErrs, receivedDrop, receivedFifo, receivedFrame, receivedCompressed, receivedMulticast, transmittedPackets, transmittedErrs, transmittedDrop, transmittedFifo, transmittedColls, transmittedCarrier, transmittedCompressed)
}
Expand Down
2 changes: 2 additions & 0 deletions config/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ var Options struct {

Output string `short:"o" long:"output" description:"the output channel to send printer output (valid output: stdout, file, tcp)" default:"stdout"`
OutputTarget string `long:"target" description:"for output 'file' the location, for 'tcp' the url to the tcp server"`

NetworkDevice string `long:"netdev" description:"The network device used for the virtual traffic"`
}
4 changes: 3 additions & 1 deletion printers/ncurses.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ func printDomain(window *goncurses.Window, fields []string, values map[string][]
func sortDomainIDsByField(values map[string][]string, sortByColumn int) []KeyValue {
var sorted []KeyValue
for key, value := range values {
sorted = append(sorted, KeyValue{key, value[sortByColumn]})
if len(value) >= sortByColumn {
sorted = append(sorted, KeyValue{key, value[sortByColumn]})
}
}
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].Value > sorted[j].Value
Expand Down
59 changes: 59 additions & 0 deletions util/sys-cpu.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package util

import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
)

// SysCPU reflects cpu system information from /sys/devices/system/cpu/cpu*
type SysCPU struct {
MaxFreq float32
MinFreq float32
CurFreq float32
}

// GetSysCPU returns the system CPU information for available cores
func GetSysCPU() []SysCPU {
stats := []SysCPU{}

files, err := filepath.Glob("/sys/devices/system/cpu/cpu[0-999]")
if err != nil {
fmt.Fprintf(os.Stderr, "Cannot read cpu infos from sys fs: %s\n", err)
return stats
}

var filepath string
var filecontent []byte
for _, f := range files {
cpuStat := SysCPU{}

filepath = fmt.Sprint(f + "/cpufreq/cpuinfo_max_freq")
filecontent, _ = ioutil.ReadFile(filepath)
fmt.Fscan(
bytes.NewBuffer(filecontent),
&cpuStat.MaxFreq,
)

filepath = fmt.Sprint(f + "/cpufreq/cpuinfo_min_freq")
filecontent, _ = ioutil.ReadFile(filepath)
fmt.Fscan(
bytes.NewBuffer(filecontent),
&cpuStat.MinFreq,
)

filepath = fmt.Sprint(f + "/cpufreq/scaling_cur_freq")
filecontent, _ = ioutil.ReadFile(filepath)
fmt.Fscan(
bytes.NewBuffer(filecontent),
&cpuStat.CurFreq,
)

stats = append(stats, cpuStat)

}

return stats
}
24 changes: 24 additions & 0 deletions util/sys-net-speed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package util

import (
"bytes"
"fmt"
"io/ioutil"
)

// SysNetSpeed reflects network interface speed from /sys/class/net/$iface/speed
type SysNetSpeed struct {
Value float32
}

// GetSysNetSpeed reads the network device's speed from /sys/class/net
func GetSysNetSpeed(devName string) SysNetSpeed {
stat := SysNetSpeed{}
filepath := fmt.Sprint("/sys/class/net/" + devName + "/speed")
filecontent, _ := ioutil.ReadFile(filepath)
fmt.Fscan(
bytes.NewBuffer(filecontent),
&stat.Value,
)
return stat
}

0 comments on commit 76f8b53

Please sign in to comment.