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

Commit b390435

Browse files
authored
Merge pull request #966 from iotaledger/fix/prometheus-init-data-race
Fix prometheus init data race
2 parents 521e90a + 0fd1f01 commit b390435

File tree

6 files changed

+77
-60
lines changed

6 files changed

+77
-60
lines changed

components/prometheus/collector/collection.go

+15-11
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

+34-23
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,50 @@ 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+
47+
return true
48+
})
4249
}
4350

4451
// Update updates the value of the existing metric defined by the subsystem and metricName.
@@ -78,11 +85,14 @@ func (c *Collector) ResetMetric(namespace string, metricName string) {
7885
}
7986

8087
func (c *Collector) Shutdown() {
81-
for _, collection := range c.collections {
82-
for _, metric := range collection.metrics {
88+
c.collections.ForEach(func(_ string, collection *Collection) bool {
89+
collection.metrics.ForEach(func(_ string, metric *Metric) bool {
8390
metric.shutdown()
84-
}
85-
}
91+
return true
92+
})
93+
94+
return true
95+
})
8696
}
8797

8898
func (c *Collector) getMetric(subsystem string, metricName string) *Metric {
@@ -95,9 +105,10 @@ func (c *Collector) getMetric(subsystem string, metricName string) *Metric {
95105
}
96106

97107
func (c *Collector) getCollection(subsystem string) *Collection {
98-
if collection, exists := c.collections[subsystem]; exists {
99-
return collection
108+
collection, exists := c.collections.Get(subsystem)
109+
if !exists {
110+
return nil
100111
}
101112

102-
return nil
113+
return collection
103114
}

components/prometheus/component.go

+24-23
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-
}

pkg/toolset/benchmark.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func benchmarkIO(args []string) error {
6969
ts := time.Now()
7070

7171
lastStatusTime := time.Now()
72-
for i := 0; i < objectCnt; i++ {
72+
for i := range objectCnt {
7373
// one read operation and one write operation per cycle
7474
batchWriter.Enqueue(newBenchmarkObject(store, writeDoneWaitGroup, iotago_tpkg.RandBytes(32), iotago_tpkg.RandBytes(size)))
7575

@@ -154,7 +154,7 @@ func benchmarkCPU(args []string) error {
154154
}
155155
}()
156156

157-
for i := 0; i < numWorkers; i++ {
157+
for range numWorkers {
158158
wg.Add(1)
159159
go func() {
160160
defer wg.Done()

pkg/toolset/pwd_hash.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//nolint:err113
12
package toolset
23

34
import (
@@ -128,7 +129,6 @@ func hashPasswordAndSalt(args []string) error {
128129
}
129130

130131
if *outputJSONFlag {
131-
132132
result := struct {
133133
Password string `json:"passwordHash"`
134134
Salt string `json:"passwordSalt"`

pkg/toolset/toolset.go

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const (
5555
)
5656

5757
const (
58+
//nolint:gosec // there is no hardcoded password
5859
passwordEnvKey = "IOTA_CORE_TOOL_PASSWORD"
5960

6061
// printStatusInterval is the interval for printing status messages.

0 commit comments

Comments
 (0)