golang zap日志模块封装sentry

news2024/9/21 23:24:26

我们自己写个log日志包,把zap和sentry封装到一起。
下面直接贴上主要部分代码(两个模块初始化部分的代码请自行查阅官方文档):

  • logger.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
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中携带的消息内容
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2091214.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Redis如何实现集群会话同步?

使用Redis如何实现集群会话同步? 1、为什么选择Redis?2、如何实现?1. 环境准备2. 配置Web服务器3. 测试与验证4. 监控与优化 💖The Begin💖点点关注,收藏不迷路💖 在分布式Web应用中&#xff0c…

探索全能型AI与专业型AI的未来趋势

目录 前言1. 全能型AI与专业型AI的对比1.1 经济市场与用户吸引力1.2 精度与效果 2. AI模型的全面评估与比较2.1 精度2.2 速度2.3 鲁棒性 3. 专精化与可扩展性的权衡3.1 专精化的优势与挑战3.2 全能型AI的可扩展性 结语 前言 在人工智能领域,随着技术的迅猛发展&…

解决:pip install flash-attn安装失败案例【cuda】【torch】【flash-attn】

问题描述 在一个容器中部署项目环境中,遇到的flash-attn库总是安装失败,报错信息大致是:FileNotFoundError: [Errno 2] No such file or directory: :/usr/local/cuda/bin/nvcc,以及后来可能会提示’torch’未安装,却…

Android中服务(service)的基本用法

文章目录 Android中服务(service)的基本用法服务是什么定义一个服务启动和停止服务 Android中服务(service)的基本用法 服务是什么 服务(Service)是Android中实现程序后台运行的解决方案,它非…

智能停车场管理小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,车位信息管理,车位预订管理,系统管理 微信端账号功能包括:系统首页,地图,我的 开发系统:Windows 架构模式…

Golang | Leetcode Golang题解之第386题字典序排数

题目&#xff1a; 题解&#xff1a; func lexicalOrder(n int) []int {ans : make([]int, n)num : 1for i : range ans {ans[i] numif num*10 < n {num * 10} else {for num%10 9 || num1 > n {num / 10}num}}return ans }

如何处理时间序列异常值?理解、检测和替换时间序列中的异常值

异常值的类型 (欢迎来到雲闪世界) 异常值是与正常行为有显著偏差的观察结果。 时间序列可能会因某些异常和非重复事件而出现异常值。这些异常值会影响时间序列分析&#xff0c;并误导从业者得出错误的结论或有缺陷的预测。因此&#xff0c;识别和处理异常值是确保时间序列建模…

域名是什么

在这个数字世界中&#xff0c;域名无疑是连接用户与网站的关键纽带。域名&#xff0c;是由一串字符组成的地址&#xff0c;用于在互联网上唯一标识和定位一个特定的资源。本文将深入探讨域名的概念、作用以及对互联网发展的重要性。 一、域名的定义与结构 域名可以看作是互联网…

用矩阵乘法的底层原理来理解“特征融合”

大家好啊&#xff0c;我是董董灿。 在很多 AI 模型中&#xff0c;都会出现内积运算。无论是卷积/全连接还是 Transformer 架构中的矩阵乘法&#xff08;或线性映射&#xff09;&#xff0c;其核心运算逻辑都是内积运算。 因此&#xff0c;很多时候&#xff0c;我们也把内积运…

Java 输入与输出之 NIO.2【AIO】【内存映射文件】【自动资源管理】探索之【四】

一&#xff0c;自动资源管理 Java 7 增加了一个新特性&#xff0c;该特性提供了另外一种管理资源的方式&#xff0c;这种方式能自动关闭文件等系统资源。这个特性又被称为自动资源管理(Automatic Resource Management, ARM)&#xff0c; 该特性以 try 语句的扩展版为基础。自动…

泛微E9开发 申请流程时,通过附件ID带出文件

申请流程时&#xff0c;通过附件ID带出文件 1、需求说明2、实现操作3、标准API知识-修改单个字段值&#xff08;不支持附件类型&#xff09;3.1.格式3.2.参数说明3.3.样例3.4.特别注意 1、需求说明 在用户申请流程表单的时候&#xff0c;需要用到系统中已经存在的文档&#xf…

MySQL-进阶篇-锁(全局锁、表级锁、行级锁)

文章目录 1. 锁概述2. 全局锁2.1 介绍2.2 数据备份2.3 使用全局锁造成的问题 3. 表级锁3.1 表锁3.1.1 语法3.1.2 读锁3.1.3 写锁3.1.4 读锁和写锁的区别 3.2 元数据锁&#xff08;Meta Data Lock&#xff0c;MDL&#xff09;3.3 意向锁3.3.1 案例引入3.3.2 意向锁的分类 4. 行级…

【超详细】从 0 到 1 打包你的 uni-app 应用:安卓篇打包指南

一. 介绍 在当前移动应用开发的大环境下&#xff0c;uni-app 作为一种使用 Vue.js 开发多平台应用的框架&#xff0c;为开发者提供了快速构建跨平台应用的能力。本文将为你介绍如何将 uni-app 项目打包成安卓应用&#xff0c;让你的应用在安卓设备上运行并上架应用市场。 二.…

学习之MySQL函数(字符串,数值,日期,流程)

字符串函数 函数是指一段可以直接被另一段程序或代码 案例&#xff1a; – 1、由于业务需求变更&#xff0c;企业员工的工号&#xff0c;统一为5位数&#xff0c;目前不足5位数的全部在前面补0、比如:1号员工的工号应该为00001. update emp set worknolpad(workno, 5, 0) 运…

2024大模型学习:机器学习在安全领域的应用|从大数据中识别潜在安全威胁

机器学习在安全领域的应用&#xff1a;从大数据中识别潜在安全威胁 &#x1f9d1; 作者简介&#xff1a;现任阿里巴巴嵌入式技术专家&#xff0c;15年工作经验&#xff0c;深耕嵌入式人工智能领域&#xff0c;精通嵌入式领域开发、技术管理、简历招聘面试。CSDN优质创作者&…

【王树森】RNN模型与NLP应用(8/9):Attention(个人向笔记)

前言 基于RNN的Seq2Seq模型无法记住长序列Attentnion机制可以大幅度提升Seq2Seq模型 Seq2Seq Model with Attention Attention可以让句子在逐步变长的时候不忘记前面的输入信息Attention还可以告诉Decoder应该关注哪一个状态优点&#xff1a;Attention可以大幅度提高准确率缺…

中小企业数字化营销突围秘籍,快来解锁!

​嘿&#xff0c;各位中小企业主们&#xff01;在如今这个数字化时代&#xff0c;市场竞争那叫一个激烈。传统营销方式渐渐力不从心&#xff0c;而数字化营销则成为咱们中小企业突出重围的关键路径。 现状不容乐观 目前呢&#xff0c;有一部分中小企业已经迈出了数字化营销的步…

【hot100篇-python刷题记录】【最小覆盖子串】

R7-子串篇 class Solution:def minWindow(self, s: str, t: str) -> str:ret_left,ret_right-1,len(s)left0#s子串字母出现的次数cnt_sCounter()#t中字母出现的次数cnt_tCounter(t)for right,c in enumerate(s):cnt_s[c]1while cnt_s>cnt_t:#找到更短的子串if right-left…

破解“目录名称无效”难题:数据恢复实战指南

在数字化生活日益普及的今天&#xff0c;数据存储与管理成为了我们日常不可或缺的一部分。然而&#xff0c;当您尝试访问某个文件夹时&#xff0c;却遇到了“目录名称无效”的错误提示&#xff0c;这无疑会让人感到焦虑和困惑。本文将深入探讨“目录名称无效”这一问题的根源&a…

Unet改进11:在不同位置添加MLCA||轻量级的混合本地信道注意机制

本文内容:在不同位置添加MLCA注意力机制 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 注意机制是计算机视觉中应用最广泛的组成部分之一,它可以帮助神经网络突出重要元素,抑制无关元素。然而,绝大多数通道注意机制只包含通道特征信息,忽略了空间特征…