132 lines
4.5 KiB
Go
132 lines
4.5 KiB
Go
|
package bugsnag
|
||
|
|
||
|
import (
|
||
|
"github.com/bugsnag/bugsnag-go/errors"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"os"
|
||
|
"sync"
|
||
|
|
||
|
// Fixes a bug with SHA-384 intermediate certs on some platforms.
|
||
|
// - https://github.com/bugsnag/bugsnag-go/issues/9
|
||
|
_ "crypto/sha512"
|
||
|
)
|
||
|
|
||
|
// The current version of bugsnag-go.
|
||
|
const VERSION = "1.0.2"
|
||
|
|
||
|
var once sync.Once
|
||
|
var middleware middlewareStack
|
||
|
|
||
|
// The configuration for the default bugsnag notifier.
|
||
|
var Config Configuration
|
||
|
|
||
|
var defaultNotifier = Notifier{&Config, nil}
|
||
|
|
||
|
// Configure Bugsnag. The only required setting is the APIKey, which can be
|
||
|
// obtained by clicking on "Settings" in your Bugsnag dashboard. This function
|
||
|
// is also responsible for installing the global panic handler, so it should be
|
||
|
// called as early as possible in your initialization process.
|
||
|
func Configure(config Configuration) {
|
||
|
Config.update(&config)
|
||
|
once.Do(Config.PanicHandler)
|
||
|
}
|
||
|
|
||
|
// Notify sends an error to Bugsnag along with the current stack trace. The
|
||
|
// rawData is used to send extra information along with the error. For example
|
||
|
// you can pass the current http.Request to Bugsnag to see information about it
|
||
|
// in the dashboard, or set the severity of the notification.
|
||
|
func Notify(err error, rawData ...interface{}) error {
|
||
|
return defaultNotifier.Notify(errors.New(err, 1), rawData...)
|
||
|
}
|
||
|
|
||
|
// AutoNotify logs a panic on a goroutine and then repanics.
|
||
|
// It should only be used in places that have existing panic handlers further
|
||
|
// up the stack. See bugsnag.Recover(). The rawData is used to send extra
|
||
|
// information along with any panics that are handled this way.
|
||
|
// Usage: defer bugsnag.AutoNotify()
|
||
|
func AutoNotify(rawData ...interface{}) {
|
||
|
if err := recover(); err != nil {
|
||
|
rawData = defaultNotifier.addDefaultSeverity(rawData, SeverityError)
|
||
|
defaultNotifier.Notify(errors.New(err, 2), rawData...)
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Recover logs a panic on a goroutine and then recovers.
|
||
|
// The rawData is used to send extra information along with
|
||
|
// any panics that are handled this way
|
||
|
// Usage: defer bugsnag.Recover()
|
||
|
func Recover(rawData ...interface{}) {
|
||
|
if err := recover(); err != nil {
|
||
|
rawData = defaultNotifier.addDefaultSeverity(rawData, SeverityWarning)
|
||
|
defaultNotifier.Notify(errors.New(err, 2), rawData...)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// OnBeforeNotify adds a callback to be run before a notification is sent to
|
||
|
// Bugsnag. It can be used to modify the event or its MetaData. Changes made
|
||
|
// to the configuration are local to notifying about this event. To prevent the
|
||
|
// event from being sent to Bugsnag return an error, this error will be
|
||
|
// returned from bugsnag.Notify() and the event will not be sent.
|
||
|
func OnBeforeNotify(callback func(event *Event, config *Configuration) error) {
|
||
|
middleware.OnBeforeNotify(callback)
|
||
|
}
|
||
|
|
||
|
// Handler creates an http Handler that notifies Bugsnag any panics that
|
||
|
// happen. It then repanics so that the default http Server panic handler can
|
||
|
// handle the panic too. The rawData is used to send extra information along
|
||
|
// with any panics that are handled this way.
|
||
|
func Handler(h http.Handler, rawData ...interface{}) http.Handler {
|
||
|
notifier := New(rawData...)
|
||
|
if h == nil {
|
||
|
h = http.DefaultServeMux
|
||
|
}
|
||
|
|
||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||
|
defer notifier.AutoNotify(r)
|
||
|
h.ServeHTTP(w, r)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// HandlerFunc creates an http HandlerFunc that notifies Bugsnag about any
|
||
|
// panics that happen. It then repanics so that the default http Server panic
|
||
|
// handler can handle the panic too. The rawData is used to send extra
|
||
|
// information along with any panics that are handled this way. If you have
|
||
|
// already wrapped your http server using bugsnag.Handler() you don't also need
|
||
|
// to wrap each HandlerFunc.
|
||
|
func HandlerFunc(h http.HandlerFunc, rawData ...interface{}) http.HandlerFunc {
|
||
|
notifier := New(rawData...)
|
||
|
|
||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||
|
defer notifier.AutoNotify(r)
|
||
|
h(w, r)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
// Set up builtin middlewarez
|
||
|
OnBeforeNotify(httpRequestMiddleware)
|
||
|
|
||
|
// Default configuration
|
||
|
Config.update(&Configuration{
|
||
|
APIKey: "",
|
||
|
Endpoint: "https://notify.bugsnag.com/",
|
||
|
Hostname: "",
|
||
|
AppVersion: "",
|
||
|
ReleaseStage: "",
|
||
|
ParamsFilters: []string{"password", "secret"},
|
||
|
// * for app-engine
|
||
|
ProjectPackages: []string{"main*"},
|
||
|
NotifyReleaseStages: nil,
|
||
|
Logger: log.New(os.Stdout, log.Prefix(), log.Flags()),
|
||
|
PanicHandler: defaultPanicHandler,
|
||
|
Transport: http.DefaultTransport,
|
||
|
})
|
||
|
|
||
|
hostname, err := os.Hostname()
|
||
|
if err == nil {
|
||
|
Config.Hostname = hostname
|
||
|
}
|
||
|
}
|