golang panic信息捕获

devtools/2025/2/22 13:49:34/

背景

我们的日志接入阿里云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 mainimport ("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信息并转换为JSONlogPanicAsJSON(r)os.Exit(1)}}()// 业务代码...testPanic()time.Sleep(1 * time.Second)
}func testPanic() {// nil指针引发panicvar 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信息并转换为JSONlogPanicAsJSON(r)os.Exit(1)}}()// 业务代码...go func() {testPanic()}()time.Sleep(1 * time.Second)
}

扩展优化

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


http://www.ppmy.cn/devtools/160953.html

相关文章

Python连接MySQL数据库完全指南

Python连接MySQL数据库完全指南 一、环境准备四部曲 1. 安装MySQL服务器(Docker极简版) docker run --name mysql2025 -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 -d mysql:8.4 2. 安装Python连接驱动 # 官方推荐量子加密版 pip install mysql-con…

使用AI创建流程图和图表的 3 种简单方法

你可能已经尝试过使用 LLMs 生成图像,但你有没有想过用它们来创建 流程图和图表?这些可视化工具对于展示流程、工作流和系统架构至关重要。 通常,在在线工具上手动绘制图表可能会耗费大量时间。但你知道吗?你可以使用 LLMs 通过简…

【05】密码学与隐私保护

5-1 零知识证明 零知识证明介绍 零知识证明的概念 设P(Prover)表示掌握某些信息,并希望证实这一事实的实体,V(Verifier)是验证这一事实的实体。 零知识证明是指P试图使V相信某一个论断是正确的,但却不向…

agent和android怎么结合:健康助手,旅游助手,学习助手

agent和android怎么结合:健康助手,旅游助手,学习助手 创新点 智能交互创新:提出全新的agent - Android交互模式,如基于手势、语音、眼动等多模态融合的交互方式。例如让agent能够同时理解用户的语音指令和手势动作,在Android设备上提供更加自然和高效的交互体验,比如在…

docker 安装redis 7.4.2并挂载配置文件以及设置密码

文章目录 docker 安装redis 7.4.2下载 redis如果你喜欢使用最新的版本创建挂载redis 配置文件创建容器 docker 安装redis 7.4.2 截至2025年2月21日,Redis的最新稳定版本是 7.4.2。 下载 redis 如果你想拉取Redis的特定版本(例如最新的稳定版本 7.4.2&a…

基于ffmpeg+openGL ES实现的视频编辑工具-添加滤镜(七)

在我们的视频编辑工具中,综合运用 ffmpeg 和 OpenGL ES 实现对图像和视频添加滤镜的功能。下面将对其核心逻辑以及相关代码进行详细阐释。 一、整体处理流程 当触发图像显示操作时,首要任务是判定图像的类型,即区分是视频还是图片。对于视频,需对其方向角实施调整并生成 …

推荐几款开源免费的 .NET MAUI 组件库

前言 今天大姚给大家推荐 3 款开源且免费的 .NET MAUI 组件库。 .NET MAUI介绍 .NET 多平台应用 UI (.NET MAUI) 是一个跨平台框架,用于使用 C# 和 XAML 创建本机移动和桌面应用。使用 .NET MAUI,可从单个共享代码库开发可在 Android、iOS、macOS 和 …

在VS-qt的程序中,后期增加PCH预编译功能,提高编译速度

由于前期创建qt程序的时候未勾选pch功能,导致没有启动预编译的功能. 这种情况下需要增加pch功能应该怎么做? 在项目中增加2个文件 stdafx.h和stdafx.cpp文件 stdafx.h增加qt常用头文件 #pragma once //windows #include <windows.h>//qt常用 #include <QObject&g…