sentry.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package sentry
  2. import (
  3. "net/http"
  4. "time"
  5. "github.com/getsentry/sentry-go"
  6. )
  7. const (
  8. // flushTimeout is the maximum time to wait for Sentry to send events
  9. flushTimeout = 5 * time.Second
  10. )
  11. // reporter is a Sentry error reporter
  12. type reporter struct {
  13. hub *sentry.Hub
  14. }
  15. // New creates and configures a new Sentry reporter
  16. func New(config *Config) (*reporter, error) {
  17. if err := config.Validate(); err != nil {
  18. return nil, err
  19. }
  20. if len(config.DSN) == 0 {
  21. return nil, nil
  22. }
  23. client, err := sentry.NewClient(sentry.ClientOptions{
  24. Dsn: config.DSN,
  25. Release: config.Release,
  26. Environment: config.Environment,
  27. })
  28. if err != nil {
  29. return nil, err
  30. }
  31. hub := sentry.NewHub(client, sentry.NewScope())
  32. return &reporter{hub: hub}, nil
  33. }
  34. func (r *reporter) Report(err error, req *http.Request, meta map[string]any) {
  35. hub := r.hub.Clone()
  36. hub.Scope().SetRequest(req)
  37. hub.Scope().SetLevel(sentry.LevelError)
  38. if meta != nil {
  39. hub.Scope().SetContext("Processing context", meta)
  40. }
  41. // imgproxy wraps almost all errors into *ierrors.Error, so Sentry will show
  42. // the same error type for all errors. We need to fix it.
  43. //
  44. // Instead of using hub.CaptureException(err), we need to create an event
  45. // manually and replace `*ierrors.Error` with the wrapped error type
  46. // (which is the previous exception type in the exception chain).
  47. if event := hub.Client().EventFromException(err, sentry.LevelError); event != nil {
  48. for i := 1; i < len(event.Exception); i++ {
  49. if event.Exception[i].Type == "*ierrors.Error" {
  50. event.Exception[i].Type = event.Exception[i-1].Type
  51. }
  52. }
  53. hub.CaptureEvent(event)
  54. }
  55. }
  56. func (r *reporter) Close() {
  57. r.hub.Flush(flushTimeout)
  58. }