API Gateway logs not showing up with terraform

Viewed 2062

I'm trying to add CloudWatch logging to my API Gateway and have followed posts like this one to create the following terraform:

resource "aws_iam_role" "iam_for_api_gateway" {
  name = "${var.name}-api-gateway-role"
  description = "custom IAM Limited Role created with \"APIGateway\" as the trusted entity"
  path = "/"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

  tags = var.resourceTags
}

resource "aws_cloudwatch_log_group" "api_gateway_log_group" {
  name              = "/aws/lambda/${var.name}-api-gateway"
  retention_in_days = 14
}

resource "aws_iam_policy" "api_gateway_logging" {
  name        = "${var.name}-api-gateway-logging"
  path        = "/"
  description = "IAM policy for logging from the api gateway"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents",
        "logs:FilterLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "gateway_logs" {
  role       = aws_iam_role.iam_for_api_gateway.id
  policy_arn = aws_iam_policy.api_gateway_logging.arn
}

resource "aws_api_gateway_rest_api" "root_api" {
  name = "${var.name}-rest-api-service"

  tags = var.resourceTags
}

# at this point there are various resource "aws_api_gateway_resource" "api" blocks, etc

resource "aws_api_gateway_account" "demo" {
  cloudwatch_role_arn = aws_iam_role.iam_for_api_gateway.arn
}

resource "aws_api_gateway_deployment" "deployment" {
  rest_api_id   = aws_api_gateway_rest_api.root_api.id
  stage_name    = var.envName
  
  depends_on    = [
    aws_cloudwatch_log_group.api_gateway_log_group,
    aws_api_gateway_integration.lang_integration,
    aws_api_gateway_account.demo
  ]

  lifecycle {
    create_before_destroy = true
  }
}


resource "aws_api_gateway_method_settings" "example" {
  rest_api_id = aws_api_gateway_rest_api.root_api.id
  stage_name  = var.envName
  method_path = "*/*"

  settings {
    metrics_enabled = true
    logging_level   = "ERROR"
  }
}

But I am seeing no log entries generated for my API Gateway, though the log group is created.

I was previously getting this error:

Error: updating API Gateway Stage failed: BadRequestException: CloudWatch Logs role ARN must be set in account settings to enable logging

  on ..\2-sub-modules\e-api-gateway\main.tf line 627, in resource "aws_api_gateway_method_settings" "example":
 627: resource "aws_api_gateway_method_settings" "example" {

But then I updated the resource "aws_api_gateway_method_settings" "example" block (as shown above).

Now, I don't get the above error, but I also don't get any API Gateway logs.

What am I missing?

2 Answers

To fix the issue with "CloudWatch Logs role ARN must be set in account settings to enable logging" you should specify this role in API Gateway Account Settigns:

resource "aws_api_gateway_account" "demo" {
  cloudwatch_role_arn = aws_iam_role.cloudwatch.arn
}

resource "aws_iam_role" "cloudwatch" {
  name = "api_gateway_cloudwatch_global"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "apigateway.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

Details: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_account

In addition to the information I provided in the comments, I would like to give a more precise answer to the question about why the logs are not displayed and how to display them in case someone runs into the same problem in the future.

With the logging_level property set to ERROR only the errors will be displayed in cloudwatch.

If we want to log all the request going through the gateway we have to use logging_level = "INFO". In order to display all the information related to the request like request URI, request headers, request body... we have to activate the data_trace_enabled property:

resource "aws_api_gateway_method_settings" "example" {
  rest_api_id = aws_api_gateway_rest_api.root_api.id
  stage_name  = var.envName
  method_path = "*/*"

  settings {
    data_trace_enabled = true
    metrics_enabled    = true
    logging_level      = "ERROR"
  }
}

Terraform data_trace_enabled property matches with the Enable Detailed CloudWatch Metrics property from the AWS API Gateway console:

API Gateway

Currently there is a known limitation in the API Gateway and all the logs events larger than 1024bytes are truncated so keep that in mind if expect calls with many headers or large bodies.

API Gateway currently limits log events to 1024 bytes. Log events larger than 1024 bytes, such as request and response bodies, will be truncated by API Gateway before submission to CloudWatch Logs.

Related