在Firebase Functions中将自定义信息添加到Stackdriver错误日志

时间:2019-11-02 13:02:59

标签: node.js firebase google-cloud-functions google-cloud-stackdriver google-cloud-error-reporting

我将Firebase函数与Stackdriver一起使用。

Stackdriver与Firebase功能很好地集成在一起,因此我可以使用console.error命令轻松记录错误。 但是,我不仅要记录错误对象,还要记录查询参数。 如果我可以在同一日志行中记录错误对象和查询参数,则可以轻松地对它们进行分组和导出。

是否有一种简单的方法可将信息添加到Stackdriver的错误日志中,如下所示?

    console.error(new Error('Invalid query'), req.query)

谢谢。

---编辑

我尝试了以下代码。这可以向日志条目添加查询参数,但是不幸的是,Stackdriver将所有错误归为一组,如下面的屏幕快照所示。即使每个错误是不同的类型并且发生在不同的文件中,所有错误也被分组在一起。我希望Stackdriver Error Reporting能够像往常一样按错误类型或堆栈跟踪对错误进行分组。

index.js

const functions = require('firebase-functions')
const raiseReferenceError = require('./raiseReferenceError')
const raiseSyntaxError = require('./raiseSyntaxError')
const raiseTypeError = require('./raiseTypeError')

exports.stackdriverErrorLogging = functions.https.onRequest((req, res) => {
  try {
    switch (Math.round(Math.random() * 2)) {
      case 0:
        raiseReferenceError()
        break

      case 1:
        raiseSyntaxError()
        break

      default:
        raiseTypeError()
        break
    }
  } catch (error) {
    console.error({
      error: error,
      method: req.method,
      query: req.query
    })
  }

  res.send('Hello from Firebase!')
})

raiseReferenceError.js

module.exports = () => {
  console.log(foo)
}

raiseSyntaxError.js

module.exports = () => {
  eval(',')
}

raiseTypeError.js

module.exports = () => {
  const foo = null
  foo()
}

10次运行的结果的屏幕截图:

Stackdriver错误报告错误摘要页面 Stackdriver error summary page Stackdriver Error Reporting错误详细信息页面 Stackdriver error details page 1 Stackdriver error details page 2

3 个答案:

答案 0 :(得分:0)

当我遇到错误时,我通常使用一个对象结构,该结构可为我提供所需的所有信息。像这样:

const query = req.query;
const myErrorObject = new Error('some error');


console.error({
    method: req.method,
    query: req.query,
    error: myErrorObject
});

希望有帮助

答案 1 :(得分:0)

[更新]-我看到您添加了更多信息,这些信息表明您正在尝试使用错误报告,而不仅仅是日志记录。您仍然可以按照here中所述使用日志记录库。

我建议使用Stackdriver日志记录library,该日志记录应允许您编写结构化日志。 Firebase documentation中对此进行了描述。

答案 2 :(得分:0)

自我答案:

我试图找到简单的方法,但是没有。因此,我决定摆脱懒惰的屁股,学习如何使用Yuri Grinshteyn提到的@ google-cloud / logging。

我找到了很多例子,但没有一个足以解决这种情况。 最后,我构建了一个函数,可以轻松报告错误并提供其他信息。

要点如下:

  1. 要将GCP控制台上的自定义错误日志显示为普通错误日志,它需要包括严重性,区域,execution_id和跟踪ID。如果缺少它们,则GCP控制台不会在默认过滤器上显示它们。也不能按执行ID标签分组。
  2. 应该从http请求中提取
  3. execution_id和跟踪ID。 (我不知道如何在另一个触发器类型的函数上获取它们。)

这花费了时间,但是最终,Stackdriver Error Reporting识别并归类了每种错误类型,并成功将自定义信息包含在错误日志的JSON有效负载中。这就是我想要的。

现在我终于可以恢复工作了。

Here is a gist I made.

这是主要代码。

// https://firebase.google.com/docs/functions/reporting-errors#manually_reporting_errors
const { Logging } = require('@google-cloud/logging')

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

module.exports = function reportError (err, context = {}, req = undefined) {
  // Use Stackdriver only on production environment.
  if (process.env.NODE_ENV !== 'production') {
    return new Promise((resolve, reject) => {
      console.error(err, context)
      return resolve()
    })
  }

  const log = logging.log('cloudfunctions.googleapis.com%2Fcloud-functions')

  // https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/MonitoredResource
  const metadata = {
    severity: 'ERROR',
    resource: {
      type: 'cloud_function',
      labels: {
        function_name: process.env.FUNCTION_NAME,
        project: process.env.GCLOUD_PROJECT,
        region: process.env.FUNCTION_REGION
      }
    }
  }

  // Extract execution_id, trace from http request
  // https://stackoverflow.com/a/55642248/7908771
  if (req) {
    const traceId = req.get('x-cloud-trace-context').split('/')[0]
    Object.assign(metadata, {
      trace: `projects/${process.env.GCLOUD_PROJECT}/traces/${traceId}`,
      labels: {
        execution_id: req.get('function-execution-id')
      }
    })
  }

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

10次运行的结果的屏幕截图:

Stackdriver Error Reporting错误摘要页面。 Stackdriver Error Reporting error summary page.

Stackdriver Logging显示带有自定义信息的错误。 Stackdriver Logging shows a error with custom information.