Skip to content
Snippets Groups Projects
Unverified Commit 082f5574 authored by Levente Pap's avatar Levente Pap
Browse files

:chart_with_upwards_trend: Autopeering NeighborCount + Network Diameter metrics

parent 927c861b
No related branches found
No related tags found
No related merge requests found
...@@ -5,6 +5,7 @@ import ( ...@@ -5,6 +5,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/iotaledger/goshimmer/packages/graph"
"github.com/iotaledger/goshimmer/packages/shutdown" "github.com/iotaledger/goshimmer/packages/shutdown"
"github.com/iotaledger/goshimmer/plugins/analysis/packet" "github.com/iotaledger/goshimmer/plugins/analysis/packet"
analysisserver "github.com/iotaledger/goshimmer/plugins/analysis/server" analysisserver "github.com/iotaledger/goshimmer/plugins/analysis/server"
...@@ -21,9 +22,57 @@ var ( ...@@ -21,9 +22,57 @@ var (
nodes = make(map[string]time.Time) nodes = make(map[string]time.Time)
// maps nodeId to outgoing connections + latest arrival of heartbeat. // maps nodeId to outgoing connections + latest arrival of heartbeat.
links = make(map[string]map[string]time.Time) links = make(map[string]map[string]time.Time)
lock sync.Mutex lock sync.RWMutex
) )
type NeighborMetric struct {
Inbound uint
Outbound uint
}
// NumOfNeighbors returns a map of nodeId-s to their neighbor count.
func NumOfNeighbors() map[string]*NeighborMetric {
lock.RLock()
defer lock.RUnlock()
result := make(map[string]*NeighborMetric)
for nodeID, _ := range nodes {
// number of outgoing neighbors
if _, exist := result[nodeID]; !exist {
result[nodeID] = &NeighborMetric{Outbound: uint(len(links[nodeID]))}
} else {
result[nodeID].Outbound = uint(len(links[nodeID]))
}
// fill in incoming neighbors
for outNeighborID, _ := range links[nodeID] {
if _, exist := result[outNeighborID]; !exist {
result[outNeighborID] = &NeighborMetric{Inbound: 1}
} else {
result[outNeighborID].Inbound++
}
}
}
return result
}
// NetworkGraph returns a graph.
func NetworkGraph() *graph.Graph {
lock.RLock()
defer lock.RUnlock()
var nodeIDs []string
for id, _ := range nodes {
nodeIDs = append(nodeIDs, id)
}
g := graph.New(nodeIDs)
for src, trgMap := range links {
for dst, _ := range trgMap {
g.AddEdge(src, dst)
}
}
return g
}
// configures the event recording by attaching to the analysis server's events. // configures the event recording by attaching to the analysis server's events.
func configureEventsRecording() { func configureEventsRecording() {
analysisserver.Events.Heartbeat.Attach(events.NewClosure(func(hb *packet.Heartbeat) { analysisserver.Events.Heartbeat.Attach(events.NewClosure(func(hb *packet.Heartbeat) {
...@@ -156,8 +205,8 @@ func cleanUp(interval time.Duration) { ...@@ -156,8 +205,8 @@ func cleanUp(interval time.Duration) {
} }
func getEventsToReplay() (map[string]time.Time, map[string]map[string]time.Time) { func getEventsToReplay() (map[string]time.Time, map[string]map[string]time.Time) {
lock.Lock() lock.RLock()
defer lock.Unlock() defer lock.RUnlock()
copiedNodes := make(map[string]time.Time, len(nodes)) copiedNodes := make(map[string]time.Time, len(nodes))
for nodeID, lastHeartbeat := range nodes { for nodeID, lastHeartbeat := range nodes {
......
package metrics package metrics
import ( import (
"fmt"
"sync" "sync"
analysisdashboard "github.com/iotaledger/goshimmer/plugins/analysis/dashboard"
"github.com/iotaledger/goshimmer/plugins/analysis/packet" "github.com/iotaledger/goshimmer/plugins/analysis/packet"
"github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/events"
"github.com/mr-tron/base58/base58" "github.com/mr-tron/base58/base58"
"go.uber.org/atomic"
) )
type ClientInfo struct { type ClientInfo struct {
...@@ -19,6 +22,7 @@ type ClientInfo struct { ...@@ -19,6 +22,7 @@ type ClientInfo struct {
var ( var (
clientsMetrics = make(map[string]ClientInfo) clientsMetrics = make(map[string]ClientInfo)
clientsMetricsMutex sync.RWMutex clientsMetricsMutex sync.RWMutex
networkDiameter atomic.Int32
) )
var onMetricHeartbeatReceived = events.NewClosure(func(hb *packet.MetricHeartbeat) { var onMetricHeartbeatReceived = events.NewClosure(func(hb *packet.MetricHeartbeat) {
...@@ -45,3 +49,15 @@ func ClientsMetrics() map[string]ClientInfo { ...@@ -45,3 +49,15 @@ func ClientsMetrics() map[string]ClientInfo {
} }
return copy return copy
} }
func calculateNetworkDiameter() {
g := analysisdashboard.NetworkGraph()
diameter := g.Diameter()
networkDiameter.Store(int32(diameter))
fmt.Println("Calculated network diameter: ", diameter)
}
// NetworkDiameter returns the current network diameter.
func NetworkDiameter() int32 {
return networkDiameter.Load()
}
...@@ -66,6 +66,10 @@ func run(_ *node.Plugin) { ...@@ -66,6 +66,10 @@ func run(_ *node.Plugin) {
gossipCurrentTx.Store(uint64(g.BytesWritten)) gossipCurrentTx.Store(uint64(g.BytesWritten))
}, 1*time.Second, shutdownSignal) }, 1*time.Second, shutdownSignal)
} }
if config.Node.GetBool(CfgMetricsGlobal) {
timeutil.Ticker(calculateNetworkDiameter, 1 * time.Minute, shutdownSignal)
}
}, shutdown.PriorityMetrics); err != nil { }, shutdown.PriorityMetrics); err != nil {
log.Panicf("Failed to start as daemon: %s", err) log.Panicf("Failed to start as daemon: %s", err)
} }
......
...@@ -3,6 +3,7 @@ package prometheus ...@@ -3,6 +3,7 @@ package prometheus
import ( import (
"strconv" "strconv"
analysisdashboard "github.com/iotaledger/goshimmer/plugins/analysis/dashboard"
"github.com/iotaledger/goshimmer/plugins/metrics" "github.com/iotaledger/goshimmer/plugins/metrics"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
...@@ -10,6 +11,9 @@ import ( ...@@ -10,6 +11,9 @@ import (
var ( var (
clientsInfoCPU *prometheus.GaugeVec clientsInfoCPU *prometheus.GaugeVec
clientsInfoMemory *prometheus.GaugeVec clientsInfoMemory *prometheus.GaugeVec
clientsNeighborCount *prometheus.GaugeVec
networkDiameter prometheus.Gauge
) )
func registerClientsMetrics() { func registerClientsMetrics() {
...@@ -39,8 +43,26 @@ func registerClientsMetrics() { ...@@ -39,8 +43,26 @@ func registerClientsMetrics() {
}, },
) )
clientsNeighborCount = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "clients_neighbor_count",
Help: "Info about client's memory usage labeled with nodeID, OS, ARCH and number of cpu cores",
},
[]string{
"nodeID",
"direction",
},
)
networkDiameter = prometheus.NewGauge(prometheus.GaugeOpts{
Name: "clients_network_diameter",
Help: "Autopeering network diameter",
})
registry.MustRegister(clientsInfoCPU) registry.MustRegister(clientsInfoCPU)
registry.MustRegister(clientsInfoMemory) registry.MustRegister(clientsInfoMemory)
registry.MustRegister(clientsNeighborCount)
registry.MustRegister(networkDiameter)
addCollect(collectClientsInfo) addCollect(collectClientsInfo)
} }
...@@ -62,4 +84,10 @@ func collectClientsInfo() { ...@@ -62,4 +84,10 @@ func collectClientsInfo() {
strconv.Itoa(clientInfo.NumCPU), strconv.Itoa(clientInfo.NumCPU),
).Set(float64(clientInfo.MemoryUsage)) ).Set(float64(clientInfo.MemoryUsage))
} }
for nodeID, neighborCount := range analysisdashboard.NumOfNeighbors() {
clientsNeighborCount.WithLabelValues(nodeID, "in").Set(float64(neighborCount.Inbound))
clientsNeighborCount.WithLabelValues(nodeID, "out").Set(float64(neighborCount.Inbound))
}
networkDiameter.Set(float64(metrics.NetworkDiameter()))
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment