diff --git a/p2p/protocols/accounting.go b/p2p/protocols/accounting.go index 06a1a58454..1266fbb116 100644 --- a/p2p/protocols/accounting.go +++ b/p2p/protocols/accounting.go @@ -16,11 +16,16 @@ package protocols -import "github.com/ethereum/go-ethereum/metrics" +import ( + "time" + + "github.com/ethereum/go-ethereum/metrics" +) //define some metrics var ( //NOTE: these metrics just define the interfaces and are currently *NOT persisted* over sessions + metricsInitialized bool //All metrics are cumulative //total amount of units credited @@ -152,6 +157,9 @@ func (ah *Accounting) Receive(peer *Peer, size uint32, msg interface{}) error { // * if the price is positive, local node has been credited; thus `err` implicitly signals the REMOTE has been dropped // * if the price is negative, local node has been debited, thus `err` implicitly signals LOCAL node "overdraft" func (ah *Accounting) doMetrics(price int64, size uint32, err error) { + if !metricsInitialized { + initMetrics() + } if price > 0 { mBalanceCredit.Inc(price) mBytesCredit.Inc(int64(size)) @@ -170,3 +178,8 @@ func (ah *Accounting) doMetrics(price int64, size uint32, err error) { } } } + +func initMetrics() { + NewMetricsStateStore(metrics.DefaultRegistry, 10*time.Second, "metrics.db") + metricsInitialized = true +} diff --git a/p2p/protocols/reporter.go b/p2p/protocols/reporter.go new file mode 100644 index 0000000000..11663a9bba --- /dev/null +++ b/p2p/protocols/reporter.go @@ -0,0 +1,71 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package protocols + +import ( + "time" + + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/swarm/state" + "github.com/rcrowley/go-metrics" +) + +type reporter struct { + reg metrics.Registry + interval time.Duration + stateStore *state.DBStore +} + +func NewMetricsStateStore(r metrics.Registry, d time.Duration, path string) { + stateStore, err := state.NewDBStore(path) + if err != nil { + return + } + + rep := &reporter{ + reg: r, + interval: d, + stateStore: stateStore, + } + + rep.run() +} + +func (r *reporter) run() { + intervalTicker := time.NewTicker(r.interval) + + for _ = range intervalTicker.C { + if err := r.send(); err != nil { + log.Error("unable to send metrics to InfluxDB. err=%v", err) + } + } +} + +func (r *reporter) send() error { + + var err error + + r.reg.Each(func(name string, i interface{}) { + switch metric := i.(type) { + case metrics.Counter: + ms := metric.Snapshot() + err = r.stateStore.Put(name, ms.Count()) + } + }) + + return err +} diff --git a/p2p/protocols/reporter_test.go b/p2p/protocols/reporter_test.go new file mode 100644 index 0000000000..c12455095c --- /dev/null +++ b/p2p/protocols/reporter_test.go @@ -0,0 +1,74 @@ +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package protocols + +import ( + "os" + "testing" + "time" + + "github.com/ethereum/go-ethereum/swarm/state" + "github.com/rcrowley/go-metrics" +) + +func TestReporter(t *testing.T) { + dir := os.TempDir() + defer os.RemoveAll(dir) + + stateStore, err := state.NewDBStore(dir + "/test.db") + if err != nil { + return + } + + rep := &reporter{ + reg: metrics.NewRegistry(), + interval: time.Millisecond, + stateStore: stateStore, + } + go rep.run() + time.Sleep(1 * time.Second) + mBalanceCredit.Inc(12) + mBytesCredit.Inc(34) + mMsgDebit.Inc(9) + + rep = nil + stateStore.Close() + stateStore, err = state.NewDBStore(dir + "/test.db") + if err != nil { + return + } + rep = &reporter{ + reg: metrics.NewRegistry(), + interval: time.Millisecond, + stateStore: stateStore, + } + go rep.run() + time.Sleep(1 * time.Second) + mBalanceCredit.Inc(11) + mBytesCredit.Inc(22) + mMsgDebit.Inc(7) + + if mBalanceCredit.Count() != 23 { + t.Fatalf("Expected counter to be %d, but is %d", 23, mBalanceCredit.Count()) + } + if mBytesCredit.Count() != 56 { + t.Fatalf("Expected counter to be %d, but is %d", 23, mBytesCredit.Count()) + } + if mMsgDebit.Count() != 16 { + t.Fatalf("Expected counter to be %d, but is %d", 23, mMsgDebit.Count()) + } +}