Cómo generar informes de errores

Los errores que emite tu función se capturan de forma automática y se informan en Stackdriver Error Reporting si producen un seguimiento de pila.

Informe automático de errores

Con el SDK de Firebase para Cloud Functions, esto se aplica a cualquier excepción no detectada y a cualquier error de tipo Error que muestres.

Por ejemplo, Stackdriver Error Reporting captura el siguiente error:

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

Stackdriver Error Reporting no captura el siguiente error:

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

Visualización de errores

Puedes ver los errores informados en Google Platform Console.

Informe manual de errores

Para informar un error a Stackdriver Error Reporting desde una función, usa la API de Stackdriver Logging.

Importación de dependencias

Desde el directorio functions, instala la biblioteca cliente de Google Stackdriver Logging para Node.js:

npm install --save @google-cloud/logging

Importa la biblioteca cliente de Google Cloud para acceder a la API de Logging:

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

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

Envío a Stackdriver

Una entrada de registro con la forma apropiada necesita un objeto MonitoredResource y un objeto ErrorEvent.

Esta función reportError de ejemplo demuestra los datos mínimos obligatorios para informar un error a 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();
    });
  });
}

La función reportError se puede usar para informar de forma manual errores que se detectaron de otra forma:

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

Los detalles del usuario se pueden pasar mediante el parámetro ErrorContext que se mostrará en la IU de Stackdriver y se pueden usar para calcular la cantidad de usuarios afectados.

Además, se le puede pasar información en una solicitud HTTP a ErrorContext:

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

Enviar comentarios sobre…

¿Necesitas ayuda? Visita nuestra página de asistencia.