【问题标题】:Add custom information to the Stackdriver error log in Firebase Functions将自定义信息添加到 Firebase Functions 中的 Stackdriver 错误日志
【发布时间】:2020-02-28 11:14:16
【问题描述】:

我将 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 错误报告错误详情页面

【问题讨论】:

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


    【解决方案1】:

    当我处理错误时,我通常会使用一个对象结构来提供我需要的所有信息。像这样的:

    const query = req.query;
    const myErrorObject = new Error('some error');
    
    
    console.error({
        method: req.method,
        query: req.query,
        error: myErrorObject
    });
    

    希望有帮助

    【讨论】:

    • 感谢您的出色建议。我试过了,但不幸的是 Stackdriver 没有按单个错误对日志进行分组。所有错误都归为一组。我会将我的尝试添加到问题中。无论如何,感谢您提供有用的信息。
    【解决方案2】:

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

    我建议使用 Stackdriver 日志记录 library,它应该允许您编写结构化日志。这在 Firebase documentation 中有描述。

    【讨论】:

    • 谢谢你告诉我官方信息。但是,了解如何使用自定义日志记录需要时间,所以我觉得很麻烦。因此,我一直在寻找一种简单的方法。我也试过'@google-cloud/error-reporting',但是找不到这个案例的好例子,也不能很好地使用它。这就是我问这个问题的原因。除了你的建议,可能没有别的办法。很高兴你对这个问题感兴趣。谢谢。
    • 感谢您再次告诉我!可能没有简单的方法。我会试试的。
    【解决方案3】:

    自我回答:

    我试图找到简单的方法,但没有。所以我决定摆脱我的懒惰,学习如何使用 @google-cloud/logging,正如 Yuri Grinshteyn 提到的那样。

    我找到了很多示例,但对于这种情况,没有一个是足够的。 最后,我构建了一个可以轻松报告错误并附带附加信息的函数。

    重点如下:

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

    这花费了一些时间,但最终,Stackdriver 错误报告会识别并分组每种错误类型,并成功地将自定义信息包含在错误日志的 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 错误报告错误摘要页面。

    Stackdriver Logging 显示包含自定义信息的错误。

    【讨论】:

    • 我遵循了这个辅助函数,但我仍然无法将我的自定义日志放入堆栈驱动程序。当我触发一个明确抛出错误的 API 时,会记录一个 DEBUG 日志,但没有自定义详细信息。日志中也没有 jsonPayload 这样的键。
    • 也检查了 google-logging 文档,但我的自定义日志仍然没有被记录
    猜你喜欢
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 2019-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多