diff options
author | Péter Szilágyi <peterke@gmail.com> | 2015-06-27 23:12:58 +0800 |
---|---|---|
committer | Jeffrey Wilcke <geffobscura@gmail.com> | 2015-06-30 06:51:02 +0800 |
commit | 2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26 (patch) | |
tree | 8b3a9064a185a0b80f5eeea4a3fb40f5d5995585 /metrics | |
parent | 7c4ed8055cc036214279e3ebded74c58d6808d05 (diff) | |
download | dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar.gz dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar.bz2 dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar.lz dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar.xz dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar.zst dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.zip |
cmd/geth, metrics: separate process metric collection, add disk
Diffstat (limited to 'metrics')
-rw-r--r-- | metrics/disk.go | 9 | ||||
-rw-r--r-- | metrics/disk_linux.go | 55 | ||||
-rw-r--r-- | metrics/disk_nop.go | 10 | ||||
-rw-r--r-- | metrics/metrics.go | 54 |
4 files changed, 128 insertions, 0 deletions
diff --git a/metrics/disk.go b/metrics/disk.go new file mode 100644 index 000000000..1b6c56773 --- /dev/null +++ b/metrics/disk.go @@ -0,0 +1,9 @@ +package metrics + +// DiskStats is the per process disk io stats. +type DiskStats struct { + ReadCount int64 // Number of read operations executed + ReadBytes int64 // Total number of bytes read + WriteCount int64 // Number of write operations executed + WriteBytes int64 // Total number of byte written +} diff --git a/metrics/disk_linux.go b/metrics/disk_linux.go new file mode 100644 index 000000000..82b204534 --- /dev/null +++ b/metrics/disk_linux.go @@ -0,0 +1,55 @@ +// Contains the Linux implementation of process disk IO counter retrieval. + +package metrics + +import ( + "bufio" + "fmt" + "io" + "os" + "strconv" + "strings" +) + +// ReadDiskStats retrieves the disk IO stats belonging to the current process. +func ReadDiskStats(stats *DiskStats) error { + // Open the process disk IO counter file + inf, err := os.Open(fmt.Sprintf("/proc/%d/io", os.Getpid())) + if err != nil { + return err + } + in := bufio.NewReader(inf) + + // Iterate over the IO counter, and extract what we need + for { + // Read the next line and split to key and value + line, err := in.ReadString('\n') + if err != nil { + if err == io.EOF { + return nil + } + return err + } + key, value := "", int64(0) + if parts := strings.Split(line, ":"); len(parts) != 2 { + continue + } else { + key = strings.TrimSpace(parts[0]) + if value, err = strconv.ParseInt(strings.TrimSpace(parts[1]), 10, 64); err != nil { + return err + } + } + // Update the counter based on the key + switch key { + case "syscr": + stats.ReadCount = value + case "syscw": + stats.WriteCount = value + case "rchar": + stats.ReadBytes = value + case "wchar": + stats.WriteBytes = value + } + } + return nil +} diff --git a/metrics/disk_nop.go b/metrics/disk_nop.go new file mode 100644 index 000000000..539ab8d1a --- /dev/null +++ b/metrics/disk_nop.go @@ -0,0 +1,10 @@ +// +build !linux + +package metrics + +import "errors" + +// ReadDiskStats retrieves the disk IO stats belonging to the current process. +func ReadDiskStats(stats *DiskStats) error { + return errors.New("Not implemented") +} diff --git a/metrics/metrics.go b/metrics/metrics.go new file mode 100644 index 000000000..cb0caaae4 --- /dev/null +++ b/metrics/metrics.go @@ -0,0 +1,54 @@ +// Package metrics provides general system and process level metrics collection. +package metrics + +import ( + "runtime" + "time" + + "github.com/ethereum/go-ethereum/logger" + "github.com/ethereum/go-ethereum/logger/glog" + "github.com/rcrowley/go-metrics" +) + +// CollectProcessMetrics periodically collects various metrics about the running +// process. +func CollectProcessMetrics(refresh time.Duration) { + // Create the various data collectors + memstats := make([]*runtime.MemStats, 2) + diskstats := make([]*DiskStats, 2) + for i := 0; i < len(memstats); i++ { + memstats[i] = new(runtime.MemStats) + diskstats[i] = new(DiskStats) + } + // Define the various metrics to collect + memAllocs := metrics.GetOrRegisterMeter("system/memory/allocs", metrics.DefaultRegistry) + memFrees := metrics.GetOrRegisterMeter("system/memory/frees", metrics.DefaultRegistry) + memInuse := metrics.GetOrRegisterMeter("system/memory/inuse", metrics.DefaultRegistry) + memPauses := metrics.GetOrRegisterMeter("system/memory/pauses", metrics.DefaultRegistry) + + var diskReads, diskReadBytes, diskWrites, diskWriteBytes metrics.Meter + if err := ReadDiskStats(diskstats[0]); err == nil { + diskReads = metrics.GetOrRegisterMeter("system/disk/readcount", metrics.DefaultRegistry) + diskReadBytes = metrics.GetOrRegisterMeter("system/disk/readdata", metrics.DefaultRegistry) + diskWrites = metrics.GetOrRegisterMeter("system/disk/writecount", metrics.DefaultRegistry) + diskWriteBytes = metrics.GetOrRegisterMeter("system/disk/writedata", metrics.DefaultRegistry) + } else { + glog.V(logger.Debug).Infof("failed to read disk metrics: %v", err) + } + // Iterate loading the different stats and updating the meters + for i := 1; ; i++ { + runtime.ReadMemStats(memstats[i%2]) + memAllocs.Mark(int64(memstats[i%2].Mallocs - memstats[(i-1)%2].Mallocs)) + memFrees.Mark(int64(memstats[i%2].Frees - memstats[(i-1)%2].Frees)) + memInuse.Mark(int64(memstats[i%2].Alloc - memstats[(i-1)%2].Alloc)) + memPauses.Mark(int64(memstats[i%2].PauseTotalNs - memstats[(i-1)%2].PauseTotalNs)) + + if ReadDiskStats(diskstats[i%2]) == nil { + diskReads.Mark(int64(diskstats[i%2].ReadCount - diskstats[(i-1)%2].ReadCount)) + diskReadBytes.Mark(int64(diskstats[i%2].ReadBytes - diskstats[(i-1)%2].ReadBytes)) + diskWrites.Mark(int64(diskstats[i%2].WriteCount - diskstats[(i-1)%2].WriteCount)) + diskWriteBytes.Mark(int64(diskstats[i%2].WriteBytes - diskstats[(i-1)%2].WriteBytes)) + } + time.Sleep(refresh) + } +} |