Логи — это записи о том, как работает любая система: будь то сайт, мобильное приложение или микросервис. Логирование происходит автоматически, информация сохраняется в файлах или специальных сервисах. Пользователь этих записей не видит, но для тестировщика логи особенно важны — ведь по ним можно определить, что происходило в системе при сбое, даже если на фронтенде отображается только общее сообщение об ошибке.

Как выглядит лог

Лог — это текстовая запись о событии, которое произошло в системе. В логах по шагам фиксируется, что происходит в приложении: например, получен запрос или обработаны данные.  Обычно в каждой записи содержится несколько обязательных элементов: дата и время события, источник (например, конкретный сервис), само сообщение с описанием того, что произошло, а также уровень логирования.

Уровень логирования — это степень важности сообщения в логах. Каждый лог может быть обычной информацией о работе системы (уровень INFO), сообщением для отладки (DEBUG), предупреждением о возможной проблеме (WARN) или ошибкой (ERROR, а в самых критичных случаях — FATAL или CRITICAL). Благодаря этому логи можно фильтровать и быстро находить действительно важные записи.

Пример содержимого лога: дата и время, уровень, источник, сообщение
Пример содержимого лога: дата и время, уровень, источник, сообщение

Иногда к записи об ошибке добавляется стек вызовов (stack trace). Это последовательность вызовов функций или методов, которые выполнялись в приложении до момента сбоя. Проще говоря, стек вызовов показывает, по какому пути программа шла внутри кода и в каком месте произошла ошибка.

Стек вызовов чаще всего встречается в логах при ошибках уровня ERROR или FATAL, а также в отчётах систем вроде Sentry или Crashlytics (о них — ниже). В стеке перечисляются файлы, классы и методы, которые участвовали в выполнении операции.

Как выглядит стек вызовов в Sentry
Как выглядит стек вызовов в Sentry

Зачем тестировщику логи

Даже если тестировщик активно пользуется Devtools или снифферами, почти всегда наступает момент, когда их становится недостаточно для локализации бага. Например, интерфейс показывает «что-то пошло не так» без деталей, или сервер отвечает статус-кодом 500, но описания ошибки нет. Иногда баг может воспроизводиться нестабильно — тогда просто неизвестно, какие шаги пользователя приводят к сбою и как именно его локализовать. То же самое может происходить на мобильном окружении — иногда кажется, что мобильное приложение падает без видимой причины.

В таких случаях на помощь приходят логи. В первую очередь они позволяют подтвердить наличие бага. Тестировщику в работе или клиенту в службе поддержки не просто померещилось, баг существует, и о нем есть запись.

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

Наконец, логи позволяют тестировщику собирать данные, которые понадобятся разработчику для фикса. Да, тестировщик не обязан чинить код, но должен уметь читать логи, находить в них полезную информацию и доносить ее до разработки.

Основные типы логов

В зависимости от архитектуры проекта тестировщику приходится работать с разными типами логов. В школе QA Studio для знакомства с логированием мы используем тренажеры собственной разработки — «Битву покемонов» и My Shows. «Битва покемонов» — это игра, где пользователь выступает в качестве тренера, создает своих покемонов и вызывает на битву покемонов других игроков, с каждой победой уровень покемонов и самого тренера растет. Цель игры — дойти до самого высокого уровня и получить кубок. Давайте на примере «Битвы» наглядно разберем разные виды логов, с которыми тестировщик сталкивается в работе.

Серверные логи

Серверные логи — один из самых распространённых источников информации при тестировании веб-приложений и API. В серверных логах записываются входящие запросы, параметры, ответы, ошибки выполнения. Часто именно серверный лог показывает причину проблемы, когда интерфейс ограничивается общим сообщением об ошибке или совсем не реагирует на сбой.

Прямое подключение к логам: SSH

Работать с серверными логами можно двумя способами: напрямую — просто получив доступ к текстовым файлам, которые лежат на сервере, или с помощью специальных инструментов (о них пойдет речь ниже). Для работы с логами напрямую используется подключение по SSH. Оно позволяет подключиться к серверу через терминал и найти нужный лог-файл. Подавляющее большинство серверов веб-приложений работает на Linux — в таком случае логи можно найти в папке /var/logs/. При этом общие логи операционной системы содержатся в файле syslogs, а логи веб-сервера называются access_log. Найдя нужный файл, можно отфильтровать данные и вычленить ошибки. В нашей школе такой формат работы с логами вынесен в отдельный тренажёр: учимся подключаться к серверу по SSH, читать, фильтровать и скачивать логи, анализировать ошибки. Это позволяет понять, как выглядят логи «без оберток» и что делать, если никакие другие инструменты логирования недоступны.

Пример отображения серверных логов при прямом подключении через SSH
Пример отображения серверных логов при прямом подключении через SSH

Инструменты для просмотра логов

Однако у чтения серверных логов через терминал много минусов: интерфейс неудобный, трудно читать объемные логи, нужно иметь права прямого доступа к серверу. Поэтому все чаще на проектах используются специальные инструменты — так называемые системы централизованного логирования, которые собирают логи из разных сервисов в одном месте и помогают быстрее находить ошибки за счёт фильтрации. В «Битве покемонов» ученики работают с серверными логами через одни из самых популярных инструментов логирования — Kibana и Sentry, а также анализируют технические дашборды в Grafana.

Kibana

Kibana позволяет искать события по уровню логирования, фильтровать их по времени и конкретному сервису, что особенно удобно при локализации плавающих багов.

Так можно находить логи ошибок 500 за последние 24 часа в Kibana
Так можно находить логи ошибок 500 за последние 24 часа в Kibana

Можно настроить Kibana так, чтобы в ней выводилось тело запроса и ответа, что помогает локализовать баг.

Примеры ошибок с одинаковым статус-кодом — 422, но разными причинами возникновения в ответе сервера
Примеры ошибок с одинаковым статус-кодом — 422, но разными причинами возникновения в ответе сервера

Sentry

В свою очередь Sentry помогает увидеть, что происходило в системе в момент сбоя: какой запрос выполнялся, где возникла ошибка и как часто она повторяется. Даже если тестировщик не знает код и не до конца понимает отчёт Sentry, эти данные важно передать разработчику — они сильно упрощают поиск причины бага и ускоряют фикс.

Информация о запросе, который вернул ошибку, в Sentry
Информация о запросе, который вернул ошибку, в Sentry

Grafana

Наконец, Grafana — это система мониторинга для построения дашбордов, которая позволяет увидеть ошибки наглядно. Grafana собирает данные обо всех ответах сервера — в том числе ошибки с кодами 400 и 500, что помогает отслеживать, как часто они возникают, в какие периоды и по каким запросам. Grafana удобна тем, что помогает заметить проблему на уровне системы без воспроизведения конкретного сценария и понять, носит ли ошибка массовый характер.

Отображение ошибок 400 и 500 в Grafana
Отображение ошибок 400 и 500 в Grafana

Но иногда полезно посмотреть на серверные логи в самом простом виде — без фильтров и графиков, как на обычный журнал событий. Это помогает лучше понять, какие записи вообще появляются в логах и в каком порядке происходят действия на сервере. Для таких логов в «Битве покемонов» используется библиотека Loguru. Она формирует обычные текстовые логи с датой, уровнем логирования и описанием происходящих событий и выводит их на отдельную страницу. В таком виде логи могут храниться на сервере сами по себе или использоваться как источник данных для других систем логирования.

Более простое отображение серверных логов через Loguru
Более простое отображение серверных логов через Loguru

Логи брокера сообщений (Apache Kafka)

Во многих современных приложениях внедряется асинхронное взаимодействие — например, через брокер сообщений Apache Kafka. Сложность состоит в том, что в подобных системах ошибки часто не видны сразу. Сообщение может не дойти до нужного сервиса, обработаться с задержкой или упасть из-за некорректного формата данных (если ты пока не знаешь, что такое брокер сообщений и как он устроен, рекомендуем почитать тут). При этом интерфейс может не показывать ошибок, и баг обнаруживается только по косвенным признакам.

В «Битве покемонов» Apache Kafka используется на этапе, когда тренер запрашивает историю своих битв. Ученики работают с логами сервисов, которые обмениваются сообщениями через Kafka. На практике логи брокеров сообщений обычно смотрят через специальные инструменты — например, SolarWinds Loggly, Datadog или Confluent Control Center. Поэтому наши логи собраны в Kibana, так что ошибки обработки сообщений, проблемы с форматом данных и сбои между сервисами можно анализировать без прямого доступа к серверам.

Примеры отображения логов Kafka в Kibana
Примеры отображения логов Kafka в Kibana

Логи мобильных приложений

При тестировании мобильных приложений логи становятся обязательным инструментом. В отличие от веба, где можно опереться на DevTools браузера, на мобильных устройствах возможности отладки сильно ограничены или вовсе отсутствуют.

Рассмотрим способы работы с мобильными логами на примере приложения «Битва покемонов». Можно использовать инструменты внутри Android Studio: ADB и Logcat. ADB (Android Debug Bridge) — это встроенная в Android Studio программа, которая позволяет подключиться к устройству или эмулятору и получить от него техническую информацию. Через ADB тестировщик фактически заглядывает внутрь работающего приложения и видит, что с ним происходит во время возникновения ошибок.

При использовании ADB также можно фильтровать логи — например, по уровню ERROR (обозначен как E)
При использовании ADB также можно фильтровать логи — например, по уровню ERROR (обозначен как E)

Logcat — это журнал событий Android-приложения: какие экраны открывались, какие действия выполнялись, какие ошибки или предупреждения возникали. Когда приложение падает или ведёт себя нестабильно, именно в Logcat можно увидеть причину. Это особенно важно, когда ошибка никак не отображается в интерфейсе.

Пример, как можно находить «зависания» и ошибки приложения через Logcat
Пример, как можно находить «зависания» и ошибки приложения через Logcat

Логи контейнеров (Docker)

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

В QA Studio мы создали приложение-тренажер под названием My Shows специально для работы с Docker и анализа логов контейнеров. В My Shows можно создать список сериалов, которые собираешься смотреть, а после просмотра — выставлять им оценки и писать отзывы. Приложение развернуто в контейнерах: отдельно работает фронтенд, веб-сервер, бэкенд и база данных. Ученики осваивают управление контейнерами (как проверить список запущенных контейнеров, как остановить и перезапустить сервис), а также пробуют самостоятельно разбираться в логах Docker.

Логи контейнеров читаются через командную строку с помощью команды docker logs. Она позволяет посмотреть вывод конкретного контейнера — например, сообщения о запуске сервиса, ошибках конфигурации или сбоях в работе приложения.

Команда docker ps выводит таблицу, показывающую, сколько контейнеров развернуто на устройстве. Из таблицы можно узнать ID отдельного контейнера и другую полезную информацию — как давно каждый был создан, когда запущен, как называется.

Также можно добавить к команде docker logs флаг -f и ID конкретного контейнера — например, в нашем случае веб-сервера Nginx или бэкенда. И тогда логи этого контейнера можно читать в режиме реального времени — так же, как это делается при просмотре серверных логов напрямую. Это удобно при перезапуске контейнера или проверке воспроизведения ошибки.

Подключение к веб-серверу Nginx приложения My Shows
Подключение к веб-серверу Nginx приложения My Shows
Подключение к бекенду приложения My Shows — видим ошибку валидации
Подключение к бекенду приложения My Shows — видим ошибку валидации

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

Зачем одному приложению столько логов

В современных проектах одно приложение редко состоит из одного сервиса. У каждого есть как минимум фронтенд, микросервисы и база данных, все чаще используются брокеры сообщений, у многих добавляется мобильный клиент. Одним словом, системы усложняются и появляются разные окружения, поэтому для одного проекта имеет смысл использоваться сразу несколько инструментов логирования. Каждый из них фиксирует события на своём уровне, ведь баг может возникнуть в любом компоненте.

Получается, что один пользовательский сценарий может оставить след сразу в нескольких местах. Иногда проблема возникает еще на этапе отправки запроса, иногда — при обработке сообщения в Kafka, а иногда — уже на стороне мобильного клиента. Логи позволяют увидеть, на каком именно этапе цепочка дала сбой, быстрее локализовать и пофиксить баг.

Трассировка запросов в Jaeger

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

Трассировка (tracing) показывает, какой путь прошёл запрос внутри системы. Один из самых популярных инструментов трассировки называется Jaeger. В Jaeger легко отследить, какие микросервисы участвовали в обработке запроса, какими HTTP-запросами и SQL-запросами обменивались сервисы и база данных, сколько времени занял каждый шаг. Для отслеживания запросов каждому из них в ответе присваивается trace_id, который можно сравнить с трек-номером для отслеживания почтовой посылки.

У «Битвы покемонов» настроена трассировка именно через Jaeger, и каждый API-запрос возвращает в ответе специальный хедер, содержащий trace_id.

В ответе на GET-запрос приходит хедер с trace_id
В ответе на GET-запрос приходит хедер с trace_id

Например, при расчете рейтинга тренеров учитывается три параметра: количество битв тренера, количество потраченных в игре «денег» и количество скачиваний истории своих битв. А значит, GET-запрос для отображения рейтинга проходит следующий путь:

  • проверка доступов пользователя — введен ли валидный токен тренера

  • обновление даты последней активности пользователя

  • запрос информации обо всех тренерах и битвах у монолита приложения — монолит берет эти данные через SQL-запрос в базу данных

  • запрос информации о сумме покупок у одного микросервиса (суммы берутся из БД)

  • запрос информации о количестве скачиваний истории битв у другого микросервиса (это количество берется из БД)

Цепочка вызовов между сервисами в Jaeger — видно, кто к кому обращался и сколько времени занял каждый этап
Цепочка вызовов между сервисами в Jaeger — видно, кто к кому обращался и сколько времени занял каждый этап

Поэтому trace_id всегда будет полезен в баг-репорте — трассировка помогает понять, дошел ли в принципе запрос до нужного микросервиса, какие данные передавались в запросах и приходили в ответах на каждом шаге и что могло пойти не так.

Итог

В работе тестировщика логи — такой же повседневный инструмент, как тест-кейсы или баг-репорты. Они помогают подтвердить проблему, понять, на каком этапе произошёл сбой, и собрать данные, которые действительно полезны разработчику. Когда тестировщик умеет читать логи, баг-репорты становятся точнее, а поиск причины бага занимает меньше времени.

Если вы хотите глубже разобраться в том, как логи помогают в тестировании — можно изучить это в рамках курса по ручному тестированию от QA Studio. А чтобы узнать больше о формате обучения и понять, чем занимается тестировщик, можно пройти бесплатный вводный курс.

Над статьей работали: Анастасия Андрусёва, Герман Дольников

Больше полезных материалов в нашем тг-канале: https://t.me/qa_studio