Skip to content
This repository was archived by the owner on Jan 24, 2025. It is now read-only.

Commit df684db

Browse files
committed
Fix prometheus init data race
1 parent 521e90a commit df684db

File tree

3 files changed

+71
-57
lines changed

3 files changed

+71
-57
lines changed

components/prometheus/collector/collection.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,41 @@
11
package collector
22

33
import (
4+
"github.com/iotaledger/hive.go/ds/shrinkingmap"
45
"github.com/iotaledger/hive.go/runtime/options"
56
)
67

78
type Collection struct {
89
CollectionName string
9-
metrics map[string]*Metric
10+
metrics *shrinkingmap.ShrinkingMap[string, *Metric]
1011
}
1112

1213
func NewCollection(name string, opts ...options.Option[Collection]) *Collection {
1314
return options.Apply(&Collection{
1415
CollectionName: name,
15-
metrics: make(map[string]*Metric),
16-
}, opts, func(c *Collection) {
17-
for _, m := range c.metrics {
18-
m.Namespace = c.CollectionName
19-
m.initPromMetric()
20-
}
16+
metrics: shrinkingmap.New[string, *Metric](),
17+
}, opts, func(collection *Collection) {
18+
collection.metrics.ForEach(func(_ string, metric *Metric) bool {
19+
metric.Namespace = collection.CollectionName
20+
metric.initPromMetric()
21+
22+
return true
23+
})
2124
})
2225
}
2326

2427
func (c *Collection) GetMetric(metricName string) *Metric {
25-
if metric, exists := c.metrics[metricName]; exists {
26-
return metric
28+
metric, exists := c.metrics.Get(metricName)
29+
if !exists {
30+
return nil
2731
}
2832

29-
return nil
33+
return metric
3034
}
3135

3236
func (c *Collection) addMetric(metric *Metric) {
3337
if metric != nil {
34-
c.metrics[metric.Name] = metric
38+
c.metrics.Set(metric.Name, metric)
3539
}
3640
}
3741

components/prometheus/collector/collector.go

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,49 @@ package collector
22

33
import (
44
"github.com/prometheus/client_golang/prometheus"
5+
6+
"github.com/iotaledger/hive.go/ds/shrinkingmap"
57
)
68

79
// Collector is responsible for creation and collection of metrics for the prometheus.
810
type Collector struct {
911
Registry *prometheus.Registry
10-
collections map[string]*Collection
12+
collections *shrinkingmap.ShrinkingMap[string, *Collection]
1113
}
1214

1315
// New creates an instance of Manager and creates a new prometheus registry for the protocol metrics collection.
1416
func New() *Collector {
1517
return &Collector{
1618
Registry: prometheus.NewRegistry(),
17-
collections: make(map[string]*Collection),
19+
collections: shrinkingmap.New[string, *Collection](),
1820
}
1921
}
2022

21-
func (c *Collector) RegisterCollection(coll *Collection) {
22-
c.collections[coll.CollectionName] = coll
23-
for _, m := range coll.metrics {
24-
c.Registry.MustRegister(m.promMetric)
25-
if m.initValueFunc != nil {
26-
metricValue, labelValues := m.initValueFunc()
27-
m.update(metricValue, labelValues...)
23+
func (c *Collector) RegisterCollection(collection *Collection) {
24+
c.collections.Set(collection.CollectionName, collection)
25+
collection.metrics.ForEach(func(_ string, metric *Metric) bool {
26+
c.Registry.MustRegister(metric.promMetric)
27+
if metric.initValueFunc != nil {
28+
metricValue, labelValues := metric.initValueFunc()
29+
metric.update(metricValue, labelValues...)
2830
}
29-
if m.initFunc != nil {
30-
m.initFunc()
31+
if metric.initFunc != nil {
32+
metric.initFunc()
3133
}
32-
}
34+
35+
return true
36+
})
3337
}
3438

3539
// Collect collects all metrics from the registered collections.
3640
func (c *Collector) Collect() {
37-
for _, collection := range c.collections {
38-
for _, metric := range collection.metrics {
41+
c.collections.ForEach(func(_ string, collection *Collection) bool {
42+
collection.metrics.ForEach(func(_ string, metric *Metric) bool {
3943
metric.collect()
40-
}
41-
}
44+
return true
45+
})
46+
return true
47+
})
4248
}
4349

4450
// Update updates the value of the existing metric defined by the subsystem and metricName.
@@ -78,11 +84,13 @@ func (c *Collector) ResetMetric(namespace string, metricName string) {
7884
}
7985

8086
func (c *Collector) Shutdown() {
81-
for _, collection := range c.collections {
82-
for _, metric := range collection.metrics {
87+
c.collections.ForEach(func(_ string, collection *Collection) bool {
88+
collection.metrics.ForEach(func(_ string, metric *Metric) bool {
8389
metric.shutdown()
84-
}
85-
}
90+
return true
91+
})
92+
return true
93+
})
8694
}
8795

8896
func (c *Collector) getMetric(subsystem string, metricName string) *Metric {
@@ -95,9 +103,10 @@ func (c *Collector) getMetric(subsystem string, metricName string) *Metric {
95103
}
96104

97105
func (c *Collector) getCollection(subsystem string) *Collection {
98-
if collection, exists := c.collections[subsystem]; exists {
99-
return collection
106+
collection, exists := c.collections.Get(subsystem)
107+
if !exists {
108+
return nil
100109
}
101110

102-
return nil
111+
return collection
103112
}

components/prometheus/component.go

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ import (
2929

3030
func init() {
3131
Component = &app.Component{
32-
Name: "Prometheus",
33-
DepsFunc: func(cDeps dependencies) { deps = cDeps },
34-
Params: params,
35-
Provide: provide,
36-
Run: run,
32+
Name: "Prometheus",
33+
DepsFunc: func(cDeps dependencies) { deps = cDeps },
34+
Params: params,
35+
Provide: provide,
36+
Configure: configure,
37+
Run: run,
3738
IsEnabled: func(_ *dig.Container) bool {
3839
return ParamsMetrics.Enabled
3940
},
@@ -56,17 +57,32 @@ type dependencies struct {
5657
Collector *collector.Collector
5758
}
5859

59-
func run() error {
60-
Component.LogInfo("Starting Prometheus exporter ...")
60+
func provide(c *dig.Container) error {
61+
return c.Provide(collector.New)
62+
}
6163

64+
func configure() error {
6265
if ParamsMetrics.GoMetrics {
6366
deps.Collector.Registry.MustRegister(collectors.NewGoCollector())
6467
}
6568
if ParamsMetrics.ProcessMetrics {
6669
deps.Collector.Registry.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}))
6770
}
6871

69-
registerMetrics()
72+
deps.Collector.RegisterCollection(TangleMetrics)
73+
deps.Collector.RegisterCollection(ConflictMetrics)
74+
deps.Collector.RegisterCollection(InfoMetrics)
75+
deps.Collector.RegisterCollection(DBMetrics)
76+
deps.Collector.RegisterCollection(CommitmentsMetrics)
77+
deps.Collector.RegisterCollection(SlotMetrics)
78+
deps.Collector.RegisterCollection(AccountMetrics)
79+
deps.Collector.RegisterCollection(SchedulerMetrics)
80+
81+
return nil
82+
}
83+
84+
func run() error {
85+
Component.LogInfo("Starting Prometheus exporter ...")
7086

7187
return Component.Daemon().BackgroundWorker("Prometheus exporter", func(ctx context.Context) {
7288
Component.LogInfo("Starting Prometheus exporter ... done")
@@ -118,18 +134,3 @@ func run() error {
118134
Component.LogInfo("Stopping Prometheus exporter ... done")
119135
}, daemon.PriorityMetrics)
120136
}
121-
122-
func provide(c *dig.Container) error {
123-
return c.Provide(collector.New)
124-
}
125-
126-
func registerMetrics() {
127-
deps.Collector.RegisterCollection(TangleMetrics)
128-
deps.Collector.RegisterCollection(ConflictMetrics)
129-
deps.Collector.RegisterCollection(InfoMetrics)
130-
deps.Collector.RegisterCollection(DBMetrics)
131-
deps.Collector.RegisterCollection(CommitmentsMetrics)
132-
deps.Collector.RegisterCollection(SlotMetrics)
133-
deps.Collector.RegisterCollection(AccountMetrics)
134-
deps.Collector.RegisterCollection(SchedulerMetrics)
135-
}

0 commit comments

Comments
 (0)