🎃
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 のコード検索をしてみたものの見つけられなかった。この記録が誰かの役に立つとうれしい。
利用するライブラリ
- goth v1.1.0
- google_api_logging v0.12.0
インストール/セットアップ
- GCP にプロジェクトを作成する。今回は
my-project
というプロジェクトを作成した - 作成したプロジェクトに Editor role を付加したサービスアカウントを作成する
-
mix.exs
へgoth
とgoogle_api_logging
の依存を追加する -
goth
のために Elixir で json 形式の private key を読みこむ- Service accountsからサービスアカウントの private key を json 形式でダウンロードする
- ダウンロードした json を読み込むよう Elixir の config を設定する
- 私は
GCP_CREDENTIALS
という環境変数に json を 1 行にしたものを直接書きこむ方法を採用した - TIPS:
jq -c . lateral-yew-251023-06197db86c63.json
のような形で json を 1 行にしたものを取得できる
- 私は
実行
# 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 へ書きこんだログが表示されている。
Discussion