package ksync import ( "fmt" "github.com/fox/fox/log" "github.com/wanghuiyt/ding" "runtime/debug" "strings" ) // 辅助函数列表 var ( DingAccessToken = "" // 钉钉token DingSecret = "" // 钉钉加签 lastAttributeCode = "" // 最近一条error信息 ) 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 "" } // 发送消息给钉钉 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()) attributeCode := getAttributeCode(stackErr) if lastAttributeCode != attributeCode { lastAttributeCode = attributeCode log.ErrorF("Recover panic:%v", msg) log.Error(stackErr) sendMessage(msg, stackErr, DingAccessToken, DingSecret) } 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) } }