From 6b18d5cf62777c0f31878bde65f6bd90bf847680 Mon Sep 17 00:00:00 2001 From: Philip Allen Date: Fri, 17 Apr 2015 10:51:07 -0400 Subject: [PATCH 1/3] Added Raygun hook. --- hooks/raygun/raygun.go | 50 +++++++++++++++++++ hooks/raygun/raygun_test.go | 97 +++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 hooks/raygun/raygun.go create mode 100644 hooks/raygun/raygun_test.go diff --git a/hooks/raygun/raygun.go b/hooks/raygun/raygun.go new file mode 100644 index 0000000..ec16719 --- /dev/null +++ b/hooks/raygun/raygun.go @@ -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, + } +} diff --git a/hooks/raygun/raygun_test.go b/hooks/raygun/raygun_test.go new file mode 100644 index 0000000..eda4b83 --- /dev/null +++ b/hooks/raygun/raygun_test.go @@ -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 +} From d97bbff05eae1c848b40de99880f374b293a5e82 Mon Sep 17 00:00:00 2001 From: Philip Allen Date: Fri, 1 May 2015 10:48:23 -0400 Subject: [PATCH 2/3] Moving raygun hook to its own repositiroy at github.com/squirkle/logrus-raygun-hook --- hooks/raygun/README.md | 18 +++++++ hooks/raygun/raygun.go | 50 ------------------- hooks/raygun/raygun_test.go | 97 ------------------------------------- 3 files changed, 18 insertions(+), 147 deletions(-) create mode 100644 hooks/raygun/README.md delete mode 100644 hooks/raygun/raygun.go delete mode 100644 hooks/raygun/raygun_test.go diff --git a/hooks/raygun/README.md b/hooks/raygun/README.md new file mode 100644 index 0000000..83e552b --- /dev/null +++ b/hooks/raygun/README.md @@ -0,0 +1,18 @@ +# [logrus-raygun-hook](https://github.com/squirkle/logrus-raygun-hook) +A Raygun.io hook for logrus + +## Usage + +```go +import ( + log "github.com/Sirupsen/logrus" + "github.com/squirkle/logrus-raygun-hook" +) + +func init() { + log.AddHook(raygun.NewHook("https://api.raygun.io/entries", "yourApiKey", true)) +} +``` + +## Project status +Both this logrus hook and the [goraygun](https://github.com/SDITools/goraygun) library are **works in progress**. Be aware of the possibility of upcoming improvements/API changes. diff --git a/hooks/raygun/raygun.go b/hooks/raygun/raygun.go deleted file mode 100644 index ec16719..0000000 --- a/hooks/raygun/raygun.go +++ /dev/null @@ -1,50 +0,0 @@ -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, - } -} diff --git a/hooks/raygun/raygun_test.go b/hooks/raygun/raygun_test.go deleted file mode 100644 index eda4b83..0000000 --- a/hooks/raygun/raygun_test.go +++ /dev/null @@ -1,97 +0,0 @@ -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 -} From 099b1bffe00aba347076c7f06dcc91210e5e9b15 Mon Sep 17 00:00:00 2001 From: Philip Allen Date: Thu, 21 May 2015 10:28:14 -0400 Subject: [PATCH 3/3] removing raygun hook from hooks dir, adding reference in hooks table of main README.md --- README.md | 1 + hooks/raygun/README.md | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 hooks/raygun/README.md diff --git a/README.md b/README.md index 64e4914..3578dea 100644 --- a/README.md +++ b/README.md @@ -211,6 +211,7 @@ func init() { | [Slackrus](https://github.com/johntdyer/slackrus) | Hook for Slack chat. | | [Journalhook](https://github.com/wercker/journalhook) | Hook for logging to `systemd-journald` | | [Graylog](https://github.com/gemnasium/logrus-hooks/tree/master/graylog) | Hook for logging to [Graylog](http://graylog2.org/) | +| [Raygun](https://github.com/squirkle/logrus-raygun-hook) | Hook for logging to [Raygun.io](http://raygun.io/) | #### Level logging diff --git a/hooks/raygun/README.md b/hooks/raygun/README.md deleted file mode 100644 index 83e552b..0000000 --- a/hooks/raygun/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# [logrus-raygun-hook](https://github.com/squirkle/logrus-raygun-hook) -A Raygun.io hook for logrus - -## Usage - -```go -import ( - log "github.com/Sirupsen/logrus" - "github.com/squirkle/logrus-raygun-hook" -) - -func init() { - log.AddHook(raygun.NewHook("https://api.raygun.io/entries", "yourApiKey", true)) -} -``` - -## Project status -Both this logrus hook and the [goraygun](https://github.com/SDITools/goraygun) library are **works in progress**. Be aware of the possibility of upcoming improvements/API changes.