golang zap日志模块封装sentry

我们自己写个log日志包,把zap和sentry封装到一起。

下面直接贴上主要部分代码(两个模块初始化部分的代码请自行查阅官方文档):

  • logger.go
go 复制代码
package log

import (
	"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
go 复制代码
package log

import (
	"fmt"
	"utils/stime"
	"github.com/getsentry/sentry-go"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"math"
	"runtime"
	"time"
)

type CustomError struct {
	msg        string
	stackTrace []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中携带的消息内容
相关推荐
明月看潮生1 小时前
青少年编程与数学 02-003 Go语言网络编程 09课题、Cookie
青少年编程·golang·网络编程·编程与数学
明月看潮生2 小时前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
明月看潮生2 小时前
青少年编程与数学 02-003 Go语言网络编程 14课题、Go语言Udp编程
青少年编程·golang·网络编程·编程与数学
hlsd#3 小时前
go 集成go-redis 缓存操作
redis·缓存·golang
qq_1728055917 小时前
GIN 反向代理功能
后端·golang·go
__AtYou__17 小时前
Golang | Leetcode Golang题解之第535题TinyURL的加密与解密
leetcode·golang·题解
kevin_tech1 天前
Go API 多种响应的规范化处理和简化策略
开发语言·后端·golang·状态模式
幺零九零零1 天前
【Golang】sql.Null* 类型使用(处理空值和零值)
数据库·sql·golang
cookies_s_s1 天前
Golang--DOS命令、变量、基本数据类型、标识符
golang
__AtYou__1 天前
Golang | Leetcode Golang题解之第541题反转字符串II
leetcode·golang·题解