Skip to content

Instantly share code, notes, and snippets.

@vmihailenco
Created September 2, 2015 10:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vmihailenco/1fe2808e1a5b77180aaf to your computer and use it in GitHub Desktop.
Save vmihailenco/1fe2808e1a5b77180aaf to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"net/http"
"reflect"
"runtime"
"github.com/codegangsta/negroni"
"gopkg.in/airbrake/gobrake.v2"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, http.StatusText(http.StatusBadRequest))
})
mux.HandleFunc("/hello", func(w http.ResponseWriter, req *http.Request) {
w.WriteHeader(http.StatusTeapot)
fmt.Fprintf(w, http.StatusText(http.StatusTeapot))
})
airbrake := gobrake.NewNotifier(1234567, "FIXME")
defer func() {
if v := recover(); v != nil {
airbrake.Notify(v, nil)
panic(v)
}
}()
defer airbrake.Flush()
n := negroni.Classic()
n.Use(&AirbrakeMiddleware{
mux: mux,
airbrake: airbrake,
})
n.UseHandler(mux)
n.Run(":3000")
}
func getFunc(fn interface{}) *runtime.Func {
v := reflect.ValueOf(fn)
return runtime.FuncForPC(v.Pointer())
}
type AirbrakeMiddleware struct {
mux *http.ServeMux
airbrake *gobrake.Notifier
}
func (m *AirbrakeMiddleware) ServeHTTP(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
next(w, req)
nw := w.(negroni.ResponseWriter)
if nw.Status() < 300 {
return
}
h, pat := m.mux.Handler(req)
msg := fmt.Sprintf("%s %s", pat, http.StatusText(nw.Status()))
notice := m.airbrake.Notice(msg, req, 12)
fn := getFunc(h)
file, line := fn.FileLine(fn.Entry())
backtrace := []gobrake.StackFrame{{file, line, fn.Name()}}
backtrace = append(backtrace, notice.Errors[0].Backtrace...)
notice.Errors[0].Backtrace = backtrace
go m.airbrake.SendNotice(notice)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment