فهرست منبع

Add some simple metrics for retry receipts

Tulir Asokan 3 سال پیش
والد
کامیت
7e6c645f19
4فایلهای تغییر یافته به همراه35 افزوده شده و 7 حذف شده
  1. 1 1
      go.mod
  2. 2 2
      go.sum
  3. 16 0
      metrics.go
  4. 16 4
      user.go

+ 1 - 1
go.mod

@@ -9,7 +9,7 @@ require (
 	github.com/mattn/go-sqlite3 v1.14.10
 	github.com/prometheus/client_golang v1.11.0
 	github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
-	go.mau.fi/whatsmeow v0.0.0-20220124150706-afc33ee3c21a
+	go.mau.fi/whatsmeow v0.0.0-20220128124639-e64fb976bf15
 	golang.org/x/image v0.0.0-20211028202545-6944b10bf410
 	google.golang.org/protobuf v1.27.1
 	gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b

+ 2 - 2
go.sum

@@ -140,8 +140,8 @@ github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
 github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
 go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910 h1:9FFhG0OmkuMau5UEaTgiUQ+7cSbtbOQ7hiWKdN8OI3I=
 go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910/go.mod h1:AufGrvVh+00Nc07Jm4hTquh7yleZyn20tKJI2wCPAKg=
-go.mau.fi/whatsmeow v0.0.0-20220124150706-afc33ee3c21a h1:e8aExGixi/O+kveh6S3wgydk9ogU5+gx0NqOmqWMapM=
-go.mau.fi/whatsmeow v0.0.0-20220124150706-afc33ee3c21a/go.mod h1:8jUjOAi3xtGubxcZgG8uSHpAdyQXBRbWAfxkctX/4y4=
+go.mau.fi/whatsmeow v0.0.0-20220128124639-e64fb976bf15 h1:BmdZu7K6IHsb+sPxvzkEjAINKxTMNeSiJRe1cvfesIY=
+go.mau.fi/whatsmeow v0.0.0-20220128124639-e64fb976bf15/go.mod h1:8jUjOAi3xtGubxcZgG8uSHpAdyQXBRbWAfxkctX/4y4=
 golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

+ 16 - 0
metrics.go

@@ -20,6 +20,7 @@ import (
 	"context"
 	"net/http"
 	"runtime/debug"
+	"strconv"
 	"sync"
 	"time"
 
@@ -50,6 +51,7 @@ type MetricsHandler struct {
 	whatsappMessageHandling *prometheus.HistogramVec
 	countCollection         prometheus.Histogram
 	disconnections          *prometheus.CounterVec
+	incomingRetryReceipts   *prometheus.CounterVec
 	puppetCount             prometheus.Gauge
 	userCount               prometheus.Gauge
 	messageCount            prometheus.Gauge
@@ -99,6 +101,10 @@ func NewMetricsHandler(address string, log log.Logger, db *database.Database) *M
 			Name: "whatsapp_disconnections",
 			Help: "Number of times a Matrix user has been disconnected from WhatsApp",
 		}, []string{"user_id"}),
+		incomingRetryReceipts: promauto.NewCounterVec(prometheus.CounterOpts{
+			Name: "whatsapp_incoming_retry_receipts",
+			Help: "Number of times a remote WhatsApp user has requested a retry from the bridge. retry_count = 5 is usually the last attempt (and very likely means a failed message)",
+		}, []string{"retry_count", "message_found"}),
 		puppetCount: promauto.NewGauge(prometheus.GaugeOpts{
 			Name: "whatsapp_puppets_total",
 			Help: "Number of WhatsApp users bridged into Matrix",
@@ -167,6 +173,16 @@ func (mh *MetricsHandler) TrackDisconnection(userID id.UserID) {
 	mh.disconnections.With(prometheus.Labels{"user_id": string(userID)}).Inc()
 }
 
+func (mh *MetricsHandler) TrackRetryReceipt(count int, found bool) {
+	if !mh.running {
+		return
+	}
+	mh.incomingRetryReceipts.With(prometheus.Labels{
+		"retry_count":   strconv.Itoa(count),
+		"message_found": strconv.FormatBool(found),
+	}).Inc()
+}
+
 func (mh *MetricsHandler) TrackLoginState(jid types.JID, loggedIn bool) {
 	if !mh.running {
 		return

+ 16 - 4
user.go

@@ -39,6 +39,7 @@ import (
 
 	"go.mau.fi/whatsmeow"
 	"go.mau.fi/whatsmeow/appstate"
+	waProto "go.mau.fi/whatsmeow/binary/proto"
 	"go.mau.fi/whatsmeow/store"
 	"go.mau.fi/whatsmeow/types"
 	"go.mau.fi/whatsmeow/types/events"
@@ -318,6 +319,19 @@ func (w *waLogger) Sub(module string) waLog.Logger         { return &waLogger{l:
 
 var ErrAlreadyLoggedIn = errors.New("already logged in")
 
+func (user *User) createClient(sess *store.Device) {
+	user.Client = whatsmeow.NewClient(sess, &waLogger{user.log.Sub("Client")})
+	user.Client.AddEventHandler(user.HandleEvent)
+	user.Client.GetMessageForRetry = func(to types.JID, id types.MessageID) *waProto.Message {
+		user.bridge.Metrics.TrackRetryReceipt(0, false)
+		return nil
+	}
+	user.Client.PreRetryCallback = func(receipt *events.Receipt, retryCount int, msg *waProto.Message) bool {
+		user.bridge.Metrics.TrackRetryReceipt(retryCount, true)
+		return true
+	}
+}
+
 func (user *User) Login(ctx context.Context) (<-chan whatsmeow.QRChannelItem, error) {
 	user.connLock.Lock()
 	defer user.connLock.Unlock()
@@ -328,8 +342,7 @@ func (user *User) Login(ctx context.Context) (<-chan whatsmeow.QRChannelItem, er
 	}
 	newSession := user.bridge.WAContainer.NewDevice()
 	newSession.Log = &waLogger{user.log.Sub("Session")}
-	user.Client = whatsmeow.NewClient(newSession, &waLogger{user.log.Sub("Client")})
-	user.Client.AddEventHandler(user.HandleEvent)
+	user.createClient(newSession)
 	qrChan, err := user.Client.GetQRChannel(ctx)
 	if err != nil {
 		return nil, fmt.Errorf("failed to get QR channel: %w", err)
@@ -351,8 +364,7 @@ func (user *User) Connect() bool {
 	}
 	user.log.Debugln("Connecting to WhatsApp")
 	user.sendBridgeState(BridgeState{StateEvent: StateConnecting, Error: WAConnecting})
-	user.Client = whatsmeow.NewClient(user.Session, &waLogger{user.log.Sub("Client")})
-	user.Client.AddEventHandler(user.HandleEvent)
+	user.createClient(user.Session)
 	err := user.Client.Connect()
 	if err != nil {
 		user.log.Warnln("Error connecting to WhatsApp:", err)