Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log 'jsonPayload' in Firebase Cloud Functions

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.

like image 463
dan.jones Avatar asked Mar 09 '18 02:03

dan.jones


People also ask

How do you log a function in Firebase?

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.

How do I print results in Stackdrive logs?

Look in Stackdriver -> Logs Viewer -> Cloud Run Revision. Select All logs. Your print() should appear there.

How long do Cloud Functions for Firebase logs stay in cloud logging?

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.

How does cloud logging work with JSON?

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.

How do I link my Firebase project to cloud logging?

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.

How do I view my Firebase 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.


2 Answers

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.

like image 171
wtk Avatar answered Oct 17 '22 14:10

wtk


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));
like image 40
MakuraYami Avatar answered Oct 17 '22 12:10

MakuraYami