TL;DR;
Does anyone know if it's possible to use console.log
in a Firebase/Google Cloud Function to log entries to Stack Driver using the jsonPayload
property so my logs are searchable (currently anything I pass to console.log gets stringified into textPayload
).
I have a multi-module project with some code running on Firebase Cloud Functions, and some running in other environments like Google Compute Engine. Simplifying things a little, I essentially have a 'core' module, and then I deploy the 'cloud-functions' module to Cloud Functions, 'backend-service' to GCE, which all depend on 'core' etc.
I'm using bunyan for logging throughout my 'core' module, and when deployed to GCE the logger is configured using '@google-cloud/logging-bunyan' so my logs go to Stack Driver.
Aside: Using this configuration in Google Cloud Functions is causing issues with Error: Endpoint read failed
which I think is due to functions not going cold and trying to reuse dead connections, but I'm not 100% sure what the real cause is.
So now I'm trying to log using console.log(arg)
where arg
is an object, not a string. I want this object to appear in Stack Driver under the jsonPayload
but it's being stringified and put into the textPayload
field.
You can see logs in real time using the Firebase console. Choose your project, click the Functions product on the left, then click the Logs tab. This user is second on the weekly Google Cloud leaderboard. Show activity on this post.
Look in Stackdriver -> Logs Viewer -> Cloud Run Revision. Select All logs. Your print() should appear there.
If you use Cloud Functions for Firebase, then your function logs will continue to be exported to Cloud Logging. If you don't delete your datasets for Hosting logs in Cloud Logging, they will persist for 30 days, then be deleted from Cloud Logging automatically.
This line is picked up and parsed by Cloud Logging and is placed into jsonPayload instead of textPayload. The data is constructed as a JSON dictionary. The snippets below demonstrate creating these log entries.
Here's how to link your Firebase project, specifically your Firebase Hosting sites, to Cloud Logging: Go to your Project settings in the Firebase console. On the Cloud Logging card, click Link. Follow the on-screen instructions to select which Hosting sites will export logs.
For Cloud Functions, you can also view your logs in the Functions dashboard of the Firebase console. By using Cloud Logging with Hosting, you can track from where and when you have visits to your site, your site's response statuses, the latency of end user requests, and more.
It took me awhile, but I finally came across this example in firebase functions samples repository. In the end I settled on something a bit like this:
const Logging = require('@google-cloud/logging');
const logging = new Logging();
const log = logging.log('my-func-logger');
const logMetadata = {
resource: {
type: 'cloud_function',
labels: {
function_name: process.env.FUNCTION_NAME ,
project: process.env.GCLOUD_PROJECT,
region: process.env.FUNCTION_REGION
},
},
};
const logData = { id: 1, score: 100 };
const entry = log.entry(logMetaData, logData);
log.write(entry)
You can add a string severity
property value to logMetaData
(e.g. "INFO" or "ERROR"). Here is the list of possible values.
Update for available node 10 env vars. These seem to do the trick:
labels: {
function_name: process.env.FUNCTION_TARGET,
project: process.env.GCP_PROJECT,
region: JSON.parse(process.env.FIREBASE_CONFIG).locationId
}
UPDATE: Looks like for Node 10 runtimes they want you to set env values explicitly during deploy. I guess there has been a grace period in place because my deployed functions are still working.
I ran into the same problem, and as stated by comments on @wtk's answer, I would like to add replicating all of the default cloud function logging behavior I could find in the snippet below, including execution_id.
At least for using Cloud Functions
with the HTTP Trigger
option the following produced correct logs for me. I have not tested for Firebase Cloud Functions
// global
const { Logging } = require("@google-cloud/logging");
const logging = new Logging();
const Log = logging.log("cloudfunctions.googleapis.com%2Fcloud-functions");
const LogMetadata = {
severity: "INFO",
type: "cloud_function",
labels: {
function_name: process.env.FUNCTION_NAME,
project: process.env.GCLOUD_PROJECT,
region: process.env.FUNCTION_REGION
}
};
// per request
const data = { foo: "bar" };
const traceId = req.get("x-cloud-trace-context").split("/")[0];
const metadata = {
...LogMetadata,
severity: 'INFO',
trace: `projects/${process.env.GCLOUD_PROJECT}/traces/${traceId}`,
labels: {
execution_id: req.get("function-execution-id")
}
};
Log.write(Log.entry(metadata, data));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With