Здравствуйте, меня зовут Дмитрий Башинский, и я возглавляю группу интеграции с маркетплейсами в компании SOKOLOV. Мы успешно наладили интеграцию с десятками различных маркетплейсов (Wildberries, Ozon, ЯндексМаркет, МегаМаркет, Lamoda, Купер, AliExpress, Avito, Flowwow и Kaspi в Казахстане), используя API для взаимодействия, и одна из ключевых задач — отслеживание данных, которые мы отправляем и получаем через HTTP-запросы.
Проблема логирования
При интеграции с несколькими маркетплейсами мы столкнулись с серьезной проблемой: необходимо было отслеживать, какие данные мы отправили и получили через HTTP-запросы. Изначально мы использовали простой регистр для хранения этих данных, но с ростом количества подключенных площадок это решение стало неэффективным:
- Проблемы с транзакциями: Если запись в регистре происходила внутри транзакции и она откатывалась, вся история логов терялась.
- Недостаток места: С увеличением объема логов регистр стал занимать слишком много места, что негативно сказывалось на бэкапах и производительности.
- Скорость чтения: Чтение информации из регистра оказалось медленным, так как данные хранились в строках неограниченной длины.
Поиск решения
Мы начали искать альтернативы и наткнулись на опыт коллег из "Самоката". Перенос логов в журнал регистрации (ЖР) позволил решить проблему с транзакциями и нехватки места. Но вот чтение данных из ЖР было медленным, и стало понятно, что нужно искать более производительное решение.
Выбор пал на ClickHouse. Благодаря инструменту от akpaevj, мы настроили экспорт логов из ЖР в отдельную базу данных на ClickHouse, немного доработав выгрузку. Это решение позволило нам эффективно хранить и затем анализировать логи.
Разработка модуля логирования
Мы разработали общий модуль `КлиентHTTPЛогирование`, который стал универсальным решением для всех наших HTTP-клиентов (HTTP-клиент, РаботаСHTTP, Новый HTTPСоединение). Этот модуль занимается логированием запросов по единому шаблону.
Пример использования исходящих запросов:
Функция Тест()
АдресЗапроса = "https://example.ru/"
Лог = КлиентHTTPЛогирование;
ЛогHTTPЗапроса = Лог.ОткрытьЛогHTTPЗапроса(КакаяНибудьСсылка);
Лог.УстановитьURL(ЛогHTTPЗапроса, АдресЗапроса);
Лог.УстановитьМетодHTTPЗапросаGET(ЛогHTTPЗапроса);
Лог.НачатьЗамерВремени(ЛогHTTPЗапроса);
Попытка
Ответ = HTTPСоединение.Записать(HTTPЗапрос);
Исключение // А сюда попадаем, когда например отсутствует интернет.
ТекстОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
Лог.ЗакрытьЛогHTTPЗапросаСОшибкой(ЛогHTTPЗапроса, ТекстОшибки);
ВызватьИсключение ТекстОшибки;
КонецПопытки;
Лог.ЗакрытьЛогHTTPЗапроса(ЛогHTTPЗапроса, Ответ);
Возврат Ответ;
КонецФункции
Пример использования входящих запросов:
Функция Тест(Запрос)
Лог = КлиентHTTPЛогирование;
ЛогЗапроса = Лог.ОткрытьЛогHTTPЗапроса(КакаяНибудьСсылка);
Лог.УстановитьМетодHTTPЗапроса(ЛогЗапроса, Запрос.HTTPМетод);
Лог.УстановитьЗаголовкиИсх(ЛогЗапроса, Запрос.Заголовки);
Лог.УстановитьURLИзВхЗапроса(ЛогЗапроса, Запрос);
Лог.УстановитьТелоЗапроса(ЛогЗапроса, Запрос.ПолучитьТелоКакСтроку());
Ответ = Новый HTTPСервисОтвет(200);
Лог.ЗакрытьЛогHTTPЗапроса(ЛогЗапроса, Ответ);
Возврат Ответ;
КонецФункции
Лог пишется в журнал регистрации с событием "Информация", а если ответ приходит с кодом состояния больше 300 или вообще не удалось выполнить запрос, то с событием "Ошибка". Проверьте, что у Вас включены нужные события в настройке журнала.
Формат логов
Чтобы удобно работать с логами, мы разработали следующий шаблон для их хранения:
[ДатаВремяНачала* ПримерноеВремяЗапроса*] МетодHTTPЗапроса* URL*
ЗаголовкиЗапроса
ТелоЗапроса
КодСостония**
ЗаголовкиОтвета
ТелоОтвета
Звездочкой отмечены поля которые всегда присутствуют в логах, остальные по требованию. Код состояния в случае ошибки запроса не указывается.
Пример лога:
[11.10.2024 11:26:11 ~0.109s] GET https://example.ru/
200
{"data":["1","2","3"]}
Пример лога с ошибкой:
[11.10.2024 11:26:12 ~15.253s] GET https://example.ru/
Ошибка работы с Интернет: Failure when receiving data from the peer
Пример логов в отчете:
Да, кстати, это скриншот отчета, который из ClickHouse достает логи и выводит их в привычном нам отчете СКД с привязкой к метаданным.
Оптимизация хранения логов
Мы пришли к выводу, что запись больших объемов данных в ЖР может значительно ухудшить производительность. Поэтому мы ограничили размер тела запроса и ответа до 5 Мб, но это можно изменить при необходимости.
Если в запросе возвращается файл в двоичном формате, мы кодируем его в base64, чтобы сохранить возможность восстановления при необходимости.
Лог.ТелоОтветаСохранитьВBase64(ЛогЗапроса)
Заголовки запросов и ответов по умолчанию отключены, кроме исключения по некоторым кодам состояния (301, 302, 429), но их можно включить при необходимости с помощью одной строки кода:
Лог.ФиксироватьЗаголовки(ЛогЗапроса)
Этот подход позволил нам сохранить баланс между полнотой логов и производительностью системы. Логи стали компактными, удобными для анализа и при этом не перегружают систему.
Преимущества решения
Теперь у нас есть полноценная система логирования для всех взаимодействий с маркетплейсами и другими сервисами. Это дало нам несколько ключевых преимуществ:
- Быстрая диагностика проблем — если что-то "не работает", мы легко можем проверить, какие запросы шли на маркетплейсы, что они вернули, и где возникла ошибка.
- Гибкость и масштабируемость — добавление новых маркетплейсов или сервисов сводится к минимальной настройке, весь процесс логирования уже отлажен.
- Удобный анализ данных — благодаря ClickHouse, мы можем быстро выгружать и анализировать логи, строить отчеты и отслеживать ключевые метрики.
Когда возникают претензии по поводу работы сервисов, мы можем быстро доказать обратное, предоставив логи, которые подтверждают корректность выполненных запросов и ответов.
Заключение
Разработанный нами модуль логирования HTTP-запросов стал незаменимым инструментом в нашей работе с маркетплейсами. Он позволяет не только эффективно отслеживать взаимодействия, но и значительно ускоряет процесс диагностики проблем.
К статье прикреплён текст модуля `КлиентHTTPЛогирование`, который, хотя и не является законченным продуктом, может оказаться полезным для многих. Мы разрабатывали и тестировали его на платформе 8.3.13.1690.
Если у вас есть интерес к более подробному изучению работы с ClickHouse, я с удовольствием подготовлю отдельную статью, в которой расскажу о том, как мы реализовали выгрузку логов, какие доработки сделали в библиотеке экспорта ЖР, с какими трудностями столкнулись и какие преимущества получили от этого подхода.
Спасибо за внимание! Если у вас есть вопросы или предложения, буду рад обсудить в комментариях!