Отладка общих ошибок API Gateway с помощью журналов доступа

Мы можем облегчить отладку ошибок API Gateway, если включим журналирование доступа и добавим сообщения об ошибках в объект журнала по умолчанию. Этот маленький трюк часто оказывается полезным, когда мы получаем общее сообщение об ошибке.

1. Изложение проблемы

На днях я играл с HTTP API API Amazon API Gateway (подробнее об этом в одном из следующих постов) и добавил интеграцию Lambda в один из маршрутов.

Маршрут должен был иметь формат /pets/{proxy+}.

Когда я вызвал API из Postman, я получил общую 500 Internal server error.

Как и некоторые другие ошибки AWS, это сообщение тоже не помогало.

2. Процесс отладки

Запрос не вызвал интеграцию Lambda, потому что я ничего не увидел в лог-группе функции в CloudWatch.

Должно быть, что-то произошло внутри API Gateway (маловероятно) или между шлюзом и функцией.

2.1. Создайте группу журналов

Хорошая идея — включить логирование доступа для API, особенно когда мы находимся на стадии разработки.

Сначала нам понадобится группа журналов, поэтому давайте создадим ее в CloudWatch, в которую API Gateway будет отправлять журналы доступа.

2.2. Включите логирование доступа

Мы можем включить логирование доступа в нижней части левого меню в AWS Console.

После включения логирования доступа с помощью ползунка, мы должны добавить ARN группы логов, которую мы создали выше. Из доступных форматов журналов выберите JSON.

API Gateway запишет в CloudWatch следующий объект:

{
  "requestId": "$context.requestId",
  "ip": "$context.identity.sourceIp",
  "requestTime": "$context.requestTime",
  "httpMethod": "$context.httpMethod",
  "routeKey": "$context.routeKey",
  "status": "$context.status",
  "protocol": "$context.protocol",
  "responseLength": "$context.responseLength"
}
Вход в полноэкранный режим Выход из полноэкранного режима

Это переменные протоколирования по умолчанию.

2.3. Добавление сообщений об ошибках

Этот объект предоставляет только основную информацию, большинство из которой мы уже знаем.

Но объект context содержит гораздо больше свойств. Я нашел два из них особенно полезными.

Свойство $context.integration.error возвращает сообщение об ошибке от интеграции, в данном случае от функции Lambda. Хотя запрос не вызвал вызов функции, Lambda все равно может вернуть ошибку. API Gateway запишет сообщение об этой ошибке здесь.

Вторая ошибка, которую я добавил, — это значение ключа $context.error.message, который возвращает сообщение об ошибке от самого API Gateway.

В итоге я добавил эти свойства в JSON журнала:

{
  "integrationError": "$context.integration.error",
  "apiGatewayError": "$context.error.message"
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Действительно, следующий вызов выявил проблему.

2.4. Создание всего маршрута за один раз

apiGatewayError вернул Internal Server Error, что не было для меня новостью.

Но свойство integrationError показало мне настоящую проблему:

The IAM role configured on the integration or API Gateway doesn't have
permission to call the integration. Check the permissions and try again.
Войти в полноэкранный режим Выход из полноэкранного режима

Сначала сообщение об ошибке показалось странным, потому что когда вы создаете интеграцию Lambda в маршрут HTTP API, API Gateway сгенерирует необходимые разрешения для вызова функции. Точнее, он добавит следующую политику к ресурсно-ориентированной политике функции Lambda:

{
  "Effect": "Allow",
  "Principal": {
    "Service": "apigateway.amazonaws.com",
  },
  "Action": "lambda:InvokeFunction",
  "Resource": "arn:aws:lambda:us-east-1:ACCOUNT_ID:function:FUNCTION_NAME",
  "Condition": {
    "ArnLike": {
      // /{proxy+} is missing from the end!!!
      "AWS:SourceArn": "arn:aws:execute-api:us-east-1:ACCOUNT_ID:API_ID/*/*/pets"
    }
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Проблема заключается в блоке Condition: /{proxy+} отсутствует в конце ARN. Поэтому, когда я вызвал /pets/SOMETHING, Lambda ответила ошибкой.

Причина была в том, что сначала я создал интеграцию для маршрута /pets, поэтому API Gateway добавил соответствующее разрешение в политику на основе ресурсов. Затем я понял, что так у меня ничего не получится, поэтому я отредактировал маршрут и добавил к нему /{proxy}. Конечно, API Gateway не обновил разрешение.

Решение заключается в том, чтобы либо добавить недостающий бит в разрешение Lambda вручную, либо создать маршрут в окончательном виде в API Gateway, либо использовать Infrastructure as Code, которая создает и обновляет разрешения.

Найти первопричину было гораздо проще с помощью журналов доступа. Это может выявить и другие проблемы и сэкономить время, которое мы тратим на поиск причины проблемы. Стоит попробовать!

3. Резюме

Журналирование доступа к API Gateway может быть полезным, когда нам нужно отладить общие сообщения об ошибках.

Объект журнала содержит только часть доступных свойств. Мы можем добавить сообщения об ошибках в журнал доступа, извлекая их из объекта context.

4. Дополнительное чтение

Настройка журналов доступа HTTP API — Больше доступных переменных для ведения журнала

The Missing Guide to AWS API Gateway Access Logs — отличное руководство Алекса ДеБри по журналам доступа в REST API.

Оцените статью
devanswers.ru
Добавить комментарий