Разрушители мифов наблюдаемости: OpenTelemetry to Lightstep 3 Ways in Go IS Possible!

В последние пару недель я провел много времени, изучая различные способы отправки данных OpenTelemetry (OTel) в Lightstep.

Если супер-очевидный заголовок не натолкнул вас на мысль, есть три разных способа сделать это:

  1. Непосредственно из приложения
  2. Коллектор OpenTelemetry
  3. Запускающие устройства (через коллектор или непосредственно из приложения).

В этой статье я подробно рассмотрю каждый из этих трех подходов, с фрагментами кода, которые объясняют, как получить данные в Lightstep Observability. Давайте сделаем это!

Примечание: Если вы ищете полные листинги кода, не паникуйте! Вы найдете их в репозитории примеров Lightstep OTel.

Содержание
  1. Предварительные требования
  2. OpenTelemetry & Lightstep
  3. Напрямую из приложения
  4. Как это работает
  5. 1- Установите необходимые библиотеки OTel
  6. 2- Настройте экспортер
  7. 3- Настройте TracerProvider
  8. 4- Инициализируйте Exporter и TracerProvider для отправки данных в Lightstep
  9. Попробуйте!
  10. 1 — Клонируйте репозиторий
  11. 2- Откройте окно терминала и запустите серверную программу
  12. 3- Откройте новое окно терминала и выберите конечную точку
  13. 4- Посмотреть в Lightstep
  14. Коллектор OpenTelemetry
  15. Как это работает
  16. 1- Установите необходимые библиотеки OTel
  17. 2- Настройте экспортер
  18. 3- Настройте TracerProvider
  19. 4- Инициализируем экспортер и TracerProvider для отправки данных в Lightstep
  20. Попробуйте!
  21. 1 — Клонируйте репозиторий
  22. 2- Запустите коллектор
  23. 3- Откройте новое окно терминала и запустите серверную программу
  24. 4- Откройте третье окно терминала и нажмите на конечную точку
  25. 5- Посмотреть в Lightstep
  26. Launcher
  27. Как это работает
  28. 1- Установите необходимые библиотеки OTel
  29. 2- Настройка запуска
  30. 3- Инициализация запуска
  31. Попробуйте!
  32. 1 — Клонируйте репозиторий
  33. 2- Запустите коллектор
  34. 3- Откройте новое окно терминала и запустите серверную программу
  35. 4- Откройте третье окно терминала и нажмите на конечную точку
  36. Задачи
  37. 1- Отладка gRPC
  38. 2- Отладочные пролеты (только для Launchers)
  39. Какой подход лучше?
  40. Заключительные мысли

Предварительные требования

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

  • Базовое понимание Golang
  • Базовое понимание коллектора OpenTelemetry Collector

Если вы хотите запустить примеры с полным кодом, вам также понадобятся:

  • Учетная запись Lightstep Observability
  • Токен доступа Lightstep, чтобы указать Lightstep, в какой проект отправлять ваши трассы
  • рабочая локальная среда разработки Golang
  • Docker (он понадобится нам для локального запуска OTel Collector)

OpenTelemetry & Lightstep

Lightstep Observability поддерживает собственный протокол OpenTelemetry Protocol (OTLP). Он может получать данные в формате OTLP либо через HTTP, либо через gRPC. Вам нужно будет указать, какой метод вы хотите использовать в своем коде, как мы увидим в последующих фрагментах кода.

Если вам интересно, как использовать gRPC и HTTP для OpenTelemetry, ознакомьтесь с этими документами.

Примечание: Другие инструменты Observability, поддерживающие OTLP, включают Honeycomb, Grafana и Jaeger.

Напрямую из приложения

Если вы начинаете работать с инструментами OpenTelemetry в своем приложении, это, вероятно, самый распространенный путь, который выбирают большинство новичков. Как следует из названия, мы отправляем данные на данный бэкэнд Observability непосредственно из кода нашего приложения.

Для этого мы должны сделать следующее:

  • Установить необходимые пакеты OpenTelemetry и импортировать их.
  • Настроить экспортер
  • Настроить TracerProvider
  • Инициализировать экспортер и TracerProvider для отправки данных в Lightstep.

Не паникуйте, если вы не знаете, что все это значит. Вскоре мы начнем разбираться.

Примечание: Вы можете посмотреть полный пример отправки данных OTel в Lightstep напрямую через OTLP по gRPC здесь. HTTP-версию можно найти здесь.

Как это работает

1- Установите необходимые библиотеки OTel

Это библиотеки, которые необходимы для отправки данных в Observability back-end (например, Lightstep).

go get go.opentelemetry.io/otel 
    go.opentelemetry.io/otel/exporters/otlp/otlptrace 
    go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc 
    go.opentelemetry.io/otel/propagation 
    go.opentelemetry.io/otel/sdk/resource 
    go.opentelemetry.io/otel/sdk/trace 
    go.opentelemetry.io/otel/semconv/v1.10.0 
    go.opentelemetry.io/otel/trace
Войдите в полноэкранный режим Выйти из полноэкранного режима

В коде нашего приложения нам нужно будет импортировать те же библиотеки:

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    "go.opentelemetry.io/otel/propagation"
    "go.opentelemetry.io/otel/sdk/resource"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
    "go.opentelemetry.io/otel/trace"
)
Вход в полноэкранный режим Выйти из полноэкранного режима

Если вы хотите использовать HTTP вместо gRPC, замените otlptracegrpc на otlptracehttp.

2- Настройте экспортер

Экспортер — это то, как мы отправляем данные в OpenTelemetry. Как я упоминал ранее, Lightstep принимает данные в формате OTLP, поэтому нам нужно определить OTLP Exporter.

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

Мы настроим наш экспортер следующим образом:

var (
   tracer         trace.Tracer
   endpoint       = "ingest.lightstep.com:443"
   lsToken        = "<LS_ACCESS_TOKEN>"
)

func newExporter(ctx context.Context) (*otlptrace.Exporter, error) {

   var headers = map[string]string{
       "lightstep-access-token": lsToken,
   }

   client := otlptracegrpc.NewClient(
       otlptracegrpc.WithHeaders(headers),
       otlptracegrpc.WithEndpoint(endpoint),
   )
   return otlptrace.New(ctx, client)
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Некоторые примечательные элементы:

  • endpoint установлен на ingest.lightstep.com:443, который указывает на публичный пул микроспутников Lightstep. Если вы используете местный спутниковый пул, ознакомьтесь с этой документацией.
  • Вы должны указать значение для <LS_ACCESS_TOKEN> с вашим собственным токеном доступа Lightstep.
  • Мы отправляем данные в Lightstep через gRPC. Если вы хотите использовать HTTP вместо gRPC, ваше клиентское соединение будет выглядеть следующим образом:
  client := otlptracehttp.NewClient(
    otlptracehttp.WithHeaders(headers),
    otlptracehttp.WithEndpoint(endpoint),
    otlptracehttp.WithURLPath("traces/otlp/v0.9"),
  )
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что мы должны добавить дополнительный параметр конфигурации, WithURLPath. Этот параметр конфигурации позволяет нам переопределить путь URL по умолчанию для отправки трасс. Значение по умолчанию — /v1/traces; однако для HTTP-соединений Lightstep ожидает, что это значение будет traces/otlp/v0.9.

3- Настройте TracerProvider

TracerProvider служит точкой входа в OpenTelemetry API. Он предоставляет доступ к Tracers. Tracer отвечает за создание Span для отслеживания заданной операции.

Мы настраиваем наш TracerProvider следующим образом:

var (
   tracer         trace.Tracer
   serviceName    = "test-go-server-grpc"
   serviceVersion = "0.1.0"
   lsEnvironment  = "dev"
)

func newTraceProvider(exp *otlptrace.Exporter) *sdktrace.TracerProvider {

   resource, rErr :=
       resource.Merge(
           resource.Default(),
           resource.NewWithAttributes(
               semconv.SchemaURL,
               semconv.ServiceNameKey.String(serviceName),
               semconv.ServiceVersionKey.String(serviceVersion),
               attribute.String("environment", lsEnvironment),
           ),
       )

   if rErr != nil {
       panic(rErr)
   }

   return sdktrace.NewTracerProvider(
       sdktrace.WithBatcher(exp),
       sdktrace.WithResource(resource),
   )
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Несколько примечательных моментов:

  • Мы определяем ресурс (Resource), чтобы предоставить OpenTelemetry кучу информации, которая идентифицирует наш сервис. Сюда входят такие вещи, как serviceName и serviceVersion, которые должны быть установлены Lightstep. Как следует из названия, serviceName — это имя микросервиса, который вы инструментируете.

4- Инициализируйте Exporter и TracerProvider для отправки данных в Lightstep

Наконец-то мы готовы отправить данные в Lightstep! Для этого мы вызываем функции newExporter и newTraceProvider из нашей функции main:

func main() {
   ctx := context.Background()

   exp, err := newExporter(ctx)
   if err != nil {
       log.Fatalf("failed to initialize exporter: %v", err)
   }

   tp := newTraceProvider(exp)
   defer func() { _ = tp.Shutdown(ctx) }()

   otel.SetTracerProvider(tp)

   // More code here
   ...
}
Вход в полноэкранный режим Выход из полноэкранного режима

Попробуйте!

Давайте посмотрим пример кода в действии. В этом примере мы запустим сервер с конечной точкой /ping. Сервер будет отправлять данные OTel в Lightstep напрямую через OTLP по gRPC. Мы будем обращаться к конечной точке с помощью curl.

1 — Клонируйте репозиторий

git clone git@github.com:lightstep/opentelemetry-examples.git
Войдите в полноэкранный режим Выйдите из полноэкранного режима

2- Откройте окно терминала и запустите серверную программу

cd opentelemetry-examples/go/opentelemetry/otlp/server
export LS_ACCESS_TOKEN=<your_access_token>
go run server.go
Войти в полноэкранный режим Выйти из полноэкранного режима

Обязательно замените <your_access_token> на ваш собственный Lightstep Access Token

3- Откройте новое окно терминала и выберите конечную точку

curl http://localhost:8081/ping
Войдите в полноэкранный режим Выйти из полноэкранного режима

Боковой пример вывода данных с сервера и команды curl:

4- Посмотреть в Lightstep

Примечание: Хотите запустить HTTP версию? Замените go run server.go в Шаге 2 на go run server-http.go.

Коллектор OpenTelemetry

Следующий подход к отправке данных в Observability back-end — это использование OpenTelemetry Collector. Для установок, не связанных с разработкой, это рекомендуемый подход к отправке данных OpenTelemetry на бэкэнд Observability.

Чтобы отправить данные, полученные с помощью приборов, на внутренний модуль Observability через Коллектор, необходимо сделать следующее:

  • Запустить где-нибудь экземпляр OpenTelemetry Collector (проще всего запустить его локально).
  • Установить необходимые пакеты OpenTelemetry и импортировать их.
  • Настроить экспортер
  • Настройте TracerProvider
  • Инициализируйте экспортер и TracerProvider

Примечание: Вы можете посмотреть полный листинг кода здесь.

Выглядит почти так же, как и прямой подход, не так ли? Почти…

В ближайшее время мы рассмотрим различия.

Как это работает

1- Установите необходимые библиотеки OTel

Это библиотеки, которые необходимы для отправки данных в Observability back-end (например, Lightstep).

go get go.opentelemetry.io/otel 
    go.opentelemetry.io/otel/exporters/otlp/otlptrace 
    go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc 
    go.opentelemetry.io/otel/propagation 
    go.opentelemetry.io/otel/sdk/resource 
    go.opentelemetry.io/otel/sdk/trace 
    go.opentelemetry.io/otel/semconv/v1.10.0 
    go.opentelemetry.io/otel/trace
Войдите в полноэкранный режим Выйти из полноэкранного режима

В коде нашего приложения нам нужно будет импортировать те же библиотеки:

import (
    "go.opentelemetry.io/otel"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    "go.opentelemetry.io/otel/propagation"
    "go.opentelemetry.io/otel/sdk/resource"
    sdktrace "go.opentelemetry.io/otel/sdk/trace"
    semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
    "go.opentelemetry.io/otel/trace"
)
Войти в полноэкранный режим Выйти из полноэкранного режима

Если вы хотите использовать HTTP вместо gRPC, замените otlptracegrpc на otlptracehttp.

2- Настройте экспортер

Как мы видели в примере Direct, мы экспортируем наши данные через OTLP (см. тип возврата otlptrace.Exporter). Разница в том, что вместо экспорта данных непосредственно в Lightstep, мы экспортируем их в OTel Collector, который получает данные OTel из нашего приложения в формате OTLP.

В нашем примере Direct, прежде чем создать новый экспортер, нам сначала нужно было создать новый клиент трассировки (otlptracegrpc.NewClient), чтобы мы могли указать OpenTelemetry, как отправлять данные в Lightstep. Нам не нужно делать этого при использовании коллектора, потому что коллектор позаботится о создании клиента трассировки для нас за кулисами, используя для этого информацию в YAML конфигурации коллектора.

Мы настраиваем наш экспортер следующим образом:

var (
   endpoint = "localhost:4317"
)

func newExporter(ctx context.Context) (*otlptrace.Exporter, error) {
    exporter, err :=
        otlptracegrpc.New(ctx,
            otlptracegrpc.WithInsecure(),
            otlptracegrpc.WithEndpoint(endpoint),
        )

    return exporter, err
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Некоторые примечательные элементы:

  • endpoint — это URL вашего коллектора.
  • В примере ниже, коллектор endpoint установлен на localhost:4317, что означает, что OpenTelemetry Collector запущен локально, с помощью Docker, прослушивая gRPC порт 4317.
  • Вам не нужно предоставлять токен Lightstep Access как часть этой конфигурации, так как это значение задается в YAML-файле конфигурации OTel Collector.
  • Обратите внимание, что опция WithInsecure установлена. Это требуется, если вы используете Коллектор, и только в том случае, если сертификат не настроен в Коллекторе. (Это статья в блоге для другого дня 😜).
  • Мы отправляем данные в Коллектор через gRPC. Если вы хотите использовать HTTP вместо gRPC, просто замените otlptracegrpc на otlptracehttp следующим образом:
  exporter, err :=
      otlptracehttp.New(ctx,
          otlptracehttp.WithInsecure(),
          otlptracehttp.WithEndpoint(endpoint),
  )
Войдите в полноэкранный режим Выход из полноэкранного режима

3- Настройте TracerProvider

Наш TracerProvider идентичен тому, который мы настроили в примере Direct:

var (
   tracer         trace.Tracer
   serviceName    = "test-go-server-grpc"
   serviceVersion = "0.1.0"
   lsEnvironment  = "dev"
)

func newTraceProvider(exp *otlptrace.Exporter) *sdktrace.TracerProvider {

   resource, rErr :=
       resource.Merge(
           resource.Default(),
           resource.NewWithAttributes(
               semconv.SchemaURL,
               semconv.ServiceNameKey.String(serviceName),
               semconv.ServiceVersionKey.String(serviceVersion),
               attribute.String("environment", lsEnvironment),
           ),
       )

   if rErr != nil {
       panic(rErr)
   }

   return sdktrace.NewTracerProvider(
       sdktrace.WithBatcher(exp),
       sdktrace.WithResource(resource),
   )
}
Вход в полноэкранный режим Выход из полноэкранного режима

4- Инициализируем экспортер и TracerProvider для отправки данных в Lightstep

Наконец-то мы готовы отправить данные в Lightstep! Для этого мы вызываем функции newExporter и newTraceProvider из нашей функции main:

func main() {
    ctx := context.Background()

    exp, err := newExporter(ctx)
    if err != nil {
        log.Fatalf("failed to initialize exporter: %v", err)
    }

    tp := newTraceProvider(exp)
    defer func() { _ = tp.Shutdown(ctx) }()

    otel.SetTracerProvider(tp)

    otel.SetTextMapPropagator(
        propagation.NewCompositeTextMapPropagator(
            propagation.TraceContext{},
            propagation.Baggage{},
        ),
    )

    tracer = tp.Tracer(serviceName, trace.WithInstrumentationVersion(serviceVersion))

   // More code here
   ...
}
Вход в полноэкранный режим Выход из полноэкранного режима

Обратите внимание, что это то же самое, что мы видели в примере Direct. Только основной код в функции newExporter отличается.

Попробуйте!

Давайте посмотрим пример кода в действии. В этом примере мы запустим сервер с конечной точкой /ping. Сервер будет отправлять данные OTel в Lightstep через коллектор по протоколу gRPC. Мы будем обращаться к конечной точке с помощью curl.

1 — Клонируйте репозиторий

git clone git@github.com:lightstep/opentelemetry-examples.git
Войдите в полноэкранный режим Выйдите из полноэкранного режима

2- Запустите коллектор

Откройте новое окно терминала. Сначала вам нужно будет отредактировать файл collector.yaml. Обязательно замените ${LIGHTSTEP_ACCESS_TOKEN} на ваш собственный токен доступа Lightstep.

Теперь вы можете запустить коллектор:

cd opentelemetry-examples/collector/vanilla
docker run -it --rm -p 4317:4317 -p 4318:4318 
    -v $(pwd)/collector.yaml:/otel-config.yaml 
    --name otelcol otel/opentelemetry-collector-contrib:0.53.0  
    "/otelcol-contrib" 
    "--config=otel-config.yaml"  
Войти в полноэкранный режим Выйти из полноэкранного режима

Примечание: Это может занять некоторое время, если вы впервые запускаете изображение Коллектора.

Образец вывода:

3- Откройте новое окно терминала и запустите серверную программу

cd opentelemetry-examples/go/opentelemetry/collector/server
go run server.go
Войти в полноэкранный режим Выход из полноэкранного режима

4- Откройте третье окно терминала и нажмите на конечную точку

curl http://localhost:8081/ping
Войти в полноэкранный режим Выйти из полноэкранного режима

Бок о бок примеры вывода из вывода сервера и команды curl:

И ваш вывод Collector должен выглядеть примерно так:

5- Посмотреть в Lightstep

Launcher

Последний подход, который мы рассмотрим сегодня — это Launcher. Если вы просмотрели документацию по OpenTelemetry и не увидели нигде упоминания о Launcher, это потому, что они не являются частью OTel как таковой.

Вы можете думать о лаунчерах как обертках вокруг SDK OTel. Изначально Launchers были созданы некоторыми талантливыми инженерами в Lightstep, чтобы обеспечить способ инкапсуляции установки и конфигурации OpenTelemetry. Проще говоря, пусковые установки были созданы потому, что они устали дублировать код настройки SDK. И снова лень разработчика в выигрыше! (Для справки, я твердо убежден, что лень разработчиков — это то, что делает отличное программное обеспечение. Мы просто ненавидим повторения!) Launchers также добавляют уровень проверки, чтобы дать пользователям лучшее понимание всех необходимых параметров. Подробнее о лаунчерах читайте в этой статье Теда Янга.

В настоящее время у нас есть Launchers для Go, Python, Java и Node.JS.

Хорошо… теперь, когда мы поняли, зачем существуют Launchers, давайте выясним, как использовать их для отправки данных OTel в Lightstep.

Для этого мы должны сделать следующее:

  • Установить необходимые пакеты OpenTelemetry и Launcher и импортировать их.
  • Настроить Launcher
  • Инициализировать Launcher

Выглядит немного иначе, чем в двух других примерах, не так ли? Как вы видите, Launcher берет на себя заботу о конфигурации и инициализации Exporter и TracerProvider.

Давайте покопаемся в этом.

Примечание: Полный пример отправки данных OTel в Lightstep с помощью Go Launcher через коллектор по gRPC вы можете посмотреть здесь. Прямую версию (через Launcher) можно найти здесь.

Как это работает

1- Установите необходимые библиотеки OTel

go get github.com/lightstep/otel-launcher-go/launcher  
    go.opentelemetry.io/otel  
    go.opentelemetry.io/otel/semconv/v1.10.0  
    go.opentelemetry.io/otel/trace
Войдите в полноэкранный режим Выйти из полноэкранного режима

В коде нашего приложения нам нужно будет импортировать те же библиотеки:

import (
    "github.com/lightstep/otel-launcher-go/launcher"
    "go.opentelemetry.io/otel"
    semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
    "go.opentelemetry.io/otel/trace"
)
Войти в полноэкранный режим Выйти из полноэкранного режима

Хм… меньше пакетов для установки и импорта!

2- Настройка запуска

Здесь мы настраиваем Launcher, аналогично тому, что мы делали, когда настраивали Exporter и TracerProvider. Только все это заключено в этом чудесном launcher.ConfigureOpentelemetry! Супер круто. 😎

var (
    tracer         trace.Tracer
    serviceName    = "test-go-server-launcher"
    serviceVersion = "0.1.0"
    endpoint       = "ingest.lightstep.com:443"
    lsToken        = "<LS_ACCESS_TOKEN>"
)

func newLauncher() launcher.Launcher {

    otelLauncher := launcher.ConfigureOpentelemetry(
        launcher.WithServiceName(serviceName),
        launcher.WithServiceVersion(serviceVersion),
        launcher.WithAccessToken(lsToken),
        launcher.WithSpanExporterEndpoint(endpoint),
        launcher.WithMetricExporterEndpoint(endpoint),    
        launcher.WithPropagators([]string{"tracecontext", "baggage"}),
        launcher.WithResourceAttributes(map[string]string{
            string(semconv.ContainerNameKey): "my-container-name",
        }),
    )

    return otelLauncher
}
Вход в полноэкранный режим Выход из полноэкранного режима

Некоторые примечательные элементы:

  • endpoint установлен на ingest.lightstep.com:443, который указывает на публичный пул микроспутников Lightstep. Если вы используете местный спутниковый пул, ознакомьтесь с этой документацией.
  • Вы должны указать значение для <LS_ACCESS_TOKEN> с вашим собственным токеном доступа Lightstep.
  • Запускающие устройства используют только gRPC. Честно говоря, это не проблема.

Это все хорошо, но что если вы хотите использовать коллектор? Разве я не говорил, что это предпочтительный метод для установок без разработчиков? Да, я говорил! И не волнуйтесь, потому что вы можете использовать Launchers для отправки данных OTel в коллектор, а не напрямую в Lightstep. Для этого вам просто нужно:

  • Изменить значение endpoint на localhost:4317.
  • Установить WithSpanExporterInsecure на true
  • Установите WithMetricExporterInsecure в true
  • Удалите параметр WithAccessToken (поскольку он обрабатывается YAML-файлом конфигурации OTel Collector).

Это означает, что ваш код будет выглядеть следующим образом:

  var (
      tracer         trace.Tracer
      serviceName    = "test-go-server-launcher"
      serviceVersion = "0.1.0"
      endpoint       = "ingest.lightstep.com:443"
  )

  func newLauncher() launcher.Launcher {
      otelLauncher := launcher.ConfigureOpentelemetry(
          launcher.WithServiceName(serviceName),
          launcher.WithServiceVersion(serviceVersion),
          launcher.WithSpanExporterInsecure(true),
          launcher.WithSpanExporterEndpoint(endpoint),
          launcher.WithMetricExporterEndpoint(endpoint),
          launcher.WithMetricExporterInsecure(true),
          launcher.WithPropagators([]string{"tracecontext", "baggage"}),
          launcher.WithResourceAttributes(map[string]string{
            string(semconv.ContainerNameKey): "my-container-name",
          }),
      )

    return otelLauncher
  }
Вход в полноэкранный режим Выход из полноэкранного режима

3- Инициализация запуска

Все, что нам нужно сделать, это вызвать нашу функцию newLauncher, и все готово!

func main() {
    otelLauncher := newLauncher()
    defer otelLauncher.Shutdown()

    tracer = otel.Tracer(serviceName)

// More code here
  ...
}
Вход в полноэкранный режим Выход из полноэкранного режима

В целом, подход Launcher требует меньше кода по сравнению с двумя другими подходами sans-Launcher.

Попробуйте!

Давайте посмотрим пример кода в действии. В этом примере мы запустим сервер с конечной точкой /ping. Сервер будет отправлять данные OTel в Lightstep с помощью Go Launcher через коллектор, по gRPC. Мы будем обращаться к конечной точке с помощью curl.

1 — Клонируйте репозиторий

git clone git@github.com:lightstep/opentelemetry-examples.git
Войдите в полноэкранный режим Выйдите из полноэкранного режима

2- Запустите коллектор

Откройте новое окно терминала. Сначала вам нужно будет отредактировать файл collector.yaml. Обязательно замените ${LIGHTSTEP_ACCESS_TOKEN} на ваш собственный токен доступа Lightstep.

Теперь вы можете запустить коллектор:

cd opentelemetry-examples/collector/vanilla
docker run -it --rm -p 4317:4317 -p 4318:4318 
    -v $(pwd)/collector.yaml:/otel-config.yaml 
    --name otelcol otel/opentelemetry-collector-contrib:0.53.0  
    "/otelcol-contrib" 
    "--config=otel-config.yaml"  
Войдите в полноэкранный режим Выйти из полноэкранного режима

Примечание: Это может занять некоторое время, если вы впервые запускаете изображение Коллектора.

Образец вывода:

3- Откройте новое окно терминала и запустите серверную программу

cd opentelemetry-examples/go/launcher/server
go run server.go
Войти в полноэкранный режим Выход из полноэкранного режима

4- Откройте третье окно терминала и нажмите на конечную точку

curl http://localhost:8081/ping
Войти в полноэкранный режим Выйти из полноэкранного режима

Бок о бок примеры вывода из вывода сервера и команды curl:

И ваш вывод Collector должен выглядеть примерно так:

  1. Посмотреть в Lightstep

Примечание: Хотите запустить прямую версию с помощью Launcher? Просто пропустите Шаг 2. В Шаге 3 установите переменную окружения LS_ACCESS_TOKEN: export LS_ACCESS_TOKEN=<your_access_token>, где <your_access_token> — ваш собственный Lightstep Access Token, и замените go run server.go на go run server-otlp.go.

Задачи

Пока я возился с каждым из трех подходов, я столкнулся с несколькими проблемами, поэтому я решил поделиться ими здесь.

1- Отладка gRPC

gRPC — это бич моего существования. Особенно когда я вижу это прекрасное сообщение context deadline exceeded. Это заставляет мою кровь кипеть. К счастью, мои друзья OTel из Lighstep рассказали мне о двух небольших флагах, которые немного облегчают отладку gRPC:

export GRPC_GO_LOG_VERBOSITY_LEVEL=99
export GRPC_GO_LOG_SEVERITY_LEVEL=info
Войти в полноэкранный режим Выйти из полноэкранного режима

Установите эти красивые флажки, и вы относительно быстро узнаете, если не можете подключиться к конечной точке gRPC. Вот как выглядит успешное соединение:

2022/07/26 16:28:36 Using default LS endpoint ingest.lightstep.com:443
2022/07/26 16:28:36 INFO: [core] [Channel #1] Channel created
2022/07/26 16:28:36 INFO: [core] [Channel #1] original dial target is: "ingest.lightstep.com:443"
2022/07/26 16:28:36 INFO: [core] [Channel #1] parsed dial target is: {Scheme:ingest.lightstep.com Authority: Endpoint:443 URL:{Scheme:ingest.lightstep.com Opaque:443 User: Host: Path: RawPath: ForceQuery:false RawQuery: Fragment: RawFragment:}}
2022/07/26 16:28:36 INFO: [core] [Channel #1] fallback to scheme "passthrough"
2022/07/26 16:28:36 INFO: [core] [Channel #1] parsed dial target is: {Scheme:passthrough Authority: Endpoint:ingest.lightstep.com:443 URL:{Scheme:passthrough Opaque: User: Host: Path:/ingest.lightstep.com:443 RawPath: ForceQuery:false RawQuery: Fragment: RawFragment:}}
2022/07/26 16:28:36 INFO: [core] [Channel #1] Channel authority set to "ingest.lightstep.com:443"
2022/07/26 16:28:36 INFO: [core] [Channel #1] Resolver state updated: {
  "Addresses": [
    {
      "Addr": "ingest.lightstep.com:443",
      "ServerName": "",
      "Attributes": null,
      "BalancerAttributes": null,
      "Type": 0,
      "Metadata": null
    }
  ],
  "ServiceConfig": null,
  "Attributes": null
} (resolver returned new addresses)
2022/07/26 16:28:36 INFO: [core] [Channel #1] Channel switches to new LB policy "pick_first"
2022/07/26 16:28:36 INFO: [core] [Channel #1 SubChannel #2] Subchannel created
2022/07/26 16:28:36 Using default service name test-go-client-grpc
2022/07/26 16:28:36 Using default service version 0.1.0
2022/07/26 16:28:36 Using default environment dev
2022/07/26 16:28:36 INFO: [core] [Channel #1 SubChannel #2] Subchannel Connectivity change to CONNECTING
2022/07/26 16:28:36 INFO: [core] [Channel #1 SubChannel #2] Subchannel picks a new address "ingest.lightstep.com:443" to connect
2022/07/26 16:28:36 INFO: [core] pickfirstBalancer: UpdateSubConnState: 0x14000380100, {CONNECTING <nil>}
2022/07/26 16:28:36 INFO: [core] [Channel #1] Channel Connectivity change to CONNECTING
Get "http://localhost:8081/ping": dial tcp [::1]:8081: connect: connection refused
2022/07/26 16:28:37 INFO: [core] [Channel #1 SubChannel #2] Subchannel Connectivity change to READY
2022/07/26 16:28:37 INFO: [core] pickfirstBalancer: UpdateSubConnState: 0x14000380100, {READY <nil>}
2022/07/26 16:28:37 INFO: [core] [Channel #1] Channel Connectivity change to READY
Войти в полноэкранный режим Выход из полноэкранного режима

2- Отладочные пролеты (только для Launchers)

Если вы используете Launcher и ваши Spans не отображаются в Lightstep, вы можете установить флаг OTEL_LOG_LEVEL перед запуском кода:

export OTEL_LOG_LEVEL=debug
go run <your_app>.go
Войти в полноэкранный режим Выйти из полноэкранного режима

Ваш отладочный вывод будет выглядеть примерно так:

2022/07/26 15:39:10 debug logging enabled
2022/07/26 15:39:10 configuration
2022/07/26 15:39:10 {
        "SpanExporterEndpoint": "localhost:4317",
        "SpanExporterEndpointInsecure": true,
        "ServiceName": "test-go-client-launcher",
        "ServiceVersion": "0.1.0",
        "Headers": null,
        "MetricExporterEndpoint": "localhost:4317",
        "MetricExporterEndpointInsecure": true,
        "MetricExporterTemporalityPreference": "cumulative",
        "MetricsEnabled": true,
        "LogLevel": "debug",
        "Propagators": [
                "tracecontext",
                "baggage"
        ],
...
}
Вход в полноэкранный режим Выход из полноэкранного режима

Какой подход лучше?

Когда я только начинал свое путешествие по OTel в 2021 году (в дни, предшествовавшие Lightstep), я отправлял данные OTel на бэкэнд Observability с помощью OTel Collector. Для меня это было несложно, потому что коллектор может:

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

Я лично являюсь большим поклонником коллектора, и я поддерживаю свое заявление о том, что хорошей практикой является запуск OTel Collector в средах Pre-Prod/Prod для отправки данных OpenTelemetry на бэкэнд Observability.

НО… я должен признать, что я думал об этой проблеме скорее с точки зрения эксплуатации, чем с точки зрения разработчика.

Дело в том, что когда вы начинаете работать с OTel, есть шанс, что вы начинаете с нуля. Это означает, что вам уже приходится разбираться со всем этим инструментарием. Это и так достаточно напряженно. Добавьте к этому попытку создать коллектор, и вы получите слишком много движущихся частей и, вероятно, очень перегруженного разработчика… даже если вы запустите его с самой простой конфигурацией (т.е. локально, через Docker). К тому же, действительно ли вам нужно запускать Collector, если вы просто ведете локальную разработку? Вероятно, это больше усилий, чем пользы.

НО… я также узнал из личного опыта, что подключение к Observability back-end через прямой подход — это королевская боль в заднице. Документация была очень скудной. Примеры были неполными. Излишне говорить, что это было очень трудное путешествие. И у меня были трудности с использованием HTTP и gRPC.

В связи с этим возникает вопрос: какой хороший и простой способ инструментировать ваш код и отправить его на бэкэнд Observability? Вот тут-то и вступают в игру Launchers! Потому что они дают вам лучшее из двух миров. Вы можете подключиться непосредственно к бэкенду Observability, ИЛИ вы можете подключиться через OTel Collector. Кроме того, Launchers не ограничивает вас в использовании Lightstep в качестве бэкенда Observability, потому что:

  1. Если вы подключаетесь к коллектору из Launcher, коллектор автоматически дает вам возможность отправлять на несколько бэкэндов Observability.
  2. Если вы решили подключиться напрямую к бэкенду, не относящемуся к Lightstep Observability, который принимает данные OTel в формате OTLP из Launcher.

Должен признаться, что до использования Go Launcher я относился к нему довольно скептически. В конце концов, это не ванильный OTel, что заставило меня подумать… «О-о-о… блокировка поставщика! Разве не этого пытается избежать OTel?».

Но две вещи изменили мое мнение об этом. Во-первых, тот факт, что вы не привязаны к конкретному поставщику (см. выше). Во-вторых, наши друзья из Honeycomb работают над внедрением лаунчеров в сообщество, согласно работе, проделанной здесь, так что есть шанс, что лаунчеры могут стать (ванильным) будущим OTel!

Мой вывод: Launcher выигрывает благодаря своей гибкости и общей простоте по сравнению с аналогами.

Заключительные мысли

Мы узнали о том, как мы можем отправлять данные OTel в Lightstep тремя различными способами:

  • Непосредственно из нашего приложения
  • Через OTel Collector
  • Используя Launchers, которые могут отправлять данные непосредственно в Lightstep или через коллектор.

При использовании коллектора предпочтительным способом отправки данных в Observability является использование коллектора; однако, если вы только начинаете работать с OTel, отправка данных OTel непосредственно в Observability имеет наибольший смысл, поскольку вам придется иметь дело с меньшим количеством движущихся частей.

Тем не менее, использование ванильного OTel для выполнения любого из вышеперечисленных действий может быть немного перегруженным, поэтому на помощь приходят Launchers, которые абстрагируют кучу вещей, связанных с подключением, что упрощает отправку данных на вашу Observability back-end, будь то напрямую или через коллектор.

Ух ты! Было о чем подумать и что принять! Похлопайте себя по спине, потому что мы многое рассмотрели! А теперь, пожалуйста, наслаждайтесь фотографией коз.

Мира, любви и кода. 🦄 🌈 💫


Есть вопросы по инструментарию OTel с Golang? Свяжитесь с нами! Свяжитесь с нами по электронной почте или напишите мне в Twitter. Надеюсь услышать вас всех!

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