Skip to content

Commit

Permalink
Make sure MetricsHandler doesn't crash upon multiple concurrent writes
Browse files Browse the repository at this point in the history
With heavy traffic, concurrent usage of TrackLoginState() and similar
could result in `fatal error: concurrent map read and map write`,
crashing the whole process.
  • Loading branch information
tadzik authored and tulir committed Oct 28, 2021
1 parent 923f9c4 commit 13cb1e5
Showing 1 changed file with 17 additions and 6 deletions.
23 changes: 17 additions & 6 deletions metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"net/http"
"runtime/debug"
"sync"
"time"

"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -58,12 +59,15 @@ type MetricsHandler struct {
unencryptedGroupCount prometheus.Gauge
unencryptedPrivateCount prometheus.Gauge

connected prometheus.Gauge
connectedState map[whatsapp.JID]bool
loggedIn prometheus.Gauge
loggedInState map[whatsapp.JID]bool
syncLocked prometheus.Gauge
syncLockedState map[whatsapp.JID]bool
connected prometheus.Gauge
connectedState map[whatsapp.JID]bool
connectedStateLock sync.Mutex
loggedIn prometheus.Gauge
loggedInState map[whatsapp.JID]bool
loggedInStateLock sync.Mutex
syncLocked prometheus.Gauge
syncLockedState map[whatsapp.JID]bool
syncLockedStateLock sync.Mutex
bufferLength *prometheus.GaugeVec
}

Expand Down Expand Up @@ -180,6 +184,8 @@ func (mh *MetricsHandler) TrackLoginState(jid whatsapp.JID, loggedIn bool) {
if !mh.running {
return
}
mh.loggedInStateLock.Lock()
defer mh.loggedInStateLock.Unlock()
currentVal, ok := mh.loggedInState[jid]
if !ok || currentVal != loggedIn {
mh.loggedInState[jid] = loggedIn
Expand All @@ -195,6 +201,9 @@ func (mh *MetricsHandler) TrackConnectionState(jid whatsapp.JID, connected bool)
if !mh.running {
return
}

mh.connectedStateLock.Lock()
defer mh.connectedStateLock.Unlock()
currentVal, ok := mh.connectedState[jid]
if !ok || currentVal != connected {
mh.connectedState[jid] = connected
Expand All @@ -210,6 +219,8 @@ func (mh *MetricsHandler) TrackSyncLock(jid whatsapp.JID, locked bool) {
if !mh.running {
return
}
mh.syncLockedStateLock.Lock()
defer mh.syncLockedStateLock.Unlock()
currentVal, ok := mh.syncLockedState[jid]
if !ok || currentVal != locked {
mh.syncLockedState[jid] = locked
Expand Down

0 comments on commit 13cb1e5

Please sign in to comment.