Knowledge sharing - Enable cloud watch logs for API Gateway using Serverless

Serverless team are still working to add this feature in core service directly (https://github.com/serverless/serverless/issues/4461). If you need enable cloud watch logs for API Gateway using Serverless now, please follow this document.

Get most help from this ticket How to enable cloud watch logs for API Gateway using Serverless

But I still can’t make it work, if you follow its codes. So I need to understand how it works, how to enable cloudwatch logs in API Gateway.

  1. Provide an iam role ARN that has write access to CloudWatch logs in API gateway.

Go through this documents

https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-cloudwatch-logs/

in general, you need to do:

  • Create a new IAM role (for example, apigateway-cloudwatch-logs-role) with trust policy apigateway.amazonaws.com
  • Attach aws exist policy AmazonAPIGatewayPushToCloudWatchLogs to this role
  • Record this IAM role’s ARN
  • Add this iam role’s arn to apigatewa-> settings -> CloudWatch log role ARN*

These are manual tasks.

With this setup, all your api gateways are ready for generating access logs in Cloudwatch. This is a global setting for API Gateway, that’s the reason why it can’t be managed by serverless framework (in serverless.yml)

  1. Enable access logs

Add below lines into serverless.yml, that’s all.

plugins:
  - serverless-plugin-stage-variables

resources:
  Resources:
     ApiGatewayStage:
      Type: AWS::ApiGateway::Stage
      Properties:
        MethodSettings:
          - DataTraceEnabled: true
            HttpMethod: "*"
            LoggingLevel: INFO
            ResourcePath: "/*"
            MetricsEnabled: true

Notes: Don’t define Provider -> role with the new role you created above, because the Provider:role used in serverless.yml is for lambda function, not for api gateway. If you do that, you lost all permissions in lambda functions.

  1. Install the plugin serverless-plugin-stage-variables and run sls deploy

  2. Trigger several api gateway access, you should see the access logs in cloudwatch now.

The log group name is:

 API-Gateway-Execution-Logs_{rest-api-id}/{stage_name}

References:

http://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-logging.html

6 Likes

What is the point of serverless-plugin-stage-variables here?

serverless framework does’t support stage ( api gateway stage) currently, so you need the plugin to help

1 Like

Using that just gives me this error:

Cannot read property 'stageVariables' of undefined

Does it just want you to put something empty if you don’t want to use it? Maybe I’m missing something from your post.

Add this to serverless.yml:

custom:
stageVariables:
env: ${self:provider.stage}

Hi Bill,

Thanks for your docs!

I’m getting this error when I run sls deploy:

An error occurred: apiGatewayStage - Property RestApiId cannot be empty..

I’ve configured the API Gateway CloudWatch ARN, installed serverless-plugin-stage-variables and added this to resources.Resources:

ApiGatewayStage:
  Type: AWS::ApiGateway::Stage
  Properties:
    MethodSettings:
      - DataTraceEnabled: true
        HttpMethod: "*"
        LoggingLevel: INFO
        ResourcePath: "/*"
        MetricsEnabled: true

Any clues?

Solve this by adding RestApiId:

ApiGatewayStage:
  Type: AWS::ApiGateway::Stage
  Properties:
    RestApiId:
      Ref: ApiGatewayRestApi
    MethodSettings:
      - DataTraceEnabled: true
        HttpMethod: "*"
        LoggingLevel: INFO
        ResourcePath: "/*"
        MetricsEnabled: true
1 Like

Nice to hear your problem is fixed.

I didn’t have to set RestApiId in my serverless.yml, but good to know this.

Hi Bill,

I am getting the following error .

Serverless Error ---------------------------------------

  An error occurred: ApiGatewayStage - 1 validation error detected: Value null at 'createStageInput.deploymentId' failed to satisfy constraint: Member must not be null (Service: AmazonApiGateway; Status Code: 400; Error Code: ValidationException; Request ID: 270600b3-97f0-11e8-b138-2f94522f87b3).

Wondering where I can get this deployment ID from?

My serverless code looks like this

ApiGatewayStage:
      Type: AWS::ApiGateway::Stage
      Properties:
        RestApiId:
          Ref: ApiGatewayRestApi
        StageName: ${self:provider.stage}
        MethodSettings:
          - DataTraceEnabled: true
            HttpMethod: "*"
            LoggingLevel: INFO
            ResourcePath: "/*"
            MetricsEnabled: true
1 Like

I am getting the same error :frowning_face:. I opened a issue on the plugins github (https://github.com/svdgraaf/serverless-plugin-stage-variables/issues/15) but I am starting to think its not necessarily related to that.

The deploymentId comes from here https://github.com/awslabs/aws-apigateway-sdk-java/blob/master/src/main/java/com/amazonaws/services/apigateway/model/CreateStageInput.java.

1 Like

I am having issues getting this working. I am a bit new to SLS.

resources:
  - ${file(dynamodb.yml):resources} # DynamoDB
  - Resources: # API Gateway Logging
     ApiGatewayStage:
      Type: AWS::ApiGateway::Stage
      Properties:
        RestApiId:
            Ref: ApiGatewayRestApi
        StageName: ${self:provider.stage}
        MethodSettings:
          - DataTraceEnabled: true
            HttpMethod: "*"
            LoggingLevel: INFO
            ResourcePath: "/*"
            MetricsEnabled: true

The error I am getting is:

An error occurred: ApiGatewayStage - qa already exists.

I am adding logging to an existing deployment, so the environment/stage does already exist, but I am unsure how to let it add to that environment/stage.

I can’t enable CloudWatch logs for API Gateway. It doesn’t give error but when I check serverless logs I can see somehow logLevel is OFF and tracingEnabled is false.

This is my serverless file:

        service: my-api-project
        package:
          individually: true
          exclude:
            - ./**
        provider:
          name: aws
          runtime: nodejs10.x
          region: eu-west-1
        plugins:
          - serverless-plugin-stage-variables
        custom: 
          stage: ${self:provider.stage, 'dev'}
          region: ${self:provider.region, 'eu-west-1'}
        functions:
          api:
            handler: dist/lambda.handler
            package:
              include:
                - dist/**
                - node_modules/**
                - ormconfig.js
            events:
              - http: ANY /
              - http: 'ANY {proxy+}'
        resources:
          Resources:
             ApiGatewayStage:
              Type: AWS::ApiGateway::Stage
              Properties:
                RestApiId:
                    Ref: ApiGatewayRestApi
                StageName: ${self:provider.stage}
                MethodSettings:
                  - DataTraceEnabled: true
                    HttpMethod: "*"
                    LoggingLevel: INFO
                    ResourcePath: "/*"
                    MetricsEnabled: true

These are the serverless logs:

Serverless: [AWS sts 200 0.341s 0 retries] getCallerIdentity({})
Serverless: [AWS apigateway 200 0.128s 0 retries] getRestApis({ position: undefined, limit: 500 })
Serverless: [AWS apigateway 200 0.113s 0 retries] getStage({ restApiId: 'xxx', stageName: 'dev' })
Serverless: [AWS apigateway 200 0.203s 0 retries] updateStage({ restApiId: 'xxx',
  stageName: 'dev',
  patchOperations:
   [ { op: 'replace', path: '/tracingEnabled', value: 'false' },
     { op: 'replace', path: '/*/*/logging/dataTrace', value: 'false' },
     { op: 'replace', path: '/*/*/logging/loglevel', value: 'OFF' },
     [length]: 3 ] })
Serverless: [AWS cloudwatchlogs 400 0.094s 0 retries] deleteLogGroup({ logGroupName: '/aws/api-gateway/my-api-project-dev' })
Serverless: Invoke aws:deploy:finalize
Serverless: [AWS s3 200 0.136s 0 retries] listObjectsV2({ Bucket:
   'my-api-project-dev-serverlessdeploymentbucket-xxx',
  Prefix: 'serverless/my-api-project/dev' })

Does anyone have an idea why I can’t enable CloudWatch logs? By the way I have already set a CloudWatch log role ARN in API Gateway settings. I just need to enable logging for API Gateway.

You need to put in the log key in your serverless file as follow:

provider:
  name: aws
  runtime: nodejs10.x
  stage: dev
  logs:
    restApi: true 

It works for me on sls version 1.44.1

However, this leads to another problem as the Access Log format seems to be hardcoded in as well. I was not able to use my own format so i had to revert back to 1.41.1 which allow me to enable logging and specify my own custom access log format. This can be seen at line 177 in the code https://github.com/serverless/serverless/blob/0b53d71a8ff28e51f0080afbe8e0f513bfccb797/lib/plugins/aws/package/compile/events/apiGateway/lib/hack/updateStage.js

Maybe the author can shed some lights as to why the access log format is hardcoded in the code?

My sls version is 1.44.1 as well. I have added the following key under provider:

  logs:
    restApi: true

However the result is still the same and logs have the following lines as well which I think that it means somehow logging settings are OFF although I say resAPI is true.

Serverless: [AWS apigateway 200 0.213s 0 retries] updateStage({ restApiId: 'XXX',
  stageName: 'dev',   patchOperations:
   [ { op: 'replace', path: '/tracingEnabled', value: 'false' },
 { op: 'replace', path: '/*/*/logging/dataTrace', value: 'false' },
 { op: 'replace', path: '/*/*/logging/loglevel', value: 'OFF' },
 [length]: 3 ] })

Is there a way I can create API gateway resource with CloudFormation script rather than serverless creation? Because even if I manage to enable logs, I need to enable caching and access logging as well.

Try downgrading to serverless 1.41.1 , able to configure cloud watch logs and access logs

I have tried with 1.41.1 and it didn’t work and then I have installed the latest version(1.45.1) and tried again. It didn’t work and it gave the following error message:

Rest API could not be resolved. This might be casued by a custom API Gateway setup. With you current setup stage specific configurations such as tracing, logs and tags are not supportedPlease update your configuration or open up an issue if you feel that there's a way to support your setup.

By the way there is a spelling mistake in the error message; casued should be replaced with caused.

I have deleted the whole stack and tried again and finally it worked with the following key:

  logs:
    restApi: true

Thanks for helping me out! :slight_smile: