From 0c9aad538c565de68a1c24ae7a06179b69b0366f Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 10 Apr 2017 11:46:48 +0800 Subject: [PATCH] feat: get error logs from fail notifications. (#213) --- gorush/log.go | 41 +++++++++++----------------- gorush/notification.go | 53 +++++++++++++++++++++++++++++++------ gorush/notification_test.go | 12 ++++++--- gorush/server.go | 3 ++- 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/gorush/log.go b/gorush/log.go index 7031b47..35eed7d 100644 --- a/gorush/log.go +++ b/gorush/log.go @@ -39,21 +39,6 @@ type LogPushEntry struct { Token string `json:"token"` Message string `json:"message"` Error string `json:"error"` - - // Android - To string `json:"to,omitempty"` - CollapseKey string `json:"collapse_key,omitempty"` - DelayWhileIdle bool `json:"delay_while_idle,omitempty"` - TimeToLive uint `json:"time_to_live,omitempty"` - RestrictedPackageName string `json:"restricted_package_name,omitempty"` - DryRun bool `json:"dry_run,omitempty"` - - // iOS - ApnsID string `json:"apns_id,omitempty"` - Topic string `json:"topic,omitempty"` - Badge int `json:"badge,omitempty"` - Sound string `json:"sound,omitempty"` - Category string `json:"category,omitempty"` } var isTerm bool @@ -212,17 +197,11 @@ func hideToken(token string, markLen int) string { return result } -// LogPush record user push request and server response. -func LogPush(status, token string, req PushNotification, errPush error) { - var plat, platColor, resetColor, output string +func getLogPushEntry(status, token string, req PushNotification, errPush error) LogPushEntry { + var errMsg string - if isTerm { - platColor = colorForPlatForm(req.Platform) - plat = typeForPlatForm(req.Platform) - resetColor = reset - } + plat := typeForPlatForm(req.Platform) - errMsg := "" if errPush != nil { errMsg = errPush.Error() } @@ -231,13 +210,25 @@ func LogPush(status, token string, req PushNotification, errPush error) { token = hideToken(token, 10) } - log := &LogPushEntry{ + return LogPushEntry{ Type: status, Platform: plat, Token: token, Message: req.Message, Error: errMsg, } +} + +// LogPush record user push request and server response. +func LogPush(status, token string, req PushNotification, errPush error) { + var platColor, resetColor, output string + + if isTerm { + platColor = colorForPlatForm(req.Platform) + resetColor = reset + } + + log := getLogPushEntry(status, token, req, errPush) if PushConf.Log.Format == "json" { logJSON, _ := json.Marshal(log) diff --git a/gorush/notification.go b/gorush/notification.go index 471968f..54f3481 100644 --- a/gorush/notification.go +++ b/gorush/notification.go @@ -65,6 +65,7 @@ type PushNotification struct { Data D `json:"data,omitempty"` Retry int `json:"retry,omitempty"` wg *sync.WaitGroup + log *[]LogPushEntry // Android APIKey string `json:"api_key,omitempty"` @@ -87,13 +88,27 @@ type PushNotification struct { MutableContent bool `json:"mutable-content,omitempty"` } -// Done decrements the WaitGroup counter. -func (p *PushNotification) Done() { +// WaitDone decrements the WaitGroup counter. +func (p *PushNotification) WaitDone() { if p.wg != nil { p.wg.Done() } } +// AddWaitCount increments the WaitGroup counter. +func (p *PushNotification) AddWaitCount() { + if p.wg != nil { + p.wg.Add(1) + } +} + +// AddLog record fail log of notification +func (p *PushNotification) AddLog(log LogPushEntry) { + if p.log != nil { + *p.log = append(*p.log, log) + } +} + // CheckMessage for check request message func CheckMessage(req PushNotification) error { var msg string @@ -221,9 +236,10 @@ func startWorker() { } // queueNotification add notification to queue list. -func queueNotification(req RequestPush) int { +func queueNotification(req RequestPush) (int, []LogPushEntry) { var count int wg := sync.WaitGroup{} + newNotification := []PushNotification{} for _, notification := range req.Notifications { switch notification.Platform { case PlatFormIos: @@ -235,8 +251,16 @@ func queueNotification(req RequestPush) int { continue } } - wg.Add(1) - notification.wg = &wg + newNotification = append(newNotification, notification) + } + + log := make([]LogPushEntry, 0, count) + for _, notification := range newNotification { + if PushConf.Core.Sync { + notification.wg = &wg + notification.log = &log + notification.AddWaitCount() + } QueueNotification <- notification count += len(notification.Tokens) } @@ -247,7 +271,7 @@ func queueNotification(req RequestPush) int { StatStorage.AddTotalCount(int64(count)) - return count + return count, log } func iosAlertDictionary(payload *payload.Payload, req PushNotification) *payload.Payload { @@ -366,7 +390,9 @@ func GetIOSNotification(req PushNotification) *apns.Notification { // PushToIOS provide send notification to APNs server. func PushToIOS(req PushNotification) bool { LogAccess.Debug("Start push notification for iOS") - defer req.Done() + if PushConf.Core.Sync { + defer req.WaitDone() + } var retryCount = 0 var maxRetry = PushConf.Ios.MaxRetry @@ -389,6 +415,9 @@ Retry: if err != nil { // apns server error LogPush(FailedPush, token, req, err) + if PushConf.Core.Sync { + req.AddLog(getLogPushEntry(FailedPush, token, req, err)) + } StatStorage.AddIosError(1) newTokens = append(newTokens, token) isError = true @@ -399,6 +428,9 @@ Retry: // error message: // ref: https://github.com/sideshow/apns2/blob/master/response.go#L14-L65 LogPush(FailedPush, token, req, errors.New(res.Reason)) + if PushConf.Core.Sync { + req.AddLog(getLogPushEntry(FailedPush, token, req, errors.New(res.Reason))) + } StatStorage.AddIosError(1) newTokens = append(newTokens, token) isError = true @@ -471,7 +503,9 @@ func GetAndroidNotification(req PushNotification) gcm.HttpMessage { // PushToAndroid provide send notification to Android server. func PushToAndroid(req PushNotification) bool { LogAccess.Debug("Start push notification for Android") - defer req.Done() + if PushConf.Core.Sync { + defer req.WaitDone() + } var APIKey string var retryCount = 0 var maxRetry = PushConf.Android.MaxRetry @@ -514,6 +548,9 @@ Retry: isError = true newTokens = append(newTokens, req.Tokens[k]) LogPush(FailedPush, req.Tokens[k], req, errors.New(result.Error)) + if PushConf.Core.Sync { + req.AddLog(getLogPushEntry(FailedPush, req.Tokens[k], req, errors.New(result.Error))) + } continue } diff --git a/gorush/notification_test.go b/gorush/notification_test.go index 0ea310a..6ee6f97 100644 --- a/gorush/notification_test.go +++ b/gorush/notification_test.go @@ -567,8 +567,9 @@ func TestSenMultipleNotifications(t *testing.T) { }, } - count := queueNotification(req) + count, logs := queueNotification(req) assert.Equal(t, 3, count) + assert.Equal(t, 0, len(logs)) } func TestDisabledAndroidNotifications(t *testing.T) { @@ -600,8 +601,9 @@ func TestDisabledAndroidNotifications(t *testing.T) { }, } - count := queueNotification(req) + count, logs := queueNotification(req) assert.Equal(t, 1, count) + assert.Equal(t, 0, len(logs)) } func TestSyncModeForNotifications(t *testing.T) { @@ -636,8 +638,9 @@ func TestSyncModeForNotifications(t *testing.T) { }, } - count := queueNotification(req) + count, logs := queueNotification(req) assert.Equal(t, 3, count) + assert.Equal(t, 2, len(logs)) } func TestDisabledIosNotifications(t *testing.T) { @@ -669,8 +672,9 @@ func TestDisabledIosNotifications(t *testing.T) { }, } - count := queueNotification(req) + count, logs := queueNotification(req) assert.Equal(t, 2, count) + assert.Equal(t, 0, len(logs)) } func TestWrongIosCertificateExt(t *testing.T) { diff --git a/gorush/server.go b/gorush/server.go index c8fc545..e807ae6 100644 --- a/gorush/server.go +++ b/gorush/server.go @@ -56,11 +56,12 @@ func pushHandler(c *gin.Context) { return } - counts := queueNotification(form) + counts, logs := queueNotification(form) c.JSON(http.StatusOK, gin.H{ "success": "ok", "counts": counts, + "logs": logs, }) }