Skip to content

Commit f43c181

Browse files
authored
Structured logging support for logrus (#1036)
1 parent f28f498 commit f43c181

File tree

6 files changed

+912
-166
lines changed

6 files changed

+912
-166
lines changed

_examples/logrus/main.go

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,47 @@ import (
66
"os"
77
"time"
88

9-
"github.com/sirupsen/logrus"
10-
119
"github.com/getsentry/sentry-go"
1210
sentrylogrus "github.com/getsentry/sentry-go/logrus"
11+
"github.com/sirupsen/logrus"
1312
)
1413

1514
func main() {
15+
// Initialize Logrus
1616
logger := logrus.New()
1717

1818
// Log DEBUG and higher level logs to STDERR
1919
logger.Level = logrus.DebugLevel
2020
logger.Out = os.Stderr
2121

22-
// Send only ERROR and higher level logs to Sentry
23-
sentryLevels := []logrus.Level{logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel}
22+
// send logs on InfoLevel
23+
logHook, err := sentrylogrus.NewLogHook(
24+
[]logrus.Level{logrus.InfoLevel},
25+
sentry.ClientOptions{
26+
Dsn: "your-public-dsn",
27+
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
28+
if hint.Context != nil {
29+
if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
30+
// You have access to the original Request
31+
fmt.Println(req)
32+
}
33+
}
34+
fmt.Println(event)
35+
return event
36+
},
37+
// need to have logs enabled
38+
EnableLogs: true,
39+
Debug: true,
40+
AttachStacktrace: true,
41+
})
2442

25-
sentryHook, err := sentrylogrus.New(sentryLevels, sentry.ClientOptions{
26-
Dsn: "",
43+
// send events on Error, Fatal, Panic levels
44+
eventHook, err := sentrylogrus.NewEventHook([]logrus.Level{
45+
logrus.ErrorLevel,
46+
logrus.FatalLevel,
47+
logrus.PanicLevel,
48+
}, sentry.ClientOptions{
49+
Dsn: "your-public-dsn",
2750
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
2851
if hint.Context != nil {
2952
if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
@@ -40,14 +63,19 @@ func main() {
4063
if err != nil {
4164
panic(err)
4265
}
43-
defer sentryHook.Flush(5 * time.Second)
44-
logger.AddHook(sentryHook)
66+
defer eventHook.Flush(5 * time.Second)
67+
defer logHook.Flush(5 * time.Second)
68+
logger.AddHook(eventHook)
69+
logger.AddHook(logHook)
4570

4671
// Flushes before calling os.Exit(1) when using logger.Fatal
4772
// (else all defers are not called, and Sentry does not have time to send the event)
48-
logrus.RegisterExitHandler(func() { sentryHook.Flush(5 * time.Second) })
73+
logrus.RegisterExitHandler(func() {
74+
eventHook.Flush(5 * time.Second)
75+
logHook.Flush(5 * time.Second)
76+
})
4977

50-
// Log a InfoLevel entry STDERR which is not sent to Sentry
78+
// Log a InfoLevel entry STDERR which is sent as a log to Sentry
5179
logger.Infof("Application has started")
5280

5381
// Log an error to STDERR which is also sent to Sentry

logrus/README.md

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,32 +32,78 @@ import (
3232
func main() {
3333
// Initialize Logrus
3434
logger := logrus.New()
35+
36+
// Log DEBUG and higher level logs to STDERR
3537
logger.Level = logrus.DebugLevel
3638
logger.Out = os.Stderr
3739

38-
// Define log levels to send to Sentry
39-
sentryLevels := []logrus.Level{logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel}
40-
41-
// Initialize Sentry
42-
sentryHook, err := sentrylogrus.New(sentryLevels, sentry.ClientOptions{
40+
// send logs on InfoLevel
41+
logHook, err := sentrylogrus.NewLogHook(
42+
[]logrus.Level{logrus.InfoLevel},
43+
sentry.ClientOptions{
44+
Dsn: "your-public-dsn",
45+
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
46+
if hint.Context != nil {
47+
if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
48+
// You have access to the original Request
49+
fmt.Println(req)
50+
}
51+
}
52+
fmt.Println(event)
53+
return event
54+
},
55+
// need to have logs enabled
56+
EnableLogs: true,
57+
Debug: true,
58+
AttachStacktrace: true,
59+
})
60+
61+
// send events on Error, Fatal, Panic levels
62+
eventHook, err := sentrylogrus.NewEventHook([]logrus.Level{
63+
logrus.ErrorLevel,
64+
logrus.FatalLevel,
65+
logrus.PanicLevel,
66+
}, sentry.ClientOptions{
4367
Dsn: "your-public-dsn",
4468
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
45-
fmt.Println(event) // Optional debugging
69+
if hint.Context != nil {
70+
if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
71+
// You have access to the original Request
72+
fmt.Println(req)
73+
}
74+
}
75+
fmt.Println(event)
4676
return event
4777
},
48-
Debug: true,
78+
Debug: true,
79+
AttachStacktrace: true,
4980
})
5081
if err != nil {
5182
panic(err)
5283
}
53-
defer sentryHook.Flush(5 * time.Second)
54-
logger.AddHook(sentryHook)
84+
defer eventHook.Flush(5 * time.Second)
85+
defer logHook.Flush(5 * time.Second)
86+
logger.AddHook(eventHook)
87+
logger.AddHook(logHook)
88+
89+
// Flushes before calling os.Exit(1) when using logger.Fatal
90+
// (else all defers are not called, and Sentry does not have time to send the event)
91+
logrus.RegisterExitHandler(func() {
92+
eventHook.Flush(5 * time.Second)
93+
logHook.Flush(5 * time.Second)
94+
})
5595

56-
// Example logging
57-
logger.WithField("user", "test-user").Error("An error occurred")
96+
// Log a InfoLevel entry STDERR which is sent as a log to Sentry
97+
logger.Infof("Application has started")
98+
99+
// Log an error to STDERR which is also sent to Sentry
100+
logger.Errorf("oh no!")
58101

59-
// Ensure all events are flushed before exit
60-
logrus.RegisterExitHandler(func() { sentryHook.Flush(5 * time.Second) })
102+
// Log a fatal error to STDERR, which sends an event to Sentry and terminates the application
103+
logger.Fatalf("can't continue...")
104+
105+
// Example of logging with attributes
106+
logger.WithField("user", "test-user").Error("An error occurred")
61107
}
62108
```
63109

logrus/go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,14 @@ require (
99
github.com/google/go-cmp v0.6.0
1010
github.com/pkg/errors v0.9.1
1111
github.com/sirupsen/logrus v1.9.3
12+
github.com/stretchr/testify v1.8.4
1213
)
1314

1415
require (
16+
github.com/davecgh/go-spew v1.1.1 // indirect
17+
github.com/kr/text v0.2.0 // indirect
18+
github.com/pmezard/go-difflib v1.0.0 // indirect
1519
golang.org/x/sys v0.18.0 // indirect
1620
golang.org/x/text v0.14.0 // indirect
21+
gopkg.in/yaml.v3 v3.0.1 // indirect
1722
)

logrus/go.sum

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
1+
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
12
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
23
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
34
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
45
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
56
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
67
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
78
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
9+
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
10+
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
11+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
12+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
813
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
914
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
1015
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
1116
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
1217
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1318
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
19+
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
20+
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
1421
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
1522
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
1623
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
1724
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
18-
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
19-
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
25+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
26+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
2027
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
2128
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
2229
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -25,6 +32,8 @@ golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
2532
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
2633
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
2734
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
35+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
36+
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
2837
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
2938
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
3039
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)