浏览代码

cmd/geth, metrics: separate process metric collection, add disk

Péter Szilágyi 10 年之前
父节点
当前提交
2aeeb72fa5
共有 5 个文件被更改,包括 130 次插入22 次删除
  1. 2 22
      cmd/geth/main.go
  2. 9 0
      metrics/disk.go
  3. 55 0
      metrics/disk_linux.go
  4. 10 0
      metrics/disk_nop.go
  5. 54 0
      metrics/metrics.go

+ 2 - 22
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() {

+ 9 - 0
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
+}

+ 55 - 0
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
+}

+ 10 - 0
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")
+}

+ 54 - 0
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)
+	}
+}