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

将Go标准库日志重定向到logrus是否线程安全?

Is redirecting Go's standard log to logrus via log.SetOutput(gLog.logrus.Writer()) thread-safe?

Question

I'm using logrus for structured logging in my Go project, with the following setup:

// Global variable for logging
var gLog = &Logger{moduleName: ModuleName, logrus: logrus.New()}
type Logger struct {
    moduleName string
    logrus *logrus.Logger
}
func SetupGlobalLogger(logPrefix string, logMode string) error {
    if logMode == "file" {
        logFilePath := fmt.Sprintf("var/%s.log", vite.Environment())
        file, err := os.OpenFile(logFilePath, logFileFlags, logFilePermission)
        if err != nil {
            return err
        }
        gLog.logrus.SetOutput(file)
        // redirect logs written using standard log library to same place as logrus
        log.SetOutput(gLog.logrus.Writer())
        log.Println(vite.MarkInfo, "redirect log to file:", logFilePath)
    }
    return nil
}

My project uses standard library log statements like log.Println() in many places, which I've redirected to logrus using log.SetOutput(gLog.logrus.Writer()). I'm wondering:

  1. Is this redirection operation thread-safe?
  2. Will there be issues when one goroutine executes log.Println() while another runs gLog.logrus.Info() or other logrus methods?

Answer

Great question! Let's break down the thread safety here step by step:

1. Logrus is inherently thread-safe

The logrus.Logger instance uses an internal sync.Mutex to guard all write operations. Whether you call logrus methods directly (like Info(), Print()) or write to the Writer() returned by the logger, the same mutex will be acquired to ensure only one goroutine is writing logs at a time. This prevents interleaved or corrupted log entries from concurrent logrus calls.

2. The standard log package is also thread-safe

Go's built-in log package has its own internal sync.Mutex that protects operations like Println(). When you redirect its output to logrus's writer, every call to log.Println() will first acquire this standard log mutex before writing to the logrus writer.

3. Concurrent calls to log.Println() and logrus methods are safe

When one goroutine runs log.Println() and another runs gLog.logrus.Info():

  • The log.Println() goroutine will hold the standard log mutex, then call the logrus writer's Write method. This method will in turn acquire logrus's internal mutex to write the log entry.
  • The gLog.logrus.Info() goroutine will directly acquire logrus's mutex (waiting if it's already held by the other goroutine).

Since these are two separate mutexes (one from the standard log package, one from logrus), there's no risk of deadlock. All log writes (whether from standard log or direct logrus calls) are ultimately serialized by logrus's mutex, so you won't see messy, interleaved log lines.

A quick note on async logging

If you've configured logrus to use asynchronous hooks or output (e.g., AsyncHook), you'll want to double-check the thread safety of those components. But for the default synchronous setup you've shown, everything is safe.


内容的提问来源于stack exchange,提问作者Yogesh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:57:07