diff --git a/README.md b/README.md index 90cdb79..d8efaf3 100644 --- a/README.md +++ b/README.md @@ -107,11 +107,15 @@ seen as a hint you want to add a field, however, you can still use the #### Hooks You can add hooks for logging levels. For example to send errors to an exception -tracking service on `Error`, `Fatal` and `Panic` or info to StatsD. +tracking service on `Error`, `Fatal` and `Panic` or info to StatsD. Note this is +not the real implementation of the Airbrake hook in logrus, just a sample. ```go -log = logrus.New() -log.Hooks.Add(new(AirbrakeHook)) +var log = logrus.New() + +func init() { + log.Hooks.Add(new(AirbrakeHook)) +} type AirbrakeHook struct{} @@ -139,6 +143,23 @@ func (hook *AirbrakeHook) Levels() []logrus.Level { } ``` +Logrus comes with built-in hooks. Add those, or your custom hook, in `init`: + +```go +import ( + "github.com/Sirupsen/logrus" + "github.com/Sirupsen/logrus/hooks/airbrake" +) + +func init() { + log.Hooks.Add(new(logrus_airbrake.AirbrakeHook)) +} +``` + +* [`github.com/Sirupsen/logrus/hooks/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. + #### Level logging Logrus has six logging levels: Debug, Info, Warning, Error, Fatal and Panic. diff --git a/airbrake.go b/airbrake.go new file mode 100644 index 0000000..69a151b --- /dev/null +++ b/airbrake.go @@ -0,0 +1,43 @@ +package logrus + +import ( + "github.com/tobi/airbrake-go" +) + +// AirbrakeHook to send exceptions to an exception-tracking service compatible +// with the Airbrake API. You must set: +// * airbrake.Endpoint +// * airbrake.ApiKey +// * airbrake.Environment (only sends exceptions when set to "production") +// +// Before using this hook, to send exceptions. Entries that trigger an Error, +// Fatal or Panic should now include an "Error" field to send to Airbrake. +type AirbrakeHook struct{} + +func (hook *AirbrakeHook) Fire(entry *Entry) error { + if entry.Data["error"] == nil { + entry.Logger.WithFields(Fields{ + "source": "airbrake", + "endpoint": airbrake.Endpoint, + }).Warn("Exceptions sent to Airbrake must have an 'error' key with the error") + return nil + } + + err := airbrake.Notify(entry.Data["error"].(error)) + if err != nil { + entry.Logger.WithFields(Fields{ + "source": "airbrake", + "endpoint": airbrake.Endpoint, + }).Warn("Failed to send error to Airbrake") + } + + return nil +} + +func (hook *AirbrakeHook) Levels() []Level { + return []Level{ + Error, + Fatal, + Panic, + } +} diff --git a/examples/basic/basic.go b/examples/basic/basic.go new file mode 100644 index 0000000..3594550 --- /dev/null +++ b/examples/basic/basic.go @@ -0,0 +1,29 @@ +package main + +import ( + "github.com/Sirupsen/logrus" +) + +var log = logrus.New() + +func init() { + log.Formatter = new(logrus.JSONFormatter) + log.Formatter = new(logrus.TextFormatter) // default +} + +func main() { + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(logrus.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(logrus.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") +} diff --git a/examples/hook/hook.go b/examples/hook/hook.go new file mode 100644 index 0000000..42e7a4c --- /dev/null +++ b/examples/hook/hook.go @@ -0,0 +1,35 @@ +package main + +import ( + "github.com/Sirupsen/logrus" + "github.com/Sirupsen/logrus/hooks/airbrake" + "github.com/tobi/airbrake-go" +) + +var log = logrus.New() + +func init() { + log.Formatter = new(logrus.TextFormatter) // default + log.Hooks.Add(new(logrus_airbrake.AirbrakeHook)) +} + +func main() { + airbrake.Endpoint = "https://exceptions.whatever.com/notifier_api/v2/notices.xml" + airbrake.ApiKey = "whatever" + airbrake.Environment = "production" + + log.WithFields(logrus.Fields{ + "animal": "walrus", + "size": 10, + }).Info("A group of walrus emerges from the ocean") + + log.WithFields(logrus.Fields{ + "omg": true, + "number": 122, + }).Warn("The group's number increased tremendously!") + + log.WithFields(logrus.Fields{ + "omg": true, + "number": 100, + }).Fatal("The ice breaks!") +} diff --git a/examples/text.go b/examples/text.go deleted file mode 100644 index cc4bfec..0000000 --- a/examples/text.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "os" - - "github.com/Sirupsen/logrus" -) - -func main() { - log := logrus.New() - if os.Getenv("LOG_FORMAT") == "json" { - log.Formatter = new(logrus.JSONFormatter) - } else { - log.Formatter = new(logrus.TextFormatter) - } - - for { - log.WithFields(logrus.Fields{ - "animal": "walrus", - "size": 10, - }).Print("A group of walrus emerges from the ocean") - - log.WithFields(logrus.Fields{ - "omg": true, - "number": 122, - }).Warn("The group's number increased tremendously!") - - log.WithFields(logrus.Fields{ - "animal": "walrus", - "size": 10, - }).Print("A giant walrus appears!") - - log.WithFields(logrus.Fields{ - "animal": "walrus", - "size": 9, - }).Print("Tremendously sized cow enters the ocean.") - - log.WithFields(logrus.Fields{ - "omg": true, - "number": 100, - }).Fatal("The ice breaks!") - } -} diff --git a/hooks/airbrake/airbrake.go b/hooks/airbrake/airbrake.go new file mode 100644 index 0000000..1dff9b2 --- /dev/null +++ b/hooks/airbrake/airbrake.go @@ -0,0 +1,44 @@ +package logrus_airbrake + +import ( + "github.com/Sirupsen/logrus" + "github.com/tobi/airbrake-go" +) + +// AirbrakeHook to send exceptions to an exception-tracking service compatible +// with the Airbrake API. You must set: +// * airbrake.Endpoint +// * airbrake.ApiKey +// * airbrake.Environment (only sends exceptions when set to "production") +// +// Before using this hook, to send exceptions. Entries that trigger an Error, +// Fatal or Panic should now include an "Error" field to send to Airbrake. +type AirbrakeHook struct{} + +func (hook *AirbrakeHook) Fire(entry *logrus.Entry) error { + if entry.Data["error"] == nil { + entry.Logger.WithFields(logrus.Fields{ + "source": "airbrake", + "endpoint": airbrake.Endpoint, + }).Warn("Exceptions sent to Airbrake must have an 'error' key with the error") + return nil + } + + err := airbrake.Notify(entry.Data["error"].(error)) + if err != nil { + entry.Logger.WithFields(logrus.Fields{ + "source": "airbrake", + "endpoint": airbrake.Endpoint, + }).Warn("Failed to send error to Airbrake") + } + + return nil +} + +func (hook *AirbrakeHook) Levels() []logrus.Level { + return []logrus.Level{ + logrus.Error, + logrus.Fatal, + logrus.Panic, + } +}