簡體   English   中英

Go日志結構實例化實用程序的Goroutine線程安全性

[英]Goroutine thread safety of Go logging struct instantiation utility method

我正在使用新的go服務,並且我具有SetupLogger實用程序功能,該功能創建go-kit的日志記錄結構log.Logger的新實例。

從單獨的go例程中處理請求的代碼中調用該方法是否安全?

package utils

import (
    "fmt"
    "github.com/go-kit/kit/log"
    "io"
    "os"
    "path/filepath"
)

// If the environment-specified directory for writing log files exists, open the existing log file
// if it already exists or create a log file if no log file exists.
// If the environment-specified directory for writing log files does not exist, configure the logger
// to log to process stdout.
// Returns an instance of go-kit logger
func SetupLogger() log.Logger {
    var logWriter io.Writer
    var err error

    LOG_FILE_DIR := os.Getenv("CRAFT_API_LOG_FILE_DIR")
    LOG_FILE_NAME := os.Getenv("CRAFT_API_LOG_FILE_NAME")

    fullLogFilePath := filepath.Join(
        LOG_FILE_DIR,
        LOG_FILE_NAME,
    )

    if dirExists, _ := Exists(&ExistsOsCheckerStruct{}, LOG_FILE_DIR); dirExists {
        if logFileExists, _ := Exists(&ExistsOsCheckerStruct{}, fullLogFilePath); !logFileExists {
            os.Create(fullLogFilePath)
        }
        logWriter, err = os.OpenFile(fullLogFilePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
        if err != nil {
            fmt.Println("Could not open log file. ", err)
        }
    } else {
        logWriter = os.Stdout
    }

    return log.NewContext(log.NewJSONLogger(logWriter)).With(
        "timestamp", log.DefaultTimestampUTC,
        "caller", log.DefaultCaller,
    )
}

由於您的Logger設置僅涉及庫實例化,如果不存在則創建日志文件,打開日志文件且不涉及寫入,因此不會從不同的例程調用它,因為共享數據未獲取篡改。

旁注:明智的設計(假設Logger正在寫入同一文件)可以傳遞Logger的唯一實例化實例以進行日志記錄,這樣可以防止兩個go-routines同時調用您的setup函數。

第一個建議:使用-race標志進行go buildgo test 它幾乎總是能夠告訴您您是否有比賽狀況。 盡管在這種情況下可能不會,因為您最終可能同時調用os.Create()os.OpenFile()

因此,第二個建議是盡可能避免使用“如果存在/匹配/具有權限,然后打開/刪除/任何內容”模式。

這種模式會導致TOCTTOU(檢查時間到使用時間)錯誤,該錯誤通常是安全性錯誤,至少會導致數據丟失。

為了避免這種情況,可以將檢查並包裝到同一個互斥鎖中,也可以使用原子操作,例如創建文件的OpenFile調用,或者如果文件已經存在則返回錯誤(盡管從技術上講,它已鎖定在OS內核中。例如基本的CPU操作如何鎖定在硬件總線中。)。

在您的情況下,我不確定您為什么要進行兩次Open呼叫,因為看起來只有一個可以勝任。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM