概要
Google Cloud Platform からログデータを取得する.
logadmin パッケージが提供する,Stackdriver クライアントは使いやすいのだが,
手に入る各ログエントリーは logging.Entry型で,ペイロードの取得が手間である.
本稿では,ログエントリー及びそのペイロード取得方法をまとめる.
logadmin パッケージ
logadmin は,比較的新しいパッケージで, ログの取得に関わる操作を提供している.
変数filter
に入っているクエリにマッチするログデータのみを取得するならば,
下記の通りでよい.
import (
"cloud.google.com/go/logging/logadmin"
"golang.org/x/net/context"
"google.golang.org/api/iterator"
)
func GetLogEntries(filter string) error{
ctx := context.Background()
client, err := logadmin.NewClient(ctx, "your-project-id")
if err != nil {
return err
}
defer client.Close()
iter := client.Entries(ctx, logadmin.Filter(filter))
for {
e, err := iter.Next()
if err == iterator.Done {
return nil
} else if err != nil {
return err
}
// logging.Entry型のログデータ e に対する操作
}
}
logging.Entry
上記の操作で手に入るログデータは,logging.Entry構造体になっている.
この構造体では,ペイロードは interface{}
型と定義されており,利用するためにはキャストが必要になる.
なお,Google Cloud Platform ではこのペイロードはほとんどの場合 JSON オブジェクトである.
また,実際に利用する場合は,フィルタの値からスキーマがある程度分かっていることが多いと思う.
さて,手元で調べたところ,このペイロードは structpb.Struct
型へのポインタになっている.
このstructpb.Struct
型から目的のログデータを表す構造体へ変換するのだが,
簡単な方法が分からなかったので,自作の関数 structpbconv.Convert
で変換することにした.
(そのコードはここで公開している)
型変換
例えば次のコードは,このstructpbconvを使って,structpb.StructからCompute Engine VM インスタンスの
activity_log を取得している.
import (
"github.com/golang/protobuf/ptypes/struct"
"github.com/jkawamoto/structpbconv"
)
type ActivityPayload struct {
EventTimestampUs string `structpb:"event_timestamp_us"`
EventType string `structpb:"event_type"`
TraceID string `structpb:"trace_id"`
Actor struct {
User string
}
Resource struct {
Zone string
Type string
ID string
Name string
}
Version string
EventSubtype string `structpb:"event_subtype"`
Operation struct {
Zone string
Type string
ID string
Name string
}
}
func NewActivityPayload(payload *structpb.Struct) *ActivityPayload {
var res ActivityPayload
structpbconv.Convert(payload, &res)
return &res
}
ActivityPayload
構造体は, activity_log のペイロードに合わせて作成する.
実際は JSON オブジェクトなので,小文字+アンダーバーなど命名規則が異なっている部分の対応付けには,
structpb
タグを用いる.
先ほどのログエントリー取得と合わせると,
// イベントタイプが GCE_OPERATION_DONE のログだけを取得する
iter := client.Entries(ctx, logadmin.Filter("jsonPayload.event_type = \"GCE_OPERATION_DONE\""))
for {
e, err := iter.Next()
if err == iterator.Done {
return nil
} else if err != nil {
return err
}
// logging.Entry型のログデータ e に対する操作
if s, ok := e.Payload.(*structpb.Struct); ok {
payload := NewActivityPayload(s)
fmt.Println(payload.TraceID) // trace_id を出力
}
}
などのようにログデータを使用できる.