Add connection state to prometheus metrics

This commit is contained in:
Tulir Asokan 2020-09-27 22:30:08 +03:00
parent f88abe98bf
commit 3dae9b1999
4 changed files with 48 additions and 0 deletions

View file

@ -551,6 +551,7 @@ func (handler *CommandHandler) CommandDeleteConnection(ce *CommandEvent) {
}
ce.User.Conn.RemoveHandlers()
ce.User.Conn = nil
ce.User.bridge.Metrics.TrackConnectionState(ce.User.JID, false)
ce.Reply("Successfully disconnected. Use the `reconnect` command to reconnect.")
}
@ -572,6 +573,7 @@ func (handler *CommandHandler) CommandDisconnect(ce *CommandEvent) {
} else if len(sess.Wid) > 0 {
ce.User.SetSession(&sess)
}
ce.User.bridge.Metrics.TrackConnectionState(ce.User.JID, false)
ce.Reply("Successfully disconnected. Use the `reconnect` command to reconnect.")
}

View file

@ -30,6 +30,7 @@ import (
"maunium.net/go/mautrix/id"
"maunium.net/go/mautrix-whatsapp/database"
"maunium.net/go/mautrix-whatsapp/types"
)
type MetricsHandler struct {
@ -52,6 +53,9 @@ type MetricsHandler struct {
encryptedPrivateCount prometheus.Gauge
unencryptedGroupCount prometheus.Gauge
unencryptedPrivateCount prometheus.Gauge
connected *prometheus.GaugeVec
loggedIn *prometheus.GaugeVec
}
func NewMetricsHandler(address string, log log.Logger, db *database.Database) *MetricsHandler {
@ -94,6 +98,15 @@ func NewMetricsHandler(address string, log log.Logger, db *database.Database) *M
encryptedPrivateCount: portalCount.With(prometheus.Labels{"type": "private", "encrypted": "true"}),
unencryptedGroupCount: portalCount.With(prometheus.Labels{"type": "group", "encrypted": "false"}),
unencryptedPrivateCount: portalCount.With(prometheus.Labels{"type": "private", "encrypted": "false"}),
loggedIn: promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "bridge_logged_in",
Help: "Users logged into the bridge",
}, []string{"jid", "bridge_logged_in"}),
connected: promauto.NewGaugeVec(prometheus.GaugeOpts{
Name: "bridge_connected",
Help: "Users connected to WhatsApp",
}, []string{"jid", "bridge_connected"}),
}
}
@ -119,6 +132,32 @@ func (mh *MetricsHandler) TrackDisconnection(userID id.UserID) {
mh.disconnections.With(prometheus.Labels{"user_id": string(userID)}).Inc()
}
func (mh *MetricsHandler) TrackLoginState(jid types.WhatsAppID, loggedIn bool) {
if !mh.running {
return
}
var loggedInVal float64 = 0
if loggedIn {
loggedInVal = 1
}
metric := mh.loggedIn.MustCurryWith(prometheus.Labels{"jid": jid})
metric.With(prometheus.Labels{"bridge_logged_in": "true"}).Set(loggedInVal)
metric.With(prometheus.Labels{"bridge_logged_in": "false"}).Set(1 - loggedInVal)
}
func (mh *MetricsHandler) TrackConnectionState(jid types.WhatsAppID, connected bool) {
if !mh.running {
return
}
var connectedVal float64 = 0
if connected {
connectedVal = 1
}
metric := mh.connected.MustCurryWith(prometheus.Labels{"jid": jid})
metric.With(prometheus.Labels{"bridge_connected": "true"}).Set(connectedVal)
metric.With(prometheus.Labels{"bridge_connected": "false"}).Set(1 - connectedVal)
}
func (mh *MetricsHandler) updateStats() {
start := time.Now()
var puppetCount int

View file

@ -111,6 +111,7 @@ func (prov *ProvisioningAPI) DeleteConnection(w http.ResponseWriter, r *http.Req
}
user.Conn.RemoveHandlers()
user.Conn = nil
user.bridge.Metrics.TrackConnectionState(user.JID, false)
jsonResponse(w, http.StatusOK, Response{true, "Disconnected from WhatsApp and connection deleted"})
}
@ -140,6 +141,7 @@ func (prov *ProvisioningAPI) Disconnect(w http.ResponseWriter, r *http.Request)
} else if len(sess.Wid) > 0 {
user.SetSession(&sess)
}
user.bridge.Metrics.TrackConnectionState(user.JID, false)
jsonResponse(w, http.StatusOK, Response{true, "Disconnected from WhatsApp"})
}

View file

@ -109,6 +109,7 @@ func (user *User) removeFromJIDMap() {
user.bridge.usersLock.Lock()
delete(user.bridge.usersByJID, user.JID)
user.bridge.usersLock.Unlock()
user.bridge.Metrics.TrackLoginState(user.JID, false)
}
func (bridge *Bridge) GetAllUsers() []*User {
@ -407,6 +408,8 @@ func (cl ChatList) Swap(i, j int) {
}
func (user *User) PostLogin() {
user.bridge.Metrics.TrackConnectionState(user.JID, true)
user.bridge.Metrics.TrackLoginState(user.JID, true)
user.log.Debugln("Locking processing of incoming messages and starting post-login sync")
user.syncWait.Add(1)
user.syncStart <- struct{}{}
@ -689,6 +692,7 @@ func (user *User) HandleError(err error) {
if closed, ok := err.(*whatsapp.ErrConnectionClosed); ok {
user.bridge.Metrics.TrackDisconnection(user.MXID)
if closed.Code == 1000 && user.cleanDisconnection {
user.bridge.Metrics.TrackConnectionState(user.JID, false)
user.cleanDisconnection = false
user.log.Infoln("Clean disconnection by server")
return
@ -703,6 +707,7 @@ func (user *User) HandleError(err error) {
}
func (user *User) tryReconnect(msg string) {
user.bridge.Metrics.TrackConnectionState(user.JID, false)
if user.ConnectionErrors > user.bridge.Config.Bridge.MaxConnectionAttempts {
user.sendMarkdownBridgeAlert("%s. Use the `reconnect` command to reconnect.", msg)
return