Merge pull request #261 from gemnasium/move-airbrake

Move airbrake
diff --git a/README.md b/README.md
index a0c0644..e23e701 100644
--- a/README.md
+++ b/README.md
@@ -75,17 +75,12 @@
 import (
   "os"
   log "github.com/Sirupsen/logrus"
-  "github.com/Sirupsen/logrus/hooks/airbrake"
 )
 
 func init() {
   // Log as JSON instead of the default ASCII formatter.
   log.SetFormatter(&log.JSONFormatter{})
 
-  // Use the Airbrake hook to report errors that have Error severity or above to
-  // an exception tracker. You can create custom hooks, see the Hooks section.
-  log.AddHook(airbrake.NewHook("https://example.com", "xyz", "development"))
-
   // Output to stderr instead of stdout, could also be a file.
   log.SetOutput(os.Stderr)
 
@@ -182,13 +177,16 @@
 ```go
 import (
   log "github.com/Sirupsen/logrus"
-  "github.com/Sirupsen/logrus/hooks/airbrake"
+  "gopkg.in/gemnasium/logrus-airbrake-hook.v2" // the package is named "aibrake"
   logrus_syslog "github.com/Sirupsen/logrus/hooks/syslog"
   "log/syslog"
 )
 
 func init() {
-  log.AddHook(airbrake.NewHook("https://example.com", "xyz", "development"))
+
+  // Use the Airbrake hook to report errors that have Error severity or above to
+  // an exception tracker. You can create custom hooks, see the Hooks section.
+  log.AddHook(airbrake.NewHook(123, "xyz", "production"))
 
   hook, err := logrus_syslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
   if err != nil {
@@ -202,7 +200,8 @@
 
 | Hook  | Description |
 | ----- | ----------- |
-| [Airbrake](https://github.com/Sirupsen/logrus/blob/master/hooks/airbrake/airbrake.go) | Send errors to an exception tracking service compatible with the Airbrake API. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
+| [Airbrake](https://github.com/gemnasium/logrus-airbrake-hook) | Send errors to the Airbrake API V3. Uses the official [`gobrake`](https://github.com/airbrake/gobrake) behind the scenes. |
+| [Airbrake "legacy"](https://github.com/gemnasium/logrus-airbrake-legacy-hook) | Send errors to an exception tracking service compatible with the Airbrake API V2. Uses [`airbrake-go`](https://github.com/tobi/airbrake-go) behind the scenes. |
 | [Papertrail](https://github.com/Sirupsen/logrus/blob/master/hooks/papertrail/papertrail.go) | Send errors to the Papertrail hosted logging service via UDP. |
 | [Syslog](https://github.com/Sirupsen/logrus/blob/master/hooks/syslog/syslog.go) | Send errors to remote syslog server. Uses standard library `log/syslog` behind the scenes. |
 | [BugSnag](https://github.com/Sirupsen/logrus/blob/master/hooks/bugsnag/bugsnag.go) | Send errors to the Bugsnag exception tracking service. |
diff --git a/hooks/airbrake/airbrake.go b/hooks/airbrake/airbrake.go
deleted file mode 100644
index b0502c3..0000000
--- a/hooks/airbrake/airbrake.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package airbrake
-
-import (
-	"errors"
-	"fmt"
-
-	"github.com/Sirupsen/logrus"
-	"github.com/tobi/airbrake-go"
-)
-
-// AirbrakeHook to send exceptions to an exception-tracking service compatible
-// with the Airbrake API.
-type airbrakeHook struct {
-	APIKey      string
-	Endpoint    string
-	Environment string
-}
-
-func NewHook(endpoint, apiKey, env string) *airbrakeHook {
-	return &airbrakeHook{
-		APIKey:      apiKey,
-		Endpoint:    endpoint,
-		Environment: env,
-	}
-}
-
-func (hook *airbrakeHook) Fire(entry *logrus.Entry) error {
-	airbrake.ApiKey = hook.APIKey
-	airbrake.Endpoint = hook.Endpoint
-	airbrake.Environment = hook.Environment
-
-	var notifyErr error
-	err, ok := entry.Data["error"].(error)
-	if ok {
-		notifyErr = err
-	} else {
-		notifyErr = errors.New(entry.Message)
-	}
-
-	airErr := airbrake.Notify(notifyErr)
-	if airErr != nil {
-		return fmt.Errorf("Failed to send error to Airbrake: %s", airErr)
-	}
-
-	return nil
-}
-
-func (hook *airbrakeHook) Levels() []logrus.Level {
-	return []logrus.Level{
-		logrus.ErrorLevel,
-		logrus.FatalLevel,
-		logrus.PanicLevel,
-	}
-}
diff --git a/hooks/airbrake/airbrake_test.go b/hooks/airbrake/airbrake_test.go
deleted file mode 100644
index 058a91e..0000000
--- a/hooks/airbrake/airbrake_test.go
+++ /dev/null
@@ -1,133 +0,0 @@
-package airbrake
-
-import (
-	"encoding/xml"
-	"net/http"
-	"net/http/httptest"
-	"testing"
-	"time"
-
-	"github.com/Sirupsen/logrus"
-)
-
-type notice struct {
-	Error NoticeError `xml:"error"`
-}
-type NoticeError struct {
-	Class   string `xml:"class"`
-	Message string `xml:"message"`
-}
-
-type customErr struct {
-	msg string
-}
-
-func (e *customErr) Error() string {
-	return e.msg
-}
-
-const (
-	testAPIKey    = "abcxyz"
-	testEnv       = "development"
-	expectedClass = "*airbrake.customErr"
-	expectedMsg   = "foo"
-	unintendedMsg = "Airbrake will not see this string"
-)
-
-var (
-	noticeError = make(chan NoticeError, 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 := startAirbrakeServer(t)
-	defer ts.Close()
-
-	hook := NewHook(ts.URL, testAPIKey, "production")
-	log.Hooks.Add(hook)
-
-	log.Error(expectedMsg)
-
-	select {
-	case received := <-noticeError:
-		if received.Message != expectedMsg {
-			t.Errorf("Unexpected message received: %s", received.Message)
-		}
-	case <-time.After(time.Second):
-		t.Error("Timed out; no notice received by Airbrake 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 := startAirbrakeServer(t)
-	defer ts.Close()
-
-	hook := NewHook(ts.URL, testAPIKey, "production")
-	log.Hooks.Add(hook)
-
-	log.WithFields(logrus.Fields{
-		"error": &customErr{expectedMsg},
-	}).Error(unintendedMsg)
-
-	select {
-	case received := <-noticeError:
-		if received.Message != expectedMsg {
-			t.Errorf("Unexpected message received: %s", received.Message)
-		}
-		if received.Class != expectedClass {
-			t.Errorf("Unexpected error class: %s", received.Class)
-		}
-	case <-time.After(time.Second):
-		t.Error("Timed out; no notice received by Airbrake API")
-	}
-}
-
-// TestLogEntryWithNonErrorTypeNotReceived confirms that, when passing a
-// non-error type using logrus.Fields, a HTTP server emulating an Airbrake
-// endpoint receives the logrus.Entry.Message string.
-//
-// Only error types are supported when setting the 'error' field using
-// logrus.WithFields().
-func TestLogEntryWithNonErrorTypeNotReceived(t *testing.T) {
-	log := logrus.New()
-	ts := startAirbrakeServer(t)
-	defer ts.Close()
-
-	hook := NewHook(ts.URL, testAPIKey, "production")
-	log.Hooks.Add(hook)
-
-	log.WithFields(logrus.Fields{
-		"error": expectedMsg,
-	}).Error(unintendedMsg)
-
-	select {
-	case received := <-noticeError:
-		if received.Message != unintendedMsg {
-			t.Errorf("Unexpected message received: %s", received.Message)
-		}
-	case <-time.After(time.Second):
-		t.Error("Timed out; no notice received by Airbrake API")
-	}
-}
-
-func startAirbrakeServer(t *testing.T) *httptest.Server {
-	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		var notice notice
-		if err := xml.NewDecoder(r.Body).Decode(&notice); err != nil {
-			t.Error(err)
-		}
-		r.Body.Close()
-
-		noticeError <- notice.Error
-	}))
-
-	return ts
-}