はじめに

みなさんもちろん log は取っていますよね?

最近は機械学習や deep learning などでも頻繁に使われているのでますます重要性が高まっています。
log の設計もなかなか難しいですよね。

自分が所属するチームでは Golang 製 Web Framework の echo を利用して API を開発しております。
業務で Golang を扱うのは初めてですが、とても素直で書きやすいという印象を持っています。

今回は最近開発するにあたって調査した内容を共有いたします。
初歩的な内容かもしれませんが、どなたかのお役に立てれば。

※ この記事は 2017 年 8 月現在の最新版 v3.2.1 を元に作成しています。

2 つの logger

echo には Echo#LoggerLogger Middleware 2 つの logger があります。

これらにはそれぞれ別の役割があります。

Echo#Logger

echo の内部的なエラー処理 (DefaultHTTPErrorHandler) などで使われています。

https://github.com/labstack/echo/blob/v3.2.1/echo.go#L343
https://github.com/labstack/echo/blob/v3.2.1/response.go#L43

echo 本体では interface しか定義されておらず、内部的には同じく labstack の gommon/log が使われています。

gommon – GoDoc

標準の出力先は os.Stdout です。変更する場合 Echo#Logger.SetOutput で io.Writer 型の出力先を設定します。実際に呼び出されるのは gommon/log の SetOutput です。

https://godoc.org/github.com/labstack/gommon/log#Logger.SetOutput

func GetTest() echo.HandlerFunc {
    return func(c echo.Context) error {
        c.Echo().Logger.Debug("debug at handler")
        return c.JSON(http.StatusOK, "hello world!")
    }
}
    e.Debug = true
    e.Logger.SetOutput(file)

Logger Middleware

Logger middleware logs the information about each HTTP request.

という事でリクエストを logging します。
利用する際には Echo#Use して必要に応じて Configration を与えます。

標準の出力先は os.Stdout です。変更する場合には LogConfig の Output に io.Writer 型の出力先を設定します。

e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
    Output: file,
}))

colog

自分の所属するチームでは colog というライブラリも利用する予定です。これは文字列の先頭で log level を出し分け出来る手軽なライブラリです。

colog.Register() で標準の log の出力先に colog のインスタンスが設定されます。colog の標準の出力先は os.Stderr です。

https://github.com/comail/colog/blob/fba8e7b1f46c3607f09760ce3880066e7ff57c5a/colog.go#L175-L176
https://github.com/comail/colog/blob/fba8e7b1f46c3607f09760ce3880066e7ff57c5a/colog.go#L29

colog のインスタンスは colog の global に置かれているので colog.Register() で利用する場合は出力先を変更できません。
newColog の引数に出力先を指定してインスタンスを作成し、Register 内部の処理と同様標準 log に SetOutput すれば良いようです。

var out = colog.NewCoLog(file, "", 0)
out.SetFormatter(&colog.JSONFormatter{
    TimeFormat: time.RFC3339,
    Flag: log.Lshortfile,
})

log.SetOutput(out)

Example

今回の内容を確認できる example を作りましたのでよろしければ御覧ください。

https://github.com/kysnm/echo_log_practice

おわりに

こう見てみると log 周りは少し煩雑ですね。
標準の出力先以外を設定したい場合それぞれに設定する必要があるのは少しめんどうです。
今後この辺が改善されるといいなと思います。
colog も出力先を設定できるような API がほしいので、いいアイデアを思いついたら pull request を出したいですね。

Golang に Web Framework はいらない。net/http で作った方がいい という意見を見かける事がありますが、ある程度のセキュリティが担保され、HTTP Header の定義や middleware などの用意された Framework を利用するのはそれほど規模の大きくないアプリケーションを構築するには適しているのではないでしょうか?

それでは Happy Logging!!


Goodpatchでは、Golang や GCP、Kubernetes などの技術を使ってユーザーに品質の高いサービスを提供していきたいと考えています。
興味のある方は、ぜひ一度遊びにきてください!