在golang的web应用中,我什么时候去关闭log文件?

发布于 2022-09-11 21:18:16 字数 1862 浏览 39 评论 0

基于gin框架构建了一个web应用
并且引入了logrus来写日志

package logger

import (
    "log"
    "os"
    "runtime"

    "quanzi/service/setting"

    "github.com/sirupsen/logrus"
)

type P map[string]interface{}

var Logger = logrus.New()

func init() {
    //打开日志文件
    file, err := os.OpenFile(setting.LogConf.Path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalln("open log file err, file path:", setting.LogConf.Path, ",err:", err)
    }

    //修改日志的输出方式
    Logger.Out = file
    //设置日志格式为json
    Logger.Formatter = &logrus.JSONFormatter{}
}

func Info(msg string, err error, params map[string]interface{}) {
    fields := formatLog(err, params)

    Logger.WithFields(fields).Info(msg)
}

func Debug(msg string, err error, params map[string]interface{}) {
    fields := formatLog(err, params)

    Logger.WithFields(fields).Debug(msg)
}

func Error(msg string, err error, params map[string]interface{}) {
    fields := formatLog(err, params)

    Logger.WithFields(fields).Error(msg)
}

func Fatal(msg string, err error, params map[string]interface{}) {
    fields := formatLog(err, params)

    Logger.WithFields(fields).Fatal(msg)
}

/**
 * 为日志字段增加文件和行号
 */
func formatLog(err error, params map[string]interface{}) logrus.Fields {
    _, file, line, ok := runtime.Caller(2)

    if !ok {
        log.Fatalln("runtime caller err")
    }

    var fields = logrus.Fields{
        "file":   file,
        "line":   line,
        "error":  err,
        "params": params,
    }

    return fields
}

我是在这个包的init方法中,打开日志文件的文件句柄,并传递给logger,让日志写入文件
但是我不知道应该什么时候关闭这个文件句柄

还是这种方法就错了?因为我发现只有这个web应用启动,我就没办法删除或修改这个日志文件,这和nginx的日志好像不一样

我是不是应该在写入的时候,再打开文件句柄,写完了再关闭文件句柄?
可是我觉得这样不是很好,因为这是一个常驻进程,每次写入都要打开关闭不是很浪费资源吗?不应该是一直打开文件句柄,然后写入吗?

这种常驻进程,日志是如何写的?文件句柄是一直打开?还是写的时候打开,写完了关闭?

求大神指点

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

岁吢 2022-09-18 21:18:16

资源的释放一般发生在不需要使用这个资源的时候,给定 struct 赋值特定的字段绑定到该资源,
在资源结束的时候调用 Close 方法去关闭该资源,

package main

import (
    "context"
    "github.com/sirupsen/logrus"
    "net/http"
    "os"
    "os/signal"
)

type Server struct {
    l       *logrus.Logger
    server  *http.Server
    logFile *os.File
}

func (s *Server) Close() {
    // 平滑关闭服务器
    s.server.Shutdown(context.Background())
    // 关闭日志句柄
    s.logFile.Close()
}

func NewServer() *Server {

    log := logrus.New()
    f, _ := os.OpenFile("log.log", os.O_WRONLY|os.O_APPEND, 0777, )
    log.SetOutput(f)

    return &Server{
        l:       log,
        logFile: f,
    }
}

// 这里不是重点
func (s *Server) Start() {
    s.server = &http.Server{
        Addr: ":8080",
    }
    go func() {
        err := s.server.ListenAndServe()
        if err != nil {
            s.l.Errorf("server closed: %s", err)
        }
    }()
    return
}
// 第一种 使用信号,ctrl+c 的时候会通知 <- ch. s.Close 得以执行
func main() {
    s := NewServer()
    s.Start()
    ch := make(chan os.Signal, 1)
    signal.Notify(ch, os.Kill, os.Interrupt)

    <-ch

    s.Close()
}

// 第二种
func main() {
    s := NewServer()
    defer s.Close()
    s.Start()
}

╄→承喏 2022-09-18 21:18:16

当然用完就关闭啊
你的日志打印很频繁吗?,一直打开,占用句柄也很不合理啊

别再吹冷风 2022-09-18 21:18:16

对服务日志这种场景,server关闭的时候,才需要执行关闭日志文件。或者单个日志文件内容太大,做拆分的时候,也建议执行Close操作

紫轩蝶泪 2022-09-18 21:18:16

朋友 最后怎么解决

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文