Relatar erros

Como relatar erros automaticamente

Informe um erro de uma das Cloud Functions para o Stackdriver Error Reporting, conforme mostrado abaixo:

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');

Se você quiser um relatório de erros mais refinado, use as bibliotecas de cliente do Stackdriver Error Reporting.

Veja os erros informados no Stackdriver Error Reporting do Console do GCP. Você também pode ver os erros informados de uma função específica quando a seleciona na lista de funções no Console do GCP.

As exceções não identificadas produzidas pela função serão exibidas no Stackdriver Error Reporting. Observe que algumas exceções não identificadas, como aquelas lançadas de maneira assíncrona, podem causar uma inicialização a frio em uma invocação futura. Isso reduz o desempenho da função.

Como relatar erros manualmente

Para relatar erros em uma função ao Stackdriver Error Reporting, use a API Stackdriver Logging.

Como importar dependências

No seu diretório functions, instale a Biblioteca de cliente do Google Stackdriver Logging para Node.js:

npm install --save @google-cloud/logging

Importe a Biblioteca de cliente do Google Cloud para acessar a Logging API:

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

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

Como enviar dados para o Stackdriver

Uma entrada de registro com formatação correta requer os objetos MonitoredResource e ErrorEvent.

Veja nesta função reportError de exemplo os dados mínimos necessários para relatar um erro ao 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();
    });
  });
}

A função reportError pode ser usada para informar erros manualmente:

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

É possível transmitir detalhes do usuário por meio do parâmetro ErrorContext. A IU do Stackdriver exibe esses detalhes e os utiliza para calcular o número de usuários afetados.

ErrorContext também pode receber informações de uma solicitação 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();
  });
});