From 51f52d511fc592b337c69f71bacb08248da9148b Mon Sep 17 00:00:00 2001 From: capossele <angelocapossele@gmail.com> Date: Thu, 18 Jun 2020 23:47:30 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=88=20Add=20FPC=20global=20metrics=20t?= =?UTF-8?q?o=20prometheus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/metrics/events.go | 16 ++++ packages/metrics/metrics.go | 1 + packages/vote/opinion.go | 9 ++ plugins/analysis/client/fpc_heartbeato.go | 4 +- plugins/analysis/dashboard/fpc_livefeed.go | 10 ++- plugins/prometheus/clients_info.go | 100 ++++++++++++++++++++- 6 files changed, 136 insertions(+), 4 deletions(-) diff --git a/packages/metrics/events.go b/packages/metrics/events.go index 727c35f1..067cc2b3 100644 --- a/packages/metrics/events.go +++ b/packages/metrics/events.go @@ -1,6 +1,7 @@ package metrics import ( + "github.com/iotaledger/goshimmer/packages/vote" "github.com/iotaledger/hive.go/events" ) @@ -17,6 +18,7 @@ type CollectionEvents struct { MessageTips *events.Event QueryReceived *events.Event QueryReplyError *events.Event + AnalysisFPCFinalized *events.Event } // QueryReceivedEvent is used to pass information through a QueryReceived event. @@ -30,6 +32,16 @@ type QueryReplyErrorEvent struct { 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{}) { handler.(func(ev *QueryReceivedEvent))(params[0].(*QueryReceivedEvent)) } @@ -49,3 +61,7 @@ func float64Caller(handler interface{}, params ...interface{}) { func boolCaller(handler interface{}, params ...interface{}) { handler.(func(bool))(params[0].(bool)) } + +func fpcFinalizedEventCaller(handler interface{}, params ...interface{}) { + handler.(func(ev *AnalysisFPCFinalizedEvent))(params[0].(*AnalysisFPCFinalizedEvent)) +} diff --git a/packages/metrics/metrics.go b/packages/metrics/metrics.go index b6e40aea..01c67730 100644 --- a/packages/metrics/metrics.go +++ b/packages/metrics/metrics.go @@ -24,6 +24,7 @@ func new() *CollectionEvents { MessageTips: events.NewEvent(uint64Caller), QueryReceived: events.NewEvent(queryReceivedEventCaller), QueryReplyError: events.NewEvent(queryReplyErrorEventCaller), + AnalysisFPCFinalized: events.NewEvent(fpcFinalizedEventCaller), } } diff --git a/packages/vote/opinion.go b/packages/vote/opinion.go index 7ae14466..7a87c028 100644 --- a/packages/vote/opinion.go +++ b/packages/vote/opinion.go @@ -51,6 +51,15 @@ func ConvertInt32Opinion(x int32) Opinion { 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. func ConvertOpinionToInt32(x Opinion) int32 { switch { diff --git a/plugins/analysis/client/fpc_heartbeato.go b/plugins/analysis/client/fpc_heartbeato.go index 582a9fee..5a3f8e9f 100644 --- a/plugins/analysis/client/fpc_heartbeato.go +++ b/plugins/analysis/client/fpc_heartbeato.go @@ -14,9 +14,9 @@ var ( finalizedMutex sync.RWMutex ) -func onFinalized(id string, opinion vote.Opinion) { +func onFinalized(ev *vote.OpinionEvent) { finalizedMutex.Lock() - finalized[id] = opinion + finalized[ev.ID] = ev.Opinion finalizedMutex.Unlock() } diff --git a/plugins/analysis/dashboard/fpc_livefeed.go b/plugins/analysis/dashboard/fpc_livefeed.go index 42f04c2b..7397834c 100644 --- a/plugins/analysis/dashboard/fpc_livefeed.go +++ b/plugins/analysis/dashboard/fpc_livefeed.go @@ -4,6 +4,7 @@ import ( "time" "github.com/gorilla/websocket" + "github.com/iotaledger/goshimmer/packages/metrics" "github.com/iotaledger/goshimmer/packages/shutdown" "github.com/iotaledger/goshimmer/packages/vote" "github.com/iotaledger/goshimmer/plugins/analysis/packet" @@ -120,9 +121,16 @@ func createFPCUpdate(hb *packet.FPCHeartbeat, recordEvent bool) *FPCUpdate { Status: conflictDetail.Status, } 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()) if err != nil { log.Errorf("Error while writing on MongoDB: %s", err) diff --git a/plugins/prometheus/clients_info.go b/plugins/prometheus/clients_info.go index 49841f76..c4b27e75 100644 --- a/plugins/prometheus/clients_info.go +++ b/plugins/prometheus/clients_info.go @@ -3,19 +3,57 @@ package prometheus import ( "strconv" + metricspkg "github.com/iotaledger/goshimmer/packages/metrics" + "github.com/iotaledger/goshimmer/packages/vote" analysisdashboard "github.com/iotaledger/goshimmer/plugins/analysis/dashboard" "github.com/iotaledger/goshimmer/plugins/metrics" + "github.com/iotaledger/hive.go/events" "github.com/prometheus/client_golang/prometheus" ) +const ( + // LIKE conflict outcome + LIKE = "LIKE" + // DISLIKE conflict outcome + DISLIKE = "DISLIKE" +) + var ( clientsInfoCPU *prometheus.GaugeVec clientsInfoMemory *prometheus.GaugeVec clientsNeighborCount *prometheus.GaugeVec 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() { clientsInfoCPU = prometheus.NewGaugeVec( prometheus.GaugeOpts{ @@ -46,7 +84,7 @@ 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", + Help: "Info about client's neighbors count", }, []string{ "nodeID", @@ -59,12 +97,64 @@ func registerClientsMetrics() { 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(clientsInfoMemory) registry.MustRegister(clientsNeighborCount) registry.MustRegister(networkDiameter) + registry.MustRegister(conflictFinalizationRounds) + registry.MustRegister(conflictFinalizationRounds) + registry.MustRegister(conflictInitialOpinion) + registry.MustRegister(conflictOutcome) + addCollect(collectClientsInfo) + + metricspkg.Events().AnalysisFPCFinalized.Attach(onFPCFinalized) } func collectClientsInfo() { @@ -89,5 +179,13 @@ func collectClientsInfo() { clientsNeighborCount.WithLabelValues(nodeID, "in").Set(float64(neighborCount.Inbound)) clientsNeighborCount.WithLabelValues(nodeID, "out").Set(float64(neighborCount.Inbound)) } + networkDiameter.Set(float64(metrics.NetworkDiameter())) } + +func opinionToString(opinion vote.Opinion) string { + if opinion == vote.Like { + return LIKE + } + return DISLIKE +} -- GitLab