chore(logging): 更新日志重定向与捕获功能

- 在 .gitignore 中添加调试日志文件的忽略规则,避免不必要的调试信息被提交
- 修改 application.go 中的 stdout 重定向逻辑,使用 log.CaptureStream 以支持更灵活的日志捕获
- 更新 README 文档,增加对日志重定向功能的说明
This commit is contained in:
2026-07-13 07:45:51 +08:00
parent e14c9742c1
commit 6b689f3a1b
23 changed files with 1316 additions and 1836 deletions
+20 -35
View File
@@ -1,7 +1,6 @@
package hotime
import (
"bufio"
"context"
"database/sql"
"fmt"
@@ -26,6 +25,8 @@ import (
. "code.hoteas.com/golang/hotime/db"
"code.hoteas.com/golang/hotime/log"
mysql "github.com/go-sql-driver/mysql"
logrus "github.com/sirupsen/logrus"
"github.com/rs/zerolog"
)
type Application struct {
@@ -189,7 +190,7 @@ func (that *Application) Run(router Router) {
return // 停机过程中的 panic 不触发重启
}
//that.SetError(errors.New(fmt.Sprint(err)), LOG_FMT)
that.Log.Warnf("%v", err)
that.Log.EmitRecoveredPanic(err)
that.Run(router)
}
@@ -346,7 +347,8 @@ func (that *Application) SetConfig(configPath ...string) {
}
// 重定向 os.Stdout 和标准 log 包,捕获 fmt.Println 等绕过 HoTime Logger 的输出
redirectStdout(that.Log)
stdoutW := redirectStdout(that.Log)
bridgeThirdPartyStdout(stdoutW)
// 重定向 os.Stderr,捕获 panic 栈、MySQL driver errLog 等写 stderr 的输出
// 注意:Logger 在此之前已创建,ConsoleWriter.Out 已绑定到原始 os.Stderr,无循环风险
redirectStderr(that.Log)
@@ -660,52 +662,35 @@ func getLocalIP() string {
}
// redirectStdout 重定向 os.Stdout 和标准 log 包到 HoTime Logger。
// 捕获 fmt.Println/fmt.Printf 等绕过 HoTime 日志系统的输出,
// 以 INFO 级别 + source="stdout" 字段写入,后续经 SeqWriter 推送到 Seq。
func redirectStdout(l *log.Logger) {
// 返回管道写端,供 logrus 等第三方库桥接。
func redirectStdout(l *log.Logger) *os.File {
r, w, err := os.Pipe()
if err != nil {
return
return nil
}
os.Stdout = w
stdlog.SetOutput(w)
go func() {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
if line != "" {
l.Info().Str("source", "stdout").Msg(line)
}
}
if err := scanner.Err(); err != nil {
l.Errorf("[stdout redirect] scanner error: %v", err)
}
}()
go log.CaptureStream(l, zerolog.InfoLevel, "stdout", r)
return w
}
// bridgeThirdPartyStdout 将 import 时钉死原始 stdout 的第三方日志指到捕获管道。
func bridgeThirdPartyStdout(w *os.File) {
if w == nil {
return
}
logrus.SetOutput(w)
}
// redirectStderr 重定向 os.Stderr 到 HoTime Loggerlevel=error, source=stderr)。
// 捕获 Go runtime panic 栈、MySQL driver errLog 等直写 stderr 的输出。
// 必须在 Logger 创建之后调用:ConsoleWriter.Out 已绑定原始 os.Stderr 文件指针,
// 重定向后 ConsoleWriter 仍写真实终端,不会形成循环。
func redirectStderr(l *log.Logger) {
r, w, err := os.Pipe()
if err != nil {
l.Warnf("[redirectStderr] create pipe failed: %v", err)
l.EmitCaptured(zerolog.WarnLevel, "stderr-capture", fmt.Sprintf("create pipe failed: %v", err))
return
}
os.Stderr = w
go func() {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
if line != "" {
l.Error().Str("source", "stderr").Msg(line)
}
}
if err := scanner.Err(); err != nil {
l.Warnf("[redirectStderr] scanner error: %v", err)
}
}()
go log.CaptureStream(l, zerolog.ErrorLevel, "stderr", r)
}
// Init 初始化application