Skip to content

Commit 90acff1

Browse files
authored
Merge pull request #53 from scribd/laynax/SERF-1828/fix-sentry
[SERF-1828] Send sentry event via hook only of error is provided
2 parents c8fad6a + 91353e9 commit 90acff1

File tree

5 files changed

+83
-42
lines changed

5 files changed

+83
-42
lines changed

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,14 +542,15 @@ production:
542542
dsn: "https://<key>@sentry.io/<project>"
543543
```
544544

545-
The tracking can be enabled from the `Builder` with the `SetTracking`
546-
function:
545+
The tracking can be enabled from the `Logger Builder` with the `SetTracking`
546+
function. To trigger tracking, use `logger` with `WithError(err)` as follows:
547547

548548
```go
549549
package main
550550
551551
import (
552552
"log"
553+
"errors"
553554
554555
sdklogger "github.com/scribd/go-sdk/pkg/logger"
555556
sdktracking "github.com/scribd/go-sdk/pkg/tracking"
@@ -573,6 +574,9 @@ func main() {
573574
if Logger, err = sdklogger.NewBuilder(loggerConfig).SetTracking(trackingConfig).Build(); err != nil {
574575
log.Fatalf("Failed to load SDK logger: %s", err.Error())
575576
}
577+
578+
err = errors.New("new error")
579+
logger.WithError(err).Errorf("trying sentry error functionality")
576580
```
577581

578582
A logger build with a valid tracking configuration will automatically

pkg/logger/logger.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,6 @@ type Logger interface {
5353
// Note that it doesn't log until you call Debug, Print, Info,
5454
// Warn, Fatal or Panic on the Entry it returns.
5555
WithFields(keyValues Fields) Logger
56+
// WithError sets an error field value with logurs.Errorkey key.
57+
WithError(err error) Logger
5658
}

pkg/logger/logrus.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ func (l *logrusLogEntry) WithFields(fields Fields) Logger {
151151
}
152152
}
153153

154+
// WithError sets an error field on logrus logger.
155+
func (l *logrusLogEntry) WithError(err error) Logger {
156+
return &logrusLogEntry{
157+
entry: l.entry.WithError(err),
158+
}
159+
}
160+
154161
// SetTracking configures and enables the error reporting.
155162
func (l *logrusLogEntry) setTracking(trackingConfig *tracking.Config) error {
156163
hook, err := tracking.NewSentryHook(trackingConfig)

pkg/tracking/sentry.go

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package tracking
22

33
import (
4+
"fmt"
5+
46
"github.com/getsentry/sentry-go"
57
"github.com/sirupsen/logrus"
68
)
@@ -22,7 +24,6 @@ var (
2224
// It's used for sending errors and messages to Sentry on specific
2325
// log levels. It wraps a default Sentry client.
2426
type Hook struct {
25-
client *sentry.Client
2627
levels []logrus.Level
2728
tags map[string]string
2829
release string
@@ -38,21 +39,23 @@ func (hook *Hook) Levels() []logrus.Level {
3839
// Fire uses the configured Sentry client to report the given Logrus Entry as
3940
// Sentry Event.
4041
func (hook *Hook) Fire(entry *logrus.Entry) error {
41-
exceptions := []sentry.Exception{}
42-
43-
if err, ok := entry.Data[logrus.ErrorKey].(error); ok && err != nil {
44-
stacktrace := sentry.ExtractStacktrace(err)
45-
if stacktrace == nil {
46-
stacktrace = sentry.NewStacktrace()
47-
}
48-
exceptions = append(exceptions, sentry.Exception{
49-
Type: entry.Message,
50-
Value: err.Error(),
51-
Stacktrace: stacktrace,
52-
})
42+
entryError, ok := entry.Data[logrus.ErrorKey].(error)
43+
if !ok || entryError == nil {
44+
return nil
45+
}
46+
47+
stacktrace := sentry.ExtractStacktrace(entryError)
48+
if stacktrace == nil {
49+
stacktrace = sentry.NewStacktrace()
5350
}
5451

55-
event := sentry.Event{
52+
exceptions := []sentry.Exception{{
53+
Type: entry.Message,
54+
Value: entryError.Error(),
55+
Stacktrace: stacktrace,
56+
}}
57+
58+
event := &sentry.Event{
5659
Level: levelsMap[entry.Level],
5760
Message: entry.Message,
5861
Extra: map[string]interface{}(entry.Data),
@@ -62,8 +65,7 @@ func (hook *Hook) Fire(entry *logrus.Entry) error {
6265
Exception: exceptions,
6366
}
6467

65-
hub := sentry.CurrentHub()
66-
hook.client.CaptureEvent(&event, nil, hub.Scope())
68+
sentry.CaptureEvent(event)
6769

6870
return nil
6971
}
@@ -92,15 +94,10 @@ func (hook *Hook) SetEnvironment(environment string) {
9294
}
9395

9496
// NewSentryHook creates a hook to be added to an instance of logger
95-
// and initializes the Sentry client.
97+
// and initializes Sentry in package level. SentryHook will be triggered
98+
// on Panic, Fatal and Error levels.
9699
func NewSentryHook(config *Config) (*Hook, error) {
97-
levels := []logrus.Level{
98-
logrus.PanicLevel,
99-
logrus.FatalLevel,
100-
logrus.ErrorLevel,
101-
}
102-
103-
client, err := sentry.NewClient(sentry.ClientOptions{
100+
if err := sentry.Init(sentry.ClientOptions{
104101
// The DSN to use. If the DSN is not set, the client is effectively disabled.
105102
Dsn: config.SentryDSN,
106103
// In debug mode, the debug information is printed to stdout to help you understand what
@@ -116,20 +113,18 @@ func NewSentryHook(config *Config) (*Hook, error) {
116113
Release: config.release,
117114
// The environment to be sent with events.
118115
Environment: config.environment,
119-
})
120-
if err != nil {
121-
return nil, err
116+
}); err != nil {
117+
return nil, fmt.Errorf("initializing sentry. err: %w", err)
122118
}
123119

124-
hook := Hook{
125-
client: client,
126-
levels: levels,
127-
tags: map[string]string{},
128-
}
129-
130-
if len(hook.levels) == 0 {
131-
hook.levels = logrus.AllLevels
120+
levels := []logrus.Level{
121+
logrus.PanicLevel,
122+
logrus.FatalLevel,
123+
logrus.ErrorLevel,
132124
}
133125

134-
return &hook, nil
126+
return &Hook{
127+
levels: levels,
128+
tags: map[string]string{},
129+
}, nil
135130
}

pkg/tracking/sentry_test.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,37 @@
11
package tracking
22

33
import (
4+
"errors"
5+
"io/ioutil"
46
"testing"
57

8+
"github.com/getsentry/sentry-go"
69
"github.com/sirupsen/logrus"
710
"github.com/stretchr/testify/assert"
811
)
912

10-
const testSentryDSN = "https://[email protected]/0000000"
13+
const (
14+
testSentryDSNValid = "https://[email protected]/0000000"
15+
testSentryDSNInvalid = "invalidSentryDSN"
16+
)
17+
18+
func TestNewSentryHook(t *testing.T) {
19+
hook, err := NewSentryHook(&Config{})
20+
assert.NoError(t, err)
21+
22+
logger := newMockLogger(hook)
23+
24+
assert.Empty(t, sentry.LastEventID(),
25+
"eventID must be empty without calling sentry hook levels")
26+
27+
logger.Errorf("sample message")
28+
assert.Empty(t, sentry.LastEventID(),
29+
"eventID must be empty without calling WithError")
30+
31+
logger.WithError(errors.New("sample error")).Errorf("sample message")
32+
assert.NotEmpty(t, sentry.LastEventID(),
33+
"last eventID must be set as expected")
34+
}
1135

1236
func TestSentryHookLevels(t *testing.T) {
1337
config := Config{}
@@ -17,19 +41,19 @@ func TestSentryHookLevels(t *testing.T) {
1741
}
1842

1943
func TestSentryHookDsn(t *testing.T) {
20-
config := Config{SentryDSN: testSentryDSN}
44+
config := Config{SentryDSN: testSentryDSNValid}
2145
_, err := NewSentryHook(&config)
2246
assert.NoError(t, err)
2347
}
2448

2549
func TestSentryHookErrorOnInvalidDsn(t *testing.T) {
26-
config := Config{SentryDSN: "invalidSentryDSN"}
50+
config := Config{SentryDSN: testSentryDSNInvalid}
2751
_, err := NewSentryHook(&config)
2852
assert.Error(t, err)
2953
}
3054

3155
func TestSentryHookManualTag(t *testing.T) {
32-
config := Config{SentryDSN: testSentryDSN}
56+
config := Config{SentryDSN: testSentryDSNValid}
3357
hook, err := NewSentryHook(&config)
3458
assert.NoError(t, err)
3559

@@ -46,3 +70,12 @@ func TestSentryHookManualTag(t *testing.T) {
4670
assert.NoError(t, err)
4771
assert.Equal(t, value, hook.tags[key])
4872
}
73+
74+
func newMockLogger(hook *Hook) *logrus.Logger {
75+
logger := logrus.New()
76+
77+
logger.SetOutput(ioutil.Discard)
78+
logger.Hooks.Add(hook)
79+
80+
return logger
81+
}

0 commit comments

Comments
 (0)