Laravel: Использование логов для отладки API

Источник: «Using Logs to Debug a Laravel API»
Недавно мы создавали Laravel API для мобильного приложения созданного отдельной командой. Когда пользователь сообщил о проблеме, одним из первых вопросов был Эта ошибка связана с API или мобильным приложением? В этой статье я поделюсь стратегией ведения лога, которую мы использовали для быстрого поиска причин проблемы.

Идеальный сценарий заключался в регистрации каждого запроса к API вместе с возвращаемым ответом. Каждый раз, когда хотите что-то сделать с каждым запросом, логичным местом для размещения этого кода будет middleware. В этом случае мы решили использовать завершаемое middleware, чтобы зафиксировать окончательный ответ. В качестве бонуса завершаемое middleware запускается после того, как ответ возвращается пользователю, поэтому оно совсем не замедляет время отклика.

Внутри метода terminate нашего middleware мы могли бы создать точный лог полезной нагрузки, которую мы хотим захватить:

<?php
$context = [
'request' => [
'full_url' => $request->fullUrl(),
'method' => $request->method(),
'body' => $this->redactedRequestBody($request),
'user_id' => $request->user()->id ?? 0,
],
'response' => [
'status_code' => $response->status(),
'body' => $response->getContent(),
'headers' => $response->headers->all(),
],
];

Важная деталь заключается в том, что мы также сохраняем конфиденциальные данные. Например, API запрос содержит их Bearer токен. Мы не хотим, чтобы эти токены оставались в наших логах. Точно также вы можете сохранить поля пароля или что-то ещё, что считается слишком конфиденциальным для обычного текстового лога. Также полезно записывать эти данные в отдельный канал лога, чтобы они не смешивались с другими логами приложения, которые вы уже собираете. Хорошо иметь один выделенный набор логов для хранения только API запросов и ответов.

Может быть, вам интересно почему бы просто не использовать что-то вроде New Relic или Bugsnag для отладки неудачных ответов? На самом деле мы используем оба этих инструмента в этом проекте. Они великолепны и чрезвычайно полезны, но иногда запрос не завершается ошибкой или не выдаёт исключение, и всё же это полезно увидеть в журнале аудита. Например, запрос не прошёл проверку. Bugsnag не собирается собирать данные об ответе 422. Вы можете настроить его для этого, но на самом деле это не является его задачей, и в конечном итоге создаст шум, который может заглушить необрабатываемое исключение.

Последней часть настройки были Amazon CloudWatch Logs. Наша инфраструктура находится на AWS, но вы всё равно можете отправлять логи в AWS (или другим подобным поставщикам логов), если хотите. Настроить агент Cloudwatch Logs для получения логов API было довольно просто, и теперь мы можем выполнять несколько действительно мощных запросов в консоли CloudWatch на AWS. Поскольку данные структурированы как JSON, теперь мы можем быстро выполнять запросы на основе любой части данных:

Более того, вы можете сохранить некоторые из этих запросов в качестве метрик CloudWatch, а затем отображать изменения во времени или настроить автоматические оповещения.

Я доволен этим подходом, и он значительно сократил время необходимое для исследования и решения проблемы о которой сообщают пользователи.

Дополнительные материалы

Предыдущая Статья

Laravel: Как начать тестировать приложение

Следующая Статья

Laravel: Перенос проекта с Webpack на Vite