honeybadger.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. package honeybadger
  2. import (
  3. "log/slog"
  4. "net/http"
  5. "reflect"
  6. "strings"
  7. "github.com/honeybadger-io/honeybadger-go"
  8. "github.com/imgproxy/imgproxy/v3/ierrors"
  9. )
  10. var (
  11. metaReplacer = strings.NewReplacer("-", "_", " ", "_")
  12. )
  13. type reporter struct {
  14. client *honeybadger.Client
  15. }
  16. func New(config *Config) (*reporter, error) {
  17. if err := config.Validate(); err != nil {
  18. return nil, err
  19. }
  20. if len(config.Key) == 0 {
  21. return nil, nil
  22. }
  23. client := honeybadger.New(honeybadger.Configuration{
  24. APIKey: config.Key,
  25. Env: config.Env,
  26. })
  27. return &reporter{client: client}, nil
  28. }
  29. func (r *reporter) Report(err error, req *http.Request, meta map[string]any) {
  30. extra := make(honeybadger.CGIData, len(req.Header)+len(meta))
  31. for k, v := range req.Header {
  32. key := "HTTP_" + metaReplacer.Replace(strings.ToUpper(k))
  33. extra[key] = v[0]
  34. }
  35. for k, v := range meta {
  36. key := metaReplacer.Replace(strings.ToUpper(k))
  37. extra[key] = v
  38. }
  39. hbErr := honeybadger.NewError(err)
  40. if e, ok := err.(*ierrors.Error); ok {
  41. hbErr.Class = reflect.TypeOf(e.Unwrap()).String()
  42. }
  43. if _, repErr := r.client.Notify(hbErr, req.URL, extra); repErr != nil {
  44. slog.Warn("Failed to report error to Honeybadger", "error", repErr)
  45. }
  46. }
  47. func (r *reporter) Close() {
  48. r.client.Flush()
  49. }