GCPで提供されているFaaS (Functions as a Service)、Cloud Functions ではちょっとしたスクリプトやバッチ(「関数」と呼ばれる)をクラウド上で実行でき、十分な無料枠も準備されているので、個人ユースでもとても便利なサービスです。

Cloud Functions で関数を実行した結果を確認するために、GCPのログ管理サービス Cloud Logging へログを出力できます。
CLoud Logging に保管されたログは GCP のスマホアプリで確認したりもできますが、全てのログを表示すると確認が不要なログも多く表示されてしまい、必要な情報が埋もれてしまいます。

そこで、構造化ログ として出力することで、ログ毎にレベルを設定し、絞り込みをして必要なログのみを表示させることが可能です。

ログの作成、表示、処理 - Google Cloud Functions に関するドキュメント
しかし、GCPの公式ドキュメントを読むと Cloud Logging クライアント ライブラリ とか Logging API とか書いてあってよく分からなくなった(あとで使い分けを理解した)ので、サクッと使えるように一番簡単な方法をまとめてみました。

※ Cloud Functions だけでなく、Cloud Run でも同じ方法が使えるようです。

結論

標準出力にJSONで出力する

1
{"severity":"INFO","message":"This is info message."}

"severity" の値にログレベル"message" の値にログテキストを指定する。
GCP側で "severity" の値を読み取って、ログにレベルを設定してくれる。

JSONの出力方法

各言語の標準出力へ文字列を出力するメソッドを使用すればOK。

  • Python
    print()
  • Go
    fmt.Printf / fmt.Println
  • Node.js
    console.log()
    • console.info() console.warn() console.error() といったメソッドもあるが、ログレベルの違いとしては認識されない…?

ログレベルとして指定可能な値

  • DEFAULT (レベル設定なし)
  • DEBUG (重大度:低)
  • INFO
  • NOTICE
  • WARNING
  • ERROR
  • CRITICAL
  • ALERT
  • EMERGENCY (重大度:高)

通常使用するレベルとしては DEBUG、INFO、WARNING、ERROR あたりでしょうか。

Cloud Functions では、重大度の最も低い DEBUG レベルで、関数の作成、設定変更、呼び出し、開始、終了…等の細かいログが自動的に出力されます。

任意の処理結果の情報(日付と処理件数…等)をログ出力しておき後から確認したい場合は INFO レベルで出力しておき、ログ確認時に INFO レベル以上 を絞り込み表示することで、確認不要な DEBUG レベルのログが表示されずスマートです。

言語別サンプルコード

各言語 (Python 3/Go/Node.js) で INFO レベルのログを出力するサンプルコード
2行目は、日付(文字列)と処理件数(整数値)をログに出力する想定です。

1
2
{"severity":"INFO","message":"This is info message."}
{"severity":"INFO","message":"Date: 2021/01/13 / Count: 123"}

Python 3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import json


def logJSON(logLevel, message):
    return json.dumps({
        "serverity": logLevel,
        "message": message,
    })


print(logJSON("INFO", "This is info message."))

date = "2021/01/13"
count = 123
print(logJSON("INFO", f"Date: {date} / Count: {count}"))

Go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import (
        "encoding/json"
        "fmt"
)

func logJSON(logLevel, message string) string {
	entry := map[string]string{
		"severity": logLevel,
		"message":  message,
	}
	bytes, _ := json.Marshal(entry)
	return string(bytes)
}

func main() {
	fmt.Println(logJSON("INFO", "This is info message."))

	date := "2021/01/13"
	count := 123
	fmt.Println(logJSON("INFO", fmt.Sprintf("Date: %s / Count: %d", date, count)))
}

Node.js

1
2
3
4
5
6
7
8
9
10
11
12
function logJSON(logLevel, message) {
  return JSON.stringify({
    severity: logLevel,
    message: message,
  });
}

console.log(logJSON("INFO", "This is info message."));

let date = "2021/01/13"
let count = 123
console.log(logJSON("INFO", `Date: ${date} / Count: ${count}`));

まとめ

Cloud Functions からレベル付きログを出力するだけであれば、設定したいレベルとテキストをJSONで標準出力するだけでOKでした。
個人的なちょっとしたスクリプトやバッチ程度であればサクッと適用できますね。

Cloud Logging クライアント ライブラリ(言語別ライブラリ)を使えば Cloud Functions では対応していない PHP や Ruby といった言語のスクリプトから、Logging API を使えば Cloud Functions 以外のプラットフォームからも GCP の Cloud Logging へログを送れるようなので、機会があれば試してみようと思います。

参考