Информация о трассировке прибора с использованием OpenTelemetry

1. Введение

5af4a7e43b0feaab.png

Последнее обновление: 5 марта 2021 г.

Наблюдаемость приложения

Наблюдаемость и OpenTelemetry

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

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

Распределенная трассировка

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

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

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

adbd3ecd69d410cb.png

Google Cloud Trace — это один из вариантов распределенной серверной части трассировки, который хорошо интегрируется с другими продуктами в Google Cloud.

Что ты построишь

В этой лаборатории кода вы собираетесь инструментировать информацию трассировки в службах под названием Shakesapp, которые работают в кластере Kubernetes, работающем на Google Kubernetes Engine. Архитектура Shakesapp описана ниже:

68873c018a7be7de.png

  • Клиенты отправляют строку запроса на сервер
  • Сервер принимает запрос от клиента, извлекает все произведения Шекспира в текстовом формате из Google Cloud Storage, ищет строки, содержащие запрос, и возвращает номер строки, совпадающей с клиентом.

Вы будете инструментировать информацию трассировки по всему запросу.

Что вы узнаете

  • Как начать работу с библиотеками OpenTelemetry Trace в проекте Python
  • Как создать диапазон с помощью библиотеки
  • Как передавать контексты диапазона по сети между компонентами приложения
  • Как отправить данные трассировки в Google Cloud Trace
  • Как проанализировать трассировку в Google Cloud Trace

В этой кодовой лаборатории объясняется, как инструментировать ваши микросервисы. Чтобы упростить понимание, этот пример содержит только 3 компонента (генератор нагрузки, клиент и сервер), но вы можете применить тот же процесс, описанный в этой кодовой лаборатории, к более сложным и большим системам.

Что вам понадобится

  • Знание Python 3.

2. Настройка и требования

Самостоятельная настройка среды

Если у вас еще нет учетной записи Google (Gmail или Google Apps), вам необходимо ее создать . Войдите в консоль Google Cloud Platform ( console.cloud.google.com ) и создайте новый проект.

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

15b8b6ac4d917005.png

и нажмите кнопку «НОВЫЙ ПРОЕКТ» в появившемся диалоговом окне, чтобы создать новый проект:

7136b3ee36ebaf89.png

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

90977ce514204b51.png

Последующий диалог создания проекта позволяет вам ввести детали вашего нового проекта:

6d9573e346e930b4.png

Запомните идентификатор проекта, который является уникальным именем для всех проектов Google Cloud (имя, указанное выше, уже занято и не подойдет вам, извините!). Позже в этой лаборатории он будет называться PROJECT_ID.

Далее, если вы еще этого не сделали, вам необходимо включить выставление счетов в консоли разработчика, чтобы использовать ресурсы Google Cloud и включить Cloud Trace API .

eb5325f65619ad6a.png

Выполнение этой кодовой лаборатории не должно стоить вам больше нескольких долларов, но может стоить больше, если вы решите использовать больше ресурсов или оставите их включенными (см. раздел «Очистка» в конце этого документа). Цены на Google Cloud Trace, Google Kubernetes Engine и реестр Google Artifacat указаны в официальной документации.

Новые пользователи Google Cloud Platform имеют право на бесплатную пробную версию за 300 долларов США , что делает эту лабораторию кода совершенно бесплатной.

Настройка Google Cloud Shell

Хотя Google Cloud и Google Cloud Trace можно управлять удаленно с вашего ноутбука, в этой лаборатории мы будем использовать Google Cloud Shell , среду командной строки, работающую в облаке.

Эта виртуальная машина на базе Debian оснащена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Это означает, что все, что вам понадобится для этой лаборатории кода, — это браузер (да, он работает на Chromebook).

Чтобы активировать Cloud Shell из Cloud Console, просто нажмите «Активировать Cloud Shell». gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A (подготовка и подключение к среде займет всего несколько минут).

ff81d016724c4f67.png

fbe156ee6edfbb2e.png

После подключения к Cloud Shell вы увидите, что вы уже прошли аутентификацию и что для проекта уже установлен ваш PROJECT_ID .

gcloud auth list

Вывод команды

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

Вывод команды

[core]
project = <PROJECT_ID>

Если по какой-то причине проект не установлен, просто введите следующую команду:

gcloud config set project <PROJECT_ID>

Ищете свой PROJECT_ID ? Узнайте, какой идентификатор вы использовали на этапах настройки, или найдите его на панели управления Cloud Console:

a3e716fc9e7454e9.png

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

echo $GOOGLE_CLOUD_PROJECT

Выход команды

<PROJECT_ID>

Наконец, установите зону по умолчанию и конфигурацию проекта.

gcloud config set compute/zone us-central1-f

Вы можете выбрать множество различных зон. Дополнительную информацию см. в разделе «Регионы и зоны» .

Настройка Python

В этой кодовой лаборатории мы используем «поэзию» для строгого управления версиями пакетов. Выполните следующую команду в Cloud Shell:

curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -
source $HOME/.poetry/env

Настройка кластера Google Kubernetes

В этой лаборатории кода вы запустите кластер микросервисов в Google Kubernetes Engine (GKE). Процесс этой кодовой лаборатории выглядит следующим образом:

  1. Загрузите базовый проект в Cloud Shell.
  2. Встраивайте микросервисы в контейнеры
  3. Загрузите контейнеры в реестр артефактов Google (GAR).
  4. Развертывание контейнеров в GKE
  5. Измените исходный код служб для инструментов трассировки.
  6. Перейти к шагу 2

Включить движок Kubernetes

Сначала мы настраиваем кластер Kubernetes, в котором Shakesapp работает на GKE, поэтому нам нужно включить GKE. Перейдите в меню «Kubernetes Engine» и нажмите кнопку ВКЛЮЧИТЬ.

56c680e93e169731.png

Теперь вы готовы создать кластер Kubernetes.

Создать кластер Kubernetes

В Cloud Shell выполните следующую команду, чтобы создать кластер Kubernetes. Подтвердите, что значение зоны соответствует региону , который вы использовали для создания репозитория реестра артефактов. Измените значение зоны us-central1-f если регион вашего репозитория не охватывает эту зону.

gcloud container clusters create otel-trace-codelab --zone us-central1-f \
--num-nodes 1 \
--machine-type e2-highcpu-4

Вывод команды

Creating cluster otel-trace-codelab in us-central1-f... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/psychic-order-307806/zones/us-central1-f/clusters/otel-trace-codelab].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab?project=psychic-order-307806
kubeconfig entry generated for otel-trace-codelab.
NAME                LOCATION       MASTER_VERSION    MASTER_IP        MACHINE_TYPE  NODE_VERSION      NUM_NODES  STATUS
otel-trace-codelab  us-central1-f  1.18.12-gke.1210  104.154.162.176  e2-medium     1.18.12-gke.1210  3          RUNNING

Реестр артефактов и настройка скаффолда

Теперь у нас есть кластер Kubernetes, готовый к развертыванию. Затем мы готовим реестр контейнеров для отправки и развертывания контейнеров. Для этого шага нам нужно настроить GAR и скаффолд для его использования.

Настройка реестра артефактов

Перейдите в меню «Реестр артефактов» и нажмите кнопку ВКЛЮЧИТЬ.

f7493243bae0cdf7.png

Через несколько секунд вы увидите браузер репозитория GAR. Нажмите кнопку «СОЗДАТЬ РЕПОЗИТОРИЙ» и введите имя репозитория.

f97f337f5476651.png

В этой кодовой лаборатории я называю новый репозиторий trace-codelab . Формат артефакта — «Docker», а тип местоположения — «Регион». Выберите регион, близкий к тому, который вы установили для зоны по умолчанию Google Compute Engine. Например, в этом примере выше выбрано «us-central1-f», поэтому здесь мы выбираем «us-central1 (Айова)». Затем нажмите кнопку «СОЗДАТЬ».

2f04143077ca56db.png

Теперь вы видите «trace-codelab» в браузере репозитория.

7a3c1f47346bea15.png

Мы вернемся сюда позже, чтобы проверить путь к реестру.

Установка строительных лесов

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

Снова откройте Cloud Shell и убедитесь, что skaffold установлен. (Cloud Shell по умолчанию устанавливает скаффолд в среду.) Выполните следующую команду и посмотрите версию скаффолда.

skaffold version

Вывод команды

v1.20.0

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

55173fe922f40327.png

Затем вы увидите следы хлебных крошек в верхней части страницы. Нажмите e157b1359c3edc06.png значок, чтобы скопировать путь реестра в буфер обмена.

a9b0fa44c37e0178.png

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

«us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab» скопирован.

Вернитесь в облачную оболочку. Запустите команду skaffold config set default-repo со значением, которое вы только что скопировали с панели управления.

skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab

Вывод команды

set value default-repo to us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab for context gke_stackdriver-sandbox-3438851889_us-central1-b_stackdriver-sandbox

Кроме того, вам необходимо настроить реестр в соответствии с конфигурацией Docker. Выполните следующую команду:

gcloud auth configure-docker us-central1-docker.pkg.dev --quiet

Вывод команды

{
  "credHelpers": {
    "gcr.io": "gcloud",
    "us.gcr.io": "gcloud",
    "eu.gcr.io": "gcloud",
    "asia.gcr.io": "gcloud",
    "staging-k8s.gcr.io": "gcloud",
    "marketplace.gcr.io": "gcloud",
    "us-central1-docker.pkg.dev": "gcloud"
  }
}
Adding credentials for: us-central1-docker.pkg.dev

Теперь можно перейти к следующему шагу — настройке контейнера Kubernetes в GKE.

Краткое содержание

На этом этапе вы настраиваете среду кодовой лаборатории:

  • Настройте Cloud Shell
  • Создан репозиторий Artifact Registy для реестра контейнеров.
  • Настройте skaffold для использования реестра контейнеров.
  • Создан кластер Kubernetes, в котором работают микросервисы Codelab.

Дальше

На следующем этапе вы создадите, отправите и развернете свои микросервисы в кластере.

3. Создавайте, распространяйте и развертывайте микросервисы.

Загрузите материал codelab

На предыдущем шаге мы создали все необходимые условия для этой лаборатории кода. Теперь вы готовы запускать поверх них целые микросервисы. Материалы Codelab размещены на GitHub, поэтому загрузите их в среду Cloud Shell с помощью следующей команды git.

cd ~
git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git

Структура каталогов проекта следующая:

shakesapp-python
├── LICENSE
├── manifests
│   ├── client.yaml
│   ├── loadgen.yaml
│   └── server.yaml
├── proto
│   └── shakesapp.proto
├── skaffold.yaml
└── src
    ├── client
    ├── loadgen
    └── server
  • манифесты: файлы манифеста Kubernetes.
  • proto: определение протокола для связи между клиентом и сервером.
  • src: каталоги с исходным кодом каждого сервиса.
  • skaffold.yaml: файл конфигурации для skaffold.

Запустить команду скаффолда

Наконец, вы готовы собирать, отправлять и развертывать весь контент в только что созданном кластере Kubernetes. Кажется, что это несколько шагов, но на самом деле skaffold делает все за вас. Давайте попробуем это с помощью следующей команды:

cd shakesapp-python
skaffold run --tail

Как только вы запустите команду, вы увидите выходные данные журнала docker build и сможете подтвердить, что они успешно отправлены в реестр.

Вывод команды

...
---> Running in c39b3ea8692b
 ---> 90932a583ab6
Successfully built 90932a583ab6
Successfully tagged us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step1
The push refers to repository [us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice]
cc8f5a05df4a: Preparing
5bf719419ee2: Preparing
2901929ad341: Preparing
88d9943798ba: Preparing
b0fdf826a39a: Preparing
3c9c1e0b1647: Preparing
f3427ce9393d: Preparing
14a1ca976738: Preparing
f3427ce9393d: Waiting
14a1ca976738: Waiting
3c9c1e0b1647: Waiting
b0fdf826a39a: Layer already exists
88d9943798ba: Layer already exists
f3427ce9393d: Layer already exists
3c9c1e0b1647: Layer already exists
14a1ca976738: Layer already exists
2901929ad341: Pushed
5bf719419ee2: Pushed
cc8f5a05df4a: Pushed
step1: digest: sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe size: 2001

После отправки всех сервисных контейнеров развертывание Kubernetes запускается автоматически.

Вывод команды

sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 size: 1997
Tags used in deployment:
 - serverservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step4@sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe
 - clientservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/clientservice:step4@sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8
 - loadgen -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/loadgen:step4@sha256:eea2e5bc8463ecf886f958a86906cab896e9e2e380a0eb143deaeaca40f7888a
Starting deploy...
 - deployment.apps/clientservice created
 - service/clientservice created
 - deployment.apps/loadgen created
 - deployment.apps/serverservice created
 - service/serverservice created

Внимание ! Если вы получаете сообщение об ошибке типа «Нет принудительного доступа к указанному репозиторию изображений», проверьте, пытается ли команда skaffold отправить изображения в Docker Hub (docker.io) независимо от вашей конфигурации в репозитории по умолчанию в skaffold. В этом случае попробуйте добавить параметр «–default-repo» к «запуску скаффолда», как показано ниже.

$ skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[ID проекта]/[имя репозитория]

После развертывания вы увидите фактические журналы приложений, отправляемые на стандартный вывод в каждом контейнере, например:

Вывод команды

[server] {"event": "starting server: 0.0.0.0:5050", "severity": "info", "timestamp": "2021-03-17T05:25:56.758575Z"}
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Starting gunicorn 20.0.4
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Listening at: http://0.0.0.0:8080 (1)
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Using worker: threads
[client] [2021-03-17 05:25:54 +0000] [7] [INFO] Booting worker with pid: 7
[client] {"event": "server address is serverservice:5050", "severity": "info", "timestamp": "2021-03-17T05:25:54.888627Z"}
[client] {"event": "request to server with query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.550923Z"}
[server] {"event": "query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.567048Z"}
[loadgen] {"event": "check connectivity: http://clientservice:8080/_healthz", "severity": "info", "timestamp": "2021-03-17T05:26:11.533605Z"}
[loadgen] {"event": "/_healthz response: ok", "severity": "info", "timestamp": "2021-03-17T05:26:11.544267Z"}
[loadgen] {"event": "confirmed connection ot clientservice", "severity": "info", "timestamp": "2021-03-17T05:26:11.544527Z"}

Наконец, вы готовы приступить к оснащению своего приложения OpenTelemetry для распределенной трассировки служб.

Краткое содержание

На этом этапе вы подготовили материал codelab в своей среде и подтвердили ожидаемое выполнение скаффолда.

Дальше

На следующем шаге вы измените исходный код службы loadgen для инструментирования информации трассировки.

4. Инструментарий для HTTP

Концепция инструментирования и распространения трассировки

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

c8c659deaa9c9091.png

В этом примере мы используем код для экспорта информации Trace и Span в Cloud Trace и распространения контекста трассировки по запросу от службы Loadgen к серверной службе.

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

OpenTelemetry поможет вам:

  • для создания уникального идентификатора трассировки и идентификатора диапазона
  • для экспорта идентификатора трассировки и идентификатора диапазона на серверную часть
  • для распространения контекстов трассировки на другие службы

Первый диапазон прибора

Сервис генератора инструментальной нагрузки

Откройте редактор Cloud Shell, нажав кнопку 776a11bfb2122549.png в правом верхнем углу Cloud Shell. Откройте src/loadgen/loadgen.py из проводника на левой панели и найдите main функцию.

src/loadgen/loadgen.py

def main():
    ...
    # start request loop to client service
    logger.info("start client request loop")
    addr = f"http://{target}"
    while True:
        logger.info("start request to client")
        call_client(addr)
        logger.info("end request to client")
        time.sleep(2.0)

В main функции вы видите цикл, вызывающий в нем функцию call_client . В текущей реализации сектоин имеет 2 строки журнала, в которых фиксируется начало и окончание вызова функции. Теперь давайте инструментируем информацию Span для отслеживания задержки вызова функции.

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

 import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.instrumentation.requests import RequestsInstrumentor
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator

Поскольку генератор нагрузки вызывает клиентское приложение по HTTP через модуль requests , мы используем пакет расширения для requests и включаем инструментирование.

 from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()

Затем настройте экземпляр Tracer, который обрабатывает Trace Contenxt и настройки экспортера.

     target = os.environ.get("CLIENT_ADDR", "0.0.0.0:8080")

+    exporter = CloudTraceSpanExporter()
+    trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+    tracer = trace.get_tracer(__name__)
+    propagate.set_global_textmap(CloudTraceFormatPropagator())
+    trace.set_tracer_provider(TracerProvider())
+
     # connectivity check to client service
     healthz = f"http://{target}/_healthz"
     logger.info(f"check connectivity: {healthz}")

Обратите внимание: поскольку это лабораторная работа, позволяющая понять, как работает инструментарий трассировки, мы настраиваем Tracer для записи каждого отдельного запроса и отправки его на серверную часть. ( SimpleSpanProcessor() ) Это не подходит для производственных сред, поэтому обязательно измените эту часть при инструментировании рабочего приложения.

Теперь вы можете инструментировать промежутки с помощью Tracer. Дело в том, что вам нужно явно сгенерировать Span, и все! Хотя есть две строки, которые добавляют метаданные событий в Span, вам не нужно вручную генерировать уникальные идентификаторы Trace ID и Span ID и встраивать их в Span.

     logger.info("start client request loop")
     addr = f"http://{target}"
     while True:
-        logger.info("start request to client")
-        call_client(addr)
-        logger.info("end request to client")
+        with tracer.start_as_current_span("loadgen") as root_span:
+            root_span.add_event(name="request_start")
+            logger.info("start request to client")
+            call_client(addr)
+            root_span.add_event(name="request_end")
+            logger.info("end request to client")
         time.sleep(2.0)

Чтобы сборка Docker извлекла необходимые пакеты OpenTelemetry, выполните следующую команду:

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-requests=^0.20b0"

Вы можете убедиться, что соответствующее описание зависимости записано в pyproject.toml .

Клиентское обслуживание инструментов

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

ae074d4513c9931f.png

Откройте редактор Cloud Shell и добавьте необходимые модули, как мы это сделали для службы генератора нагрузки.

источник/клиент/client.py

 import flask
 import grpc
 import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import \
+    CloudTraceFormatPropagator

 import shakesapp_pb2
 import shakesapp_pb2_grpc

Вы заметили, что только что импортировали FlaskInstrumentor , который позволяет автоматизировать инструментирование приложения Flask от имени пользователей для извлечения заголовков HTTP для получения контекстов трассировки с помощью одной строки кода. Сообщество OpenTelemetry предоставляет аналогичные полезные интеграции с другими крупными библиотеками. Для получения дополнительной информации вы можете обратиться к официальной документации .

 app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)

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

 logger.info(f"server address is {SERVER_ADDR}")

+exporter = CloudTraceSpanExporter()
+trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+propagate.set_global_textmap(CloudTraceFormatPropagator())
+trace.set_tracer_provider(TracerProvider())

 @app.route("/")
 def main_handler():
    ....

Теперь все готово для добавления инструментов в обработчик. Найдите main_handler() и измените часть, которая отправляет запрос gRPC службе сервера.

@app.route("/")
def main_handler():
    q, count = random.choice(list(queries.items()))

    # get Tracer
    tracer = trace.get_tracer(__name__)

    with tracer.start_as_current_span("client") as cur_span:
        channel = grpc.insecure_channel(SERVER_ADDR)
        stub = shakesapp_pb2_grpc.ShakespeareServiceStub(channel)
        logger.info(f"request to server with query: {q}")
        cur_span.add_event("server_call_start")
        resp = stub.GetMatchCount(shakesapp_pb2.ShakespeareRequest(query=q))
        cur_span.add_event("server_call_end")
        if count != resp.match_count:
            raise UnexpectedResultError(
                f"The expected count for '{q}' was {count}, but result was {resp.match_count } obtained"
            )
        result = str(resp.match_count)
        logger.info(f"matched count for '{q}' is {result}")
    return result

Аналогично службе генератора загрузки добавьте необходимые пакеты в pyproject.toml с помощью следующей команды.

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-flask=^0.20b0"

Затем попробуйте запустить приложение с помощью команды skaffold run и посмотрите, что показывает панель управления Cloud Trace:

skaffold run --tail

После просмотра некоторых сообщений о сборке, отправке и развертывании вы увидите журналы приложений в форматах JSON. Перейдите в Cloud Trace > Список трассировки, чтобы проверить, получаете ли вы информацию о трассировке. Поскольку служба генератора нагрузки периодически отправляет запросы клиентской службе, а вы включили трассировку для всех запросов, вы начинаете видеть много точек в списке трассировки.

f7440360551980e.png

Нажав на один из них, вы увидите каскадный график, подобный приведенному ниже, который объясняет задержку каждой части процесса запроса и ответа. Установите флажок рядом с «Показать события», после чего вы получите аннотации внутри каскадного графика. Эти аннотации — это те, которые вы добавили в код с помощью метода span.add_event() .

67596a4a313738.png

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

Краткое содержание

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

Дальше

На следующем этапе вы будете инструментировать клиентскую и серверную службы, чтобы подтвердить, как распространять контекст трассировки через gRPC.

5. Инструментарий для gRPC

На предыдущем шаге мы инструментировали первую половину запроса в этом микросервисе. На этом этапе мы пытаемся реализовать связь gRPC между службой клиента и службой сервера. (Зелено-фиолетовый прямоугольник на картинке ниже)

c4dec3e741c3ab4f.png

Автоматическое инструментирование для клиента gRPC

Экосистема OpenTelemetry предлагает множество удобных библиотек, которые помогают разработчикам инструментировать приложения. На предыдущем шаге мы использовали автоматическое инструментирование для модуля «запросы». На этом этапе, когда мы пытаемся распространить контекст трассировки через gRPC, мы используем для этого библиотеку.

источник/клиент/client.py

 import flask
 import grpc
 import structlog
 from opentelemetry import propagate, trace
 from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
 from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient
 from opentelemetry.sdk.trace import TracerProvider
 from opentelemetry.sdk.trace.export import SimpleSpanProcessor
 from opentelemetry.propagators.cloud_trace_propagator import \
     CloudTraceFormatPropagator
 import shakesapp_pb2
 import shakesapp_pb2_grpc


 app = flask.Flask(__name__)
 FlaskInstrumentor().instrument_app(app)
+GrpcInstrumentorClient().instrument()

Для обслуживания клиентов нам нужно сделать довольно мало инструментов. Мы хотим распространить контекст трассировки, который представляет собой комбинацию идентификатора трассировки и идентификатора диапазона текущего диапазона, через gRPC. Поэтому мы вызываем GrpcInstrumentatorClient.instrument() , чтобы клиент gRPC в функции-обработчике мог встроить контекст трассировки в HTTP-заголовок ниже.

Обязательно добавьте новые зависимости в pyproject.toml с помощью команды poetry add :

poetry add "opentelemetry-instrumentation-grpc=^0.20b0"

Автоматическое оснащение сервера gRPC

Как и в случае с клиентом gRPC, мы вызываем автоматическое инструментирование для сервера gRPC. Добавьте импорт, как показано ниже, и вызовите GrpcInstrumentationServer().instrument() в верхней части файла.

Внимание : обязательно позвоните.

GrpcInstrumentationServe() 

на этом этапе не

GrpcInstrumentationClient()

.

источник/сервер/server.py

 import grpc
 import structlog
 from google.cloud import storage
 from grpc_health.v1 import health_pb2, health_pb2_grpc
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator

 import shakesapp_pb2
 import shakesapp_pb2_grpc


 BUCKET_NAME = "dataflow-samples"
 BUCKET_PREFIX = "shakespeare/"

+# enable auto gRPC server trace instrumentation
+GrpcInstrumentorServer().instrument()
+

Затем вы добавите экспортер для отправки информации трассировки в серверную часть Cloud Trace. Добавьте следующий код в функцию serve() .

def serve():
+    # start trace exporter
+    trace.set_tracer_provider(TracerProvider())
+    trace.get_tracer_provider().add_span_processor(
+        SimpleSpanProcessor(CloudTraceSpanExporter())
+    )
+    propagators.set_global_textmap(CloudTraceFormatPropagator())
+
+    # add gRPC services to server
     server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
     service = ShakesappService()
     shakesapp_pb2_grpc.add_ShakespeareServiceServicer_to_server(service, server)
     health_pb2_grpc.add_HealthServicer_to_server(service, server)

Обязательно добавьте новые пакеты в службу сервера.

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation=^0.20b0"

Запустите микросервис и подтвердите трассировку.

Затем запустите измененный код с помощью команды skaffold.

skaffold run --tail

Теперь вы снова видите кучу трассировок на странице списка трассировок Cloud Trace. Щелкните одну из трассировок, и теперь вы обнаружите, что она охватывает весь запрос от службы генератора нагрузки к службе сервера.

141cb620245b689d.png

Краткое содержание

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

6. Поздравления

Вы успешно создали распределенные трассировки с помощью OpenTelemery и подтвердили задержки запросов в микросервисе в Google Cloud Trace.

Для расширенных упражнений вы можете самостоятельно попробовать следующие темы.

  • Текущая реализация отправляет все промежутки, созданные в результате проверки работоспособности. Как отфильтровать эти промежутки из Cloud Traces? Подсказка здесь .
  • Сопоставьте журналы событий с интервалами и посмотрите, как это работает в Google Cloud Trace и Google Cloud Logging. Подсказка здесь .
  • Замените какой-либо сервис сервисом на другом языке и попробуйте оснастить его OpenTelemetry для этого языка.

Внимание : Google Kubernetes Engine и Google Artifact Registry постоянно потребляют этот ресурс.

Очистить

После этой лабораторной работы остановите кластер Kubernetes и обязательно удалите проект, чтобы не получить неожиданные расходы на Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry.

Сначала удалите кластер с помощью следующей команды:

skaffold delete

Вывод команды

Cleaning up...
 - deployment.apps "clientservice" deleted
 - service "clientservice" deleted
 - deployment.apps "loadgen" deleted
 - deployment.apps "serverservice" deleted
 - service "serverservice" deleted

После удаления кластера в панели меню выберите «IAM и администратор» > «Настройки», а затем нажмите кнопку «ЗАВЕРШИТЬ».

578ca2b72a161e9d.png

Затем введите идентификатор проекта (а не имя проекта) в форму в диалоговом окне и подтвердите закрытие.