この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
データアナリティクス事業本部、池田です。
少し前にGoogle CloudのLoggingのPythonライブラリに関するアップデートがありました。
【 Getting Started with Google Cloud Logging Python v3.0.0 】
記事によると、Cloud Functionsなどでログのドロップが起きにくくなったようです。
これまであまりきちんとしたログ実装をしていなかったので、この機会に使い方を調べてみました。
ライブラリをローカルから使ってみる
Google Cloud Python logging libraryは、Google Cloudのサービス上に限らず、 ローカルからでもログを送ることができるようなので、まずローカル(Python 3.7.7)で試してみました。
import google.cloud.logging
client = google.cloud.logging.Client()
client.setup_logging()
import logging
logging.warning("Hello World")
上記の内容のPythonファイルを作成し、
export GOOGLE_APPLICATION_CREDENTIALS="{credentialファイルのパス}"
のように認証情報を環境変数に設定して実行すると、↓Google Cloudプロジェクトへログが送信されていました。
warningの黄色いアイコンになっています。
※ Cloud Shell からであれば認証情報のexportは不要でした
Cloud FunctionsでのLogging
今回は、Pub/Subに紐づくCloud Functionsを実装し、 print()での出力とライブラリでのログ出力をやってみました。
(以降ではCloud Shell上でのコマンド発行を前提としています。)
Pub/Subトピックの作成
メッセージの送受信のために、
Pub/Sub のトピックを
sample_logging_topic
という名前で作成しました。
gcloud pubsub topics create sample_logging_topic
print()する関数を作成
比較用に標準のprint()関数で出力をするCloud Functionsの関数を作成してみます。
main.py
import base64
import os
import json
def sample_print_fn(event, context):
pubsub_message = base64.b64decode(event["data"]).decode("utf-8")
print(f"pubsub_message: {pubsub_message}")
print(json.dumps(event))
print(event)
print(f"env: {os.getenv('ENV_VAR')}")
try:
print("print at try")
_ = 1 / 0
except Exception:
print("print at except")
raise
finally:
print("print at finally")
内容としては、関数のパラメータ( event["data"]
)や環境変数( os.getenv('ENV_VAR')
)を
print()しています。最後にゼロ除算で例外を起こしています。
上記のファイルを以下のコマンドで sample_print_fn
という関数名でデプロイします。
gcloud functions deploy sample_print_fn \
--region asia-northeast1 \
--runtime python39 \
--trigger-topic sample_logging_topic \
--timeout 30 \
--memory 128MB \
--set-env-vars ENV_VAR=環境変数からの値
( --entry-point
を指定していないので、関数名のsample_print_fnが実行されます。)
ライブラリを利用する関数を作成
ライブラリを使用するパターンのコードが以下です。
main.py
import base64
import os
import json
from logging import getLogger, DEBUG
import google.cloud.logging
logging_client = google.cloud.logging.Client()
logging_client.setup_logging()
logger = getLogger(__name__)
logger.setLevel(DEBUG)
def sample_logging_fn(event, context):
pubsub_message = base64.b64decode(event["data"]).decode("utf-8")
logger.info(f"pubsub_message: {pubsub_message}")
logger.debug(json.dumps(event))
logger.debug(event)
logger.warning(f"env: {os.getenv('ENV_VAR')}")
try:
logger.info("info at try")
_ = 1 / 0
except Exception:
logger.error("error at except")
raise
finally:
logger.debug("debug at finally")
Python標準のloggingライブラリと連携して使うことが推奨のようです。
ログレベルを設定しない( logger.setLevel(DEBUG)
が無い)場合は、info()はログ出力されてdebug()は出力されませんでした。
コンソールのログ エクスプローラなどで参照する時にもフィルタができるので、細かいログレベルで出力してしまって良いかなと思いました。
ライブラリを利用できるように 依存関係を別ファイルに記述 します。
requirements.txt
google.cloud.logging>=3.0.0
あとは、同様に sample_logging_fn
という関数名でデプロイします。
gcloud functions deploy sample_logging_fn \
--region asia-northeast1 \
--runtime python39 \
--trigger-topic sample_logging_topic \
--timeout 30 \
--memory 128MB \
--set-env-vars ENV_VAR=環境変数からの値
メッセージの発行~ログ確認
Pub/Subにメッセージを発行して、関数を動作させてログを確認してみます。
gcloud pubsub topics publish sample_logging_topic --message="pubsubのメッセージ"
↓print()のパターンのログ(Cloud Functionsの「ログ」タブ)。
コンソール上の「重大度」は「デフォルト」として扱われます。
↓ライブラリを使ったパターンのログ。
ログレベルが設定されていることがアイコンからも分かります。
↓ログ エクスプローラで見た場合。
ちなみに logger.debug(json.dumps(event))
でも logger.debug(event)
でも、ログ上は違いは見受けられませんでした。
おわりに
ログは奥が深いので、ハンドラなどの使い方にも慣れたらブログにしたいと思います。たぶん。