JSON in JSON なログファイルビューア
プログラミング処理の中で、JSON の中に JSON を入れるのは比較的簡単です。エスケープはライブラリがよしなにやってくれますから。でもその多段に JSON を突っ込まれた JSON 文字列をCLIでハンドリングするのはちょっと面倒くさいです。
例えばこんなん。
{
"message": "{\"level\":\"info\",\"ts\":1557004280.5372975,\"caller\":\"zap/server_interceptors.go:40\",\"msg\":\"finished unary call with code OK\",\"grpc.start_time\":\"2019-05-04T21:11:20Z\",\"system\":\"grpc\",\"span.kind\":\"server\",\"grpc.service\":\"FooService\",\"grpc.method\":\"GetBar\",\"grpc.code\":\"OK\",\"grpc.time_ms\":248.45199584960938}\n",
"namespace": "foo-service",
"podName": "foo-86495899d8-m2vfl",
"containerName": "foo-service"
}
JSON の message の value に JSON が入ってる。
昨今、石を投げればこのような多段 JSON in JSON なログに遭遇します。
この JSON in JSON 状態のエスケープされてる中身を目parseするか、なんとかCLI上で parse するか、という話。
それ、 jq の fromjson でできるよ!というのが今のところのベターアプローチだと思います。
$ stern | jq '. | {message: (.message|fromjson), namespace,podName,containerName}'
{
"containerName" : "foo-service",
"podName" : "foo-86495899d8-m2vfl",
"namespace" : "foo-service",
"message" : {
"grpc.service" : "FooService",
"grpc.method" : "GetBar",
"grpc.code" : "OK",
"span.kind" : "server",
"caller" : "zap/server_interceptors.go:40",
"system" : "grpc",
"msg" : "finished unary call with code OK",
"grpc.start_time" : "2019-05-04T21:11:20Z",
"grpc.time_ms" : 248.451995849609,
"level" : "info",
"ts" : 1557004280.5373
}
}
でもこれ、面倒くさくないです?
というわけで、JSON in JSON を再帰的にさっといい感じにしてくれるやつ書きました。
JSON in JSON Log Viewer ということで jl じぇいえる コマンドです。
App::jl モジュールに同梱されてます。
$ stern | jl
{
"podName" : "foo-86495899d8-m2vfl",
"message" : {
"system" : "grpc",
"grpc.time_ms" : 248.451995849609,
"msg" : "finished unary call with code OK",
"grpc.method" : "GetBar",
"span.kind" : "server",
"level" : "info",
"grpc.start_time" : "2019-05-04T21:11:20Z",
"ts" : 1557004280.5373,
"grpc.code" : "OK",
"caller" : "zap/server_interceptors.go:40",
"grpc.service" : "FooService"
},
"containerName" : "foo-service",
"namespace" : "foo-service"
}
超絶簡単ですね! JSON in JSON を再帰的にやっつけます。デフォルトだと最大10段ネストしててもなんとかしてくれます。
--no-pretty
オプションをつけて再度 jq に渡すとかすると、便利かもしれません。
$ stern | jl | jq .message.msg
"finished unary call with code OK"
圧倒的に覚えることが減る。
満足した。