오류 보고

오류 자동 보고

아래와 같이 Cloud 함수에서 Stackdriver Error Reporting으로 오류를 내보낼 수 있습니다.

Node.js

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

// These will NOT be reported to Stackdriver Error Reporting
console.info(new Error('I failed you')); // Logging an Error object at the info level
console.error('I failed you'); // Logging something other than an Error object
throw 1; // Throwing something other than an Error object
callback('I failed you');
res.status(500).send('I failed you');

Stackdriver Error Reporting 클라이언트 라이브러리를 사용하면 보다 세밀하게 오류를 보고할 수 있습니다.

GCP Console의 Stackdriver Error Reporting에서 보고된 오류를 확인할 수 있습니다. 또한 GCP Console의 함수 목록에서 특정 함수를 선택하면 해당 함수에서 보고된 오류를 확인할 수 있습니다.

함수로 생성되었지만 발견되지 않은 예외는 Stackdriver Error Reporting에 표시됩니다. 일부 포착되지 않은 예외(예: 비동기적으로 발생)는 향후 함수 호출 시 콜드 스타트를 유발할 수 있습니다. 그러면 함수 성능이 저하됩니다.

오류 수동 보고

함수에서 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) {
       return reject(error);
      }
      return resolve();
    });
  });
}

reportError 함수를 사용하여 수동으로 오류를 보고할 수 있습니다.

// Charge the Stripe customer whenever an amount is created in Cloud Firestore
exports.createStripeCharge = functions.firestore.document('stripe_customers/{userId}/charges/{id}').onCreate(async (snap, context) => {
      const val = snap.data();
      try {
        // Look up the Stripe customer id written in createStripeCustomer
        const snapshot = await admin.firestore().collection(`stripe_customers`).doc(context.params.userId).get()
        const snapval = snapshot.data();
        const customer = snapval.customer_id
        // 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;
        }
        const response = await stripe.charges.create(charge, {idempotency_key: idempotencyKey});
        // If the result is successful, write it back to the database
        return snap.ref.set(response, { merge: true });
      } catch(error) {
        // We want to capture errors and render them in a user-friendly way, while
        // still logging an exception with StackDriver
        console.log(error);
        await snap.ref.set({error: userFacingMessage(error)}, { merge: true });
        return reportError(error, {user: context.params.userId});
      }
    });

ErrorContext 매개변수를 통해 사용자 세부정보를 전달할 수 있습니다. Stackdriver UI에 표시되는 세부정보를 활용해 영향을 받는 사용자의 수를 계산합니다.

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();
  });
});