2020-05-05 08:36:24 +02:00
|
|
|
package log
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
|
|
|
|
"github.com/getsentry/sentry-go"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
// conversion from logrus log level to sentry log level
|
|
|
|
var (
|
|
|
|
levelMap = map[logrus.Level]sentry.Level{
|
|
|
|
logrus.TraceLevel: sentry.LevelDebug,
|
|
|
|
logrus.DebugLevel: sentry.LevelDebug,
|
|
|
|
logrus.InfoLevel: sentry.LevelInfo,
|
|
|
|
logrus.WarnLevel: sentry.LevelWarning,
|
|
|
|
logrus.ErrorLevel: sentry.LevelError,
|
|
|
|
logrus.FatalLevel: sentry.LevelFatal,
|
|
|
|
logrus.PanicLevel: sentry.LevelFatal,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// SentryHook provides a logrus hook which enables error logging to sentry platform.
|
|
|
|
// This is helpful in order to provide better monitoring and alerting on errors
|
|
|
|
// as well as the given error details can help to find the root cause of bugs.
|
|
|
|
type SentryHook struct {
|
|
|
|
levels []logrus.Level
|
|
|
|
Hub *sentry.Hub
|
|
|
|
tags map[string]string
|
|
|
|
Event *sentry.Event
|
|
|
|
correlationID string
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewSentryHook initializes sentry sdk with dsn and creates new hook
|
|
|
|
func NewSentryHook(sentryDsn, correlationID string) SentryHook {
|
2020-07-28 17:19:33 +02:00
|
|
|
Entry().Debugf("Initializing Sentry with DSN %v", sentryDsn)
|
2020-05-05 08:36:24 +02:00
|
|
|
if err := sentry.Init(sentry.ClientOptions{
|
|
|
|
Dsn: sentryDsn,
|
|
|
|
AttachStacktrace: true,
|
|
|
|
}); err != nil {
|
2020-05-06 18:22:02 +02:00
|
|
|
Entry().Warnf("cannot initialize sentry: %v", err)
|
2020-05-05 08:36:24 +02:00
|
|
|
}
|
|
|
|
h := SentryHook{
|
2020-05-12 22:11:52 +02:00
|
|
|
levels: []logrus.Level{logrus.PanicLevel, logrus.FatalLevel},
|
2020-05-05 08:36:24 +02:00
|
|
|
Hub: sentry.CurrentHub(),
|
|
|
|
tags: make(map[string]string),
|
|
|
|
Event: sentry.NewEvent(),
|
|
|
|
correlationID: correlationID,
|
|
|
|
}
|
|
|
|
return h
|
|
|
|
}
|
|
|
|
|
|
|
|
// Levels returns the supported log level of the hook.
|
|
|
|
func (sentryHook *SentryHook) Levels() []logrus.Level {
|
|
|
|
return sentryHook.levels
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fire creates a new event from the error and sends it to sentry
|
|
|
|
func (sentryHook *SentryHook) Fire(entry *logrus.Entry) error {
|
2020-05-06 18:22:02 +02:00
|
|
|
sentryHook.Event.Level = levelMap[entry.Level]
|
|
|
|
sentryHook.Event.Message = entry.Message
|
|
|
|
errValue := ""
|
2020-05-05 08:36:24 +02:00
|
|
|
sentryHook.tags["correlationId"] = sentryHook.correlationID
|
2020-06-26 07:38:27 +02:00
|
|
|
sentryHook.tags["category"] = GetErrorCategory().String()
|
2020-05-05 08:36:24 +02:00
|
|
|
for k, v := range entry.Data {
|
|
|
|
if k == "stepName" || k == "category" {
|
|
|
|
sentryHook.tags[k] = fmt.Sprint(v)
|
|
|
|
}
|
2020-05-06 18:22:02 +02:00
|
|
|
if k == "error" {
|
|
|
|
errValue = fmt.Sprint(v)
|
|
|
|
}
|
|
|
|
sentryHook.Event.Extra[k] = v
|
2020-05-05 08:36:24 +02:00
|
|
|
}
|
|
|
|
sentryHook.Hub.Scope().SetTags(sentryHook.tags)
|
|
|
|
|
2020-05-06 18:22:02 +02:00
|
|
|
exception := sentry.Exception{
|
|
|
|
Type: entry.Message,
|
|
|
|
Value: errValue,
|
|
|
|
}
|
|
|
|
|
|
|
|
// if error type found overwrite exception value and add stacktrace
|
2020-05-05 08:36:24 +02:00
|
|
|
err, ok := entry.Data[logrus.ErrorKey].(error)
|
|
|
|
if ok {
|
2020-05-06 18:22:02 +02:00
|
|
|
exception.Value = err.Error()
|
|
|
|
sentryHook.Event.Message = reflect.TypeOf(err).String()
|
2020-05-05 08:36:24 +02:00
|
|
|
if sentryHook.Hub.Client().Options().AttachStacktrace {
|
|
|
|
exception.Stacktrace = sentry.ExtractStacktrace(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2020-05-06 18:22:02 +02:00
|
|
|
sentryHook.Event.Exception = []sentry.Exception{exception}
|
2020-05-05 08:36:24 +02:00
|
|
|
|
2020-05-06 18:22:02 +02:00
|
|
|
sentryHook.Hub.CaptureEvent(sentryHook.Event)
|
2020-05-05 08:36:24 +02:00
|
|
|
return nil
|
|
|
|
}
|