报告错误

自动报告错误

您可以将 Cloud Functions 函数发出的错误提交到 Stackdriver Error Reporting,只需将 Error 对象记录到控制台上的错误级别即可:

console.error(new Error('message'));

您可以在 API 控制台的 Stackdriver Error Reporting 中查看报告的错误。如果从 API 控制台的函数列表中选择特定函数,您还可以看到该函数报告的错误。

如果您的函数产生未捕获到的错误,或如果您明确抛出 Error 类型的对象,Stackdriver Error Reporting 中也会显示相应错误。但是,未被捕获的错误和异常会导致在未来调用函数时强制执行冷启动。因此,考虑到性能原因,您应该使用第一种方法(记录 Error 对象)。

请注意,以下情况不会发出 Stackdriver 错误:

  • 抛出的内容不是 Error 对象:例如 throw 1;
  • 将错误对象记录到信息级别:例如 console.info(new Error('message'));
  • 记录的内容不是 Error 对象:例如 console.error('message');
  • 您的函数正常完成但返回错误结果:例如 res.status(500).send('message');(对于 HTTP 函数)和 callback('message');(对于所有其他后台触发器)。

try-catch 语句的 catch 块中或 Promise 的 catch 回调中报告错误时,err 对象通常已经是类型化的 Error 对象。如果您是通过 Google 提供的库使用 Google 服务,则只需直接记录所提供的 err 对象:

Node.js

try {
  // Throw an Error object (to simulate a GCP API failure)
  throw new Error('Error object!');
} catch (err) {
  // err is already an Error object
  console.error(err);
}

如果您不确定提供的 err 是否为 Error 对象,则可以按照以下方式进行检查:

Node.js

try {
  // Throw an unknown error type
  if (someCondition) {
    throw 'Error string!';
  } else {
    throw new Error('Error object!');
  }
} catch (err) {
  // Determine the error type
  if (err instanceof Error) {
    console.error(err);
  } else {
    console.error(new Error(err));
  }
}

手动报告错误

要从某个函数向 Stackdriver Error Reporting 报告错误,请使用 Stackdriver Logging API。

导入依赖项

functions 目录中,安装适用于 Node.js 的 Google Stackdriver Logging 客户端库:

npm install --save @google-cloud/logging

导入 Google Cloud 客户端库以访问 Logging API:

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) {
       return reject(error);
      }
      return 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}')
    .onCreate((snap, context) => {
      const val = snap.val();
      // Look up the Stripe customer id written in createStripeCustomer
      return admin.database().ref(`/stripe_customers/${context.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 idempotencyKey = context.params.id;
            const charge = {amount, currency, customer};
            if (val.source !== null) {
              charge.source = val.source;
            }
            return stripe.charges.create(charge, {idempotency_key: idempotencyKey});
          }).then((response) => {
            // If the result is successful, write it back to the database
            return snap.ref.set(response);
          }).catch((error) => {
            // We want to capture errors and render them in a user-friendly way, while
            // still logging an exception with StackDriver
            return snap.ref.child('error').set(userFacingMessage(error));
          }).then(() => {
            return reportError(error, {user: context.params.userId});
          });
        });

您可以通过 ErrorContext 参数传递用户详细信息。Stackdriver 界面会显示这些详细信息并将其用于计算受影响的用户数。

还可以用 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();
  });
});

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面