diff --git a/README.md b/README.md index 9ab0bc2..6b82928 100644 --- a/README.md +++ b/README.md @@ -8,22 +8,21 @@ func modifyToSentryLogger(log *zap.Logger, client *sentry.Client) *zap.Logger { cfg := zapsentry.Configuration{ Level: zapcore.ErrorLevel, //when to send message to sentry EnableBreadcrumbs: true, // enable sending breadcrumbs to Sentry - BreadcrumbLevel: zapcore.InfoLevel, // at what level should we sent breadcrumbs to sentry + BreadcrumbLevel: zapcore.InfoLevel, // at what level should we sent breadcrumbs to sentry, this level can't be higher than `Level` Tags: map[string]string{ "component": "system", }, } core, err := zapsentry.NewCore(cfg, zapsentry.NewSentryClientFromClient(client)) - //in case of err it will return noop core. so we can safely attach it + // don't use value if error was returned. Noop core will be replaced to nil soon. if err != nil { - log.Warn("failed to init zap", zap.Error(err)) + panic(err) } log = zapsentry.AttachCoreToLogger(core, log) - // to use breadcrumbs feature - create new scope explicitly - // and attach after attaching the core + // if you have web service, create a new scope somewhere in middleware to have valid breadcrumbs. return log.With(zapsentry.NewScope()) } ``` diff --git a/core.go b/core.go index 6199aed..8b69503 100644 --- a/core.go +++ b/core.go @@ -3,7 +3,6 @@ package zapsentry import ( "errors" "reflect" - "strings" "time" "github.com/getsentry/sentry-go" @@ -20,48 +19,8 @@ const ( var ( ErrInvalidBreadcrumbLevel = errors.New("breadcrumb level must be lower than or equal to error level") - - defaultFrameMatchers = FrameMatchers{ - SkipModulePrefixFrameMatcher("github.com/TheZeroSlave/zapsentry"), - SkipFunctionPrefixFrameMatcher("go.uber.org/zap"), - } -) - -type ( - FrameMatcher interface { - Matches(f sentry.Frame) bool - } - FrameMatchers []FrameMatcher - FrameMatcherFunc func(f sentry.Frame) bool - SkipModulePrefixFrameMatcher string - SkipFunctionPrefixFrameMatcher string ) -func (f FrameMatcherFunc) Matches(frame sentry.Frame) bool { - return f(frame) -} - -func (f SkipModulePrefixFrameMatcher) Matches(frame sentry.Frame) bool { - return strings.HasPrefix(frame.Module, string(f)) -} - -func (f SkipFunctionPrefixFrameMatcher) Matches(frame sentry.Frame) bool { - return strings.HasPrefix(frame.Function, string(f)) -} - -func (ff FrameMatchers) Matches(frame sentry.Frame) bool { - for i := range ff { - if ff[i].Matches(frame) { - return true - } - } - return false -} - -func CombineFrameMatchers(matcher ...FrameMatcher) FrameMatcher { - return FrameMatchers(matcher) -} - func NewScopeFromScope(scope *sentry.Scope) zapcore.Field { f := zap.Skip() f.Interface = scope @@ -88,18 +47,19 @@ func NewCore(cfg Configuration, factory SentryClientFactory) (zapcore.Core, erro cfg.MaxBreadcrumbs = defaultMaxBreadcrumbs } - // copy default values to avoid accidental modification + // copy default values to prevent accidental modification. matchers := make(FrameMatchers, len(defaultFrameMatchers), len(defaultFrameMatchers)+1) copy(matchers, defaultFrameMatchers) - switch m := cfg.FrameMatcher.(type) { - case nil: - cfg.FrameMatcher = matchers - case FrameMatchers: - // in case the configured matcher was already a collection, append the default ones to avoid nested looping - cfg.FrameMatcher = append(matchers, m...) - default: + if cfg.FrameMatcher != nil { cfg.FrameMatcher = append(matchers, cfg.FrameMatcher) + } else { + cfg.FrameMatcher = matchers + } + + var flushTimeout = time.Second * 5 + if cfg.FlushTimeout > 0 { + flushTimeout = cfg.FlushTimeout } core := core{ @@ -110,14 +70,10 @@ func NewCore(cfg Configuration, factory SentryClientFactory) (zapcore.Core, erro breadcrumbsLevel: cfg.BreadcrumbLevel, enableBreadcrumbs: cfg.EnableBreadcrumbs, }, - flushTimeout: 5 * time.Second, + flushTimeout: flushTimeout, fields: make(map[string]interface{}), } - if cfg.FlushTimeout > 0 { - core.flushTimeout = cfg.FlushTimeout - } - return &core, nil } @@ -138,8 +94,7 @@ func (c *core) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.Check func (c *core) Write(ent zapcore.Entry, fs []zapcore.Field) error { clone := c.with(c.addSpecialFields(ent, fs)) - // only when we have local sentryScope to avoid collecting all breadcrumbs ever in a global scope - if c.cfg.EnableBreadcrumbs && c.cfg.BreadcrumbLevel.Enabled(ent.Level) && c.scope() != nil { + if c.cfg.EnableBreadcrumbs && c.cfg.BreadcrumbLevel.Enabled(ent.Level) { breadcrumb := sentry.Breadcrumb{ Message: ent.Message, Data: clone.fields, @@ -363,10 +318,6 @@ func (c *core) with(fs []zapcore.Field) *core { } } -type ClientGetter interface { - GetClient() *sentry.Client -} - func (c *core) GetClient() *sentry.Client { return c.client } @@ -404,13 +355,3 @@ func (c *core) filterFrames(frames []sentry.Frame) []sentry.Frame { return frames } - -type LevelEnabler struct { - zapcore.LevelEnabler - enableBreadcrumbs bool - breadcrumbsLevel zapcore.LevelEnabler -} - -func (l *LevelEnabler) Enabled(lvl zapcore.Level) bool { - return l.LevelEnabler.Enabled(lvl) || (l.enableBreadcrumbs && l.breadcrumbsLevel.Enabled(lvl)) -} diff --git a/frame_matcher.go b/frame_matcher.go new file mode 100644 index 0000000..334b82f --- /dev/null +++ b/frame_matcher.go @@ -0,0 +1,50 @@ +package zapsentry + +import ( + "strings" + + "github.com/getsentry/sentry-go" +) + +type ( + FrameMatchers []FrameMatcher + FrameMatcherFunc func(f sentry.Frame) bool + SkipModulePrefixFrameMatcher string + SkipFunctionPrefixFrameMatcher string +) + +type FrameMatcher interface { + Matches(f sentry.Frame) bool +} + +var ( + defaultFrameMatchers = FrameMatchers{ + SkipModulePrefixFrameMatcher("github.com/TheZeroSlave/zapsentry"), + SkipFunctionPrefixFrameMatcher("go.uber.org/zap"), + } +) + +func (f FrameMatcherFunc) Matches(frame sentry.Frame) bool { + return f(frame) +} + +func (f SkipModulePrefixFrameMatcher) Matches(frame sentry.Frame) bool { + return strings.HasPrefix(frame.Module, string(f)) +} + +func (f SkipFunctionPrefixFrameMatcher) Matches(frame sentry.Frame) bool { + return strings.HasPrefix(frame.Function, string(f)) +} + +func (ff FrameMatchers) Matches(frame sentry.Frame) bool { + for i := range ff { + if ff[i].Matches(frame) { + return true + } + } + return false +} + +func CombineFrameMatchers(matcher ...FrameMatcher) FrameMatcher { + return FrameMatchers(matcher) +} diff --git a/core_test.go b/frame_matcher_test.go similarity index 100% rename from core_test.go rename to frame_matcher_test.go diff --git a/level.go b/level.go new file mode 100644 index 0000000..1d5ec65 --- /dev/null +++ b/level.go @@ -0,0 +1,13 @@ +package zapsentry + +import "go.uber.org/zap/zapcore" + +type LevelEnabler struct { + zapcore.LevelEnabler + enableBreadcrumbs bool + breadcrumbsLevel zapcore.LevelEnabler +} + +func (l *LevelEnabler) Enabled(lvl zapcore.Level) bool { + return l.LevelEnabler.Enabled(lvl) || (l.enableBreadcrumbs && l.breadcrumbsLevel.Enabled(lvl)) +}