Stackdriver Error Reporting for PHPをGCE上で使ってみる


こんにちは、 @mshibuya です。

GCE上で動いているPHPアプリケーションにおいて適切にエラーの収集・解決ができるようにStackdriver Error Reporting for PHPを導入しようとしているのですが、はまりどころがいくつかあったので共有します。。

なおこの記事はオプトテクノロジーズアドベントカレンダー11日目の代打エントリーです…(←遅刻ではないという主張)。

Stackdriver Error Reportingとは

GCPが提供するモニタリングシステムStackdriverの機能のひとつで、アプリケーションレベルのエラーや例外を一元管理しわかりやすくリアルタイム表示できるエラー通知ツールです。この手のツールではAirbrakeやSentryあたりが有名ですね。

公式サイトはこちら

Stackdriver Error Reporting for PHP

この手のサービスのご多分にもれず、各種言語向けのSDKが用意されていて簡単にアプリケーションに統合できるようになっており、PHP版も存在します。が、公式サイトに記載のある通りベータ版のステータスであり(2018/12/24現在)、あんまりドキュメント等充実していません。。

はまりポイント1:必要な権限に注意

ローカルで試そうとしていて、自分自身に Error Reportingエラー書き込み の権限をつけ、エラーになるPHPコードを実行させるも一向にエラーとして検知されず…。

で、なんでかと思いSDKのソースコードを追いかけて調べました。

結論、こちらに記載

次のいずれかの方法で、エラーを Google Compute Engine アプリケーションから Stackdriver Error Reporting に送信できます。

Stackdriver Logging にロギングする。すでに Stackdriver Logging を使用している場合、追加設定は不要です。フォーマット設定の要件について詳しくは、例外のロギングをご覧ください。

Stackdriver Error Reporting API を使用する。アプリケーションでは、REST API を使用して HTTP リクエストを送信したり、試験運用中のライブラリを複数の言語で使用したりできます。

のある通り通知経路は2パターンあるわけですが、

  • 通知経路によって異なる権限が必要(Stackdriver Logging経由の場合は Logging → ログ書き込み 、Stackdriver Error Reporting API経由の場合は Error Reporting → エラー書き込み
  • PHP SDKの場合、例外ハンドラにひっかけてエラー通知される時は必ずStackdriver Logging経由となる。Error Reporting API経由で送られるのはアプリケーションから明示的に呼び出した場合のみ

ということで、ログ書き込みがないと書けないのでした。

えー、「Stackdriver Error Reportingを使うからエラー書き込みの権限があればいいよね!」って思うじゃないですか普通…。

はまりポイント2:GCE上で使うときの罠

で、権限の謎は解けたものの、ローカルでやってもGCE上でやっても一向に出ず…。GAEで動いてる別アプリでは問題なく出てるので、条件を近づけようとしてあれこれ試して判明したことは

  • service名が空だとLoggingには流れるものの、Error Reportingに拾われない

ということ。

でmetadata providerからserviceIdを取得しているわけですが、GAE上ではちゃんとサービス名が返るのに対しGCE上やローカルでは値が取れず、結果Error Reporting側に拾われないのでした…。

解決策としては、vendor ディレクトリの直上に ErrorReportingBootstrap の名前で

<?php
  use Google\Cloud\Logging\LoggingClient;
  return (new LoggingClient())->psrLogger('app-error', [
    'batchEnabled' => true,
    'debugOutput' => true,
    'batchOptions' => ['numWorkers' => 2],
    'metadataProvider' => new Google\Cloud\Core\Report\SimpleMetadataProvider(
      [], '', 'my-service'
    )
  ]);

のようなファイルを作っておくとOKです( my-service のところは適切に名前を入れてあげてください)。こうすることで

の処理がファイルを読んでくれて、ちゃんとservice名の入ったmetadata providerを持つloggerを使えるようになります。

まとめ

Stackdriverはシステムに必要ないろんなモニタリングツールが揃っていて便利なのですが、もうちょっと親切さが増してくれるとより活用しやすいのになーといった感想です。

アプリケーションエラーの適切な収集・解決はシステムの安定稼働にとって重要なので、こういったツールを活用していい感じの運用体制を作っていけるとよいですねー