我们自己写个log日志包,把zap和sentry封装到一起。
下面直接贴上主要部分代码(两个模块初始化部分的代码请自行查阅官方文档):
- logger.go
package logimport ("github.com/getsentry/sentry-go""go.uber.org/zap"
)type Logger struct {*zap.Logger
}// Debug logs a message at DebugLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func (log *Logger) Debug(msg string, fields ...zap.Field) {log.Logger.Debug(msg, fields...)NewMessage(sentry.LevelDebug, msg, fields)
}// Info logs a message at InfoLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func (log *Logger) Info(msg string, fields ...zap.Field) {log.Logger.Info(msg, fields...)NewMessage(sentry.LevelInfo, msg, fields)
}// Warn logs a message at WarnLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func (log *Logger) Warn(msg string, fields ...zap.Field) {log.Logger.Warn(msg, fields...)NewMessage(sentry.LevelWarning, msg, fields)
}// Error logs a message at ErrorLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
func (log *Logger) Error(msg string, fields ...zap.Field) {log.Logger.Error(msg, fields...)NewMessage(sentry.LevelError, msg, fields)
}// Fatal logs a message at FatalLevel. The message includes any fields passed
// at the log site, as well as any fields accumulated on the logger.
//
// The logger then calls os.Exit(1), even if logging at FatalLevel is
// disabled.
func (log *Logger) Fatal(msg string, fields ...zap.Field) {log.Logger.Fatal(msg, fields...)NewMessage(sentry.LevelFatal, msg, fields)
}
- sentry.go
package logimport ("fmt""utils/stime""github.com/getsentry/sentry-go""go.uber.org/zap""go.uber.org/zap/zapcore""math""runtime""time"
)type CustomError struct {msg stringstackTrace []uintptr
}func (e *CustomError) Error() string {return e.msg
}
func (e *CustomError) StackTrace() []uintptr {return e.stackTrace
}func NewMessage(level sentry.Level, msg string, fields []zap.Field) {if sentryUsable {sentry.WithScope(func(scope *sentry.Scope) {scope.SetLevel(level)scope.SetExtra("msg", msg)if len(fields) > 0 {for _, field := range fields {switch field.Type {case zapcore.StringType:scope.SetExtra(field.Key, field.String)case zapcore.ErrorType:scope.SetExtra(field.Key, field.Interface.(error).Error())case zapcore.StringerType:scope.SetExtra(field.Key, field.Interface.(fmt.Stringer).String())case zapcore.Int8Type, zapcore.Int16Type, zapcore.Int32Type, zapcore.Int64Type, zapcore.Uint8Type, zapcore.Uint16Type, zapcore.Uint32Type, zapcore.Uint64Type:scope.SetExtra(field.Key, field.Integer)case zapcore.Float32Type, zapcore.Float64Type:floatVal := math.Float32frombits(uint32(field.Integer))scope.SetExtra(field.Key, floatVal)case zapcore.BoolType:scope.SetExtra(field.Key, field.Integer == 1)case zapcore.TimeFullType:if ts, ok := field.Interface.(time.Time); ok {scope.SetExtra(field.Key, ts.Format(stime.Format_Normal_YMDhms))}case zapcore.TimeType:scope.SetExtra(field.Key, time.Unix(0, field.Integer).UTC())default:scope.SetExtra(field.Key, fmt.Sprintf("%+v", field.Interface))}}}scope.SetFingerprint([]string{msg})if level == sentry.LevelError {stackTrace := make([]uintptr, 20)runtime.Callers(6, stackTrace)err := &CustomError{msg: msg,stackTrace: stackTrace,}sentry.CaptureException(err)} else {sentry.CaptureMessage(msg)}})}
}
效果展示:
错误消息会展示错误类型,其它的debug、info等会直接展示消息名称
错误消息详情:
- 详情中包含错误位置和调用方法,我就不单独写调用示例了。
- 消息详情中可已看到zap.Field中携带的消息内容