OpenTelemetry и Sentry - недооцененные инструменты трассировки распределенных систем на Golang



Книга OpenTelemetry и Sentry - недооцененные инструменты трассировки распределенных систем на Golang

Краткое описание 🚶


Создадим небольшой пример инструментирования приложения на Golang с его настройкой, использованием OpenTelemetry и передачей получаемых трассировок на бэкенд Sentry. Вот ссылка на него в Github (с этапами запуска самого примера):



Введение 👋


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


Проблема большого количества бэкендов с трассировками 🤔


Но здесь есть небольшая проблема. Бывает так, что техтребования и гайды по контексту трассировок объявлены, а вопрос инструментирования приложений по-прежнему решается в каждом конкретном бэкенде своими средствами. Потому что есть много разных бэкендов (Sentry, Jaeger, Google Cloud Tracing, New Relic, ElasticAPM и другие), которые визуализируют трассировки. И у каждого из них свои пакеты SDK для инструментирования.


Сегодня задействуем для инструментирования микросервиса пакеты SDK для Elastic APM. А что, если завтра они покажутся слишком тяжелыми? Перейдем на что-то более легкое (Jaeger или Sentry)?


Но тогда придется проводить инструментирование всего приложения заново, и с пакетом SDK, используемым только в Jaeger или Sentry. А это приведет к огромным накладным расходам.



И тут приходится кстати OpenTelemetry 🚀


С OpenTelemetry этого делать не придется: выполним инструментирование приложения один раз, после чего эти трассировки будут отправляться в коллектор OpenTelemetry, а оттуда  —  экспортироваться сразу в несколько бэкендов.



Почему Sentry? 👀


Потому что у него как инструмента трассировки распределенных систем много достоинств, среди которых мне особенно по нраву:


  • Его компактность и меньшая ресурсоемкость в сравнении с другими. Мы раньше использовали New Relic и Elastic APM, предоставлявшие полноценную поддержку логирования, трассировок и метрик. Но они очень ресурсоемки. Нужен надежный инструмент, который размещается на простой машине EC2, а не полномасштабном кластере k8s? Тогда Sentry  —  то, что надо.
  • Sentry вне конкуренции по оповещению об ошибках и их преодолению.

Есть и недостатки:


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

Инструментирование приложения на Golang. Практика ⚒️


Мы использовали пакет SDK для OpenTelemetry на Go, размещенный на Github, и следовали инструкциям в документации для Golang.


Пройдем шаг за шагом процесс инструментирования приложения (полностью находится в файле main.go в репозитории на Github).


Инициализация трассировщика



Сначала инициализируем трассировщик, который обрабатывается в методе initTracer(). Здесь создается new exporter (новый экспортер OLTP), который подключен к порту коллектора 4317 по протоколу gRPC (через otel-collector.observability.svc.cluster.local:4317) . То есть подключение идет к сервису otel-collector в пространстве имен наблюдаемости через порт 4317).


Затем создаем новый ресурс resource и задаем имя сервиса test-service.


Дальше получаем обработчик Span и создаем поставщика трассировок TracerProvider, который впоследствии задается в приложении глобально. Также определяем, сколько отбирать трассировок. Сейчас установлено AlwaysSample(), т. е. трассировки отбираются через tracerprovider все время.


Для среды разработки это нормально, а вот для эксплуатационной среды частоту отбора желательно понизить до 10–20% во избежание технических недоработок в системе (трассировки обычно довольно тяжелые).


Начало и завершение спана, распространение его контекста


Базовый tracerprovider готов. Разберемся, как именно начинаются, завершаются и записываются события в span на Golang.



Эта функция находится в somework/service.go. Спан  —  это непрерывный отрезок времени с определенным началом и концом. Метод tracer.Start() отмечает начало спана, а метод span.End()  —  его завершение. В какой-то момент в спане добавляются события и записываются ошибки с помощью span.AddEvent() и span.RecordError() соответственно.


Текущий контекст спана (в данном случае ctx2) просто передается в следующую функцию. Вот как это было сделано в функции ErrorWork():



Настройка коллектора и экспортера OpenTelemetry 🚢


Это простая часть: выполняется всего три настройки в файле конфигурации.



Сначала настраиваем получатели receivers, в которые экспортер пакета SDK будет передавать трассировки. Здесь получатель OLTP подключается по двум протоколам: gRPC и HTTP (порт по умолчанию 4317).


Затем понадобятся обработчики processors и расширения extensions. Здесь использованы обработчики memory_limiter и batch, чтобы коллектор не превысил пик в 512 МиБ и лимит памяти в 1500 МиБ.


Настраиваем сразу несколько экспортеров exporter: экспортер logging (который экспортирует трассировки в терминал модуля) и экспортер sentry, экспортирующий трассировки одновременно на пользовательский интерфейс Sentry.


После настройки создаем конвейер pipeline, в котором есть получатель, обработчик и экспортер. Красота!


Полезные ссылки 🔖



1001   0  

Comments

    Ничего не найдено.