当前位置: 首页 > news >正文

golang zap日志模块封装sentry

我们自己写个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中携带的消息内容
    在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【 html+css 绚丽Loading 】 000027 旋风破云扇
  • C++学习,指针空指针
  • 万亿低空经济:无人机飞手考证正当时
  • ArcGIS栅格裁剪与合并,制作等高线
  • 使用对象池优化 C++ 程序性能的实用指南
  • 虚幻引擎(Unreal Engine)技术使得《黑神话悟空传》大火,现在重视C++的开始吃香了,JAVA,Go,Unity都不能和C++相媲美!
  • 使用 ip route 命令配置 Linux 路由表的详细指南
  • java基础之 静态代码块、实例代码块、构造方法执行顺序问题
  • udp可靠传输中ACK与NACK的选择
  • 用 CSS 实现太阳系运行效果
  • REGTR: End-to-end Point Cloud Correspondences with Transformers 论文解读
  • 解题-写一个程序判断当前机器的大小端存储模式 #两种方法
  • uniapp + Vue3自定义封装弹窗组件
  • Linux 数据结构 顺序表 链表
  • SpringBoot SSM vue在线作业考试系统
  • 【comparator, comparable】小总结
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • Angular 响应式表单 基础例子
  • CentOS 7 修改主机名
  • express如何解决request entity too large问题
  • laravel with 查询列表限制条数
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • Redux 中间件分析
  • SQLServer之索引简介
  • unity如何实现一个固定宽度的orthagraphic相机
  • Vue2 SSR 的优化之旅
  • vue脚手架vue-cli
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 今年的LC3大会没了?
  • 码农张的Bug人生 - 见面之礼
  • 前端知识点整理(待续)
  • 三分钟教你同步 Visual Studio Code 设置
  • 数组的操作
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • # .NET Framework中使用命名管道进行进程间通信
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (Java)【深基9.例1】选举学生会
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (算法)大数的进制转换
  • (原)记一次CentOS7 磁盘空间大小异常的解决过程
  • (转)linux 命令大全
  • (转)四层和七层负载均衡的区别
  • .net framework 4.0中如何 输出 form 的name属性。
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • .net 流——流的类型体系简单介绍
  • .NET周刊【7月第4期 2024-07-28】
  • .so文件(linux系统)
  • /使用匿名内部类来复写Handler当中的handlerMessage()方法
  • @Async注解的坑,小心
  • @cacheable 是否缓存成功_让我们来学习学习SpringCache分布式缓存,为什么用?
  • @JsonFormat与@DateTimeFormat注解的使用
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • [ 物联网 ]拟合模型解决传感器数据获取中数据与实际值的误差的补偿方法