瀏覽代碼

Add processing options and source image URL to error reports

DarthSim 1 年之前
父節點
當前提交
71aea9b507

+ 3 - 0
CHANGELOG.md

@@ -1,6 +1,9 @@
 # Changelog
 
 ## [Unreleased]
+### Add
+- Add processing/info options and source image URL to error reports.
+
 ### Change
 - Support configuring OpenTelemetry with standard [general](https://opentelemetry.io/docs/languages/sdk-configuration/general/) and [OTLP Exporter](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/) environment variables.
 - `IMGPROXY_MAX_SRC_RESOLUTION` default value is increased to 50.

+ 19 - 4
errorreport/airbrake/airbrake.go

@@ -2,12 +2,18 @@ package airbrake
 
 import (
 	"net/http"
+	"strings"
 
 	"github.com/airbrake/gobrake/v5"
+
 	"github.com/imgproxy/imgproxy/v3/config"
 )
 
-var notifier *gobrake.Notifier
+var (
+	notifier *gobrake.Notifier
+
+	metaReplacer = strings.NewReplacer(" ", "-")
+)
 
 func Init() {
 	if len(config.AirbrakeProjecKey) > 0 {
@@ -19,10 +25,19 @@ func Init() {
 	}
 }
 
-func Report(err error, req *http.Request) {
-	if notifier != nil {
-		notifier.Notify(err, req)
+func Report(err error, req *http.Request, meta map[string]any) {
+	if notifier == nil {
+		return
 	}
+
+	notice := notifier.Notice(err, req, 2)
+
+	for k, v := range meta {
+		key := metaReplacer.Replace(strings.ToLower(k))
+		notice.Context[key] = v
+	}
+
+	notifier.SendNoticeAsync(notice)
 }
 
 func Close() {

+ 11 - 3
errorreport/bugsnag/bugsnag.go

@@ -4,6 +4,7 @@ import (
 	"net/http"
 
 	"github.com/bugsnag/bugsnag-go/v2"
+
 	"github.com/imgproxy/imgproxy/v3/config"
 )
 
@@ -19,8 +20,15 @@ func Init() {
 	}
 }
 
-func Report(err error, req *http.Request) {
-	if enabled {
-		bugsnag.Notify(err, req)
+func Report(err error, req *http.Request, meta map[string]any) {
+	if !enabled {
+		return
+	}
+
+	extra := make(bugsnag.MetaData)
+	for k, v := range meta {
+		extra.Add("Processing Context", k, v)
 	}
+
+	bugsnag.Notify(err, req, extra)
 }

+ 26 - 4
errorreport/errorreport.go

@@ -1,6 +1,7 @@
 package errorreport
 
 import (
+	"context"
 	"net/http"
 
 	"github.com/imgproxy/imgproxy/v3/errorreport/airbrake"
@@ -9,6 +10,8 @@ import (
 	"github.com/imgproxy/imgproxy/v3/errorreport/sentry"
 )
 
+type metaCtxKey struct{}
+
 func Init() {
 	bugsnag.Init()
 	honeybadger.Init()
@@ -16,11 +19,30 @@ func Init() {
 	airbrake.Init()
 }
 
+func StartRequest(req *http.Request) context.Context {
+	meta := make(map[string]any)
+	return context.WithValue(req.Context(), metaCtxKey{}, meta)
+}
+
+func SetMetadata(req *http.Request, key string, value any) {
+	meta, ok := req.Context().Value(metaCtxKey{}).(map[string]any)
+	if !ok || meta == nil {
+		return
+	}
+
+	meta[key] = value
+}
+
 func Report(err error, req *http.Request) {
-	bugsnag.Report(err, req)
-	honeybadger.Report(err, req)
-	sentry.Report(err, req)
-	airbrake.Report(err, req)
+	meta, ok := req.Context().Value(metaCtxKey{}).(map[string]any)
+	if !ok {
+		meta = nil
+	}
+
+	bugsnag.Report(err, req, meta)
+	honeybadger.Report(err, req, meta)
+	sentry.Report(err, req, meta)
+	airbrake.Report(err, req, meta)
 }
 
 func Close() {

+ 17 - 9
errorreport/honeybadger/honeybadger.go

@@ -5,13 +5,14 @@ import (
 	"strings"
 
 	"github.com/honeybadger-io/honeybadger-go"
+
 	"github.com/imgproxy/imgproxy/v3/config"
 )
 
 var (
 	enabled bool
 
-	headersReplacer = strings.NewReplacer("-", "_")
+	metaReplacer = strings.NewReplacer("-", "_", " ", "_")
 )
 
 func Init() {
@@ -24,15 +25,22 @@ func Init() {
 	}
 }
 
-func Report(err error, req *http.Request) {
-	if enabled {
-		headers := make(honeybadger.CGIData)
+func Report(err error, req *http.Request, meta map[string]any) {
+	if !enabled {
+		return
+	}
 
-		for k, v := range req.Header {
-			key := "HTTP_" + headersReplacer.Replace(strings.ToUpper(k))
-			headers[key] = v[0]
-		}
+	extra := make(honeybadger.CGIData, len(req.Header)+len(meta))
 
-		honeybadger.Notify(err, req.URL, headers)
+	for k, v := range req.Header {
+		key := "HTTP_" + metaReplacer.Replace(strings.ToUpper(k))
+		extra[key] = v[0]
 	}
+
+	for k, v := range meta {
+		key := metaReplacer.Replace(strings.ToUpper(k))
+		extra[key] = v
+	}
+
+	honeybadger.Notify(err, req.URL, extra)
 }

+ 17 - 9
errorreport/sentry/sentry.go

@@ -5,6 +5,7 @@ import (
 	"time"
 
 	"github.com/getsentry/sentry-go"
+
 	"github.com/imgproxy/imgproxy/v3/config"
 )
 
@@ -26,14 +27,21 @@ func Init() {
 	}
 }
 
-func Report(err error, req *http.Request) {
-	if enabled {
-		hub := sentry.CurrentHub().Clone()
-		hub.Scope().SetRequest(req)
-		hub.Scope().SetLevel(sentry.LevelError)
-		eventID := hub.CaptureException(err)
-		if eventID != nil {
-			hub.Flush(timeout)
-		}
+func Report(err error, req *http.Request, meta map[string]any) {
+	if !enabled {
+		return
+	}
+
+	hub := sentry.CurrentHub().Clone()
+	hub.Scope().SetRequest(req)
+	hub.Scope().SetLevel(sentry.LevelError)
+
+	if meta != nil {
+		hub.Scope().SetContext("Processing context", meta)
+	}
+
+	eventID := hub.CaptureException(err)
+	if eventID != nil {
+		hub.Flush(timeout)
 	}
 }

+ 3 - 0
processing_handler.go

@@ -241,6 +241,9 @@ func handleProcessing(reqID string, rw http.ResponseWriter, r *http.Request) {
 	po, imageURL, err := options.ParsePath(path, r.Header)
 	checkErr(ctx, "path_parsing", err)
 
+	errorreport.SetMetadata(r, "Source Image URL", imageURL)
+	errorreport.SetMetadata(r, "Processing Options", po)
+
 	err = security.VerifySourceURL(imageURL)
 	checkErr(ctx, "security", err)
 

+ 3 - 0
server.go

@@ -132,6 +132,9 @@ func withSecret(h router.RouteHandler) router.RouteHandler {
 
 func withPanicHandler(h router.RouteHandler) router.RouteHandler {
 	return func(reqID string, rw http.ResponseWriter, r *http.Request) {
+		ctx := errorreport.StartRequest(r)
+		r = r.WithContext(ctx)
+
 		defer func() {
 			if rerr := recover(); rerr != nil {
 				if rerr == http.ErrAbortHandler {