回答:
- 単一のlog.Loggerを作成して渡しますか?
それは可能です。A log.Loggerは、複数のゴルーチンから同時に使用することができます。
- そのlog.Loggerへのポインタを渡しますか?
log.Newは、*Logger
通常、オブジェクトをポインタとして渡す必要があることを示すを返します。値として渡すと、構造体のコピー(つまり、ロガーのコピー)が作成され、複数のゴルーチンが同じio.Writerに同時に書き込む可能性があります。ライターの実装によっては、それが深刻な問題になる可能性があります。
- 各ゴルーチンまたは関数はロガーを作成する必要がありますか?
関数やゴルーチンごとに個別のロガーを作成することはありません。ゴルーチン(および関数)は、個別のロガーの保守を正当化しない非常に軽量なタスクに使用されます。プロジェクトのより大きなコンポーネントごとにロガーを作成することをお勧めします。たとえば、プロジェクトがメールの送信にSMTPサービスを使用している場合、メールサービス用に別のロガーを作成すると、出力を個別にフィルタリングしてオフにできるので、良い考えのように思えます。
- ロガーをグローバル変数として作成する必要がありますか?
それはあなたのパッケージに依存します。前のメールサービスの例では、サービスのインスタンスごとに1つのロガーを用意することをお勧めします。これにより、ユーザーは、ローカルのMTAを使用しているときに発生した障害(たとえばsendmail )。
単純なケースでは、ログパッケージで定義されたグローバルロガーがありますlog.Logger
。このグローバルロガーは、を介して設定できますlog.SetFlags
。
その後、そのグローバルインスタンスを使用するlog.Printf
やなどのログパッケージの最上位関数を呼び出すことができlog.Fatalf
ます。
io.Writer
インターフェースを実装し、を介してデフォルトのロガーの出力を変更する場合、カスタムロガーを使用できますSetOutput()
。
これはシンプルなロガーです
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")
}
私はこの質問が少し古いことを知っていますが、私のように、プロジェクトが複数の小さなファイルで構成されてlogger.go
いる場合、4番目のオプションに投票します-私はパッケージメインの一部であるを作成しました。この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)
}
defer errorlog.Close()
実行の最後に、またはその終了を確実にするために、Goのシグナルパッケージgolang.org/pkg/os/signal
これは古い質問ですが、http://github.com/romana/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ポートに変換されます)。
考慮できるロギングモジュールの1つはklogです。です。特定のレベルでログを記録する柔軟性を提供する「V」ログをサポートします
klogはglogのフォークであり、以下の欠点を克服しています
実装例
package main
import (
"flag"
"k8s.io/klog"
)
type myError struct {
str string
}
func (e myError) Error() string {
return e.str
}
func main() {
klog.InitFlags(nil)
flag.Set("v", "1")
flag.Parse()
klog.Info("hello", "val1", 1, "val2", map[string]int{"k": 1})
klog.V(3).Info("nice to meet you")
klog.Error(nil, "uh oh", "trouble", true, "reasons", []float64{0.1, 0.11, 3.14})
klog.Error(myError{"an error occurred"}, "goodbye", "code", -1)
klog.Flush()
}
ブログを確認してください。GOlangでのLOGの使用について説明します。 ください
例:// Se declara la variable Log。Estaseráusada para reregstrar los eventos。var(ログ* log.Logger = Loggerx())
func Loggerx() *log.Logger {
LOG_FILE_LOCATION := os.Getenv("LOG_FILE_LOCATION")
//En el caso que la variable de entorno exista, el sistema usa la configuración del docker.
if LOG_FILE_LOCATION == "" {
LOG_FILE_LOCATION = "../logs/" + APP_NAME + ".log"
} else {
LOG_FILE_LOCATION = LOG_FILE_LOCATION + APP_NAME + ".log"
}
flag.Parse()
//Si el archivo existe se rehusa, es decir, no elimina el archivo log y crea uno nuevo.
if _, err := os.Stat(LOG_FILE_LOCATION); os.IsNotExist(err) {
file, err1 := os.Create(LOG_FILE_LOCATION)
if err1 != nil {
panic(err1)
}
//si no existe,se crea uno nuevo.
return log.New(file, "", log.Ldate|log.Ltime|log.Lshortfile)
} else {
//si existe se rehusa.
file, err := os.OpenFile(LOG_FILE_LOCATION, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
if err != nil {
panic(err)
}
return log.New(file, "", log.Ldate|log.Ltime|log.Lshortfile)
}
}