chore: add logger for push notifications
This commit is contained in:
@@ -3,8 +3,11 @@ package service
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
webpush "github.com/SherClockHolmes/webpush-go"
|
||||
@@ -81,10 +84,13 @@ func (p *PushSender) SendToUser(ctx context.Context, userID string, payload Push
|
||||
Endpoint: s.Endpoint,
|
||||
Keys: webpush.Keys{P256dh: s.P256dh, Auth: s.Auth},
|
||||
}
|
||||
status, err := p.sendWithRetry(ctx, body, sub)
|
||||
status, respBody, err := p.sendWithRetry(ctx, body, sub)
|
||||
if err != nil {
|
||||
failed++
|
||||
p.logger.Warn("push: send failed", zap.String("user", userID), zap.Error(err))
|
||||
p.logger.Warn("push: send failed",
|
||||
zap.String("user", userID),
|
||||
zap.String("host", endpointHost(s.Endpoint)),
|
||||
zap.Error(err))
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
@@ -96,7 +102,13 @@ func (p *PushSender) SendToUser(ctx context.Context, userID string, payload Push
|
||||
}
|
||||
case status >= 400:
|
||||
failed++
|
||||
p.logger.Warn("push: non-2xx", zap.Int("status", status), zap.String("user", userID))
|
||||
// The response body carries the real reason (e.g. a VAPID
|
||||
// credential mismatch, malformed request) — log it.
|
||||
p.logger.Warn("push: non-2xx",
|
||||
zap.Int("status", status),
|
||||
zap.String("user", userID),
|
||||
zap.String("host", endpointHost(s.Endpoint)),
|
||||
zap.String("body", respBody))
|
||||
default:
|
||||
sent++
|
||||
}
|
||||
@@ -108,8 +120,10 @@ func (p *PushSender) SendToUser(ctx context.Context, userID string, payload Push
|
||||
|
||||
// sendWithRetry posts one notification, retrying on transient failures
|
||||
// (network error or 429/5xx) with a short backoff that honors Retry-After.
|
||||
// Returns the final HTTP status, or an error if every attempt errored.
|
||||
func (p *PushSender) sendWithRetry(ctx context.Context, body []byte, sub *webpush.Subscription) (int, error) {
|
||||
// Returns the final HTTP status and, on a 4xx/5xx, a snippet of the response
|
||||
// body (the push service's error reason). Returns an error if every attempt
|
||||
// errored at the transport level.
|
||||
func (p *PushSender) sendWithRetry(ctx context.Context, body []byte, sub *webpush.Subscription) (int, string, error) {
|
||||
var lastErr error
|
||||
for attempt := 1; attempt <= pushMaxAttempts; attempt++ {
|
||||
resp, err := webpush.SendNotification(body, sub, &webpush.Options{
|
||||
@@ -127,18 +141,33 @@ func (p *PushSender) sendWithRetry(ctx context.Context, body []byte, sub *webpus
|
||||
sleepCtx(ctx, backoff(attempt))
|
||||
continue
|
||||
}
|
||||
return 0, err
|
||||
return 0, "", err
|
||||
}
|
||||
status := resp.StatusCode
|
||||
retryAfter := resp.Header.Get("Retry-After")
|
||||
_ = resp.Body.Close()
|
||||
if isTransientStatus(status) && attempt < pushMaxAttempts {
|
||||
_ = resp.Body.Close()
|
||||
sleepCtx(ctx, retryDelay(retryAfter, attempt))
|
||||
continue
|
||||
}
|
||||
return status, nil
|
||||
// Final attempt — capture the body on errors for diagnostics.
|
||||
var snippet string
|
||||
if status >= 400 {
|
||||
b, _ := io.ReadAll(io.LimitReader(resp.Body, 512))
|
||||
snippet = strings.TrimSpace(string(b))
|
||||
}
|
||||
_ = resp.Body.Close()
|
||||
return status, snippet, nil
|
||||
}
|
||||
return 0, lastErr
|
||||
return 0, "", lastErr
|
||||
}
|
||||
|
||||
// endpointHost extracts the host of a push endpoint for log context.
|
||||
func endpointHost(endpoint string) string {
|
||||
if u, err := url.Parse(endpoint); err == nil {
|
||||
return u.Host
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func isTransientStatus(s int) bool {
|
||||
|
||||
Reference in New Issue
Block a user