You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 15:27:04