Elixirを使ってログをStackdriverのLoggingへ送る

GCPにはログの収集、保管、検索を容易に行えるStackdriver Loggingという機能がある。Elixirを使ってログをStackdriver Loggingへ送る方法を書く。

StackdriverはGCPの永久無料枠(always free)で利用可能であり、Pricingによると、プロジェクト毎に1ヶ月あたり50GiBが無料枠となるそうだ。(50GiBという表記は何かの間違いではないかと思えるほどの量であるが、ドキュメントにはそう書いてある)

Elixirを使ってログをStackdrive Loggingへ送る最小限の設定を発見できた。2019-08-25現在はGoogleやGithubのコード検索をしてみたものの見つけられなかった。この記録が誰かの役に立つとうれしい。

利用するライブラリ

インストール/セットアップ

実行

# GCPに作成したprojectのID。Nameではなく、IDの方。
my_project_id = "lateral-yew-251023"

# 以下を満たす任意のログ名
# - 512文字以下
# - 大文字、小文字の英文字
# - スラッシュ(/)、アンダースコア(_)、ハイフン(-)、ピリオド(.)
my_log_name = "my_log_name"

# Gothを利用しStackdriverに送付する権限を持ったtokenを取得する
#
# 有効な文字列は以下のURLを参照のこと。
# https://cloud.google.com/logging/docs/access-control#scopes
{:ok, %{token: token}} = Goth.Token.for_scope("https://www.googleapis.com/auth/logging.write")
conn = GoogleApi.Logging.V2.Connection.new(token)

# 監視しているリソースの種類および名前
#
# https://hexdocs.pm/google_api_logging/0.12.0/api-reference.html
#
# typeとlobalの有効な組み合わせは以下のURLを参照のこと。
# https://cloud.google.com/logging/docs/api/v2/resource-list#resource-types
#
# GCPでもAWSでもない場所から利用しようとするときのtypeはglobalくらいしか該当するものがなさそうだった。
# GCPやAWSからの場合はgeneric_nodeやgeneric_taskも検討に値するかもしれない。
monitored_resource = %GoogleApi.Logging.V2.Model.MonitoredResource{type: "global", labels: %{project_id: my_project_id}}

# Stackdriverに送りたいログを作る
#
# https://hexdocs.pm/google_api_logging/0.12.0/GoogleApi.Logging.V2.Model.LogEntry.html
#
# logNameではどのような値が有効かは以下のURLにあるlogNameフィールドの解説が読みやすい。
# https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry
#
# Stackdriverが初めてのlogNameを受けとると、そのlogNameのlogsが新規作成される。
# logNameを収める場所を作成するという手順は必要ない。
# https://cloud.google.com/logging/docs/api/tasks/creating-logs#creating_logs
entry = %GoogleApi.Logging.V2.Model.LogEntry{resource: monitored_resource, logName: "projects/#{my_project_id}/logs/#{my_log_name}", textPayload: "Hello StackDriver!!"}

# Stackdriverへ送りたいログのまとまりを作る
#
# https://hexdocs.pm/google_api_logging/0.12.0/GoogleApi.Logging.V2.Model.WriteLogEntriesRequest.html
#
# ドキュメントによると、ログを沢山送るような環境では、送信のスループット向上やStackdriverのクォータ制限にかからないようにEntryを複数リストにして送るとよいようだ。
entries = %GoogleApi.Logging.V2.Model.WriteLogEntriesRequest{entries: [entry]}

# Stackdriverへログを送る
#
# https://hexdocs.pm/google_api_logging/GoogleApi.Logging.V2.Api.Entries.html#logging_entries_write/3
{:ok, _} = GoogleApi.Logging.V2.Api.Entries.logging_entries_write(conn, body: entries)

Viewerを開き、Resouceの選択画面をGlobalにするとStackdriverへ書きこんだログが表示されている。