feat: capture logged errors and forward them to sentry when enabled
Cadoles/bouncer/pipeline/head This commit looks good
Details
Cadoles/bouncer/pipeline/head This commit looks good
Details
This commit is contained in:
parent
169578c25d
commit
867e7c549f
|
@ -70,7 +70,7 @@ func assertRequestUser(w http.ResponseWriter, r *http.Request) (auth.User, bool)
|
|||
ctx := r.Context()
|
||||
user, err := auth.CtxUser(ctx)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve user", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve user", logger.CapturedE(errors.WithStack(err)))
|
||||
|
||||
forbidden(w, r)
|
||||
|
||||
|
|
|
@ -35,5 +35,5 @@ func invalidDataErrorResponse(w http.ResponseWriter, r *http.Request, err *schem
|
|||
|
||||
func logAndCaptureError(ctx context.Context, message string, err error) {
|
||||
sentry.CaptureException(err)
|
||||
logger.Error(ctx, message, logger.E(err))
|
||||
logger.Error(ctx, message, logger.CapturedE(err))
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ func Middleware(authenticators ...Authenticator) func(http.Handler) http.Handler
|
|||
for _, auth := range authenticators {
|
||||
user, err = auth.Authenticate(ctx, r)
|
||||
if err != nil {
|
||||
logger.Debug(ctx, "could not authenticate request", logger.E(errors.WithStack(err)))
|
||||
logger.Debug(ctx, "could not authenticate request", logger.CapturedE(errors.WithStack(err)))
|
||||
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ func RunCommand() *cli.Command {
|
|||
}
|
||||
|
||||
if err := tmpl.Execute(w, data); err != nil {
|
||||
logger.Error(ctx.Context, "could not execute template", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx.Context, "could not execute template", logger.CapturedE(errors.WithStack(err)))
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ func (l *Locker) WithLock(ctx context.Context, key string, timeout time.Duration
|
|||
|
||||
defer func() {
|
||||
if err := lock.Release(ctx); err != nil {
|
||||
logger.Error(ctx, "could not release lock", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not release lock", logger.CapturedE(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
logger.Debug(ctx, "lock released")
|
||||
|
|
|
@ -30,7 +30,7 @@ func retryWithBackoff(ctx context.Context, attempts int, fn func(ctx context.Con
|
|||
return errors.Wrapf(err, "execution failed after %d attempts", attempts)
|
||||
}
|
||||
|
||||
logger.Error(ctx, "error while executing func, retrying with backoff", logger.E(err), logger.F("backoffDelay", backoffDelay), logger.F("remainingAttempts", attempts-count))
|
||||
logger.Error(ctx, "error while executing func, retrying with backoff", logger.CapturedE(err), logger.F("backoffDelay", backoffDelay), logger.F("remainingAttempts", attempts-count))
|
||||
|
||||
time.Sleep(backoffDelay)
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ func (d *Director) RequestTransformer() proxy.RequestTransformer {
|
|||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not retrieve layers from context", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve layers from context", logger.CapturedE(errors.WithStack(err)))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ func (d *Director) Middleware() proxy.Middleware {
|
|||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
r, err := d.rewriteRequest(r)
|
||||
if err != nil {
|
||||
logger.Error(r.Context(), "could not rewrite request", logger.E(errors.WithStack(err)))
|
||||
logger.Error(r.Context(), "could not rewrite request", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -240,7 +240,7 @@ func (d *Director) Middleware() proxy.Middleware {
|
|||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not retrieve proxy and layers from context", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve proxy and layers from context", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
|
|
@ -29,7 +29,7 @@ func (l *Layer) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
|
||||
options, err := fromStoreOptions(layer.Options)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not parse layer options", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not parse layer options", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -42,7 +42,7 @@ func (l *Layer) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
}
|
||||
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not execute pre-auth hook", logger.E(err))
|
||||
logger.Error(ctx, "could not execute pre-auth hook", logger.CapturedE(err))
|
||||
l.renderErrorPage(w, r, layer, options, err)
|
||||
|
||||
return
|
||||
|
@ -68,7 +68,7 @@ func (l *Layer) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
}
|
||||
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not authenticate user", logger.E(err))
|
||||
logger.Error(ctx, "could not authenticate user", logger.CapturedE(err))
|
||||
l.renderErrorPage(w, r, layer, options, err)
|
||||
|
||||
return
|
||||
|
@ -81,7 +81,7 @@ func (l *Layer) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
}
|
||||
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not apply rules", logger.E(err))
|
||||
logger.Error(ctx, "could not apply rules", logger.CapturedE(err))
|
||||
l.renderErrorPage(w, r, layer, options, err)
|
||||
|
||||
return
|
||||
|
@ -99,7 +99,7 @@ func (l *Layer) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
}
|
||||
|
||||
err = errors.WithStack(err)
|
||||
logger.Error(ctx, "could not execute post-auth hook", logger.E(err))
|
||||
logger.Error(ctx, "could not execute post-auth hook", logger.CapturedE(err))
|
||||
l.renderErrorPage(w, r, layer, options, err)
|
||||
|
||||
return
|
||||
|
@ -162,7 +162,7 @@ func (l *Layer) renderPage(w http.ResponseWriter, r *http.Request, page string,
|
|||
|
||||
tmpl, err := template.New("").Funcs(sprig.FuncMap()).ParseGlob(pattern)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not load authn templates", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not load authn templates", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -171,7 +171,7 @@ func (l *Layer) renderPage(w http.ResponseWriter, r *http.Request, page string,
|
|||
w.Header().Add("Cache-Control", "no-cache")
|
||||
|
||||
if err := tmpl.ExecuteTemplate(w, block, templateData); err != nil {
|
||||
logger.Error(ctx, "could not render authn page", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not render authn page", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
|
|
@ -44,7 +44,7 @@ func (a *Authenticator) PreAuthentication(w http.ResponseWriter, r *http.Request
|
|||
|
||||
sess, err := a.store.Get(r, a.getCookieName(options.Cookie.Name, layer.Proxy, layer.Name))
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve session", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve session", logger.CapturedE(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
loginCallbackURL, err := a.getLoginCallbackURL(originalURL, layer.Proxy, layer.Name, options)
|
||||
|
@ -128,7 +128,7 @@ func (a *Authenticator) Authenticate(w http.ResponseWriter, r *http.Request, lay
|
|||
|
||||
defer func() {
|
||||
if err := sess.Save(r, w); err != nil {
|
||||
logger.Error(ctx, "could not save session", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not save session", logger.CapturedE(errors.WithStack(err)))
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ func (c *Client) Provider() *oidc.Provider {
|
|||
func (c *Client) Authenticate(w http.ResponseWriter, r *http.Request, sess *sessions.Session, postLoginRedirectURL string) (*oidc.IDToken, error) {
|
||||
idToken, err := c.getIDToken(r, sess)
|
||||
if err != nil {
|
||||
logger.Warn(r.Context(), "could not retrieve idtoken", logger.E(errors.WithStack(err)))
|
||||
logger.Warn(r.Context(), "could not retrieve idtoken", logger.CapturedE(errors.WithStack(err)))
|
||||
|
||||
c.login(w, r, sess, postLoginRedirectURL)
|
||||
|
||||
|
@ -68,7 +68,7 @@ func (c *Client) login(w http.ResponseWriter, r *http.Request, sess *sessions.Se
|
|||
sess.Values[sessionKeyPostLoginRedirectURL] = postLoginRedirectURL
|
||||
|
||||
if err := sess.Save(r, w); err != nil {
|
||||
logger.Error(ctx, "could not save session", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not save session", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -127,7 +127,7 @@ func (c *Client) HandleLogout(w http.ResponseWriter, r *http.Request, sess *sess
|
|||
|
||||
rawIDToken, err := c.getRawIDToken(sess)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve raw id token", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve raw id token", logger.CapturedE(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
sess.Values[sessionKeyIDToken] = nil
|
||||
|
|
|
@ -52,7 +52,7 @@ func (q *Queue) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
|
||||
options, err := fromStoreOptions(layer.Options, q.defaultKeepAlive)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not parse layer options", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not parse layer options", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -71,7 +71,7 @@ func (q *Queue) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
|
||||
cookie, err := r.Cookie(cookieName)
|
||||
if err != nil && !errors.Is(err, http.ErrNoCookie) {
|
||||
logger.Error(ctx, "could not retrieve cookie", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve cookie", logger.CapturedE(errors.WithStack(err)))
|
||||
}
|
||||
|
||||
if cookie == nil {
|
||||
|
@ -89,7 +89,7 @@ func (q *Queue) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
|
||||
rank, err := q.adapter.Touch(ctx, queueName, sessionID)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve session rank", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve session rank", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -126,7 +126,7 @@ func (q *Queue) updateSessionsMetric(ctx context.Context, proxyName store.ProxyN
|
|||
|
||||
status, err := q.adapter.Status(ctx, queueName)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve queue status", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve queue status", logger.CapturedE(errors.WithStack(err)))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueNam
|
|||
|
||||
status, err := q.adapter.Status(ctx, queueName)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not retrieve queue status", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not retrieve queue status", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -157,7 +157,7 @@ func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueNam
|
|||
|
||||
tmpl, err := template.New("").Funcs(sprig.FuncMap()).ParseGlob(pattern)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not load queue templates", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not load queue templates", logger.CapturedE(errors.WithStack(err)))
|
||||
|
||||
return
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueNam
|
|||
})
|
||||
|
||||
if q.tmpl == nil {
|
||||
logger.Error(ctx, "queue page templates not loaded", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "queue page templates not loaded", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -195,7 +195,7 @@ func (q *Queue) renderQueuePage(w http.ResponseWriter, r *http.Request, queueNam
|
|||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
|
||||
if err := q.tmpl.ExecuteTemplate(w, "queue", templateData); err != nil {
|
||||
logger.Error(ctx, "could not render queue page", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not render queue page", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -211,7 +211,7 @@ func (q *Queue) refreshQueue(ctx context.Context, layerName store.LayerName, kee
|
|||
|
||||
if err := q.adapter.Refresh(ctx, string(layerName), keepAlive); err != nil {
|
||||
logger.Error(ctx, "could not refresh queue",
|
||||
logger.E(errors.WithStack(err)),
|
||||
logger.CapturedE(errors.WithStack(err)),
|
||||
logger.F("queue", layerName),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ func (l *Layer) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
|
||||
options, err := fromStoreOptions(layer.Options)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not parse layer options", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not parse layer options", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -52,7 +52,7 @@ func (l *Layer) Middleware(layer *store.Layer) proxy.Middleware {
|
|||
return
|
||||
}
|
||||
|
||||
logger.Error(ctx, "could not apply request rules", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not apply request rules", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
|
|
@ -223,7 +223,7 @@ func (s *Server) createReverseProxy(ctx context.Context, target *url.URL) *httpu
|
|||
func (s *Server) handleDefault(w http.ResponseWriter, r *http.Request) {
|
||||
err := errors.Errorf("no proxy target found")
|
||||
|
||||
logger.Error(r.Context(), "proxy error", logger.E(err))
|
||||
logger.Error(r.Context(), "proxy error", logger.CapturedE(err))
|
||||
sentry.CaptureException(err)
|
||||
|
||||
s.renderErrorPage(w, r, err, http.StatusBadGateway, http.StatusText(http.StatusBadGateway))
|
||||
|
@ -232,7 +232,7 @@ func (s *Server) handleDefault(w http.ResponseWriter, r *http.Request) {
|
|||
func (s *Server) handleError(w http.ResponseWriter, r *http.Request, err error) {
|
||||
err = errors.WithStack(err)
|
||||
|
||||
logger.Error(r.Context(), "proxy error", logger.E(err))
|
||||
logger.Error(r.Context(), "proxy error", logger.CapturedE(err))
|
||||
sentry.CaptureException(err)
|
||||
|
||||
s.renderErrorPage(w, r, err, http.StatusBadGateway, http.StatusText(http.StatusBadGateway))
|
||||
|
@ -266,7 +266,7 @@ func (s *Server) renderPage(w http.ResponseWriter, r *http.Request, page string,
|
|||
|
||||
tmpl, err := template.New("").Funcs(sprig.FuncMap()).ParseGlob(pattern)
|
||||
if err != nil {
|
||||
logger.Error(ctx, "could not load proxy templates", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not load proxy templates", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
@ -287,7 +287,7 @@ func (s *Server) renderPage(w http.ResponseWriter, r *http.Request, page string,
|
|||
}
|
||||
|
||||
if err := blockTmpl.Execute(w, templateData); err != nil {
|
||||
logger.Error(ctx, "could not render proxy page", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "could not render proxy page", logger.CapturedE(errors.WithStack(err)))
|
||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||
|
||||
return
|
||||
|
|
|
@ -56,7 +56,7 @@ func newRedisClient(conf config.RedisConfig) redis.UniversalClient {
|
|||
|
||||
for range timer.C {
|
||||
if _, err := client.Ping(ctx).Result(); err != nil {
|
||||
logger.Error(ctx, "redis disconnected", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "redis disconnected", logger.CapturedE(errors.WithStack(err)))
|
||||
connected = false
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -34,6 +34,10 @@ func SetupSentry(ctx context.Context, conf config.SentryConfig, release string)
|
|||
return nil, errors.WithStack(err)
|
||||
}
|
||||
|
||||
logger.SetCaptureFunc(func(err error) {
|
||||
sentry.CaptureException(err)
|
||||
})
|
||||
|
||||
flush := func() {
|
||||
sentry.Flush(time.Duration(*conf.FlushTimeout))
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ func WithRetry(ctx context.Context, client redis.UniversalClient, key string, fn
|
|||
for attempt := 0; attempt < maxAttempts; attempt++ {
|
||||
if err = WithTx(ctx, client, key, fn); err != nil {
|
||||
err = errors.WithStack(err)
|
||||
logger.Debug(ctx, "redis transaction failed", logger.E(err))
|
||||
logger.Debug(ctx, "redis transaction failed", logger.CapturedE(err))
|
||||
|
||||
if errors.Is(err, redis.TxFailedErr) {
|
||||
logger.Debug(ctx, "retrying redis transaction", logger.F("attempts", attempt), logger.F("delay", delay))
|
||||
|
@ -97,7 +97,7 @@ func WithRetry(ctx context.Context, client redis.UniversalClient, key string, fn
|
|||
return nil
|
||||
}
|
||||
|
||||
logger.Error(ctx, "redis error", logger.E(errors.WithStack(err)))
|
||||
logger.Error(ctx, "redis error", logger.CapturedE(errors.WithStack(err)))
|
||||
|
||||
return errors.WithStack(redis.TxFailedErr)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue