0

I'm trying to follow this guide to put some custom logging into a firebase function. The function itself is running, and I can see the data being passed in (it's an https 'callable' function). But as soon as it hits the line where it tries to actually write that log entry, I get "Error: 7 PERMISSION_DENIED"

Since the console.log() calls write to the cloud logs, I'd assumed the firebase function has access to Cloud Logging. But perhaps it needs additional permission? I can't find any reference to where this should be set on that page though.

// Logging, logName, region, functions are provided by the surrounding app

const logging = new Logging()
const log = logging.log(logName)
const METADATA = {
  resource: {
    type: 'cloud_function',
    labels: {
      function_name: 'CustomLog',
      region
    }
  }
};

exports = module.exports = functions.https.onCall(async data => {
  const exVersion = 6
  const exId = data.exId

  console.log('***** exVersion:', exVersion, 'exId:', exId)  // exId from caller
  
  const entry = log.entry(METADATA, data.error)  // data.error from caller
  console.log('METADATA:', METADATA)  // Shows in Logs Explorer
  console.log('entry:', entry)  // Shows in Logs Explorer

  log.write(entry)  // Results in Error: 7 PERMISSION_DENIED

  return {
    exVersion,
    exId,
  }
})

If I run it from the CLI using firebase function:shell, the log entry is created correctly, so I'm pretty confident the code is correct.

dsl101
  • 1,715
  • 16
  • 36
  • I don't see a few important things present in your snippet: ```const { Logging } = require('@google-cloud/logging');``` and a definition for your variable ```region``` in your metadata structure... – LeadDreamer Jan 19 '22 at 18:46
  • See the comment on line 1—they are all there, but out of context for this example. The code runs fine locally. – dsl101 Jan 19 '22 at 20:40

3 Answers3

2

OK, I finally tracked it down. According to this answer, the service account used by firebase functions is {project-id}@appspot.gserviceaccount.com, and in my project, that account did not have the 'Logs Writer' role. Adding that role solves the problem.

I find it odd that the firebase functions don't need that role to log messages using console.log(), but perhaps that call is intercepted by the functions environment, and the logs are written as a different service account. It also explains why the functions running locally were able to write the logs, as they run using the 'owner' service account, which has full access.

dsl101
  • 1,715
  • 16
  • 36
0

According to the Firebase documentation page you have linked:

The recommended solution for logging from a function is to use the logger SDK. You can instead use standard JavaScript logging calls such as console.log and console.error, but you first need to require a special module to patch the standard methods to work correctly:

require("firebase-functions/lib/logger/compat");

Once you have required the logger compatibility module, you can use console.log() methods as normal in your code.

Thus you might to require this library, however I am not sure this is producing your "Error: 7 PERMISSION_DENIED error, but you might also try some solutions that have worked for some members of the community.

llompalles
  • 3,072
  • 11
  • 20
0

Perhaps the logging API is not enabled in your project. You'll get a permission denied error when attempting to use it in that case.

It's a couple levels in, but the guide you linked points to https://github.com/googleapis/nodejs-logging#before-you-begin, which includes a step to "Enable the Cloud Logging API"

Kirk Kelsey
  • 4,259
  • 1
  • 23
  • 26