将自定义信息添加到 Firebase Functions 中的 Stackdriver 错误日志
Add custom information to the Stackdriver error log in Firebase Functions
我将 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 Reporting 错误详情页面
当我处理错误时,我通常使用一个对象结构来提供我需要的所有信息。像这样:
const query = req.query;
const myErrorObject = new Error('some error');
console.error({
method: req.method,
query: req.query,
error: myErrorObject
});
希望对您有所帮助
[更新] - 我看到您添加了更多信息,表明您正在尝试使用错误报告,而不仅仅是日志记录。您仍然可以使用记录的日志库 here.
我建议使用 Stackdriver 日志记录 library that should allow you to write structured logs. This is described in the Firebase documentation。
自己回答:
我试图找到简单的方法,但没有。所以我决定摆脱我的懒惰,学习如何使用 Yuri Grinshteyn 提到的@google-cloud/logging。
我找到了很多示例,但是 none 对于这种情况已经足够了。
最后,我构建了一个可以轻松报告错误和附加信息的函数。
重点如下:
- 要在 GCP 控制台上将自定义错误日志显示为普通错误日志,它需要包括严重性、区域、execution_id、跟踪 ID。如果缺少它们,GCP 控制台不会在默认过滤器上显示它们。也不能按执行 ID 标记分组。
- execution_id 和跟踪 ID 应从 http 请求中提取。 (我不知道如何让它们出现在另一个触发器类型的函数上。)
这需要时间,但最终,Stackdriver 错误报告识别并分组了每种错误类型,并成功地将自定义信息包含在错误日志的 JSON 负载中。这就是我想要的。
现在我终于可以回去工作了。
这是主要代码。
// 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
//
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 显示自定义信息错误。
我将 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 错误报告错误摘要页面
当我处理错误时,我通常使用一个对象结构来提供我需要的所有信息。像这样:
const query = req.query;
const myErrorObject = new Error('some error');
console.error({
method: req.method,
query: req.query,
error: myErrorObject
});
希望对您有所帮助
[更新] - 我看到您添加了更多信息,表明您正在尝试使用错误报告,而不仅仅是日志记录。您仍然可以使用记录的日志库 here.
我建议使用 Stackdriver 日志记录 library that should allow you to write structured logs. This is described in the Firebase documentation。
自己回答:
我试图找到简单的方法,但没有。所以我决定摆脱我的懒惰,学习如何使用 Yuri Grinshteyn 提到的@google-cloud/logging。
我找到了很多示例,但是 none 对于这种情况已经足够了。 最后,我构建了一个可以轻松报告错误和附加信息的函数。
重点如下:
- 要在 GCP 控制台上将自定义错误日志显示为普通错误日志,它需要包括严重性、区域、execution_id、跟踪 ID。如果缺少它们,GCP 控制台不会在默认过滤器上显示它们。也不能按执行 ID 标记分组。
- execution_id 和跟踪 ID 应从 http 请求中提取。 (我不知道如何让它们出现在另一个触发器类型的函数上。)
这需要时间,但最终,Stackdriver 错误报告识别并分组了每种错误类型,并成功地将自定义信息包含在错误日志的 JSON 负载中。这就是我想要的。
现在我终于可以回去工作了。
这是主要代码。
// 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
//
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 显示自定义信息错误。