I'm using Firebase functions along with Stackdriver.
Stackdriver is very well integrated with Firebase functions, so I can easily log errors with the console.error
command.
But, I want to record not only about error object but also query parameters.
If I can record error object and query paramters in the same log line, they can be easily grouped and exported.
Is there a easy way to add information to error log on Stackdriver like below?
console.error(new Error('Invalid query'), req.query)
Thanks.
--- edit
I tried the following code. This can add a query parameter to the log entry, but unfortunately Stackdriver puts all the errors in one group as shown in the screenshot below. All errors are grouped together even though each error is different type and occurs in different file. I expect Stackdriver Error Reporting to group errors by error type or stack trace as usual.
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()
}
Screenshot of results of 10 runs:
Stackdriver Error Reporting error summary page Stackdriver Error Reporting error details page
Self answer:
I tried to find easy way, but there was not. So I decided to get off my lazy butt and learn how to use @google-cloud/logging that as Yuri Grinshteyn mentioned.
I found a lot of examples, but none were sufficient for this case. At last, I built a function that reports error with additional information easily.
The important points are as follows:
It took time, but finally, Stackdriver Error Reporting recognize and group each error type and successfully include custom information in the error log's JSON payload. This is what I wanted.
Now I can finally get back to work.
Here is a main code.
// 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()
})
})
}
Screenshot of results of 10 runs: