1. Введение

Последнее обновление: 05.03.2021
Наблюдаемость приложения
Наблюдаемость и OpenTelemetry
Наблюдаемость — это термин, используемый для описания атрибута системы. Система, обладающая наблюдаемостью, позволяет командам активно отлаживать свою систему. В этом контексте три основных компонента наблюдаемости — журналы, метрики и трассировки — являются фундаментальными инструментами для обеспечения наблюдаемости системы.
OpenTelemetry — это набор спецификаций и SDK, ускоряющих сбор и экспорт телеметрических данных (журналов, метрик и трассировок), необходимых для обеспечения наблюдаемости. OpenTelemetry — это открытый стандарт и проект, управляемый сообществом в рамках CNCF. Используя библиотеки, предоставляемые проектом и его экосистемой, разработчики могут внедрять инструменты в свои приложения независимым от поставщика способом и для различных архитектур.
Распределенная трассировка
Среди логов, метрик и трассировок, трассировка — это телеметрия, которая показывает задержку конкретной части процесса в системе. Особенно в эпоху микросервисов распределенная трассировка является мощным инструментом для выявления узких мест задержки в распределенной системе в целом.
При анализе распределенных трассировок визуализация данных трассировки является ключом к быстрому пониманию общей задержки системы. В распределенной трассировке мы обрабатываем набор вызовов для выполнения одного запроса к точке входа в систему в виде трассировки, содержащей несколько сегментов (Span).
Спан представляет собой отдельную единицу работы, выполняемой в распределенной системе, с указанием времени начала и окончания. Спаны часто имеют иерархические связи друг с другом — на рисунке ниже все меньшие спаны являются дочерними спанами большого спана /messages и объединены в один трассировочный файл (Trace), показывающий путь работы в системе.

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

- Клиент отправляет на сервер строку запроса.
- Сервер принимает запрос от клиента, извлекает все произведения Шекспира в текстовом формате из Google Cloud Storage, ищет строки, содержащие запрос, и возвращает клиенту номер строки, которая совпала с запросом.
Вы будете собирать информацию о трассировке по всему запросу.
Что вы узнаете
- Как начать работу с библиотеками OpenTelemetry Trace в проекте Python
- Как создать элемент `<span>` с помощью библиотеки
- Как передавать контексты span между компонентами приложения по сети
- Как отправить данные трассировки в Google Cloud Trace
- Как анализировать трассировку в Google Cloud Trace
В этом практическом занятии объясняется, как инструментировать ваши микросервисы. Для простоты понимания этот пример содержит всего 3 компонента (генератор нагрузки, клиент и сервер), но вы можете применить тот же процесс, описанный в этом занятии, к более сложным и крупным системам.
Что вам понадобится
- Знание Python 3
2. Настройка и требования
Настройка среды для самостоятельного обучения
Если у вас еще нет учетной записи Google (Gmail или Google Apps), вам необходимо ее создать . Войдите в консоль Google Cloud Platform ( console.cloud.google.com ) и создайте новый проект.
Если у вас уже есть проект, щелкните раскрывающееся меню выбора проекта в левом верхнем углу консоли:

и нажмите кнопку «СОЗДАТЬ ПРОЕКТ» в появившемся диалоговом окне, чтобы создать новый проект:

Если у вас ещё нет проекта, вы увидите диалоговое окно, подобное этому, для создания вашего первого проекта:

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

Запомните идентификатор проекта (Project ID), который является уникальным именем для всех проектов Google Cloud (указанное выше имя уже занято и вам не подойдёт, извините!). В дальнейшем в этом практическом занятии он будет обозначаться как PROJECT_ID.
Далее, если вы еще этого не сделали, вам необходимо включить оплату в консоли разработчика, чтобы использовать ресурсы Google Cloud и активировать API Cloud Trace .

Выполнение этого практического задания не должно обойтись вам дороже нескольких долларов, но может обойтись дороже, если вы решите использовать больше ресурсов или оставите их запущенными (см. раздел «очистка» в конце этого документа). Цены на Google Cloud Trace, Google Kubernetes Engine и Google Artifacat Registry указаны в официальной документации.
- Цены на Google Cloud Observability
- Цены | Документация Kubernetes Engine
- Цены на реестр артефактов | Документация по реестру артефактов
Новые пользователи Google Cloud Platform могут воспользоваться бесплатной пробной версией стоимостью 300 долларов , что сделает этот практический семинар совершенно бесплатным.
Настройка Google Cloud Shell
Хотя Google Cloud и Google Cloud Trace можно запускать удаленно с ноутбука, в этом практическом занятии мы будем использовать Google Cloud Shell — среду командной строки, работающую в облаке.
Эта виртуальная машина на базе Debian содержит все необходимые инструменты разработки. Она предоставляет постоянный домашний каталог размером 5 ГБ и работает в облаке Google, что значительно повышает производительность сети и аутентификацию. Это означает, что для выполнения этого практического задания вам понадобится только браузер (да, он работает и на Chromebook).
Для активации Cloud Shell из консоли Cloud Console просто нажмите кнопку «Активировать Cloud Shell».
(Подготовка и подключение к среде займут всего несколько минут).


После подключения к 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 ? Проверьте, какой ID вы использовали на этапах настройки, или найдите его на панели управления Cloud Console:

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). Процесс выполнения этого практического занятия выглядит следующим образом:
- Загрузите базовый проект в Cloud Shell.
- Внедряйте микросервисы в контейнеры.
- Загрузите контейнеры в реестр артефактов Google (GAR).
- Развертывание контейнеров в GKE
- Измените исходный код сервисов для трассировочного мониторинга.
- Перейдите к шагу 2
Включить Kubernetes Engine
Сначала настроим кластер Kubernetes, в котором Shakesapp будет работать на GKE, поэтому нам нужно включить GKE. Перейдите в меню "Kubernetes Engine" и нажмите кнопку "Включить".

Теперь вы готовы создать кластер Kubernetes.
Создание кластера Kubernetes
В Cloud Shell выполните следующую команду для создания кластера Kubernetes. Убедитесь, что значение зоны находится в регионе , который вы использовали для создания репозитория Artifact Registry. Измените значение зоны 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
Настройка реестра артефактов и Skaffold.
Теперь у нас есть кластер Kubernetes, готовый к развертыванию. Далее мы подготовим реестр контейнеров для отправки и развертывания контейнеров. Для этого нам нужно настроить GAR и skaffold для его использования.
Настройка реестра артефактов
Перейдите в меню «Реестр артефактов» и нажмите кнопку «Включить».

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

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

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

Мы вернемся сюда позже, чтобы проверить путь в реестре.
установка строительных лесов
Skaffold — удобный инструмент при работе над созданием микросервисов, работающих на Kubernetes. Он управляет процессом сборки, отправки и развертывания контейнеров приложений с помощью небольшого набора команд. По умолчанию Skaffold использует Docker Registry в качестве реестра контейнеров, поэтому вам необходимо настроить Skaffold для распознавания GAR при отправке контейнеров.
Откройте Cloud Shell еще раз и убедитесь, что skaffold установлен. (Cloud Shell устанавливает skaffold в среду по умолчанию.) Выполните следующую команду, чтобы увидеть версию skaffold.
skaffold version
вывод команды
v1.20.0
Теперь вы можете зарегистрировать репозиторий по умолчанию для использования Skaffold. Чтобы получить путь к реестру, перейдите на панель управления Artifact Registry и щелкните имя репозитория, который вы только что настроили на предыдущем шаге.

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

При нажатии на кнопку копирования внизу браузера появится диалоговое окно с сообщением следующего вида:
"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 Registry для реестра контейнеров.
- Настройте Skaffold для использования реестра контейнеров.
- Создан кластер Kubernetes, в котором работают микросервисы из Codelab.
Далее
На следующем этапе вы создадите, отправите и развернете свои микросервисы в кластере.
3. Создайте, разверните и создайте микросервисы.
Скачайте материалы для практического занятия.
На предыдущем шаге мы подготовили все необходимые условия для этого практического занятия. Теперь вы готовы запустить на их основе целые микросервисы. Материалы для практического занятия размещены на 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
Выполните команду 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
Внимание : если вы получаете ошибку типа "No push access to specified image repository", проверьте, пытается ли команда skaffold отправить образы в Docker Hub (docker.io) независимо от вашей конфигурации репозитория по умолчанию в skaffold. В этом случае попробуйте добавить опцию "–default-repo" к команде "skaffold run", как показано ниже.
$ skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[project ID]/[repository name]
После развертывания вы увидите фактические логи приложения, выводимые в стандартный поток вывода каждого контейнера, примерно такого вида:
вывод команды
[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 для распределенной трассировки сервисов.
Краткое содержание
На этом этапе вы подготовили материалы для лабораторной работы в своей среде и подтвердили, что Skaffold работает должным образом.
Далее
На следующем шаге вы измените исходный код службы loadgen, чтобы добавить инструменты для обработки информации трассировки.
4. Инструментарий для HTTP
Концепция трассировочной аппаратуры и распространения
Прежде чем редактировать исходный код, позвольте мне кратко объяснить принцип работы распределенных трассировок на простой схеме.

В этом примере мы добавляем в код инструменты для экспорта информации о трассировке и сегментации в Cloud Trace и распространения контекста трассировки по запросу от службы генерации нагрузки к серверной службе.
Приложению необходимо отправлять метаданные трассировки, такие как идентификатор трассировки (Trace ID) и идентификатор сегмента (Span ID), чтобы Cloud Trace мог объединить все сегменты с одинаковым идентификатором трассировки в одну трассировку. Кроме того, приложению необходимо передавать контексты трассировки (комбинацию идентификатора трассировки и идентификатора сегмента родительского сегмента) при запросе к нижестоящим сервисам, чтобы они могли знать, какой контекст трассировки они обрабатывают.
OpenTelemetry поможет вам:
- для генерации уникальных идентификаторов трассировки (Trace ID) и диапазона (Span ID)
- экспортировать идентификаторы трассировки (Trace ID) и идентификаторы трассировки (Span ID) в бэкэнд.
- для распространения контекстов трассировки на другие сервисы
Инструментальный первый пролет
Обслуживание генераторов с измерительной нагрузкой
Откройте редактор Cloud Shell, нажав кнопку.
В правом верхнем углу 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 . В текущей реализации этот раздел содержит две строки лога, которые записывают начало и конец вызова функции. Теперь давайте добавим информацию Span для отслеживания задержки вызова функции.
Во-первых, вам нужно создать Span с уникальными идентификаторами трассировки (Trace ID) и Span ID. 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, который будет обрабатывать параметры содержимого трассировки и экспортера.
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}")
Обратите внимание, что поскольку это практическое занятие, призванное понять, как работает инструментирование трассировки, мы настраиваем трассировщик таким образом, чтобы он записывал каждый запрос и отправлял их на бэкэнд ( SimpleSpanProcessor() ). Это не подходит для производственных сред, поэтому обязательно измените эту часть при инструментировании вашего производственного приложения.
Теперь вы можете использовать трассировщик для добавления данных в Spans. Суть в том, что вам нужно всего лишь явно сгенерировать Span, и всё! Хотя есть две строки, которые добавляют метаданные события в Span, вам не нужно вручную генерировать уникальные идентификаторы трассировки и Span и встраивать их в 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 build загрузил необходимые пакеты 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 .
Обслуживание клиентов Instrument
В предыдущем разделе мы инструментировали часть, заключенную в красный прямоугольник на рисунке ниже. Мы инструментировали информацию о трассировке в службе генератора нагрузки. Аналогично службе генератора нагрузки, теперь нам необходимо инструментировать клиентскую службу. Отличие от службы генератора нагрузки заключается в том, что клиентская служба должна извлекать информацию об идентификаторе трассировки (Trace ID), передаваемую из службы генератора нагрузки в заголовке HTTP, и использовать этот идентификатор для генерации трассировок.

Откройте редактор Cloud Shell и добавьте необходимые модули, как мы это сделали для службы генератора нагрузки.
src/client/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)
Перед началом инструментирования, опять же, необходимо подготовить экземпляр трассировщика аналогично тому, как мы это делали в службе генератора нагрузки.
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 > Список трассировок, чтобы проверить, получаете ли вы информацию о трассировке. Поскольку служба генерации нагрузки периодически отправляет запросы в клиентскую службу, и вы включили трассировку для всех запросов, вы начнете видеть множество точек в списке трассировок.

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

Вы можете заметить, что не видите данные о состоянии сервера. Это правильно, потому что мы вообще не добавляли данные о состоянии сервера в систему мониторинга.
Краткое содержание
На этом этапе вы настроили службу генератора нагрузки и клиентскую службу, а также подтвердили возможность успешного распространения контекста трассировки между службами и экспорта информации о диапазоне трассировки из обеих служб в Cloud Trace.
Далее
На следующем этапе вы добавите инструменты для клиентской и серверной служб, чтобы подтвердить, как передавать контекст трассировки через gRPC.
5. Приборы для gRPC
На предыдущем этапе мы инструментировали первую половину запроса в этом микросервисе. На этом этапе мы пытаемся инструментировать gRPC-связь между клиентским и серверным сервисами. (Зеленый и фиолетовый прямоугольники на рисунке ниже)

Автоматическая инструментация для gRPC-клиента
Экосистема OpenTelemetry предлагает множество удобных библиотек, которые помогают разработчикам инструментировать приложения. На предыдущем этапе мы использовали автоматическую инструментацию для модуля "requests". На этом этапе, поскольку мы пытаемся передать контекст трассировки через gRPC, мы используем для этого соответствующую библиотеку.
src/client/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()
.
src/server/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. Щёлкните по одной из трассировок, и вы увидите, что она охватывает запрос от службы генератора нагрузки к серверной службе.

Краткое содержание
На этом этапе вы настроили связь на основе 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 и администрирование» > «Настройки», а затем нажмите кнопку «Выключить».

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