Skip to content
Snippets Groups Projects
Unverified Commit 51f52d51 authored by capossele's avatar capossele
Browse files

:chart_with_upwards_trend: Add FPC global metrics to prometheus

parent 1a6a6997
No related branches found
No related tags found
No related merge requests found
package metrics package metrics
import ( import (
"github.com/iotaledger/goshimmer/packages/vote"
"github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/events"
) )
...@@ -17,6 +18,7 @@ type CollectionEvents struct { ...@@ -17,6 +18,7 @@ type CollectionEvents struct {
MessageTips *events.Event MessageTips *events.Event
QueryReceived *events.Event QueryReceived *events.Event
QueryReplyError *events.Event QueryReplyError *events.Event
AnalysisFPCFinalized *events.Event
} }
// QueryReceivedEvent is used to pass information through a QueryReceived event. // QueryReceivedEvent is used to pass information through a QueryReceived event.
...@@ -30,6 +32,16 @@ type QueryReplyErrorEvent struct { ...@@ -30,6 +32,16 @@ type QueryReplyErrorEvent struct {
OpinionCount int OpinionCount int
} }
// AnalysisFPCFinalizedEvent is triggered by the analysis-server to
// notify a finalized FPC vote from one node.
type AnalysisFPCFinalizedEvent struct {
ConflictID string
NodeID string
Rounds int
Opinions []vote.Opinion
Status vote.Opinion
}
func queryReceivedEventCaller(handler interface{}, params ...interface{}) { func queryReceivedEventCaller(handler interface{}, params ...interface{}) {
handler.(func(ev *QueryReceivedEvent))(params[0].(*QueryReceivedEvent)) handler.(func(ev *QueryReceivedEvent))(params[0].(*QueryReceivedEvent))
} }
...@@ -49,3 +61,7 @@ func float64Caller(handler interface{}, params ...interface{}) { ...@@ -49,3 +61,7 @@ func float64Caller(handler interface{}, params ...interface{}) {
func boolCaller(handler interface{}, params ...interface{}) { func boolCaller(handler interface{}, params ...interface{}) {
handler.(func(bool))(params[0].(bool)) handler.(func(bool))(params[0].(bool))
} }
func fpcFinalizedEventCaller(handler interface{}, params ...interface{}) {
handler.(func(ev *AnalysisFPCFinalizedEvent))(params[0].(*AnalysisFPCFinalizedEvent))
}
...@@ -24,6 +24,7 @@ func new() *CollectionEvents { ...@@ -24,6 +24,7 @@ func new() *CollectionEvents {
MessageTips: events.NewEvent(uint64Caller), MessageTips: events.NewEvent(uint64Caller),
QueryReceived: events.NewEvent(queryReceivedEventCaller), QueryReceived: events.NewEvent(queryReceivedEventCaller),
QueryReplyError: events.NewEvent(queryReplyErrorEventCaller), QueryReplyError: events.NewEvent(queryReplyErrorEventCaller),
AnalysisFPCFinalized: events.NewEvent(fpcFinalizedEventCaller),
} }
} }
......
...@@ -51,6 +51,15 @@ func ConvertInt32Opinion(x int32) Opinion { ...@@ -51,6 +51,15 @@ func ConvertInt32Opinion(x int32) Opinion {
return Unknown return Unknown
} }
// ConvertOpinionsToInts32 converts the given slice of int32 to a slice of Opinion.
func ConvertInts32ToOpinions(opinions []int32) []Opinion {
result := make([]Opinion, len(opinions))
for i, opinion := range opinions {
result[i] = ConvertInt32Opinion(opinion)
}
return result
}
// ConvertOpinionToInt32 converts the given Opinion to an int32. // ConvertOpinionToInt32 converts the given Opinion to an int32.
func ConvertOpinionToInt32(x Opinion) int32 { func ConvertOpinionToInt32(x Opinion) int32 {
switch { switch {
......
...@@ -14,9 +14,9 @@ var ( ...@@ -14,9 +14,9 @@ var (
finalizedMutex sync.RWMutex finalizedMutex sync.RWMutex
) )
func onFinalized(id string, opinion vote.Opinion) { func onFinalized(ev *vote.OpinionEvent) {
finalizedMutex.Lock() finalizedMutex.Lock()
finalized[id] = opinion finalized[ev.ID] = ev.Opinion
finalizedMutex.Unlock() finalizedMutex.Unlock()
} }
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"time" "time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/iotaledger/goshimmer/packages/metrics"
"github.com/iotaledger/goshimmer/packages/shutdown" "github.com/iotaledger/goshimmer/packages/shutdown"
"github.com/iotaledger/goshimmer/packages/vote" "github.com/iotaledger/goshimmer/packages/vote"
"github.com/iotaledger/goshimmer/plugins/analysis/packet" "github.com/iotaledger/goshimmer/plugins/analysis/packet"
...@@ -120,9 +121,16 @@ func createFPCUpdate(hb *packet.FPCHeartbeat, recordEvent bool) *FPCUpdate { ...@@ -120,9 +121,16 @@ func createFPCUpdate(hb *packet.FPCHeartbeat, recordEvent bool) *FPCUpdate {
Status: conflictDetail.Status, Status: conflictDetail.Status,
} }
i++ i++
metrics.Events().AnalysisFPCFinalized.Trigger(&metrics.AnalysisFPCFinalizedEvent{
ConflictID: ID,
NodeID: conflictDetail.NodeID,
Rounds: conflictDetail.Rounds,
Opinions: vote.ConvertInts32ToOpinions(conflictDetail.Opinions),
Status: vote.ConvertInt32Opinion(conflictDetail.Status),
})
} }
//log.Info("Storing:\n", finalizedConflicts)
err := storeFPCRecords(finalizedConflicts, mongoDB()) err := storeFPCRecords(finalizedConflicts, mongoDB())
if err != nil { if err != nil {
log.Errorf("Error while writing on MongoDB: %s", err) log.Errorf("Error while writing on MongoDB: %s", err)
......
...@@ -3,19 +3,57 @@ package prometheus ...@@ -3,19 +3,57 @@ package prometheus
import ( import (
"strconv" "strconv"
metricspkg "github.com/iotaledger/goshimmer/packages/metrics"
"github.com/iotaledger/goshimmer/packages/vote"
analysisdashboard "github.com/iotaledger/goshimmer/plugins/analysis/dashboard" analysisdashboard "github.com/iotaledger/goshimmer/plugins/analysis/dashboard"
"github.com/iotaledger/goshimmer/plugins/metrics" "github.com/iotaledger/goshimmer/plugins/metrics"
"github.com/iotaledger/hive.go/events"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
) )
const (
// LIKE conflict outcome
LIKE = "LIKE"
// DISLIKE conflict outcome
DISLIKE = "DISLIKE"
)
var ( var (
clientsInfoCPU *prometheus.GaugeVec clientsInfoCPU *prometheus.GaugeVec
clientsInfoMemory *prometheus.GaugeVec clientsInfoMemory *prometheus.GaugeVec
clientsNeighborCount *prometheus.GaugeVec clientsNeighborCount *prometheus.GaugeVec
networkDiameter prometheus.Gauge networkDiameter prometheus.Gauge
conflictCount *prometheus.GaugeVec
conflictFinalizationRounds *prometheus.GaugeVec
conflictOutcome *prometheus.GaugeVec
conflictInitialOpinion *prometheus.GaugeVec
) )
var onFPCFinalized = events.NewClosure(func(ev *metricspkg.AnalysisFPCFinalizedEvent) {
conflictCount.WithLabelValues(
ev.NodeID,
).Add(1)
conflictFinalizationRounds.WithLabelValues(
ev.ConflictID,
ev.NodeID,
).Set(float64(ev.Rounds + 1))
conflictOutcome.WithLabelValues(
ev.ConflictID,
ev.NodeID,
opinionToString(ev.Status),
).Set(1)
conflictInitialOpinion.WithLabelValues(
ev.ConflictID,
ev.NodeID,
opinionToString(ev.Opinions[0]),
).Set(1)
})
func registerClientsMetrics() { func registerClientsMetrics() {
clientsInfoCPU = prometheus.NewGaugeVec( clientsInfoCPU = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
...@@ -46,7 +84,7 @@ func registerClientsMetrics() { ...@@ -46,7 +84,7 @@ func registerClientsMetrics() {
clientsNeighborCount = prometheus.NewGaugeVec( clientsNeighborCount = prometheus.NewGaugeVec(
prometheus.GaugeOpts{ prometheus.GaugeOpts{
Name: "clients_neighbor_count", Name: "clients_neighbor_count",
Help: "Info about client's memory usage labeled with nodeID, OS, ARCH and number of cpu cores", Help: "Info about client's neighbors count",
}, },
[]string{ []string{
"nodeID", "nodeID",
...@@ -59,12 +97,64 @@ func registerClientsMetrics() { ...@@ -59,12 +97,64 @@ func registerClientsMetrics() {
Help: "Autopeering network diameter", Help: "Autopeering network diameter",
}) })
conflictCount = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "conflict_count",
Help: "Conflicts count labeled with nodeID",
},
[]string{
"nodeID",
},
)
conflictFinalizationRounds = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "conflict_finalization_rounds",
Help: "Number of rounds to finalize a given conflict labeled with conflictID and nodeID",
},
[]string{
"conflictID",
"nodeID",
},
)
conflictInitialOpinion = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "conflict_initial_opinion",
Help: "Initial opinion of a given conflict labeled with conflictID, nodeID and opinion",
},
[]string{
"conflictID",
"nodeID",
"opinion",
},
)
conflictOutcome = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "conflict_outcome",
Help: "Outcome of a given conflict labeled with conflictID, nodeID and opinion",
},
[]string{
"conflictID",
"nodeID",
"opinion",
},
)
registry.MustRegister(clientsInfoCPU) registry.MustRegister(clientsInfoCPU)
registry.MustRegister(clientsInfoMemory) registry.MustRegister(clientsInfoMemory)
registry.MustRegister(clientsNeighborCount) registry.MustRegister(clientsNeighborCount)
registry.MustRegister(networkDiameter) registry.MustRegister(networkDiameter)
registry.MustRegister(conflictFinalizationRounds)
registry.MustRegister(conflictFinalizationRounds)
registry.MustRegister(conflictInitialOpinion)
registry.MustRegister(conflictOutcome)
addCollect(collectClientsInfo) addCollect(collectClientsInfo)
metricspkg.Events().AnalysisFPCFinalized.Attach(onFPCFinalized)
} }
func collectClientsInfo() { func collectClientsInfo() {
...@@ -89,5 +179,13 @@ func collectClientsInfo() { ...@@ -89,5 +179,13 @@ func collectClientsInfo() {
clientsNeighborCount.WithLabelValues(nodeID, "in").Set(float64(neighborCount.Inbound)) clientsNeighborCount.WithLabelValues(nodeID, "in").Set(float64(neighborCount.Inbound))
clientsNeighborCount.WithLabelValues(nodeID, "out").Set(float64(neighborCount.Inbound)) clientsNeighborCount.WithLabelValues(nodeID, "out").Set(float64(neighborCount.Inbound))
} }
networkDiameter.Set(float64(metrics.NetworkDiameter())) networkDiameter.Set(float64(metrics.NetworkDiameter()))
} }
func opinionToString(opinion vote.Opinion) string {
if opinion == vote.Like {
return LIKE
}
return DISLIKE
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment