136 lines
2.8 KiB
Go
136 lines
2.8 KiB
Go
package log
|
|
|
|
import (
|
|
"go.uber.org/zap/zapcore"
|
|
"time"
|
|
)
|
|
import "github.com/getsentry/sentry-go"
|
|
|
|
type SentryCoreConfig struct {
|
|
Tags map[string]string
|
|
AttachStacktrace bool
|
|
Level zapcore.Level
|
|
FlushTimeout time.Duration
|
|
Hub *sentry.Hub
|
|
Platform string
|
|
}
|
|
|
|
type sentryCore struct {
|
|
zapcore.LevelEnabler
|
|
client sentry.Client
|
|
cfg SentryCoreConfig
|
|
flushTimeout time.Duration
|
|
fields map[string]interface{}
|
|
}
|
|
|
|
func (c *sentryCore) with(fs []zapcore.Field) *sentryCore {
|
|
m := make(map[string]interface{}, len(c.fields))
|
|
for k, v := range c.fields {
|
|
m[k] = v
|
|
}
|
|
|
|
enc := zapcore.NewMapObjectEncoder()
|
|
for _, f := range fs {
|
|
f.AddTo(enc)
|
|
}
|
|
|
|
for k, v := range enc.Fields {
|
|
m[k] = v
|
|
}
|
|
|
|
return &sentryCore{
|
|
client: c.client,
|
|
cfg: c.cfg,
|
|
fields: m,
|
|
LevelEnabler: c.LevelEnabler,
|
|
}
|
|
}
|
|
|
|
func (c *sentryCore) With(fs []zapcore.Field) zapcore.Core {
|
|
return c.with(fs)
|
|
}
|
|
|
|
func (c *sentryCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
|
|
if c.cfg.Level.Enabled(ent.Level) {
|
|
return ce.AddCore(ent, c)
|
|
}
|
|
return ce
|
|
}
|
|
|
|
func (c *sentryCore) Write(ent zapcore.Entry, fs []zapcore.Field) error {
|
|
clone := c.with(fs)
|
|
event := sentry.NewEvent()
|
|
event.Message = ent.Message
|
|
event.Timestamp = ent.Time
|
|
event.Level = sentryLevel(ent.Level)
|
|
event.Platform = c.cfg.Platform
|
|
event.Extra = clone.fields
|
|
event.Tags = c.cfg.Tags
|
|
|
|
if c.cfg.AttachStacktrace {
|
|
trace := sentry.NewStacktrace()
|
|
if trace != nil {
|
|
event.Exception = []sentry.Exception{
|
|
{
|
|
Type: ent.Message,
|
|
Value: ent.Caller.TrimmedPath(),
|
|
Stacktrace: trace,
|
|
},
|
|
}
|
|
}
|
|
}
|
|
|
|
hub := c.cfg.Hub
|
|
if hub == nil {
|
|
hub = sentry.CurrentHub()
|
|
}
|
|
_ = c.client.CaptureEvent(event, nil, hub.Scope())
|
|
|
|
if ent.Level > zapcore.ErrorLevel {
|
|
c.client.Flush(c.flushTimeout)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *sentryCore) Sync() error {
|
|
c.client.Flush(c.flushTimeout)
|
|
return nil
|
|
}
|
|
|
|
func NewSentryCore(cfg SentryCoreConfig, sentryClient *sentry.Client) zapcore.Core {
|
|
core := sentryCore{
|
|
client: *sentryClient,
|
|
cfg: cfg,
|
|
LevelEnabler: cfg.Level,
|
|
flushTimeout: 3 * time.Second,
|
|
fields: make(map[string]interface{}),
|
|
}
|
|
|
|
if cfg.FlushTimeout > 0 {
|
|
core.flushTimeout = cfg.FlushTimeout
|
|
}
|
|
|
|
return &core
|
|
}
|
|
|
|
func sentryLevel(lvl zapcore.Level) sentry.Level {
|
|
switch lvl {
|
|
case zapcore.DebugLevel:
|
|
return sentry.LevelDebug
|
|
case zapcore.InfoLevel:
|
|
return sentry.LevelInfo
|
|
case zapcore.WarnLevel:
|
|
return sentry.LevelWarning
|
|
case zapcore.ErrorLevel:
|
|
return sentry.LevelError
|
|
case zapcore.DPanicLevel:
|
|
return sentry.LevelFatal
|
|
case zapcore.PanicLevel:
|
|
return sentry.LevelFatal
|
|
case zapcore.FatalLevel:
|
|
return sentry.LevelFatal
|
|
default:
|
|
return sentry.LevelFatal
|
|
}
|
|
}
|