-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathclient.go
121 lines (103 loc) · 3.25 KB
/
client.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package honeybadger
import (
"net/http"
)
// The Payload interface is implemented by any type which can be handled by the
// Backend interface.
type Payload interface {
toJSON() []byte
}
// The Backend interface is implemented by the server type by default, but a
// custom implementation may be configured by the user.
type Backend interface {
Notify(feature Feature, payload Payload) error
}
type noticeHandler func(*Notice) error
// Client is the manager for interacting with the Honeybadger service. It holds
// the configuration and implements the public API.
type Client struct {
Config *Configuration
context *contextSync
worker worker
beforeNotifyHandlers []noticeHandler
}
// Configure updates the client configuration with the supplied config.
func (client *Client) Configure(config Configuration) {
client.Config.update(&config)
}
// SetContext updates the client context with supplied context.
func (client *Client) SetContext(context Context) {
client.context.Update(context)
}
// Flush blocks until the worker has processed its queue.
func (client *Client) Flush() {
client.worker.Flush()
}
// BeforeNotify adds a callback function which is run before a notice is
// reported to Honeybadger. If any function returns an error the notification
// will be skipped, otherwise it will be sent.
func (client *Client) BeforeNotify(handler func(notice *Notice) error) {
client.beforeNotifyHandlers = append(client.beforeNotifyHandlers, handler)
}
// Notify reports the error err to the Honeybadger service.
func (client *Client) Notify(err interface{}, extra ...interface{}) (string, error) {
extra = append([]interface{}{client.context.internal}, extra...)
notice := newNotice(client.Config, newError(err, 2), extra...)
for _, handler := range client.beforeNotifyHandlers {
if err := handler(notice); err != nil {
return "", err
}
}
notifyFn := func() error {
return client.Config.Backend.Notify(Notices, notice)
}
if client.Config.Sync {
if notifyErr := notifyFn(); notifyErr != nil {
client.Config.Logger.Printf("notify error: %v\n", notifyErr)
return "", notifyErr
}
} else {
if workerPushErr := client.worker.Push(notifyFn); workerPushErr != nil {
client.Config.Logger.Printf("worker error: %v\n", workerPushErr)
return "", workerPushErr
}
}
return notice.Token, nil
}
// Monitor automatically reports panics which occur in the function it's called
// from. Must be deferred.
func (client *Client) Monitor() {
if err := recover(); err != nil {
client.Notify(newError(err, 2))
client.Flush()
panic(err)
}
}
// Handler returns an http.Handler function which automatically reports panics
// to Honeybadger and then re-panics.
func (client *Client) Handler(h http.Handler) http.Handler {
if h == nil {
h = http.DefaultServeMux
}
fn := func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
client.Notify(newError(err, 2), r)
panic(err)
}
}()
h.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
// New returns a new instance of Client.
func New(c Configuration) *Client {
config := newConfig(c)
worker := newBufferedWorker(config)
client := Client{
Config: config,
worker: worker,
context: newContextSync(),
}
return &client
}