はじめに
こんにちは、Stackdriverで遊んでいる人です。Stackdriver Loggingは標準出力に出されたJSON形式のログをFluentdベースのエージェント経由でいい感じに表示してくれます。
一方でGoに限らず通常のロギングライブラリは標準エラーにログを吐くという感じになるのですが、Stackdriver Loggingの場合デフォルト設定だと標準エラーに吐かれたログはすべてエラー扱いになりますので(まあ当たり前だよな)、そのあたりのすり合わせ調整が必要。
標準の log
パッケージの場合
標準パッケージだけ使うのであれば、とりあえずこれだけやっておけばOK
- 標準出力に出す(GKEの場合)
- JSON形式でいくつかの決められたフィールド名(message, time, severity)を満たす
ということなのでこういう log.Logger
のインスタンスを作ってあげる感じになりそう。
func sdLog(l *log.Logger, severity, msg string) { now := time.Now().Format(time.RFC3339Nano) entry := map[string]string{ "time": now, "severity": severity, "message": msg, } b, err := json.Marshal(entry) if err != nil { log.Fatal(err) } l.Print(string(b)) } logger := log.New(os.Stdout, "", 0) sdLog(logger, "info", "hello")
logrus
を使う場合
上の条件を満たすだけなんだけども、 logrus
の場合はJSONFormatterがあるし、logrus.Logger
に各種ログレベルにあわせたメソッド(Infof
、Warnf
など)があるので楽に設定できる。
log := logrus.New() log.Level = logrus.DebugLevel log.Formatter = &logrus.JSONFormatter{ FieldMap: logrus.FieldMap{ logrus.FieldKeyTime: "timestamp", logrus.FieldKeyLevel: "severity", logrus.FieldKeyMsg: "message", }, TImestampFormat: time.RFC3339Nano, } log.Out = os.Stdout
Stackdriver LoggingのGo用のクライアントライブラリを使う
これを使っていいならはじめから使ったほうが良い。ただ個人的には logrus
のほうがseverityに応じたヘルパーメソッドがあるので使い勝手が良いように感じる。
client, _ := logging.NewClient(ctx, projectID) logger := client.Logger("my-log") // Text Payload logger.Log(logging.Entry{Payload: "Hello, world!") // JSON Payload type MyEntry struct { Name string Count int } logger.Log(logging.Entry{ Payload: MyEntry{Name: "Bob", Count: 3}, Severity: logging.Critical, })