将http panic日志打印至文件当中
创建文件
panicFile, err := os.OpenFile(conf.Logger.PanicLogFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
return nil, err
}
注入文件
r.Use(mw.InjectFile(panicFile))
// InjectFile 注入Panic File
func InjectFile(panic *os.File) func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
r = r.WithContext(context.WithValue(r.Context(), &panicFileKey, panic))
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
}
panic获取并写入文件
// LogPanic http panic recover
func LogPanic(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
file, _ := PanicFileFromContext(r.Context())
defer func() {
if rvr := recover(); rvr != nil {
// append panic info to file
panicTimae := time.Now().Format("2006-01-02 15:04:05")
if _, err := file.WriteString(fmt.Sprintf("\n%s: %v\n %s", panicTime, rvr, debug.Stack())); err != nil {
fmt.Printf("write panic file error , %s", err.Error())
}
}
}()
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
说明
- 文件是通过chi的middleware注入进去
- 通过内置函数recover去获取异常信息
- 通过debug.Stack()打印异常堆栈信息