golang panic信息捕获

news2025/4/12 0:33:49

背景

我们的日志接入阿里云sls平台,但是,日志是以json的格式存储在阿里云sls平台上,程序中产生的error,info等日志都可以实现以json的格式打印。但是,golang程序中产生的panic信息本身不是以json的格式输出,这就导致panic信息在阿里云sls平台上不方便检索。

基于上述痛点,我们期望捕获程序的panic信息,并且以json的格式打印,如此,我们就可以方便的实现在阿里云sls平台上检索的目的。

解决方案

核心的思路

通过deferrecover()机制捕获panic信息,结合Go的JSON序列化能力,将堆栈信息、错误内容等关键数据封装为结构化JSON格式。

实现步骤

定义日志的结构体

日志结构体定义:

type PanicLog struct {
	Timestamp string `json:"@timestamp"`
	Level     string `json:"level"`
	Message   string `json:"message"`
	Stack     string `json:"stack"`
	Service   string `json:"service"`
}

 封装打印日志的方法

func logPanicAsJSON(panicObj interface{}) {
	stack := string(debug.Stack()) // 获取完整堆栈

	logEntry := PanicLog{
		Timestamp: time.Now().Format(time.RFC3339),
		Level:     "PANIC",
		Message:   fmt.Sprintf("%v", panicObj),
		Stack:     stack,
		Service:   "your-service-name",
	}

	jsonData, _ := json.Marshal(logEntry)
	// 输出到SLS(根据实际日志库选择方式)
	log.Println(string(jsonData) )
}

封装方法捕获panic

defer func() {
			if r := recover(); r != nil {
				logPanicAsJSON(r) // 记录 panic 信息
				c.AbortWithStatus(http.StatusInternalServerError)
			}
}()

测试案例

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"runtime/debug"
	"time"
)

type PanicLog struct {
	Timestamp string `json:"@timestamp"`
	Level     string `json:"level"`
	Message   string `json:"message"`
	Stack     string `json:"stack"`
	Service   string `json:"service"`
}

func main() {
	defer func() {
		if r := recover(); r != nil {
			// 捕获panic信息并转换为JSON
			logPanicAsJSON(r)
			os.Exit(1)
		}
	}()
	// 业务代码...
	testPanic()
	time.Sleep(1 * time.Second)
}

func testPanic() {
	// nil指针引发panic
	var a *int
	*a = 1
}

func logPanicAsJSON(panicObj interface{}) {
	stack := string(debug.Stack()) // 获取完整堆栈

	logEntry := PanicLog{
		Timestamp: time.Now().Format(time.RFC3339),
		Level:     "PANIC",
		Message:   fmt.Sprintf("%v", panicObj),
		Stack:     stack,
		Service:   "your-service-name",
	}

	jsonData, _ := json.Marshal(logEntry)
	// 输出到SLS(根据实际日志库选择方式)
	log.Println(string(jsonData))
}

注意事项

在Go语言里,recover() 函数只能捕获当前goroutine内产生的 panic

所以,在下面的这个案例中recover不能捕获到panic信息。如果需要捕获到,需要在每个协程中都执行recover的逻辑。

func main() {
	defer func() {
		if r := recover(); r != nil {
			// 捕获panic信息并转换为JSON
			logPanicAsJSON(r)
			os.Exit(1)
		}
	}()
	// 业务代码...
	go func() {
		testPanic()
	}()
	time.Sleep(1 * time.Second)
}

扩展优化

日志结构体中增加traceId信息维度。

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

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

相关文章

一周学会Flask3 Python Web开发-http响应状态码

锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 在Flask程序中,客户端发出的请求触发相应的视图函数,获取返回值会作为响应的主体,最后生成…

goland无法debug项目

1、其实个原因是因为正在使用的Delve调试器版本太旧,无法兼容当前的Go语言版本1.2。Delve是Go语言的一个调试工具,用于提供源码级别的调试功能。Go语言每隔一段时间会发布新版本,而相应的调试器Delve也可能会更新以提供新的特性或修复已知问题…

Python VsCode DeepSeek接入

Python VsCode DeepSeek接入 创建API key 首先进入DeepSeek官网,https://www.deepseek.com/ 点击左侧“API Keys”,创建API key,输出名称为“AI” 点击“创建",将API key保存,复制在其它地方。 在VsCode中下载…

Ubuntu22.04.6如何固定ip地址

Ubuntu22.04.6如何固定ip地址 主要参见这篇博客 ubuntu 桌面版如何设置固定IP地址_ubuntu桌面版如何修改ip-CSDN博客 1.先查看一下当前的IP是多少

腿足机器人之十- SLAM地图如何用于运动控制

腿足机器人之十- SLAM地图如何用于运动控制 腿足机器人SLAM地图的表示与处理全局路径规划:地形感知的路径搜索基于A*的三维路径规划基于RRT*的可行步态序列生成 局部运动规划:实时步态调整与避障动态窗口法的腿足适配模型预测控制(MPC&#x…

毕业项目推荐:基于yolov8/yolov5/yolo11的果蔬检测识别系统(python+卷积神经网络)

文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…

pyside6学习专栏(二):程序图像资源的加载方式

pyside6中的QLabel控件可以加载图像和gif动画,可以直接从外部文件加载,也可以从QRC类型的文件(实际是一脚本文件)经编绎生成对应的资源.PY模块文件(就是将qrc文本中指定的资源文件的16制内容写入.py文件)来使用,本文对两种方式作了一简单的示…

如何在 VS Code 中快速使用 Copilot 来辅助开发

在日常开发中,编写代码往往是最耗时的环节之一。而 GitHub Copilot,作为一款 AI 编码助手,可以帮助开发者 自动补全代码、生成代码片段,甚至直接编写完整的函数,大幅提升编码效率。那么,如何在 VS Code 中快…

DeepSeek-R1论文阅读及本地调用

前言 DeepSeek已经火了一段时间了,对于这项“国运级”的技术成果,即便研究的不是这个方向,也不免好奇前来看看。本文将先解析一下DeepSeek-R1这篇论文,再对DeepSeek的本地部署使用进行研究配置。 论文标题:DeepSeek-…

自然语言处理:第九十二章 chatBI 经验(转载)

本人项目地址大全:Victor94-king/NLP__ManVictor: CSDN of ManVictor 原文连接: 一文分享 ChatBI 实践经验 写在前面: 笔者更新不易,希望走过路过点个关注和赞,笔芯!!! 写在前面: 笔者更新不易,希望走过路过点个关注和赞&#x…

体验用ai做了个python小游戏

体验用ai做了个python小游戏 写在前面使用的工具2.增加功能1.要求增加视频作为背景。2.我让增加了一个欢迎页面。3.我发现中文显示有问题。4.我提出了背景修改意见,欢迎页面和结束页面背景是视频,游戏页面背景是静态图片。5.提出增加更多游戏元素。 总结…

懒人精灵本地离线卡密验证系统教程(不联网、安全稳定、省钱、永久免费、无任何限制)

1.合集懒人精灵本地离线卡密验证系统教程(不联网、安全稳定、省钱、永久免费、无任何限制):https://www.bilibili.com/video/BV1M6rdYEEog/ 备注: 1.本地离线卡密采用最安全的非对称加解密技术,设备id采用最安全多重混合加密不可逆技术生成&…

前后端项目部署服务器(传统部署和Docker部署)

内外网 开发环境连外网(8.140.26.187),测试/生产环境连内网(172.20.59.17) 内外网地址不同,但指定的库是同一个 内网IP地址范围包括: 10.0.0.0 到 10.255.255.255172.16.0.0 到 172.31.2551…

python-leetcode 39.二叉树的直径

题目: 给定一棵二叉树的根节点,返回该树的直径。 二叉树的直径是指中间任意两个节点之间最长路径的长度。这条路径可能经过也可能不经过根节点root 两节点之间路径的长度由他们之间的边数表示 方法一:深度优先搜索 一条路径的长度为该路…

【分布式理论11】分布式协同之分布式事务(一个应用操作多个资源):从刚性事务到柔性事务的演进

文章目录 一. 什么是分布式事务?二. 分布式事务的挑战三. 事务的ACID特性四. CAP理论与BASE理论1. CAP理论1.1. 三大特性1.2. 三者不能兼得 2. BASE理论 五. 分布式事务解决方案1. 两阶段提交(2PC)2. TCC(Try-Confirm-Cancel&…

配置Api自动生成

我的飞书:https://rvg7rs2jk1g.feishu.cn/docx/TVlJdMgYLoDJrsxAwMgcCE14nxt 使用Springfox Swagger生成API,并导入Postman,完成API单元测试 Swagger: 是一套API定义的规范,按照这套规范的要求去定义接口及接口相关信息,再通过可…

适用于复杂背景的YOLOv8改进:基于DCN的特征提取能力提升研究

文章目录 1. YOLOv8的性能瓶颈与改进需求1.1 YOLOv8的优势与局限性1.2 可变形卷积(DCN)的优势 2. DCN在YOLOv8中的应用2.1 DCN的演变与YOLOv8的结合2.2 将DCN嵌入YOLOv8的结构中2.2.1 DCNv1在YOLOv8中的应用2.2.2 DCNv2与DCNv3的优化 2.3 实验与性能对比…

Redis_基础

Redis 命令启动、配置密码 Redis是绿色软件,所以直接解压就能使用 配置文件为:redis.windows.conf 启动redis 服务: redis-server.exe redis.windows.conf启动客户端: redis-cli.exe默认没有给Redis配置密码,所以在…

Linux阿里云服务器安装RocketMQ教程

本文为个人云服务器上搭建RocketMQ教程,用于帮助大家降低安装学习成本,提高学习效率。本人在服务器上(我用的是阿里云服务器)安装MQ时遇到了大大小小的问题,因此在最终完成部署后,希望能总结一个教程&#…

【JavaEE进阶】MyBatis入门

目录 🌴前言 🌲什么是MyBatis? 🌳准备工作 🚩创建工程 🚩配置数据库连接字符串 🚩数据准备 🚩编写持久层代码 🍃单元测试 🌴前言 在应⽤分层学习时,我们了解到…