various fixes

This commit is contained in:
Roberto Bampi 2014-11-06 10:07:41 +01:00
parent 0e6a27180f
commit 8bbc74e9fb
3 changed files with 68 additions and 54 deletions

View File

@ -1,12 +1,15 @@
# Sentry Hook for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:" /> # Sentry Hook for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:" />
[Sentry](https://getsentry.com) provides both self-hosted and hostes solutions for exception tracking. [Sentry](https://getsentry.com) provides both self-hosted and hosted
Both client and server are [open source](https://github.com/getsentry/sentry). solutions for exception tracking.
Both client and server are
[open source](https://github.com/getsentry/sentry).
## Usage ## Usage
Every sentry application defined on the server gets a different [DNS](https://www.getsentry.com/docs/). In the example below replace `YOUR_DSN` with the one created for your application. Every sentry application defined on the server gets a different
[DSN](https://www.getsentry.com/docs/). In the example below replace
`YOUR_DSN` with the one created for your application.
```go ```go
import ( import (
@ -27,3 +30,13 @@ func main() {
} }
} }
``` ```
## Special fields
Some logrus fields have a special meaning in this hook,
these are server_name and logger.
When logs are sent to sentry these fields are treated differently.
- server_name (also known as hostname) is the name of the server which
is logging the event (hostname.example.com)
- logger is the part of the application which is logging the event.
In go this usually means setting it to the name of the package.

View File

@ -35,21 +35,18 @@ func getAndDel(d logrus.Fields, key string) (string, bool) {
// SentryHook delivers logs to a sentry server. // SentryHook delivers logs to a sentry server.
type SentryHook struct { type SentryHook struct {
// DSN for this application
// Modifications to this field after the call to NewSentryHook have no effect
DSN string
client *raven.Client client *raven.Client
levels []logrus.Level levels []logrus.Level
} }
// NewSentryHook creates a hook to be added to an instance of logger and initializes the raven client. // NewSentryHook creates a hook to be added to an instance of logger
// and initializes the raven client.
func NewSentryHook(DSN string, levels []logrus.Level) (*SentryHook, error) { func NewSentryHook(DSN string, levels []logrus.Level) (*SentryHook, error) {
client, err := raven.NewClient(DSN, nil) client, err := raven.NewClient(DSN, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &SentryHook{DSN, client, levels}, nil return &SentryHook{client, levels}, nil
} }
// Called when an event should be sent to sentry // Called when an event should be sent to sentry
@ -74,8 +71,8 @@ func (hook *SentryHook) Fire(entry *logrus.Entry) error {
} }
packet.Extra = map[string]interface{}(d) packet.Extra = map[string]interface{}(d)
_, errCh := hook.client.Capture(packet, nil) hook.client.Capture(packet, nil)
return <-errCh return nil
} }
// Levels returns the available logging levels. // Levels returns the available logging levels.

View File

@ -25,7 +25,7 @@ func getTestLogger() *logrus.Logger {
return l return l
} }
func getTestDSN(t *testing.T) (string, <-chan *raven.Packet, func()) { func WithTestDSN(t *testing.T, tf func(string, <-chan *raven.Packet)) {
pch := make(chan *raven.Packet, 1) pch := make(chan *raven.Packet, 1)
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
defer req.Body.Close() defer req.Body.Close()
@ -38,56 +38,60 @@ func getTestDSN(t *testing.T) (string, <-chan *raven.Packet, func()) {
pch <- p pch <- p
})) }))
defer s.Close()
fragments := strings.SplitN(s.URL, "://", 2) fragments := strings.SplitN(s.URL, "://", 2)
dsn := "%s://public:secret@%s/sentry/project-id" dsn := fmt.Sprintf(
"%s://public:secret@%s/sentry/project-id",
return fmt.Sprintf(dsn, fragments[0], fragments[1]), pch, s.Close fragments[0],
fragments[1],
)
tf(dsn, pch)
} }
func TestSpecialFields(t *testing.T) { func TestSpecialFields(t *testing.T) {
logger := getTestLogger() WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
dsn, pch, closeFn := getTestDSN(t) logger := getTestLogger()
defer closeFn()
hook, err := NewSentryHook(dsn, []logrus.Level{ hook, err := NewSentryHook(dsn, []logrus.Level{
logrus.ErrorLevel, logrus.ErrorLevel,
})
if err != nil {
t.Fatal(err.Error())
}
logger.Hooks.Add(hook)
logger.WithFields(logrus.Fields{
"server_name": server_name,
"logger": logger_name,
}).Error(message)
packet := <-pch
if packet.Logger != logger_name {
t.Errorf("logger should have been %s, was %s", logger_name, packet.Logger)
}
if packet.ServerName != server_name {
t.Errorf("server_name should have been %s, was %s", server_name, packet.ServerName)
}
}) })
if err != nil {
t.Fatal(err.Error())
}
logger.Hooks.Add(hook)
logger.WithFields(logrus.Fields{
"server_name": server_name,
"logger": logger_name,
}).Error(message)
packet := <-pch
if packet.Logger != logger_name {
t.Errorf("logger should have been %s, was %s", logger_name, packet.Logger)
}
if packet.ServerName != server_name {
t.Errorf("server_name should have been %s, was %s", server_name, packet.ServerName)
}
} }
func TestSentryHandler(t *testing.T) { func TestSentryHandler(t *testing.T) {
logger := getTestLogger() WithTestDSN(t, func(dsn string, pch <-chan *raven.Packet) {
dsn, pch, closeFn := getTestDSN(t) logger := getTestLogger()
defer closeFn() hook, err := NewSentryHook(dsn, []logrus.Level{
hook, err := NewSentryHook(dsn, []logrus.Level{ logrus.ErrorLevel,
logrus.ErrorLevel, })
}) if err != nil {
if err != nil { t.Fatal(err.Error())
t.Fatal(err.Error()) }
} logger.Hooks.Add(hook)
logger.Hooks.Add(hook)
logger.Error(message) logger.Error(message)
packet := <-pch packet := <-pch
if packet.Message != message { if packet.Message != message {
t.Errorf("message should have been %s, was %s", message, packet.Message) t.Errorf("message should have been %s, was %s", message, packet.Message)
} }
})
} }