2016-04-06 13 views
0

私は新しい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, 
    ) 
} 
+2

ファイルシステムにアクセスしているので、それだけで 'mutex.Lock()'で保護します。 go-kitに関しては、新しいロガーを作成するのがスレッドセーフであれば、スタックチャネル(彼らが非常に活発である)に関する直接の質問に答えるでしょう。 – eduncan911

答えて

0

あなたのロガーのあなたの設定アップのみが存在しない場合は、ログファイルを開いて、ログファイルを作成し、ライブラリのインスタンスを含み、全く書き込みが異なるゴールーチンからそれを呼び出して問題ありません関与していないので、共有データが改ざんされていないためです。

サイドノート: デザイン賢明それは同じでセットアップ関数を呼び出す2ゴールーチンを妨げることになるロギング用のLoggerの唯一のインスタンス化されたインスタンスの周囲を通過する(Loggerが同じファイルに書き込んでいると仮定した場合)理にかなっています時間。

0

最初の推奨事項:go buildgo testには-raceフラグを使用してください。競争条件があるかどうかは、ほとんど常にあなたに伝えることができます。この場合は、os.Create()os.OpenFile()と同時に電話してしまう可能性があります。

したがって、2番目の推奨は可能な限り「存在する/一致する/権限を持っている場合は開く/削除する/何でも」というパターンを避けることです。

このパターンはTOCTTOU(Time of Check To Use Of Use)バグにつながります。これはセキュリティ上のバグであり、少なくともデータ損失を招くことがあります。

チェックを入れて同じミューテックスで使用するか、ファイルを作成するOpenFile呼び出しなどのアトミック操作を使用するか、既に存在する場合はエラーを返します(技術的ではありますがOSカーネル。ハードウェアバスにアトミックなCPU操作がロックされているように。

あなたのケースでは、なぜあなたは2つのオープンコールを持っているのか分かりません。なぜなら、ちょうど1つが仕事をするように見えるからです。

関連する問題