Search code examples
firebasegoogle-cloud-functionsstackdriver

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.


Solution

  • 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.