GKE 上にて Pythonで logger.info() を行うとCloud logging では stderr に保存され、すべてエラーになる問題への対処法
Python のアプリケーションで、Cloud logger にログを出力したいときに
- 標準の Python logging モジュールを利用して、ログを出力する
- Python Cloud Logging package を使用する
上記の2つの方法があります。
不必要にパッケージを増やしたくはないので、1 の標準モジュールで Cloud Logger へ出力できないか試してみました。
標準の Python logging モジュールを試す
標準の logging モジュールでログを出力したいときに
import logging
logger = logging.getLogger(__name__)
def hoge():
logger.info('logging Start 2021')
と、logging.info() を仕込んで、Cloud logger にログを出力してみると、logger.info() で出しているはずなのに、Cloud logger 上ではすべてエラーとして扱われてしまっています。
原因を特定するために、logger のログを見てみると logger.info() がすべて stderr
標準エラーストリームへ出力されてしまっています。
{
"textPayload": "2021-02-20 21:26:51,012 - root:predict:36 - INFO: logging Start\n",
...
},
"timestamp": "2021-02-20T12:26:51.013213826Z",
"severity": "ERROR",
"labels": {
...
},
"logName": "projects/.../logs/stderr",
"receiveTimestamp": "2021-02-20T12:26:55.050911180Z"
}
そのため、明示的に標準出力へ出力先を変更してみました。
import logging
import sys
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(sys.stdout)
logger.addHandler(handler)
def hoge():
logger.info('logging Start 2021')
これで解決できているはずと、Cloud Logger を見てみると
なぜか、stderr
への出力は残ったまま、stdout
への出力が新たに増えました。このままでも INFO レベルでログは残せているので目的は達成できていますが、stderr
への出力が残ってしまっているせいで Cloud logger 上でエラーが発生しているようになり問題です。なので、これを避けるために2つ目の方法である Python Cloud Logging package を利用してみます。 (というかパッケージをむやみに増やしたくないのだが利用せざるを得ない。)
Python Cloud Logging package を使用する
まずPython Client for Cloud Logging のチュートリアルをすすめて行きます。
Cloud logging の Python package のQuick Start にてわかりやすく導入方法が紹介されています。ここで混乱しやすいのが、GCP のLogging Client Libraries のドキュメントではまず Service Account を作って、GOOGLE_APPLICATION_CREDENTIALS
を使用して Cloud Logging の認証を行ってくださいと書かれています。
ですが、
- GCP 上での VM でパッケージを使用するなら認証は必要ない 。ただし、デフォルトの SA を使いたくない場合や、GCP 外などで動かしたい場合は SA が必要
と本元のパッケージのドキュメントでは書かれており、こちらのほうが誤解が少なくていいですね。(公式ドキュメントだと、SA 作成時に Project > Owner
を指定しろと書かれているんだけど、これって権限過多なのでは無いのだろうか??)
ちなみに GCP 上の認証過程はこちらのドキュメントが詳しく書かれているので、気になった方は御覧ください。
Authenticating as a service account
上記の認証仮定をまとめると
- GOOGLE_APPLICATION_CREDENTIALS を参照する
- ADC (Application Default Credentials) が、コードに紐付けられている SA を使用する
- ADC は各サービスの SA を利用する
- 1-3 が使用できなかった場合、認証エラーが発生する
最終的に GKE 上で Cloud logging へログを出力するためには、
以下のコードで無事に INFO
のログがstderr
に吐き出されることなく、stdout
のみにINFO
として出力されるようになります。
import logging
import sys
# NOTE: GKE ではCotainerEngineHandler が必要
from google.cloud.logging.handlers import ContainerEngineHandler
logger = logging.getLogger(__name__)
# NOTE: stream で stdout を指定する
logger.addHandler(ContainerEngineHandler(name=__name__, stream=sys.stdout))
# NOTE: ログが重複して出力されるので、propagate を切る
logger.propagate = False
logger.info('Hello Cloud Logging.')
Appendix
関連しているかもしれない記事
- 遅すぎる `pandas.read_gbq` を使わずに、Google BigQueryから高速にデータを読み込む
- How to connect the Google Compute Engine via Visual Studio Code
📮 📧 🐏: 記事への感想のおたよりをおまちしてます。 お気軽にお送りください。 メールアドレス入力があればメールで返信させていただきます。 もちろんお返事を希望せずに単なる感想だけでも大歓迎です。
このサイトの更新情報をRSSで配信しています。 お好きなフィードリーダーで購読してみてください。
このウェブサイトの運営や著者の活動を支援していただける方を募集しています。 もしよろしければ、Buy Me a Coffee からサポート(投げ銭)していただけると、著者の活動のモチベーションに繋がります✨
Amazonでほしいものリストも公開しているので、こちらからもサポートしていただけると励みになります。