aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2015-06-27 23:12:58 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2015-06-30 06:51:02 +0800
commit2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26 (patch)
tree8b3a9064a185a0b80f5eeea4a3fb40f5d5995585
parent7c4ed8055cc036214279e3ebded74c58d6808d05 (diff)
downloaddexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar.gz
dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.tar.zst
dexon-2aeeb72fa5c4f90d0ab072a361a678c3cdee8e26.zip
cmd/geth, metrics: separate process metric collection, add disk
-rw-r--r--cmd/geth/main.go24
-rw-r--r--metrics/disk.go9
-rw-r--r--metrics/disk_linux.go55
-rw-r--r--metrics/disk_nop.go10
-rw-r--r--metrics/metrics.go54
5 files changed, 130 insertions, 22 deletions
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index fcf7f27f0..6a52159ea 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -39,11 +39,11 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
+ "github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
- "github.com/rcrowley/go-metrics"
)
const (
@@ -288,27 +288,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
return nil
}
// Start system runtime metrics collection
- go func() {
- allocs := metrics.GetOrRegisterMeter("system/memory/allocs", metrics.DefaultRegistry)
- frees := metrics.GetOrRegisterMeter("system/memory/frees", metrics.DefaultRegistry)
- inuse := metrics.GetOrRegisterMeter("system/memory/inuse", metrics.DefaultRegistry)
- pauses := metrics.GetOrRegisterMeter("system/memory/pauses", metrics.DefaultRegistry)
-
- stats := make([]*runtime.MemStats, 2)
- for i := 0; i < len(stats); i++ {
- stats[i] = new(runtime.MemStats)
- }
- for i := 1; ; i++ {
- runtime.ReadMemStats(stats[i%2])
-
- allocs.Mark(int64(stats[i%2].Mallocs - stats[(i-1)%2].Mallocs))
- frees.Mark(int64(stats[i%2].Frees - stats[(i-1)%2].Frees))
- inuse.Mark(int64(stats[i%2].Alloc - stats[(i-1)%2].Alloc))
- pauses.Mark(int64(stats[i%2].PauseTotalNs - stats[(i-1)%2].PauseTotalNs))
-
- time.Sleep(3 * time.Second)
- }
- }()
+ go metrics.CollectProcessMetrics(3 * time.Second)
}
func main() {
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)
+ }
+}