2025-05-25 20:02:15 +08:00
|
|
|
|
package ksync
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"github.com/fox/fox/log"
|
|
|
|
|
"github.com/wanghuiyt/ding"
|
|
|
|
|
"runtime/debug"
|
2025-06-15 13:43:03 +08:00
|
|
|
|
"sync"
|
2025-05-25 20:02:15 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 辅助函数列表
|
|
|
|
|
var (
|
2025-05-31 08:40:41 +08:00
|
|
|
|
DingAccessToken = "" // 钉钉token
|
|
|
|
|
DingSecret = "" // 钉钉加签
|
|
|
|
|
//lastAttributeCode = "" // 最近一条error信息
|
2025-05-25 20:02:15 +08:00
|
|
|
|
)
|
|
|
|
|
|
2025-05-31 08:40:41 +08:00
|
|
|
|
//func getAttributeCode(stackErr string) string {
|
|
|
|
|
// lines := strings.Split(stackErr, "\n")
|
|
|
|
|
// // 检查是否有足够的行数,并提取第9行(索引为8,因为索引从0开始)
|
|
|
|
|
// if len(lines) >= 9 {
|
|
|
|
|
// goIndex := strings.LastIndex(lines[8], ".go")
|
|
|
|
|
// if goIndex != -1 {
|
|
|
|
|
// filteredStr := lines[8][:goIndex]
|
|
|
|
|
// filteredStr = strings.TrimLeft(filteredStr, "\t ")
|
|
|
|
|
// return filteredStr
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// return ""
|
|
|
|
|
//}
|
2025-05-25 20:02:15 +08:00
|
|
|
|
|
|
|
|
|
// 发送消息给钉钉
|
|
|
|
|
func sendMessage(msg interface{}, stackErr string, dingToken, dingSecret string) {
|
|
|
|
|
if dingToken != "" {
|
|
|
|
|
d := ding.Webhook{
|
|
|
|
|
AccessToken: dingToken, // 上面获取的 access_token
|
|
|
|
|
Secret: dingSecret, // 上面获取的加签的值
|
|
|
|
|
}
|
|
|
|
|
_ = d.SendMessageText(fmt.Sprintf("Recover panic:%v\n%v", msg, stackErr), "13145922265", "17353003985")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Recover(recoverFunc func()) {
|
|
|
|
|
if msg := recover(); msg != nil {
|
|
|
|
|
stackErr := string(debug.Stack())
|
2025-05-31 08:40:41 +08:00
|
|
|
|
//attributeCode := getAttributeCode(stackErr)
|
|
|
|
|
//if lastAttributeCode != attributeCode {
|
|
|
|
|
// lastAttributeCode = attributeCode
|
|
|
|
|
log.ErrorF("Recover panic:%v", msg)
|
|
|
|
|
log.Error(stackErr)
|
|
|
|
|
sendMessage(msg, stackErr, DingAccessToken, DingSecret)
|
|
|
|
|
//}
|
2025-05-25 20:02:15 +08:00
|
|
|
|
if recoverFunc != nil {
|
|
|
|
|
recoverFunc()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RunSafe runs the given fn, recovers if fn panics.
|
|
|
|
|
func RunSafe(fn func(), recoverFunc func()) {
|
|
|
|
|
defer Recover(recoverFunc)
|
|
|
|
|
fn()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GoSafe runs the given fn using another goroutine, recovers if fn panics.
|
|
|
|
|
func GoSafe(fn func(), recoverFunc func()) {
|
|
|
|
|
go RunSafe(fn, recoverFunc)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// WrapSafe return a RunSafe wrap func
|
|
|
|
|
func WrapSafe(fn func(), recoverFunc func()) func() {
|
|
|
|
|
return func() {
|
|
|
|
|
RunSafe(fn, recoverFunc)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-06-15 13:43:03 +08:00
|
|
|
|
|
|
|
|
|
func runSafeWg(wg *sync.WaitGroup, fn func()) {
|
|
|
|
|
defer wg.Done()
|
|
|
|
|
defer Recover(nil)
|
|
|
|
|
fn()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 安全的执行go协程组
|
|
|
|
|
func GroupGo(wg *sync.WaitGroup, fn func()) {
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
go runSafeWg(wg, fn)
|
|
|
|
|
}
|