Skip to content

Commit 9c3faba

Browse files
committed
Implement metrics.
1 parent 6a2cbb8 commit 9c3faba

File tree

5 files changed

+128
-16
lines changed

5 files changed

+128
-16
lines changed

go.mod

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,32 @@
11
module github.com/qubic/go-qubic-nodes
22

3-
go 1.22
3+
go 1.23.0
44

55
require (
66
github.com/ardanlabs/conf v1.5.0
7-
github.com/google/go-cmp v0.6.0
7+
github.com/google/go-cmp v0.7.0
88
github.com/pkg/errors v0.9.1
9+
github.com/prometheus/client_golang v1.23.2
910
github.com/qubic/go-node-connector v0.7.0
10-
github.com/stretchr/testify v1.2.2
11+
github.com/stretchr/testify v1.11.1
1112
)
1213

1314
require (
15+
github.com/beorn7/perks v1.0.1 // indirect
16+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
1417
github.com/cloudflare/circl v1.3.7 // indirect
1518
github.com/davecgh/go-spew v1.1.1 // indirect
1619
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
20+
github.com/kr/text v0.2.0 // indirect
21+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
1722
github.com/pmezard/go-difflib v1.0.0 // indirect
23+
github.com/prometheus/client_model v0.6.2 // indirect
24+
github.com/prometheus/common v0.66.1 // indirect
25+
github.com/prometheus/procfs v0.16.1 // indirect
1826
github.com/silenceper/pool v1.0.0 // indirect
1927
github.com/sirupsen/logrus v1.4.2 // indirect
20-
golang.org/x/sys v0.15.0 // indirect
28+
go.yaml.in/yaml/v2 v2.4.2 // indirect
29+
golang.org/x/sys v0.35.0 // indirect
30+
google.golang.org/protobuf v1.36.8 // indirect
31+
gopkg.in/yaml.v3 v3.0.1 // indirect
2132
)

go.sum

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,62 @@
11
github.com/ardanlabs/conf v1.5.0 h1:5TwP6Wu9Xi07eLFEpiCUF3oQXh9UzHMDVnD3u/I5d5c=
22
github.com/ardanlabs/conf v1.5.0/go.mod h1:ILsMo9dMqYzCxDjDXTiwMI0IgxOJd0MOiucbQY2wlJw=
3+
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
4+
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
5+
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
6+
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
37
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
48
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
59
github.com/cloudflare/fourq v0.0.0-20170427000316-8ada258cf9c8 h1:748sGeXXbplK0UVPDLbhh53hejCnvv/u6jn2RPBfyI8=
610
github.com/cloudflare/fourq v0.0.0-20170427000316-8ada258cf9c8/go.mod h1:13nQglQo5cpucnNY80duyW/6HK+WQ9+dHZ70UzAy6Jw=
11+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
712
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
813
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
914
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
10-
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
11-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
15+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
16+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
1217
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
1318
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
19+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
20+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
21+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
22+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
23+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
24+
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
1425
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
1526
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
1627
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1728
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
29+
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
30+
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
31+
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
32+
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
33+
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
34+
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
35+
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
36+
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
1837
github.com/qubic/go-node-connector v0.7.0 h1:PKMoPD8FavnvBXOrV8bUDYHMd85InYKX/ssQ5ccrdok=
1938
github.com/qubic/go-node-connector v0.7.0/go.mod h1:3Q9xCv5c01AqxVIx1aijMd8Pt3KJyQQiDfc4sG0UnXI=
39+
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
40+
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
2041
github.com/silenceper/pool v1.0.0 h1:JTCaA+U6hJAA0P8nCx+JfsRCHMwLTfatsm5QXelffmU=
2142
github.com/silenceper/pool v1.0.0/go.mod h1:3DN13bqAbq86Lmzf6iUXWEPIWFPOSYVfaoceFvilKKI=
2243
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
2344
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
2445
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
25-
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
2646
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
47+
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
48+
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
49+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
50+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
51+
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
52+
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
2753
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
28-
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
29-
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
54+
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
55+
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
56+
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
57+
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
58+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
59+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
60+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
61+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
62+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

main.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ package main
22

33
import (
44
"fmt"
5-
"github.com/ardanlabs/conf"
6-
"github.com/pkg/errors"
7-
"github.com/qubic/go-qubic-nodes/node"
8-
"github.com/qubic/go-qubic-nodes/web"
95
"log"
106
"net/http"
117
"os"
128
"time"
9+
10+
"github.com/ardanlabs/conf"
11+
"github.com/pkg/errors"
12+
"github.com/prometheus/client_golang/prometheus"
13+
"github.com/prometheus/client_golang/prometheus/collectors"
14+
"github.com/prometheus/client_golang/prometheus/promhttp"
15+
"github.com/qubic/go-qubic-nodes/metrics"
16+
"github.com/qubic/go-qubic-nodes/node"
17+
"github.com/qubic/go-qubic-nodes/web"
1318
)
1419

1520
const prefix = "QUBIC_NODES"
@@ -28,6 +33,9 @@ type Configuration struct {
2833
Service struct {
2934
TickerUpdateInterval time.Duration `conf:"default:15s"`
3035
}
36+
Metrics struct {
37+
Namespace string `conf:"default:qubic_nodes"`
38+
}
3139
}
3240

3341
func main() {
@@ -65,9 +73,13 @@ func run() error {
6573
}
6674
log.Printf("main: Config :\n%v\n", out)
6775

76+
prometheusRegistry := prometheus.NewRegistry()
77+
prometheusRegistry.MustRegister(collectors.NewGoCollector())
78+
m := metrics.NewNodesServiceMetrics(prometheusRegistry, config.Metrics.Namespace)
79+
6880
peerDiscovery := createPeerDiscoveryStrategy(config)
6981
peerManager := node.NewPeerManager(config.Qubic.PeerList, peerDiscovery, config.Qubic.PeerPort, config.Qubic.ExchangeTimeout)
70-
container, err := node.NewNodeContainer(peerManager, config.Qubic.MaxTickErrorThreshold, config.Qubic.ReliableTickRange)
82+
container, err := node.NewNodeContainer(peerManager, config.Qubic.MaxTickErrorThreshold, config.Qubic.ReliableTickRange, m)
7183
if err != nil {
7284
log.Printf("Error: %v\n", err)
7385
}
@@ -97,7 +109,7 @@ func run() error {
97109
router.HandleFunc("GET /status", handler.HandleStatus)
98110
router.HandleFunc("GET /max-tick", handler.HandleMaxTick)
99111
router.HandleFunc("POST /reliable-nodes", handler.GetReliableNodesWithMinimumTick)
100-
112+
router.Handle("/metrics", promhttp.HandlerFor(prometheusRegistry, promhttp.HandlerOpts{EnableOpenMetrics: true}))
101113
return http.ListenAndServe(":8080", router)
102114

103115
}

metrics/metrics.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package metrics
2+
3+
import (
4+
"github.com/prometheus/client_golang/prometheus"
5+
"github.com/prometheus/client_golang/prometheus/promauto"
6+
)
7+
8+
type NodesServiceMetrics struct {
9+
prometheusRegistry *prometheus.Registry
10+
11+
configuredNodeCount prometheus.Gauge
12+
reliableNodeCount prometheus.Gauge
13+
networkTick prometheus.Gauge
14+
}
15+
16+
func NewNodesServiceMetrics(registry *prometheus.Registry, namespace string) *NodesServiceMetrics {
17+
factory := promauto.With(registry)
18+
metrics := NodesServiceMetrics{
19+
prometheusRegistry: registry,
20+
21+
configuredNodeCount: factory.NewGauge(prometheus.GaugeOpts{
22+
Name: namespace + "_configured_node_count",
23+
Help: "The number of configured nodes.",
24+
}),
25+
reliableNodeCount: factory.NewGauge(prometheus.GaugeOpts{
26+
Name: namespace + "_reliable_node_count",
27+
Help: "The number of currently reliable nodes.",
28+
}),
29+
networkTick: factory.NewGauge(prometheus.GaugeOpts{
30+
Name: namespace + "_network_tick",
31+
Help: "The current network tick.",
32+
}),
33+
}
34+
return &metrics
35+
}
36+
37+
func (m *NodesServiceMetrics) SetConfiguredNodeCount(nodeCount int) {
38+
m.configuredNodeCount.Set(float64(nodeCount))
39+
}
40+
41+
func (m *NodesServiceMetrics) SetReliableNodeCount(nodeCount int) {
42+
m.reliableNodeCount.Set(float64(nodeCount))
43+
}
44+
45+
func (m *NodesServiceMetrics) SetNetworkTick(tickNumber uint32) {
46+
m.networkTick.Set(float64(tickNumber))
47+
}

node/container.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package node
22

33
import (
44
"cmp"
5+
56
"github.com/pkg/errors"
7+
"github.com/qubic/go-qubic-nodes/metrics"
8+
69
"log"
710
"slices"
811
"sync"
@@ -19,6 +22,7 @@ type Container struct {
1922
ReliableNodes []*Node
2023
MostReliableNode *Node
2124
mutexLock sync.RWMutex
25+
metrics *metrics.NodesServiceMetrics
2226
}
2327

2428
type ContainerResponse struct {
@@ -28,12 +32,14 @@ type ContainerResponse struct {
2832
MostReliableNode *Node
2933
}
3034

31-
func NewNodeContainer(peerManager *PeerManager, tickErrorThreshold, reliableTickRange uint32) (*Container, error) {
35+
func NewNodeContainer(peerManager *PeerManager, tickErrorThreshold, reliableTickRange uint32, m *metrics.NodesServiceMetrics) (*Container, error) {
3236
container := Container{
3337
PeerManager: peerManager,
3438
TickErrorThreshold: tickErrorThreshold,
3539
ReliableTickRange: reliableTickRange,
40+
metrics: m,
3641
}
42+
container.metrics.SetConfiguredNodeCount(len(peerManager.configuredPeers))
3743
err := container.Update()
3844
if err != nil {
3945
return nil, errors.Wrap(err, "updating container after initialization")
@@ -54,6 +60,9 @@ func (c *Container) Update() error {
5460

5561
c.Set(onlineNodes, maxTick, time.Now().UTC().Unix(), reliableNodes, mostReliableNode)
5662

63+
c.metrics.SetReliableNodeCount(len(reliableNodes))
64+
c.metrics.SetNetworkTick(maxTick)
65+
5766
log.Printf("Node count: %d\n", c.GetNumberOfKnownNodes())
5867
log.Printf("Max tick: %d\n", maxTick)
5968
log.Printf("Reliable nodes: %d / %d online\n", len(reliableNodes), len(onlineNodes))

0 commit comments

Comments
 (0)