エラーの報告

スタック トレースが生成される場合、関数から出力されたエラーは自動的に取得され、Stackdriver Error Reporting で報告されます。

エラーを自動的に報告する

Firebase SDK for Cloud Functions では、これは捕捉されなかった例外やスローしたタイプ Error のエラーに適用されます。

たとえば、次のエラーは Stackdriver Error Reporting によって取得されます。

export.helloError = functions.https.onRequest((request, response) => {
  // This will be reported to Stackdriver Error Reporting
  throw new Error('epic fail');
});

次のエラーは Stackdriver Error Reporting によって取得されません

export.errorFail = functions.https.onRequest((request, response) => {
  // This will NOT be reported to Stackdriver Error Reporting
  throw 1;
});

エラーを表示する

Google Platform Console で、報告されたエラーを表示できます。

エラーを手動で報告する

関数から Stackdriver Error Reporting にエラーを報告するには、Stackdriver Logging API を使用します。

依存関係をインポートする

functions ディレクトリから、Node.js 用の Google Stackdriver Logging クライアント ライブラリをインストールします。

npm install --save @google-cloud/logging

Logging API にアクセスするために、Google Cloud クライアント ライブラリをインポートします。

const Logging = require('@google-cloud/logging');

// Instantiates a client
const logging = Logging();

Stackdriver に送信する

ログエントリを適切に形式化するには、MonitoredResource オブジェクトと ErrorEvent オブジェクトが必要になります。

この例では、reportError 関数が Stackdriver Error Reporting にエラーを報告するために必要な最低限のデータがわかります。

function reportError(err, context = {}) {
  // This is the name of the StackDriver log stream that will receive the log
  // entry. This name can be any valid log stream name, but must contain "err"
  // in order for the error to be picked up by StackDriver Error Reporting.
  const logName = 'errors';
  const log = logging.log(logName);

  // https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/MonitoredResource
  const metadata = {
    resource: {
      type: 'cloud_function',
      labels: { function_name: process.env.FUNCTION_NAME }
    }
  };

  // https://cloud.google.com/error-reporting/reference/rest/v1beta1/ErrorEvent
  const errorEvent = {
    message: err.stack,
    serviceContext: {
      service: process.env.FUNCTION_NAME,
      resourceType: 'cloud_function'
    },
    context: context
  };

  // Write the error log entry
  return new Promise((resolve, reject) => {
    log.write(log.entry(metadata, errorEvent), error => {
      if (error) { reject(error); }
      resolve();
    });
  });
}

reportError 関数を使用すると、他の方法で捕捉されたエラーを手動で報告できます。

// Charge the Stripe customer whenever an amount is written to the Realtime database
exports.createStripeCharge = functions.database.ref('/stripe_customers/{userId}/charges/{id}').onWrite(event => {
  const val = event.data.val();
  // This onWrite will trigger whenever anything is written to the path, so
  // noop if the charge was deleted, errored out, or the Stripe API returned a result (id exists)
  if (val === null || val.id || val.error) return null;
  // Look up the Stripe customer id written in createStripeCustomer
  return admin.database().ref(`/stripe_customers/${event.params.userId}/customer_id`).once('value').then(snapshot => {
    return snapshot.val();
  }).then(customer => {
    // Create a charge using the pushId as the idempotency key, protecting against double charges
    const amount = val.amount;
    const idempotency_key = event.params.id;
    let charge = {amount, currency, customer};
    if (val.source !== null) charge.source = val.source;
    return stripe.charges.create(charge, {idempotency_key});
  }).then(response => {
      // If the result is successful, write it back to the database
      return event.data.adminRef.set(response);
    }, error => {
      // We want to capture errors and render them in a user-friendly way, while
      // still logging an exception with Stackdriver
      return event.data.adminRef.child('error').set(userFacingMessage(error)).then(() => {
        return reportError(error, {user: event.params.userId});
      });
    }
  );
});

ユーザーの詳細を ErrorContext パラメータを介して渡して Stackdriver UI に表示し、影響を受けるユーザーの数を計算するために使用することもできます。

ErrorContextHTTP リクエストに関する情報を渡すこともできます。

export.httpError = functions.https.onRequest((request, response) => {
  const error = new Error('Test error');
  const httpRequest = httpRequest = {
    method: request.method,
    url: request.originalUrl,
    userAgent: request.get('user-agent'),
    referrer: '',
    remoteIp: request.ip
  };
  reportError(error, {httpRequest}).then(() => {
    response.end();
  });
});

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。