forked from mirror/logrus
various fixes
This commit is contained in:
parent
0e6a27180f
commit
8bbc74e9fb
|
@ -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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue