Go で cronolog ライクにファイル作成・ログ出力するパッケージ
を書いてみた。似たものはあったけど、ピンポイントで欲しいものではなかったし、せっかくなので Go の勉強も兼ねて作った。
仕様
引数で受け取ったフォーマット文字列を、現在時刻に置き換えてファイルパスにする。
ファイルパスに含まれるディレクトリもなければ作成して、ファイルに文字列を出力する。
フォーマットは下記例のとおり。
入力フォーマット | 出力パス |
---|---|
/path/to/example.log.%Y%m%d | /path/to/example.log.20170205 |
/path/to/%Y/%m/%d/example.log | /path/to/2017/02/05/example.log |
だいたい cronolog にならっていて、時間をベースにファイル分割していく。
使い方
せっかくなので使い方も書いておく。
基本は、Logger と組み合わせて使う。
例えば、uber-go/zap と組み合わせるときは、👇🏼 のとおり Writer オブジェクトをつくって io.Writer
の受け口に渡してあげるだけ。
package main import ( "github.com/uber-go/zap" "github.com/utahta/go-cronowriter" // 👈🏼 ) func main() { w1 := cronowriter.MustNew("/tmp/example.log.%Y%m%d") // 👈🏼 w2 := cronowriter.MustNew("/tmp/internal_error.log.%Y%m%d") // 👈🏼 l := zap.New( zap.NewJSONEncoder(), zap.Output(zap.AddSync(w1)), zap.ErrorOutput(zap.AddSync(w2)), ) l.Info("test") } // Output: // /tmp/example.log.20170204 // {"level":"info","ts":1486198722.1201255,"msg":"test"}
他の Logger と組み合わせるときも、同じように io.Writer
に渡す。
interface 便利!
オプション
いろいろオプションも用意していて、たいていのものは揃えた。
WithLocation
タイムゾーンの設定。デフォルトはシステムロケール。
w := cronowriter.MustNew("/path/to/example.log.%Z", cronowriter.WithLocation(time.UTC)) // /path/to/example.log.UTC
WithSymlink
シンボリックリンクの設定。現在書き込み対象のファイルに対してシンボリックを貼る。
w := cronowriter.MustNew( "/path/to/example.log.%Y%m%d", cronowriter.WithSymlink("/path/to/example.log") ) // /path/to/example.log -> /path/to/example.log.20170218
WithMutex
排他制御する設定。大抵の Logger は write 前で mutex.Lock していることから writer はデフォルトで排他制御しなくした。
w := cronowriter.MustNew("/path/to/example.log.%Y%m%d", cronowriter.WithMutex())
WithDebug
デバッグ機能。ファイル書き込みと同時に標準出力する。
w := cronowriter.MustNew("/path/to/example.log.%Y%m%d", cronowriter.WithDebug())
WithInit
writer を New したときにファイルを作成する。デフォルトは Write が呼ばれたタイミングでファイルを作成している。
書き込み権限があるかどうか事前に知りたいとき使うと便利。
w := cronowriter.MustNew("/path/to/example.log.%Y%m%d", cronowriter.WithInit())
echo で使われてる logger のベンチマークをとってみた
uber-go/zap との比較が目的なので、zap のベンチマークテストと同じようなコードを書いてとってみた。
元々あったテスト(BenchmarkLog-4)と大して変わらない結果。
uber-go/zap
uber-go/zap のベンチマークを同じマシンで実行した結果。
$ go test -bench . ... BenchmarkNoContext-4 5000000 283 ns/op BenchmarkBoolField-4 5000000 344 ns/op BenchmarkFloat64Field-4 3000000 403 ns/op BenchmarkIntField-4 5000000 359 ns/op BenchmarkInt64Field-4 5000000 361 ns/op BenchmarkStringField-4 5000000 346 ns/op BenchmarkStringerField-4 5000000 368 ns/op BenchmarkTimeField-4 5000000 363 ns/op BenchmarkDurationField-4 5000000 371 ns/op BenchmarkErrorField-4 5000000 361 ns/op ...
なんだか圧倒的に早い。
ファイル・URLを同じインターフェースで開ける go-openuri パッケージを書いてみた
ruby の open-uri
のインスパイアー。
o, err := openuri.Open("/path/to/file")
o, err := openuri.Open("http://localhost")
というようにファイルパスか URL かを気にせず IO オープンできる。
ちなみに戻り値は io.ReadCloser
。