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 = "LIKE" dislike = "DISLIKE" ) // These metrics store information collected via the analysis server. var ( // Process related metrics. nodesInfoCPU *prometheus.GaugeVec nodesInfoMemory *prometheus.GaugeVec // Autopeering related metrics. nodesNeighborCount *prometheus.GaugeVec networkDiameter prometheus.Gauge // FPC related metrics. 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.Outcome), ).Set(1) conflictInitialOpinion.WithLabelValues( ev.ConflictID, ev.NodeID, opinionToString(ev.Opinions[0]), ).Set(1) }) func registerClientsMetrics() { nodesInfoCPU = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "global_nodes_info_cpu", Help: "Info about node's cpu load labeled with nodeID, OS, ARCH and number of cpu cores", }, []string{ "nodeID", "OS", "ARCH", "NUM_CPU", }, ) nodesInfoMemory = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "global_nodes_info_mem", Help: "Info about node's memory usage labeled with nodeID, OS, ARCH and number of cpu cores", }, []string{ "nodeID", "OS", "ARCH", "NUM_CPU", }, ) nodesNeighborCount = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "global_nodes_neighbor_count", Help: "Info about node's neighbors count", }, []string{ "nodeID", "direction", }, ) networkDiameter = prometheus.NewGauge(prometheus.GaugeOpts{ Name: "global_network_diameter", Help: "Autopeering network diameter", }) conflictCount = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "global_conflict_count", Help: "Conflicts count labeled with nodeID", }, []string{ "nodeID", }, ) conflictFinalizationRounds = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "global_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: "global_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: "global_conflict_outcome", Help: "Outcome of a given conflict labeled with conflictID, nodeID and opinion", }, []string{ "conflictID", "nodeID", "opinion", }, ) registry.MustRegister(nodesInfoCPU) registry.MustRegister(nodesInfoMemory) registry.MustRegister(nodesNeighborCount) registry.MustRegister(networkDiameter) registry.MustRegister(conflictCount) registry.MustRegister(conflictFinalizationRounds) registry.MustRegister(conflictInitialOpinion) registry.MustRegister(conflictOutcome) metricspkg.Events().AnalysisFPCFinalized.Attach(onFPCFinalized) addCollect(collectNodesInfo) } func collectNodesInfo() { nodeInfoMap := metrics.NodesMetrics() for nodeID, nodeMetrics := range nodeInfoMap { nodesInfoCPU.WithLabelValues( nodeID, nodeMetrics.OS, nodeMetrics.Arch, strconv.Itoa(nodeMetrics.NumCPU), ).Set(nodeMetrics.CPUUsage) nodesInfoMemory.WithLabelValues( nodeID, nodeMetrics.OS, nodeMetrics.Arch, strconv.Itoa(nodeMetrics.NumCPU), ).Set(float64(nodeMetrics.MemoryUsage)) } for nodeID, neighborCount := range analysisdashboard.NumOfNeighbors() { nodesNeighborCount.WithLabelValues(nodeID, "in").Set(float64(neighborCount.Inbound)) nodesNeighborCount.WithLabelValues(nodeID, "out").Set(float64(neighborCount.Outbound)) } networkDiameter.Set(float64(metrics.NetworkDiameter())) } func opinionToString(opinion vote.Opinion) string { if opinion == vote.Like { return like } return dislike }