Go で cronolog ライクにファイル作成・ログ出力するパッケージ

github.com

を書いてみた。似たものはあったけど、ピンポイントで欲しいものではなかったし、せっかくなので 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())

ももいろクローバーZ ももクロくらぶxoxo ~バレンタイン DE NIGHT だぁ~Z 2017 裏・表

行ってきた。とても楽しかった。
忘れても思い出せるようにメモ。

二日間あるイベントの1日目は例年のバレンタインイベントとは一味ちがう、ライブがメインではない裏と銘打たれたイベント。テーマはぐだぐだ is ファースト(トランプパロディ)

ももクロのメンバーが二人一組でドラマを即興して、その後ラジオ番組の体で内容を振り返る形式。組み合わせは百田玉井と有安高城とあーりん。

一組目の百田・玉井ペア。
旅行中ホテルに到着した設定で演技が始まった直後、

百田「うわーすごい景色!たまさ〜ん、みてー」
玉井「えーなに?なにー?」
百田「何がみえる?」
玉井「!!!??」

即興ならではだけど、始まってすぐのぶっこみに完全に意表をつかれて焦る玉井さんとしたり顔の百田さんに笑ったし感心したし、もしかしたら狙ってたのかもだけど、なんでも器用にこなす瞬発力抜群玉井さんの翻弄される姿がとても新鮮で最高だった。

どちらがPPAPをうまくこなせるか勝負するよくみる展開になり、歌番組やももクロChanで何度もモノマネを披露している玉井さんが自信満々で(やや噛みつつも)こなした後の百田さん、同じことしてもきっと面白くないしどうするんだろうな〜と思っていたら

百田「アッポーペン〜パイナッポーペ〜ン。っぽい!ま〜きのっ」

ときて、もはやPPAPじゃないし常識を打ち破る力が凄まじいし照れも臆する様子もなくこなすしまた感心した。これは見習えない。

二組目の有安・高城の推され隊コンビ。
ホテルで就寝する二人だけど、高城さんが寝つけず有安さんに助けを請う設定。

どうしたら眠れるか話しているだけなのに引き込まれたし、前の二人のようにそんな発想が?という驚きはなかったけど、淡々と延々と面白くて無限に聞いていたかった。伏線回収も良くてぐだぐだになると思いきや全然そんなことない最高だった。

最後のあーりん。
ホテルに到着したけどやることなくて暇という設定。

登場するやいなや「やっと着いたよーもう1時間待ったよー」とメタ的な文句を言い、場内のモノノフに電話をかける体で話しかけだし、黄色の女の子にかけたと思いきや「あー電波わるいやーバイバイー」とバッサリ切り捨てたり、勝手気ままな感じが似合うし面白いしなにより嫌な空気にならないのでつよい。

五人揃ってバイきんぐも加わって犯人探しのコントをしつつ百田さんがバイきんぐの「ももいろクローバーAさんですよね?」のボケに対して「ももいろクローバーKだよっ!」と謎のツッコみ天然ボケをかまして会場騒然としたり色々よかった。

ちょくちょくライブを挟みつつ、椅子に座ってのんびりコントドラマを鑑賞するゆるやかさが良くて相変わらず百田さんは非凡だし、ぐだぐだ is ファーストというテーマだけどぼくらは全く飽きなくてエンターテイメント素晴らしかった。

前日の裏とはうってかわりライブを軸にラジオドラマやお決まりのチョコレート争奪勝負を行う、例年どおりのイベント。

やっぱりライブの圧巻パフォーマンス楽しい。
横浜アリーナを縦横無尽にかけめぐりアリーナという名のスタンド脇の通路をいったりきたりしていた。
イマジネーション・デモンストレーションの百田さんのソロダンスはやっぱり良くて、幸運にも目の前で歌い上げるさまを目にできたり多幸感凄かった。
ラストの今宵ライブの下でではいつもの決め台詞を改変した「ハッピーバレンタイン」で天に召された。

本当に楽しい。今後も定期的にライブへ行けるように頑張っていくぞ。

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
...

なんだか圧倒的に早い。