目的
goで製品開発していて単純なlog.Printfよりはもう少し賢い簡単なログライブラリが必要になりました。そこで要求事項を整理した結果、まずはログの内容がinformationなのかerrorなのかをprefixで判別できるものを作ろうとなり、 [INFO] [ERROR] とログの頭につく形でログを出力することを考えました。
例えばこういうライブラリ関数になります
log.info("this is information")
log.error("this is error")
出力
- [INFO] this is information
- [ERROR] this is error
困ったこと
結果としては上の出力が得られれば問題はなかったのですが以下のような問題が出ました
・すでに結構な数のログが製品中に埋め込まれている。これらを全てどれがinfoかどれがerrorかを一つずつ見ながら対応する関数呼び出しに置き換えるのは大変
・今後ログ関数を呼び出す場合にプログラマ全員がきちんと該当するレベルのエラーを呼び出してくれるのか不安。またコードレビューの際にもログレベルが妥当かをいちいち見て指摘しなければいけない
解決策
ログの呼び出し内容にerrorが含まれていればprefixをERRORに、それ以外ならINFOにすれば自動で振り分けられるのではないか。ということで以下が実装になります。
func logger(format string, args ...interface{}) {
prefix := "[INFO] "
if args == nil {
format = prefix + format
log.Printf(format)
} else {
for _, arg := range args {
switch arg.(type) {
case error:
prefix = "[ERROR] "
break
}
}
format = prefix + format
log.Printf(format, args...)
}
}
func main(){
logger("this is information")
logger("%s","yet another information")
logger("%v",errors.New("i am error"))
}
出力
2019/10/20 00:11:20 [INFO] this is information
2019/10/20 00:11:20 [INFO] yet another information
2019/10/20 00:11:20 [ERROR] i am error
まとめ
何も考えずに、とりあえずこの関数呼び出してログ出力して貰えば適切に動いてくれる、十分製品として実用レベルのログライブラリとして活躍しました。