Search code examples
node.jsgoogle-cloud-platformgraphqlstackdriverbunyan

Getting PERMISSION_DENIED error even inside gcp's vm instance when using stackdriver logging with bunyan


I'm trying to use stackdriver logger inside a nodejs application with bunyan logger, I'm using it to log graphql requests, and I've been having problems with configuration, I've followed @google-cloud/logging-bunyan documentation.

The logger is setup like this:

import { createLogger } from 'bunyan';
import { LoggingBunyan } from '@google-cloud/logging-bunyan';


const streams = [{ stream: process.stdout, level: 'info' as 'info' }];


if (process.env.ENVIRONMENT === 'staging' || process.env.ENVIRONMENT === 'production') {
  const loggingBunyan = new LoggingBunyan();
  streams.push(loggingBunyan.stream('info'));
}


export const logger = createLogger({
  name: 'backend-logger',
  streams,
});

And the usage is setup like this:

const logRequests = async (ctx: ParameterizedContext, next: () => Promise<any>) => {
  const auth = await authMiddleware(ctx.request);
  ctx.state.auth = auth;
  const start = Date.now();
  await next();
  const duration = Date.now() - start;


  if (ctx.method === 'POST' && ctx.path === process.env.CLIENT_SERVER_ENDPOINT) {
    const { query } = ctx.request.body;
    const logData = {
      query,
      OrganizationId: auth.user?.OrganizationId,
      UserId: auth.user?.id,
      UserName: auth.user?.name,
      duration,
    };
    if (duration > 200) {
      StackLogger.warn(logData);
    } else {
      StackLogger.info(logData);
    }
  }
};

The logger is only setup on staging, problem is, I get only nginx-access logs (before, I wouldn't get that) but not what I've passed to be logged When I run with PM2, I see the error when it's supposed to log

1|api  | {"name":"backend-logger","hostname":"backend","pid":6405,"level":30,"msg":"{ logData:\n   { query:\n      'mutation LoginMutation(\\n  $email: String!\\n  $password: String!\\n) {\\n  login(Email: $email, Password: $password) {\\n    Token\\n  }\\n}\\n',\n     OrganizationId: undefined,\n     UserId: undefined,\n     UserName: undefined,\n     duration: 38 } }","time":"2020-01-09T19:17:45.428Z","v":0}
1|api  |   --> POST /graphql 200 48ms 1.71kb
1|api  | You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection:
1|api  | Error: 7 PERMISSION_DENIED: The caller does not have permission
1|api  |     at Object.callErrorFromStatus (/home/api/sl_api/node_modules/@grpc/grpc-js/src/call.ts:79:24)
1|api  |     at Http2CallStream.call.on (/home/api/sl_api/node_modules/@grpc/grpc-js/src/client.ts:155:18)
1|api  |     at Http2CallStream.emit (events.js:203:15)
1|api  |     at Http2CallStream.EventEmitter.emit (domain.js:448:20)
1|api  |     at process.nextTick (/home/api/sl_api/node_modules/@grpc/grpc-js/src/call-stream.ts:183:14)
1|api  |     at process._tickCallback (internal/process/next_tick.js:61:11)

It's inside a gcloud VM instance so I suppose I would have permission to log to stackdriver So I setup a service account and even then the logs doesn't appear in stackdriver with the same error message in stackdrive.

Anyone have any ideas on how to make this work? thanks


Solution

  • Seeing the error Error: 7 PERMISSION_DENIED: The caller does not have permission, it seems you're not using the required service account to call the api. As per the github page the prerequisites are

    1. Select or create a Cloud Platform project.
    2. Select or create a Cloud Platform project.
    3. Enable the Stackdriver Logging API.
    4. Set up authentication with a service account so you can access the API from your local workstation.

    You also mentioned you have enabled the Service account and I am assuming you have provided the correct access as per the access control guide.

    So, I would like to review the Explict Auth Setup to ensure you are calling the API for right project and with correct service account.

    NOTE: I am posting this as answer as my current reputation does not support me to comment on your post. Please feel free to let me know if I miss something or if it does not make any sense. I will edit this accordingly.