LoginSignup
6

More than 5 years have passed since last update.

Stackdriver Logging からログを取得する

Last updated at Posted at 2016-12-29

概要

English
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 を出力
    }

}

などのようにログデータを使用できる.

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6