Add platform information for push notification metrics (#27460)

* Add platform information for push notification metrics

* Address feedback

* Add the client platform returned by the devices to the normalize function

* Add "no platform" platform label to distinguish from unknown
This commit is contained in:
Daniel Espino García 2024-07-05 09:34:01 +02:00 committed by GitHub
parent 6bbf7bbb9f
commit e5a3dd7fea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 122 additions and 105 deletions

View File

@ -673,13 +673,13 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) {
}
if ack.NotificationType == model.PushTypeMessage {
c.App.CountNotificationAck(model.NotificationTypePush)
c.App.CountNotificationAck(model.NotificationTypePush, ack.ClientPlatform)
}
err := c.App.SendAckToPushProxy(&ack)
if ack.IsIdLoaded {
if err != nil {
c.App.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError)
c.App.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError, ack.ClientPlatform)
c.App.NotificationsLog().Error("Notification ack not sent to push proxy",
mlog.String("type", model.NotificationTypePush),
mlog.String("status", model.NotificationStatusError),
@ -693,7 +693,7 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) {
mlog.Err(err),
)
} else {
c.App.CountNotificationReason(model.NotificationStatusSuccess, model.NotificationTypePush, model.NotificationReason(""))
c.App.CountNotificationReason(model.NotificationStatusSuccess, model.NotificationTypePush, model.NotificationReason(""), ack.ClientPlatform)
}
// Return post data only when PostId is passed.
if ack.PostId != "" && ack.NotificationType == model.PushTypeMessage {
@ -725,7 +725,7 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
c.App.CountNotificationReason(model.NotificationStatusSuccess, model.NotificationTypePush, model.NotificationReason(""))
c.App.CountNotificationReason(model.NotificationStatusSuccess, model.NotificationTypePush, model.NotificationReason(""), ack.ClientPlatform)
ReturnStatusOK(w)
}

View File

@ -511,9 +511,9 @@ type AppIface interface {
ConvertGroupMessageToChannel(c request.CTX, convertedByUserId string, gmConversionRequest *model.GroupMessageConversionRequestBody) (*model.Channel, *model.AppError)
CopyFileInfos(rctx request.CTX, userID string, fileIDs []string) ([]string, *model.AppError)
CopyWranglerPostlist(c request.CTX, wpl *model.WranglerPostList, targetChannel *model.Channel) (*model.Post, *model.AppError)
CountNotification(notificationType model.NotificationType)
CountNotificationAck(notificationType model.NotificationType)
CountNotificationReason(notificationStatus model.NotificationStatus, notificationType model.NotificationType, notificationReason model.NotificationReason)
CountNotification(notificationType model.NotificationType, platform string)
CountNotificationAck(notificationType model.NotificationType, platform string)
CountNotificationReason(notificationStatus model.NotificationStatus, notificationType model.NotificationType, notificationReason model.NotificationReason, platform string)
CreateChannel(c request.CTX, channel *model.Channel, addMember bool) (*model.Channel, *model.AppError)
CreateChannelBookmark(c request.CTX, newBookmark *model.ChannelBookmark, connectionId string) (*model.ChannelBookmarkWithFileInfo, *model.AppError)
CreateChannelWithUser(c request.CTX, channel *model.Channel, userID string) (*model.Channel, *model.AppError)

View File

@ -24,7 +24,7 @@ func (a *App) NotifySessionsExpired() error {
// Get all mobile sessions that expired within the last hour.
sessions, err := a.ch.srv.Store().Session().GetSessionsExpired(OneHourMillis, true, true)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Cannot get sessions expired",
mlog.String("type", model.NotificationTypePush),
mlog.String("status", model.NotificationStatusError),
@ -47,7 +47,7 @@ func (a *App) NotifySessionsExpired() error {
errPush := a.sendToPushProxy(tmpMessage, session)
if errPush != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError, tmpMessage.Platform)
a.NotificationsLog().Error("Failed to send to push proxy",
mlog.String("type", model.NotificationTypePush),
mlog.String("status", model.NotificationStatusNotSent),

View File

@ -97,7 +97,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
pResult := <-pchan
if pResult.NErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error fetching profiles",
mlog.String("sender_id", sender.Id),
mlog.String("post_id", post.Id),
@ -111,7 +111,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
cmnResult := <-cmnchan
if cmnResult.NErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error fetching notify props",
mlog.String("sender_id", sender.Id),
mlog.String("post_id", post.Id),
@ -127,7 +127,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
if tchan != nil {
tResult := <-tchan
if tResult.NErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error fetching thread followers",
mlog.String("sender_id", sender.Id),
mlog.String("post_id", post.Id),
@ -146,7 +146,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
if gchan != nil {
gResult := <-gchan
if gResult.NErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error fetching group mentions",
mlog.String("sender_id", sender.Id),
mlog.String("post_id", post.Id),
@ -173,7 +173,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
group := groups[groupID]
anyUsersMentionedByGroup, err := a.insertGroupMentions(sender.Id, group, channel, profileMap, mentions)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Failed to populate group mentions",
mlog.String("sender_id", sender.Id),
mlog.String("post_id", post.Id),
@ -382,7 +382,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
for _, id := range emailRecipients {
if profileMap[id] == nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeEmail, model.NotificationReasonMissingProfile)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeEmail, model.NotificationReasonMissingProfile, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing profile",
mlog.String("type", model.NotificationTypeEmail),
mlog.String("post_id", post.Id),
@ -396,7 +396,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
//If email verification is required and user email is not verified don't send email.
if *a.Config().EmailSettings.RequireEmailVerification && !profileMap[id].EmailVerified {
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypeEmail, model.NotificationReasonEmailNotVerified)
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypeEmail, model.NotificationReasonEmailNotVerified, model.NotificationNoPlatform)
a.NotificationsLog().Debug("Email not verified",
mlog.String("type", model.NotificationTypeEmail),
mlog.String("post_id", post.Id),
@ -415,7 +415,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
c.Logger().Warn("Unable to get the sender user profile image.", mlog.String("user_id", sender.Id), mlog.Err(err))
}
if err := a.sendNotificationEmail(c, notification, profileMap[id], team, senderProfileImage); err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeEmail, model.NotificationReasonEmailSendError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeEmail, model.NotificationReasonEmailSendError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error sending email notification",
mlog.String("type", model.NotificationTypeEmail),
mlog.String("post_id", post.Id),
@ -448,7 +448,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
// Check for channel-wide mentions in channels that have too many members for those to work
if int64(len(profileMap)) > *a.Config().TeamSettings.MaxNotificationsPerChannel {
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypeAll, model.NotificationReasonTooManyUsersInChannel)
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypeAll, model.NotificationReasonTooManyUsersInChannel, model.NotificationNoPlatform)
a.NotificationsLog().Debug("Too many users to notify - will send ephemeral message",
mlog.String("sender_id", sender.Id),
mlog.String("post_id", post.Id),
@ -504,7 +504,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
for _, id := range mentionedUsersList {
if profileMap[id] == nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonMissingProfile)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonMissingProfile, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing profile",
mlog.String("type", model.NotificationTypePush),
mlog.String("post_id", post.Id),
@ -556,7 +556,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
for _, id := range allActivityPushUserIds {
if profileMap[id] == nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonMissingProfile)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonMissingProfile, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing profile",
mlog.String("type", model.NotificationTypePush),
mlog.String("post_id", post.Id),
@ -600,7 +600,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
for _, id := range notificationsForCRT.Push {
if profileMap[id] == nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonMissingProfile)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonMissingProfile, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing profile",
mlog.String("type", model.NotificationTypePush),
mlog.String("post_id", post.Id),
@ -627,7 +627,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
model.CommentsNotifyCRT,
)
} else {
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, statusReason)
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, statusReason, model.NotificationNoPlatform)
a.NotificationsLog().Debug("Notification not sent - status",
mlog.String("type", model.NotificationTypePush),
mlog.String("post_id", post.Id),
@ -703,7 +703,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
published, err := a.publishWebsocketEventForPermalinkPost(c, post, message)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Couldn't send websocket notification for permalink post",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -718,7 +718,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
removePermalinkMetadataFromPost(post)
postJSON, jsonErr := post.ToJSON()
if jsonErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonParseError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonParseError, model.NotificationNoPlatform)
a.NotificationsLog().Error("JSON parse error",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -743,7 +743,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
// This also sometimes happens when bots, which will never show up in the map, reply to threads
// Their own post goes through this and they get "notified", which we don't need to count as an error if they can't
if uid != post.UserId {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonMissingProfile)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonMissingProfile, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing profile",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -761,7 +761,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
if threadMembership == nil {
tm, err := a.Srv().Store().Thread().GetMembershipForUser(uid, post.RootId)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing thread membership",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -774,7 +774,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
return nil, errors.Wrapf(err, "Missing thread membership for participant in notifications. user_id=%q thread_id=%q", uid, post.RootId)
}
if tm == nil {
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypeWebsocket, model.NotificationReasonMissingThreadMembership)
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypeWebsocket, model.NotificationReasonMissingThreadMembership, model.NotificationNoPlatform)
a.NotificationsLog().Warn("Missing thread membership",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -789,7 +789,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
}
userThread, err := a.Srv().Store().Thread().GetThreadForUser(threadMembership, true, a.IsPostPriorityEnabled())
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing thread",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -823,7 +823,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
// should set unread mentions, and unread replies to 0
_, err = a.Srv().Store().Thread().MaintainMembership(uid, post.RootId, opts)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Failed to update thread membership",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -843,7 +843,7 @@ func (a *App) SendNotifications(c request.CTX, post *model.Post, team *model.Tea
sanitizedPost, err := a.SanitizePostMetadataForUser(c, userThread.Post, uid)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonParseError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonParseError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Failed to sanitize metadata",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -1735,26 +1735,27 @@ func ShouldAckWebsocketNotification(channelType model.ChannelType, userNotificat
return false
}
func (a *App) CountNotification(notificationType model.NotificationType) {
func (a *App) CountNotification(notificationType model.NotificationType, platform string) {
if a.notificationMetricsDisabled() {
return
}
a.Metrics().IncrementNotificationCounter(notificationType)
a.Metrics().IncrementNotificationCounter(notificationType, platform)
}
func (a *App) CountNotificationAck(notificationType model.NotificationType) {
func (a *App) CountNotificationAck(notificationType model.NotificationType, platform string) {
if a.notificationMetricsDisabled() {
return
}
a.Metrics().IncrementNotificationAckCounter(notificationType)
a.Metrics().IncrementNotificationAckCounter(notificationType, platform)
}
func (a *App) CountNotificationReason(
notificationStatus model.NotificationStatus,
notificationType model.NotificationType,
notificationReason model.NotificationReason,
platform string,
) {
if a.notificationMetricsDisabled() {
return
@ -1762,13 +1763,13 @@ func (a *App) CountNotificationReason(
switch notificationStatus {
case model.NotificationStatusSuccess:
a.Metrics().IncrementNotificationSuccessCounter(notificationType)
a.Metrics().IncrementNotificationSuccessCounter(notificationType, platform)
case model.NotificationStatusError:
a.Metrics().IncrementNotificationErrorCounter(notificationType, notificationReason)
a.Metrics().IncrementNotificationErrorCounter(notificationType, notificationReason, platform)
case model.NotificationStatusNotSent:
a.Metrics().IncrementNotificationNotSentCounter(notificationType, notificationReason)
a.Metrics().IncrementNotificationNotSentCounter(notificationType, notificationReason, platform)
case model.NotificationStatusUnsupported:
a.Metrics().IncrementNotificationUnsupportedCounter(notificationType, notificationReason)
a.Metrics().IncrementNotificationUnsupportedCounter(notificationType, notificationReason, platform)
}
}

View File

@ -117,7 +117,7 @@ func (a *App) sendPushNotificationToAllSessions(rctx request.CTX, msg *model.Pus
sessions, appErr := a.getMobileAppSessions(userID)
if appErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Failed to send mobile app sessions",
mlog.String("type", model.NotificationTypePush),
mlog.String("status", model.NotificationStatusError),
@ -129,7 +129,7 @@ func (a *App) sendPushNotificationToAllSessions(rctx request.CTX, msg *model.Pus
}
if msg == nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonParseError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonParseError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Failed to parse push notification",
mlog.String("type", model.NotificationTypePush),
mlog.String("status", model.NotificationStatusError),
@ -148,7 +148,7 @@ func (a *App) sendPushNotificationToAllSessions(rctx request.CTX, msg *model.Pus
for _, session := range sessions {
// Don't send notifications to this session if it's expired or we want to skip it
if session.IsExpired() || (skipSessionId != "" && skipSessionId == session.Id) {
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, model.NotificationReasonSessionExpired)
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, model.NotificationReasonSessionExpired, model.NotificationNoPlatform)
a.NotificationsLog().Debug("Session expired or skipped",
mlog.String("type", model.NotificationTypePush),
mlog.String("status", model.NotificationStatusNotSent),
@ -184,7 +184,7 @@ func (a *App) sendPushNotificationToAllSessions(rctx request.CTX, msg *model.Pus
err = a.sendToPushProxy(tmpMessage, session)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError, tmpMessage.Platform)
a.NotificationsLog().Error("Failed to send to push proxy",
mlog.String("type", model.NotificationTypePush),
mlog.String("status", model.NotificationStatusNotSent),
@ -212,7 +212,7 @@ func (a *App) sendPushNotificationToAllSessions(rctx request.CTX, msg *model.Pus
}
if msg.Type == model.PushTypeMessage {
a.CountNotification(model.NotificationTypePush)
a.CountNotification(model.NotificationTypePush, tmpMessage.Platform)
}
}
@ -586,7 +586,7 @@ func (a *App) getMobileAppSessions(userID string) ([]*model.Session, *model.AppE
func (a *App) ShouldSendPushNotification(user *model.User, channelNotifyProps model.StringMap, wasMentioned bool, status *model.Status, post *model.Post, isGM bool) bool {
if notifyPropsAllowedReason := DoesNotifyPropsAllowPushNotification(user, channelNotifyProps, post, wasMentioned, isGM); notifyPropsAllowedReason != "" {
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, notifyPropsAllowedReason)
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, notifyPropsAllowedReason, model.NotificationNoPlatform)
a.NotificationsLog().Debug("Notification not sent - notify props",
mlog.String("type", model.NotificationTypePush),
mlog.String("post_id", post.Id),
@ -599,7 +599,7 @@ func (a *App) ShouldSendPushNotification(user *model.User, channelNotifyProps mo
}
if statusAllowedReason := DoesStatusAllowPushNotification(user.NotifyProps, status, post.ChannelId, false); statusAllowedReason != "" {
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, statusAllowedReason)
a.CountNotificationReason(model.NotificationStatusNotSent, model.NotificationTypePush, statusAllowedReason, model.NotificationNoPlatform)
a.NotificationsLog().Debug("Notification not sent - status",
mlog.String("type", model.NotificationTypePush),
mlog.String("post_id", post.Id),
@ -726,7 +726,7 @@ func (a *App) SendTestPushNotification(deviceID string) string {
pushResponse, err := a.rawSendToPushProxy(msg)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxySendError, msg.Platform)
a.NotificationsLog().Error("Failed to send test notification to push proxy",
mlog.String("type", model.NotificationTypePush),
mlog.String("push_type", msg.Type),
@ -742,7 +742,7 @@ func (a *App) SendTestPushNotification(deviceID string) string {
case model.PushStatusRemove:
return "false"
case model.PushStatusFail:
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxyError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonPushProxyError, msg.Platform)
a.NotificationsLog().Error("Push proxy failed to send test notification",
mlog.String("type", model.NotificationTypePush),
mlog.String("push_type", msg.Type),

View File

@ -1967,7 +1967,7 @@ func (a *OpenTracingAppLayer) CopyWranglerPostlist(c request.CTX, wpl *model.Wra
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) CountNotification(notificationType model.NotificationType) {
func (a *OpenTracingAppLayer) CountNotification(notificationType model.NotificationType, platform string) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CountNotification")
@ -1979,10 +1979,10 @@ func (a *OpenTracingAppLayer) CountNotification(notificationType model.Notificat
}()
defer span.Finish()
a.app.CountNotification(notificationType)
a.app.CountNotification(notificationType, platform)
}
func (a *OpenTracingAppLayer) CountNotificationAck(notificationType model.NotificationType) {
func (a *OpenTracingAppLayer) CountNotificationAck(notificationType model.NotificationType, platform string) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CountNotificationAck")
@ -1994,10 +1994,10 @@ func (a *OpenTracingAppLayer) CountNotificationAck(notificationType model.Notifi
}()
defer span.Finish()
a.app.CountNotificationAck(notificationType)
a.app.CountNotificationAck(notificationType, platform)
}
func (a *OpenTracingAppLayer) CountNotificationReason(notificationStatus model.NotificationStatus, notificationType model.NotificationType, notificationReason model.NotificationReason) {
func (a *OpenTracingAppLayer) CountNotificationReason(notificationStatus model.NotificationStatus, notificationType model.NotificationType, notificationReason model.NotificationReason, platform string) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CountNotificationReason")
@ -2009,7 +2009,7 @@ func (a *OpenTracingAppLayer) CountNotificationReason(notificationStatus model.N
}()
defer span.Finish()
a.app.CountNotificationReason(notificationStatus, notificationType, notificationReason)
a.app.CountNotificationReason(notificationStatus, notificationType, notificationReason, platform)
}
func (a *OpenTracingAppLayer) CreateBot(rctx request.CTX, bot *model.Bot) (*model.Bot, *model.AppError) {

View File

@ -357,7 +357,7 @@ func (a *App) CreatePost(c request.CTX, post *model.Post, channel *model.Channel
if rpost.RootId != "" {
if appErr := a.ResolvePersistentNotification(c, parentPostList.Posts[post.RootId], rpost.UserId); appErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonResolvePersistentNotificationError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonResolvePersistentNotificationError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error resolving persistent notification",
mlog.String("sender_id", rpost.UserId),
mlog.String("post_id", post.RootId),
@ -488,7 +488,7 @@ func (a *App) handlePostEvents(c request.CTX, post *model.Post, user *model.User
if channel.TeamId != "" {
t, err := a.Srv().Store().Team().Get(channel.TeamId)
if err != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Missing team",
mlog.String("post_id", post.Id),
mlog.String("status", model.NotificationStatusError),
@ -783,7 +783,7 @@ func (a *App) publishWebsocketEventForPermalinkPost(c request.CTX, post *model.P
}
if !model.IsValidId(previewedPostID) {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonParseError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonParseError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Invalid post prop id for permalink post",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -798,7 +798,7 @@ func (a *App) publishWebsocketEventForPermalinkPost(c request.CTX, post *model.P
previewedPost, err := a.GetSinglePost(c, previewedPostID, false)
if err != nil {
if err.StatusCode == http.StatusNotFound {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("permalink post not found",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -815,7 +815,7 @@ func (a *App) publishWebsocketEventForPermalinkPost(c request.CTX, post *model.P
userIDs, nErr := a.Srv().Store().Channel().GetAllChannelMemberIdsByChannelId(post.ChannelId)
if nErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Cannot get channel members",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),
@ -830,7 +830,7 @@ func (a *App) publishWebsocketEventForPermalinkPost(c request.CTX, post *model.P
permalinkPreviewedChannel, err := a.GetChannel(c, previewedPost.ChannelId)
if err != nil {
if err.StatusCode == http.StatusNotFound {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonFetchError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Cannot get channel",
mlog.String("type", model.NotificationTypeWebsocket),
mlog.String("post_id", post.Id),

View File

@ -42,7 +42,7 @@ func (a *App) SaveAcknowledgementForPost(c request.CTX, postID, userID string) (
}
if appErr := a.ResolvePersistentNotification(c, post, userID); appErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonResolvePersistentNotificationError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeWebsocket, model.NotificationReasonResolvePersistentNotificationError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error resolving persistent notification",
mlog.String("sender_id", userID),
mlog.String("post_id", post.RootId),

View File

@ -67,7 +67,7 @@ func (a *App) SaveReactionForPost(c request.CTX, reaction *model.Reaction) (*mod
if post.RootId == "" {
if appErr := a.ResolvePersistentNotification(c, post, reaction.UserId); appErr != nil {
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonResolvePersistentNotificationError)
a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypeAll, model.NotificationReasonResolvePersistentNotificationError, model.NotificationNoPlatform)
a.NotificationsLog().Error("Error resolving persistent notification",
mlog.String("sender_id", reaction.UserId),
mlog.String("post_id", post.RootId),

View File

@ -139,7 +139,7 @@ func incrementWebsocketCounter(wc *platform.WebConn) {
return
}
wc.Platform.Metrics().IncrementNotificationCounter(model.NotificationTypeWebsocket)
wc.Platform.Metrics().IncrementNotificationCounter(model.NotificationTypeWebsocket, model.NotificationNoPlatform)
}
// getTypedArg returns a correctly typed hook argument with the given key, reinterpreting the type using JSON encoding

View File

@ -36,7 +36,7 @@ func (api *API) websocketNotificationAck(req *model.WebSocketRequest) (map[strin
)
// Count metrics for websocket acks
api.App.CountNotificationAck(model.NotificationTypeWebsocket)
api.App.CountNotificationAck(model.NotificationTypeWebsocket, model.NotificationNoPlatform)
status := req.Data["status"]
reason := req.Data["reason"]
@ -57,6 +57,7 @@ func (api *API) websocketNotificationAck(req *model.WebSocketRequest) (map[strin
notificationStatus,
model.NotificationTypeWebsocket,
notificationReason,
model.NotificationNoPlatform,
)
return nil, nil

View File

@ -96,12 +96,12 @@ type MetricsInterface interface {
SetReplicaLagAbsolute(node string, value float64)
SetReplicaLagTime(node string, value float64)
IncrementNotificationCounter(notificationType model.NotificationType)
IncrementNotificationAckCounter(notificationType model.NotificationType)
IncrementNotificationSuccessCounter(notificationType model.NotificationType)
IncrementNotificationErrorCounter(notificationType model.NotificationType, errorReason model.NotificationReason)
IncrementNotificationNotSentCounter(notificationType model.NotificationType, notSentReason model.NotificationReason)
IncrementNotificationUnsupportedCounter(notificationType model.NotificationType, notSentReason model.NotificationReason)
IncrementNotificationCounter(notificationType model.NotificationType, platform string)
IncrementNotificationAckCounter(notificationType model.NotificationType, platform string)
IncrementNotificationSuccessCounter(notificationType model.NotificationType, platform string)
IncrementNotificationErrorCounter(notificationType model.NotificationType, errorReason model.NotificationReason, platform string)
IncrementNotificationNotSentCounter(notificationType model.NotificationType, notSentReason model.NotificationReason, platform string)
IncrementNotificationUnsupportedCounter(notificationType model.NotificationType, notSentReason model.NotificationReason, platform string)
ObserveClientTimeToFirstByte(platform, agent string, elapsed float64)
ObserveClientFirstContentfulPaint(platform, agent string, elapsed float64)

View File

@ -168,34 +168,34 @@ func (_m *MetricsInterface) IncrementMemCacheMissCounterSession() {
_m.Called()
}
// IncrementNotificationAckCounter provides a mock function with given fields: notificationType
func (_m *MetricsInterface) IncrementNotificationAckCounter(notificationType model.NotificationType) {
_m.Called(notificationType)
// IncrementNotificationAckCounter provides a mock function with given fields: notificationType, platform
func (_m *MetricsInterface) IncrementNotificationAckCounter(notificationType model.NotificationType, platform string) {
_m.Called(notificationType, platform)
}
// IncrementNotificationCounter provides a mock function with given fields: notificationType
func (_m *MetricsInterface) IncrementNotificationCounter(notificationType model.NotificationType) {
_m.Called(notificationType)
// IncrementNotificationCounter provides a mock function with given fields: notificationType, platform
func (_m *MetricsInterface) IncrementNotificationCounter(notificationType model.NotificationType, platform string) {
_m.Called(notificationType, platform)
}
// IncrementNotificationErrorCounter provides a mock function with given fields: notificationType, errorReason
func (_m *MetricsInterface) IncrementNotificationErrorCounter(notificationType model.NotificationType, errorReason model.NotificationReason) {
_m.Called(notificationType, errorReason)
// IncrementNotificationErrorCounter provides a mock function with given fields: notificationType, errorReason, platform
func (_m *MetricsInterface) IncrementNotificationErrorCounter(notificationType model.NotificationType, errorReason model.NotificationReason, platform string) {
_m.Called(notificationType, errorReason, platform)
}
// IncrementNotificationNotSentCounter provides a mock function with given fields: notificationType, notSentReason
func (_m *MetricsInterface) IncrementNotificationNotSentCounter(notificationType model.NotificationType, notSentReason model.NotificationReason) {
_m.Called(notificationType, notSentReason)
// IncrementNotificationNotSentCounter provides a mock function with given fields: notificationType, notSentReason, platform
func (_m *MetricsInterface) IncrementNotificationNotSentCounter(notificationType model.NotificationType, notSentReason model.NotificationReason, platform string) {
_m.Called(notificationType, notSentReason, platform)
}
// IncrementNotificationSuccessCounter provides a mock function with given fields: notificationType
func (_m *MetricsInterface) IncrementNotificationSuccessCounter(notificationType model.NotificationType) {
_m.Called(notificationType)
// IncrementNotificationSuccessCounter provides a mock function with given fields: notificationType, platform
func (_m *MetricsInterface) IncrementNotificationSuccessCounter(notificationType model.NotificationType, platform string) {
_m.Called(notificationType, platform)
}
// IncrementNotificationUnsupportedCounter provides a mock function with given fields: notificationType, notSentReason
func (_m *MetricsInterface) IncrementNotificationUnsupportedCounter(notificationType model.NotificationType, notSentReason model.NotificationReason) {
_m.Called(notificationType, notSentReason)
// IncrementNotificationUnsupportedCounter provides a mock function with given fields: notificationType, notSentReason, platform
func (_m *MetricsInterface) IncrementNotificationUnsupportedCounter(notificationType model.NotificationType, notSentReason model.NotificationReason, platform string) {
_m.Called(notificationType, notSentReason, platform)
}
// IncrementPostBroadcast provides a mock function with given fields:

View File

@ -1076,7 +1076,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
Help: "Total number of notification events",
ConstLabels: additionalLabels,
},
[]string{"type"},
[]string{"type", "platform"},
)
m.Registry.MustRegister(m.NotificationTotalCounters)
@ -1088,7 +1088,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
Help: "Total number of notification events acknowledged",
ConstLabels: additionalLabels,
},
[]string{"type"},
[]string{"type", "platform"},
)
m.Registry.MustRegister(m.NotificationAckCounters)
@ -1100,7 +1100,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
Help: "Total number of successfully sent notifications",
ConstLabels: additionalLabels,
},
[]string{"type"},
[]string{"type", "platform"},
)
m.Registry.MustRegister(m.NotificationSuccessCounters)
@ -1112,7 +1112,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
Help: "Total number of errors that stop the notification flow",
ConstLabels: additionalLabels,
},
[]string{"type", "reason"},
[]string{"type", "reason", "platform"},
)
m.Registry.MustRegister(m.NotificationErrorCounters)
@ -1124,7 +1124,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
Help: "Total number of notifications the system deliberately did not send",
ConstLabels: additionalLabels,
},
[]string{"type", "reason"},
[]string{"type", "reason", "platform"},
)
m.Registry.MustRegister(m.NotificationNotSentCounters)
@ -1136,7 +1136,7 @@ func New(ps *platform.PlatformService, driver, dataSource string) *MetricsInterf
Help: "Total number of untrackable notifications due to an unsupported app version",
ConstLabels: additionalLabels,
},
[]string{"type", "reason"},
[]string{"type", "reason", "platform"},
)
m.Registry.MustRegister(m.NotificationUnsupportedCounters)
@ -1730,28 +1730,41 @@ func (mi *MetricsInterfaceImpl) SetReplicaLagTime(node string, value float64) {
mi.DbReplicaLagGaugeTime.With(prometheus.Labels{"node": node}).Set(value)
}
func (mi *MetricsInterfaceImpl) IncrementNotificationCounter(notificationType model.NotificationType) {
mi.NotificationTotalCounters.With(prometheus.Labels{"type": string(notificationType)}).Inc()
func normalizeNotificationPlatform(platform string) string {
switch platform {
case "apple_rn-v2", "apple_rnbeta-v2", "ios":
return "ios"
case "android_rn-v2", "android":
return "android"
case model.NotificationNoPlatform:
return model.NotificationNoPlatform
default:
return "unknown"
}
}
func (mi *MetricsInterfaceImpl) IncrementNotificationAckCounter(notificationType model.NotificationType) {
mi.NotificationAckCounters.With(prometheus.Labels{"type": string(notificationType)}).Inc()
func (mi *MetricsInterfaceImpl) IncrementNotificationCounter(notificationType model.NotificationType, platform string) {
mi.NotificationTotalCounters.With(prometheus.Labels{"type": string(notificationType), "platform": normalizeNotificationPlatform(platform)}).Inc()
}
func (mi *MetricsInterfaceImpl) IncrementNotificationSuccessCounter(notificationType model.NotificationType) {
mi.NotificationSuccessCounters.With(prometheus.Labels{"type": string(notificationType)}).Inc()
func (mi *MetricsInterfaceImpl) IncrementNotificationAckCounter(notificationType model.NotificationType, platform string) {
mi.NotificationAckCounters.With(prometheus.Labels{"type": string(notificationType), "platform": normalizeNotificationPlatform(platform)}).Inc()
}
func (mi *MetricsInterfaceImpl) IncrementNotificationErrorCounter(notificationType model.NotificationType, errorReason model.NotificationReason) {
mi.NotificationErrorCounters.With(prometheus.Labels{"type": string(notificationType), "reason": string(errorReason)}).Inc()
func (mi *MetricsInterfaceImpl) IncrementNotificationSuccessCounter(notificationType model.NotificationType, platform string) {
mi.NotificationSuccessCounters.With(prometheus.Labels{"type": string(notificationType), "platform": normalizeNotificationPlatform(platform)}).Inc()
}
func (mi *MetricsInterfaceImpl) IncrementNotificationNotSentCounter(notificationType model.NotificationType, notSentReason model.NotificationReason) {
mi.NotificationNotSentCounters.With(prometheus.Labels{"type": string(notificationType), "reason": string(notSentReason)}).Inc()
func (mi *MetricsInterfaceImpl) IncrementNotificationErrorCounter(notificationType model.NotificationType, errorReason model.NotificationReason, platform string) {
mi.NotificationErrorCounters.With(prometheus.Labels{"type": string(notificationType), "reason": string(errorReason), "platform": normalizeNotificationPlatform(platform)}).Inc()
}
func (mi *MetricsInterfaceImpl) IncrementNotificationUnsupportedCounter(notificationType model.NotificationType, notSentReason model.NotificationReason) {
mi.NotificationUnsupportedCounters.With(prometheus.Labels{"type": string(notificationType), "reason": string(notSentReason)}).Inc()
func (mi *MetricsInterfaceImpl) IncrementNotificationNotSentCounter(notificationType model.NotificationType, notSentReason model.NotificationReason, platform string) {
mi.NotificationNotSentCounters.With(prometheus.Labels{"type": string(notificationType), "reason": string(notSentReason), "platform": normalizeNotificationPlatform(platform)}).Inc()
}
func (mi *MetricsInterfaceImpl) IncrementNotificationUnsupportedCounter(notificationType model.NotificationType, notSentReason model.NotificationReason, platform string) {
mi.NotificationUnsupportedCounters.With(prometheus.Labels{"type": string(notificationType), "reason": string(notSentReason), "platform": normalizeNotificationPlatform(platform)}).Inc()
}
func (mi *MetricsInterfaceImpl) IncrementHTTPWebSockets(originClient string) {

View File

@ -18,6 +18,8 @@ const (
NotificationTypeWebsocket NotificationType = "websocket"
NotificationTypePush NotificationType = "push"
NotificationNoPlatform = "no_platform"
NotificationReasonFetchError NotificationReason = "fetch_error"
NotificationReasonParseError NotificationReason = "json_parse_error"
NotificationReasonPushProxyError NotificationReason = "push_proxy_error"