如何在log.Fatal()执行时自动发送HTTP请求,无需额外新增日志代码
实现方案
以下两种方案都不需要修改任何原有日志调用代码,只要在程序初始化阶段完成全局配置即可生效。
1. 标准库log的行为覆盖
Go 标准库的log包支持全局设置自定义输出的io.Writer,通过实现自定义Writer就能同时完成默认输出和日志上报:
package main import ( "bytes" "io" "log" "net/http" "os" ) // 自定义日志输出Writer type customLogWriter struct { originalWriter io.Writer // 原有默认输出目标,一般为os.Stderr reportUrl string // 你的上报服务接口地址 } func (w *customLogWriter) Write(p []byte) (n int, err error) { // 先完成原有默认输出逻辑(比如打印到控制台) n, err = w.originalWriter.Write(p) if err != nil { return n, err } // 克隆日志内容避免后续切片复用导致内容错乱 logContent := bytes.Clone(p) // Fatal级日志建议同步上报,避免程序提前退出导致上报丢失 // 其他级别日志可以用异步上报避免阻塞主流程 go func() { req, err := http.NewRequest("POST", w.reportUrl, bytes.NewBuffer(logContent)) if err != nil { // 上报异常直接输出到 stderr,不要调用log包方法避免死循环 io.WriteString(os.Stderr, "log report failed: "+err.Error()+"\n") return } req.Header.Set("Content-Type", "text/plain; charset=utf-8") client := &http.Client{} client.Do(req) }() return n, nil } // 全局初始化时替换log默认输出 func init() { log.SetOutput(&customLogWriter{ originalWriter: os.Stderr, reportUrl: "http://你的服务地址/api/log/report", }) // 原有log的格式、前缀配置不需要修改 log.SetFlags(log.LstdFlags | log.Lshortfile) }
注意:标准库
log.Fatal触发后会直接调用os.Exit(1),如果要确保Fatal日志100%上报成功,把上面的异步上报逻辑改成同步即可。
2. 第三方日志库(logrus/zap等)的实现
这类日志库原生支持全局Hook机制,实现比标准库更简单,以logrus为例:
package main import ( "bytes" "github.com/sirupsen/logrus" "net/http" ) // 自定义上报Hook type LogReportHook struct { ReportUrl string } // 配置需要触发上报的日志级别,这里示例只上报Fatal、Panic级别 func (h *LogReportHook) Levels() []logrus.Level { return []logrus.Level{logrus.FatalLevel, logrus.PanicLevel} } // 触发上报的逻辑 func (h *LogReportHook) Fire(entry *logrus.Entry) error { logContent, _ := entry.String() go func() { req, _ := http.NewRequest("POST", h.ReportUrl, bytes.NewBufferString(logContent)) req.Header.Set("Content-Type", "application/json") client := &http.Client{} client.Do(req) }() return nil } // 全局初始化时注册Hook func init() { logrus.AddHook(&LogReportHook{ ReportUrl: "http://你的服务地址/api/log/report", }) }
原有项目中所有logrus.Info、logrus.Fatal调用都不需要修改,触发对应级别日志时会自动执行上报逻辑。
注意事项
- 上报逻辑中不要调用当前日志库的Fatal/Panic方法,避免触发死循环
- 日志内容如果包含敏感信息,建议在上岗前做脱敏处理
- 若业务要求上报成功率100%,把上报逻辑改为同步执行即可
内容的提问来源于stack exchange,提问作者DoneForAiur
相关产品推荐
相关产品推荐

