...
1 package sentryhandler
2
3 import (
4 "github.com/getsentry/raven-go"
5 "github.com/pkg/errors"
6
7 "github.com/goph/emperror"
8 "github.com/goph/emperror/httperr"
9 "github.com/goph/emperror/internal/keyvals"
10 )
11
12
13 type Handler struct {
14 client *raven.Client
15
16 sendSynchronously bool
17 }
18
19
20 func New(dsn string) (*Handler, error) {
21 client, err := raven.New(dsn)
22 if err != nil {
23 return nil, errors.Wrap(err, "failed to create raven client")
24 }
25
26 return NewFromClient(client), nil
27 }
28
29
30 func NewSync(dsn string) (*Handler, error) {
31 handler, err := New(dsn)
32 if err != nil {
33 return nil, err
34 }
35
36 handler.sendSynchronously = true
37
38 return handler, nil
39 }
40
41
42 func NewFromClient(client *raven.Client) *Handler {
43 return &Handler{
44 client: client,
45 }
46 }
47
48
49 func NewSyncFromClient(client *raven.Client) *Handler {
50 handler := NewFromClient(client)
51
52 handler.sendSynchronously = true
53
54 return handler
55 }
56
57
58 func (h *Handler) Handle(err error) {
59 var interfaces []raven.Interface
60
61
62 if req, ok := httperr.HTTPRequest(err); ok {
63 interfaces = append(interfaces, raven.NewHttp(req))
64 }
65
66 packet := raven.NewPacketWithExtra(
67 err.Error(),
68 keyvals.ToMap(emperror.Context(err)),
69 append(
70 interfaces,
71 raven.NewException(
72 err,
73 raven.GetOrNewStacktrace(emperror.ExposeStackTrace(err), 1, 3, h.client.IncludePaths()),
74 ),
75 )...,
76 )
77
78 eventID, ch := h.client.Capture(packet, nil)
79
80 if h.sendSynchronously && eventID != "" {
81 <-ch
82 }
83 }
84
85
86 func (h *Handler) Close() error {
87 h.client.Close()
88 h.client.Wait()
89
90 return nil
91 }
92
View as plain text