golangでアプリケーションログ取る時、一般的にはlogパッケージが用いられると思います。
が、あれイロイロ不便なので自分で作りました。
既存の問題
標準のlogや、他の人が公開してくれているloggerにはこんな問題があると思います。
- レベル別にできない。
- 関数名やgoroutine番号が出せない
- なんか作りが複雑(主に野良)
方向性
なのでこんな感じの方向性とか機能を盛り込みました。
- logをレベル付できるようにした。
- 関数名とかをログに含められるようにした。
- timeやtext/packageなどgoの標準に沿った作りにした。
サンプル
package main
import (
"github.com/umisama/golog"
"os"
)
var logger log.Logger
func OtherFuncName() {
logger.Info("here is OtherFuncName()")
}
func main() {
logger, _ = log.NewLogger(os.Stdout,
log.TIME_FORMAT_SEC, // Set time writting format.
log.LOG_FORMAT_POWERFUL, // Set log writting format.
log.LogLevel_Debug) // Set log level.
logger.Debug("debug")
logger.Info("Infomation")
logger.Warn("Warning!")
logger.Critical("Critical!")
OtherFuncName()
}
2014/2/9 12:41:59 main.go:20(main) : "debug"
2014/2/9 12:41:59 main.go:21(main) : "Infomation"
2014/2/9 12:41:59 main.go:22(main) : "Warning!"
2014/2/9 12:41:59 main.go:23(main) : "Critical!"
2014/2/9 12:41:59 main.go:11(OtherFuncName) : "here is OtherFuncName()"
NewLogger()がロガーを作ってくれますが、この時time.Format()とtext/templateに指示する表示を渡します。適当にカスタマイズもできます。一応、
LOG_FORMAT_SIMPLE = "{{.Time}} : {{.Message}} \n"
LOG_FORMAT_STANDARD = "{{.Time}} {{.ShortFileName}}:({{.LineNumber}}) : {{.Message}}\n"
LOG_FORMAT_POWERFUL = "{{.Time}} {{.ShortFileName}}:{{.LineNumber}}({{.ShortFuncName}}) : {{.Message}}\n"
こんな感じのは用意してあります。
あと、当然ですがNewLogger()にあげるレベルを変えるとそれ以下のログは出力されなくなります。
logger, _ = log.NewLogger(os.Stdout,
log.TIME_FORMAT_SEC, // Set time writting format.
log.LOG_FORMAT_POWERFUL, // Set log writting format.
log.LogLevel_Critical) // Set log level.
2014/2/9 12:41:59 main.go:23(main) : "Critical!"
レベルは一応 Debug < Info < Warn < Critical という感じになってます。
工夫点
NewLogger()で取得されるLoggerは、interfaceが帰ってきます。この時、指定されたレベルに対して必要な出力メソッドのみ中身のあるもの返し、その他は、
func (x Logger) Hoge () { return }
の様に処理の無いメソッドを持つstructを返し分けています。
これでgcの最適化が効いてインライン関数になりますから、非表示で埋まっているデバッグログのパフォーマンス影響がほぼ0になります。(分岐すらできません)
上手く行ってないぽい・・・orz
デバッグコードがプロダクトに性能低下を与えることが、どうしても許せない人にオススメです。
# いや、まぁメッチャ微々たるものだけど
今後
- プロダクトに入れて行って改良します。