Goでのアプリケーションロギングのパターンは何ですか?たとえば、ログインする必要がある5つのゴルーチンを持っている場合、...
log.Logger
を作成して渡しますか?log.Logger
へのポインターを渡しますか?
- 単一のlog.Loggerを作成して渡しますか?
それは可能です。 log.Logger は、複数のゴルーチンから同時に使用できます。
- そのlog.Loggerへのポインタを渡しますか?
log.New は*Logger
を返します。これは通常、オブジェクトをポインターとして渡す必要があることを示しています。値として渡すと、構造体のコピー(つまり、ロガーのコピー)が作成され、複数のゴルーチンが同じ io.Writer に同時に書き込む可能性があります。ライターの実装によっては、これは深刻な問題になる可能性があります。
- 各ゴルーチンまたは関数はロガーを作成する必要がありますか?
関数やゴルーチンごとに個別のロガーを作成しません。ゴルーチン(および関数)は、独立したロガーの保守を正当化しない非常に軽量なタスクに使用されます。プロジェクトの大きなコンポーネントごとにロガーを作成することをお勧めします。たとえば、プロジェクトがメールの送信にSMTPサービスを使用している場合、メールサービス用に別のロガーを作成することは、出力を個別にフィルタリングおよびオフにできるようにするための良い考えのようです。
- ロガーをグローバル変数として作成する必要がありますか?
それはパッケージによって異なります。前のメールサービスの例では、サービスのインスタンスごとに1つのロガーを用意することをお勧めします。これにより、ユーザーは、ローカルMTAの使用中に発生した障害とは異なる方法でgmailメールサービスの使用中に障害を記録できます)。
単純な場合、ログパッケージで定義されているグローバルロガー log.Logger
があります。このグローバルロガーは log.SetFlags
で設定できます。
その後、 log.Printf
や log.Fatalf
のようなログパッケージのトップレベル関数を呼び出すだけで、そのグローバルインスタンスを使用できます。
これはシンプルなロガーです
package customlogger
import (
"log"
"os"
"sync"
)
type logger struct {
filename string
*log.Logger
}
var logger *logger
var once sync.Once
// start loggeando
func GetInstance() *logger {
once.Do(func() {
logger = createLogger("mylogger.log")
})
return logger
}
func createLogger(fname string) *logger {
file, _ := os.OpenFile(fname, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777)
return &logger{
filename: fname,
Logger: log.New(file, "My app Name ", log.Lshortfile),
}
}
このように使用できます
package main
import (
"customlogger"
"fmt"
"net/http"
)
func main() {
logger := customlogger.GetInstance()
logger.Println("Starting")
http.HandleFunc("/", sroot)
http.ListenAndServe(":8080", nil)
}
func sroot(w http.ResponseWriter, r *http.Request) {
logger := customlogger.GetInstance()
fmt.Fprintf(w, "welcome")
logger.Println("Starting")
}
私はこの質問が少し古いことを知っていますが、私のように、あなたのプロジェクトが複数の小さなファイルで構成されている場合、私はあなたの4番目のオプションに投票します-私はパッケージメインの一部であるlogger.go
を作成しました。このgoファイルはロガーを作成し、それをファイルに割り当て、メインの他の部分に提供します。エラーログを閉じるための優雅な方法を思いついていないことに注意してください...
package main
import (
"fmt"
"log"
"os"
)
var errorlog *os.File
var logger *log.Logger
func init() {
errorlog, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Printf("error opening file: %v", err)
os.Exit(1)
}
logger = log.New(errorlog, "applog: ", log.Lshortfile|log.LstdFlags)
}
これは古い質問ですが、 http://github.com/romana/rlog (私たちが開発した)の使用を提案したいと思います。環境変数を使用して構成され、ロガーオブジェクトはrlogのインポート時に作成および初期化されます。したがって、ロガーを回す必要はありません。
rlogには多くの機能があります。
これは非常に小さく、標準のGolangライブラリを除き、外部の依存関係はなく、積極的に開発されています。リポジトリに例を示します。
デフォルトのログパッケージ( https://golang.org/pkg/log/ )が多少制限されていることがわかりました。たとえば、情報ログとデバッグログのサポートはありません。
いくつか調べてみたところ、 https://github.com/golang/glog を使用することに決めました。これは https://github.com/google/glog の移植であると思われ、ロギングにかなりの柔軟性を与えます。たとえば、アプリケーションをローカルで実行する場合、DEBUGレベルのログが必要な場合がありますが、実稼働環境ではINFO/ERRORレベルでのみ実行したい場合があります。完全な機能/ガイドのリストは、ここにあります https://google-glog.googlecode.com/svn/trunk/doc/glog.html (c ++モジュール用ですが、大部分はgolangポートに変換されます)