Added Raygun hook.

This commit is contained in:
Philip Allen 2015-04-17 10:51:07 -04:00
parent 55eb11d21d
commit 6b18d5cf62
2 changed files with 147 additions and 0 deletions

50
hooks/raygun/raygun.go Normal file
View File

@ -0,0 +1,50 @@
package raygun
import (
"errors"
"net/http"
"github.com/Sirupsen/logrus"
"github.com/sditools/goraygun"
)
type raygunHook struct {
client *goraygun.Client
}
func NewHook(Endpoint string, ApiKey string, Enabled bool) *raygunHook {
client := goraygun.Init(goraygun.Settings{
ApiKey: ApiKey,
Endpoint: Endpoint,
Enabled: Enabled,
}, goraygun.Entry{})
return &raygunHook{client}
}
func (hook *raygunHook) Fire(logEntry *logrus.Entry) error {
// Start with a copy of the default entry
raygunEntry := hook.client.Entry
if request, ok := logEntry.Data["request"]; ok {
raygunEntry.Details.Request.Populate(*(request.(*http.Request)))
}
var reportErr error
if err, ok := logEntry.Data["error"]; ok {
reportErr = err.(error)
} else {
reportErr = errors.New(logEntry.Message)
}
hook.client.Report(reportErr, raygunEntry)
return nil
}
func (hook *raygunHook) Levels() []logrus.Level {
return []logrus.Level{
logrus.ErrorLevel,
logrus.FatalLevel,
logrus.PanicLevel,
}
}

View File

@ -0,0 +1,97 @@
package raygun
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/Sirupsen/logrus"
"github.com/sditools/goraygun"
)
type customErr struct {
msg string
}
func (e *customErr) Error() string {
return e.msg
}
const (
testAPIKey = "abcxyz"
expectedClass = "github.com/Sirupsen/logrus/hooks/raygun"
expectedMsg = "oh no some error occured."
unintendedMsg = "Airbrake will not see this string"
)
var (
entryCh = make(chan goraygun.Entry, 1)
)
// TestLogEntryMessageReceived checks if invoking Logrus' log.Error
// method causes an XML payload containing the log entry message is received
// by a HTTP server emulating an Airbrake-compatible endpoint.
func TestLogEntryMessageReceived(t *testing.T) {
log := logrus.New()
ts := startRaygunServer(t)
defer ts.Close()
hook := NewHook(ts.URL, testAPIKey, true)
log.Hooks.Add(hook)
log.Error(expectedMsg)
select {
case received := <-entryCh:
if received.Details.Error.Message != expectedMsg {
t.Errorf("Unexpected message received: %s", received)
}
case <-time.After(time.Second):
t.Error("Timed out; no notice received by Raygun API")
}
}
// TestLogEntryMessageReceived confirms that, when passing an error type using
// logrus.Fields, a HTTP server emulating an Airbrake endpoint receives the
// error message returned by the Error() method on the error interface
// rather than the logrus.Entry.Message string.
func TestLogEntryWithErrorReceived(t *testing.T) {
log := logrus.New()
ts := startRaygunServer(t)
defer ts.Close()
hook := NewHook(ts.URL, testAPIKey, true)
log.Hooks.Add(hook)
log.WithFields(logrus.Fields{
"error": &customErr{expectedMsg},
}).Error(unintendedMsg)
select {
case received := <-entryCh:
if received.Details.Error.Message != expectedMsg {
t.Errorf("Unexpected message received: %s", received.Details.Error.Message)
}
if received.Details.Error.ClassName != expectedClass {
t.Errorf("Unexpected error class: %s", received.Details.Error.ClassName)
}
case <-time.After(time.Second):
t.Error("Timed out; no notice received by Airbrake API")
}
}
func startRaygunServer(t *testing.T) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var entry goraygun.Entry
if err := json.NewDecoder(r.Body).Decode(&entry); err != nil {
t.Error(err)
}
r.Body.Close()
entryCh <- entry
}))
return ts
}