Skip to content

OCPBUGS-5523: Catalog, fatal error: concurrent map read and map write #2913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 36 additions & 9 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package metrics

import (
"sync"
"time"

"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -199,12 +200,37 @@ var (
},
)

// subscriptionSyncCounters keeps a record of the Prometheus counters emitted by
// Subscription objects. The key of a record is the Subscription name, while the value
// is struct containing label values used in the counter
subscriptionSyncCounters = make(map[string]subscriptionSyncLabelValues)
subscriptionSyncCounters = newSubscriptionSyncCounter()
)

// subscriptionSyncCounter keeps a record of the Prometheus counters emitted by
// Subscription objects. The key of a record is the Subscription name, while the value
// is struct containing label values used in the counter. Read and Write access are
// protected by mutex.
type subscriptionSyncCounter struct {
counters map[string]subscriptionSyncLabelValues
countersLock sync.RWMutex
}

func newSubscriptionSyncCounter() subscriptionSyncCounter {
return subscriptionSyncCounter{
counters: make(map[string]subscriptionSyncLabelValues),
}
}

func (s *subscriptionSyncCounter) setValues(key string, val subscriptionSyncLabelValues) {
s.countersLock.Lock()
defer s.countersLock.Unlock()
s.counters[key] = val
}

func (s *subscriptionSyncCounter) readValues(key string) (subscriptionSyncLabelValues, bool) {
s.countersLock.RLock()
defer s.countersLock.RUnlock()
val, ok := s.counters[key]
return val, ok
}

type subscriptionSyncLabelValues struct {
installedCSV string
pkg string
Expand Down Expand Up @@ -280,14 +306,15 @@ func EmitSubMetric(sub *operatorsv1alpha1.Subscription) {
if sub.Spec == nil {
return
}

SubscriptionSyncCount.WithLabelValues(sub.GetName(), sub.Status.InstalledCSV, sub.Spec.Channel, sub.Spec.Package, string(sub.Spec.InstallPlanApproval)).Inc()
if _, present := subscriptionSyncCounters[sub.GetName()]; !present {
subscriptionSyncCounters[sub.GetName()] = subscriptionSyncLabelValues{
if _, present := subscriptionSyncCounters.readValues(sub.GetName()); !present {
subscriptionSyncCounters.setValues(sub.GetName(), subscriptionSyncLabelValues{
installedCSV: sub.Status.InstalledCSV,
pkg: sub.Spec.Package,
channel: sub.Spec.Channel,
approvalStrategy: string(sub.Spec.InstallPlanApproval),
}
})
}
}

Expand All @@ -302,7 +329,7 @@ func UpdateSubsSyncCounterStorage(sub *operatorsv1alpha1.Subscription) {
if sub.Spec == nil {
return
}
counterValues := subscriptionSyncCounters[sub.GetName()]
counterValues, _ := subscriptionSyncCounters.readValues(sub.GetName())
approvalStrategy := string(sub.Spec.InstallPlanApproval)

if sub.Spec.Channel != counterValues.channel ||
Expand All @@ -317,7 +344,7 @@ func UpdateSubsSyncCounterStorage(sub *operatorsv1alpha1.Subscription) {
counterValues.channel = sub.Spec.Channel
counterValues.approvalStrategy = approvalStrategy

subscriptionSyncCounters[sub.GetName()] = counterValues
subscriptionSyncCounters.setValues(sub.GetName(), counterValues)
}
}

Expand Down