Firebase 将于 5 月 10 日重返 Google I/O 大会!立即报名

报告错误

使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

自动报告错误

您可以将 Cloud Functions 函数报告的错误提交到 Error Reporting,如下所示:

Node.js

// These WILL be reported to Error Reporting
throw new Error('I failed you'); // Will cause a cold start if not caught

如果您需要更精细的错误报告功能,可以使用 Error Reporting 客户端库

您可以在 GCP 控制台的 Error Reporting 中查看报告的错误。您也可以在 GCP 控制台的函数列表中选择特定的函数,来查看该函数报告的错误。

您的函数产生的未捕获到的异常会显示在 Error Reporting 中。请注意,未捕获到的某些异常(例如异步抛出的异常)会导致在未来调用函数时执行冷启动,这会增加您的函数运行所需的时间。

手动报告错误

如需通过函数向 Error Reporting 报告错误,请使用 Cloud Logging API。

导入依赖项

functions 目录中,安装 Node.js 版 Cloud Logging 客户端库:

npm install --save @google-cloud/logging

导入并初始化 Cloud Logging 客户端库:

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

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

发送到 Cloud Logging

格式正确的日志条目需要一个 MonitoredResource 对象和一个 ErrorEvent 对象。

此示例 reportError 函数演示了向 Error Reporting 报告错误所需的最少数据。

function reportError(err, context = {}) {
  // This is the name of the 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 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) {
        return reject(error);
      }
      return resolve();
    });
  });
}

reportError 函数可用于手动报告错误:

exports.createStripePayment = functions.firestore
  .document('stripe_customers/{userId}/payments/{pushId}')
  .onCreate(async (snap, context) => {
    const { amount, currency, payment_method } = snap.data();
    try {
      // Look up the Stripe customer id.
      const customer = (await snap.ref.parent.parent.get()).data().customer_id;
      // Create a charge using the pushId as the idempotency key
      // to protect against double charges.
      const idempotencyKey = context.params.pushId;
      const payment = await stripe.paymentIntents.create(
        {
          amount,
          currency,
          customer,
          payment_method,
          off_session: false,
          confirm: true,
          confirmation_method: 'manual',
        },
        { idempotencyKey }
      );
      // If the result is successful, write it back to the database.
      await snap.ref.set(payment);
    } catch (error) {
      // We want to capture errors and render them in a user-friendly way, while
      // still logging an exception to Error Reporting.
      functions.logger.log(error);
      await snap.ref.set({ error: userFacingMessage(error) }, { merge: true });
      await reportError(error, { user: context.params.userId });
    }
  });

您可以通过 ErrorContext 参数传递用户详细信息。Error Reporting 界面会显示这些详细信息,并会利用这些信息来计算受影响用户的数量。

您还可以向 ErrorContext 传递有关 HTTP 请求的信息

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