1. Introducción
Última actualización: 5/3/2021
Observabilidad de la aplicación
Observabilidad y OpenTelemetry
Observabilidad es el término que se usa para describir un atributo de un sistema. Un sistema con observabilidad permite a los equipos depurar activamente su sistema. En ese contexto, tres pilares de observabilidad: los registros, las métricas y los seguimientos son la instrumentación fundamental para que el sistema adquiera observabilidad.
OpenTelemetry es un conjunto de especificaciones y SDKs que aceleran la instrumentación y la exportación de datos de telemetría (registros, métricas y seguimientos) que requiere la observabilidad. OpenTelemetry es un proyecto de estándar abierto y impulsado por la comunidad bajo la CNCF. Con el uso de las bibliotecas que proporcionan el proyecto y su ecosistema, los desarrolladores pueden instrumentar sus aplicaciones de manera independiente del proveedor y en función de múltiples arquitecturas.
Seguimiento distribuido
Entre registros, métricas y seguimientos, Trace es la telemetría que indica la latencia de una parte específica del proceso en el sistema. Especialmente en la era de los microservicios, el seguimiento distribuido es el fuerte controlador para descubrir cuellos de botella de latencia en el sistema distribuido en general.
Cuando se analizan seguimientos distribuidos, la visualización de datos de seguimiento es la clave para captar las latencias generales del sistema de un vistazo. En el seguimiento distribuido, manejamos un conjunto de llamadas para procesar una sola solicitud al punto de entrada del sistema en forma de seguimiento que contiene varios intervalos.
Un intervalo representa una unidad de trabajo individual que se realiza en un sistema distribuido y que registra los tiempos de inicio y finalización. Los intervalos suelen tener relaciones jerárquicas entre sí. En la imagen que aparece a continuación, todos los intervalos más pequeños son intervalos secundarios de un intervalo /messages grande y se ensamblan en un solo seguimiento que muestra la ruta del trabajo a través de un sistema.
Google Cloud Trace es una de las opciones de backend de seguimiento distribuido y está bien integrado a otros productos de Google Cloud.
Qué compilarás
En este codelab, instrumentarás la información de seguimiento en los servicios llamados "Shakesapp". que se ejecuta en un clúster de Kubernetes que se ejecuta en Google Kubernetes Engine. A continuación, se describe la arquitectura de Shakesapp:
- Los clientes envían una cadena de consulta al servidor
- El servidor acepta la consulta del cliente, recupera todos los trabajos de Shakespare en formato de texto de Google Cloud Storage, busca en las líneas que contienen la consulta y muestra el número de la línea que coincidió con el cliente.
instrumentarás la información de seguimiento en toda la solicitud.
Qué aprenderás
- Cómo comenzar a usar las bibliotecas de seguimiento de OpenTelemetry en un proyecto de Python
- Cómo crear un intervalo con la biblioteca
- Cómo propagar contextos de intervalos entre los componentes de una app
- Cómo enviar datos de seguimiento a Google Cloud Trace
- Cómo analizar el seguimiento en Google Cloud Trace
En este codelab, se explica cómo instrumentar tus microservicios. Para facilitar la comprensión, este ejemplo solo contiene 3 componentes (generador de cargas, cliente y servidor), pero puedes aplicar el mismo proceso que se explica en este codelab en sistemas más grandes y complejos.
Requisitos
- Conocimiento de Python 3
2. Configuración y requisitos
Configuración del entorno de autoaprendizaje
Si aún no tienes una Cuenta de Google (Gmail o Google Apps), debes crear una. Accede a Google Cloud Platform Console (console.cloud.google.com) y crea un proyecto nuevo.
Si ya tienes un proyecto, haz clic en el menú desplegable de selección de proyectos en la parte superior izquierda de la Console:
y haz clic en el botón “PROYECTO NUEVO” en el diálogo resultante para crear un proyecto nuevo:
Si aún no tienes un proyecto, deberías ver un cuadro de diálogo como este para crear el primero:
El cuadro de diálogo de creación posterior del proyecto te permite ingresar los detalles de tu proyecto nuevo:
Recuerda el ID del proyecto, que es un nombre único en todos los proyectos de Google Cloud (el nombre anterior ya se encuentra en uso y no lo podrá usar). Se mencionará más adelante en este codelab como PROJECT_ID.
A continuación, si aún no lo hiciste, deberás habilitar la facturación en Developers Console para usar los recursos de Google Cloud y habilitar la API de Cloud Trace.
Ejecutar este codelab debería costar solo unos pocos dólares, pero su costo podría aumentar si decides usar más recursos o si los dejas en ejecución (consulta la sección “Limpiar” al final de este documento). Los precios de Google Cloud Trace, Google Kubernetes Engine y Google Artifacat Registry se indican en la documentación oficial.
- Precios de Google Cloud Observability
- Precios | Documentación de Kubernetes Engine
- Precios de Artifact Registry | Documentación de Artifact Registry
Los usuarios nuevos de Google Cloud Platform están aptas para obtener una prueba gratuita de $300, por lo que este codelab es completamente gratuito.
Configuración de Google Cloud Shell
Si bien Google Cloud y Google Cloud Trace se pueden operar de forma remota desde tu laptop, en este codelab usaremos Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.
Esta máquina virtual basada en Debian está cargada con todas las herramientas de desarrollo que necesitarás. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Esto significa que todo lo que necesitarás para este Codelab es un navegador (sí, funciona en una Chromebook).
Para activar Cloud Shell desde la consola de Cloud, simplemente haz clic en Activar Cloud Shell (el aprovisionamiento y la conexión al entorno debería tardar solo unos momentos).
Una vez conectado a Cloud Shell, debería ver que ya se autenticó y que el proyecto ya se configuró con tu PROJECT_ID
:
gcloud auth list
Resultado del comando
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Resultado del comando
[core] project = <PROJECT_ID>
Si, por algún motivo, el proyecto no está configurado, solo emite el siguiente comando:
gcloud config set project <PROJECT_ID>
Si no conoce su PROJECT_ID
, Observa el ID que usaste en los pasos de configuración o búscalo en el panel de la consola de Cloud:
Cloud Shell también configura algunas variables de entorno de forma predeterminada, lo que puede resultar útil cuando ejecutas comandos futuros.
echo $GOOGLE_CLOUD_PROJECT
Salida de comando
<PROJECT_ID>
Establece la zona predeterminada y la configuración del proyecto.
gcloud config set compute/zone us-central1-f
Puedes elegir una variedad de zonas diferentes. Para obtener más información, consulta Regiones y zonas.
Configuración de Python
En este codelab, usamos "poesía" de administrar estrictamente las versiones de paquetes. Ejecuta el siguiente comando en Cloud Shell:
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 - source $HOME/.poetry/env
Configura un clúster de Google Kubernetes
En este codelab, ejecutarás un clúster de microservicios en Google Kubernetes Engine (GKE). El proceso de este codelab es el siguiente:
- Descarga el proyecto de referencia en Cloud Shell
- Compila microservicios en contenedores
- Sube contenedores a Google Artifact Registry (GAR)
- Implementa contenedores en GKE
- Modifica el código fuente de los servicios para la instrumentación de seguimiento
- Ir al paso 2
Habilitar Kubernetes Engine
Primero, configuramos un clúster de Kubernetes en el que Shakesapp se ejecuta en GKE, así que debemos habilitar GKE. Navega al menú “Kubernetes Engine”. y presiona el botón HABILITAR.
Ya está todo listo para crear un clúster de Kubernetes.
Crea un clúster de Kubernetes
En Cloud Shell, ejecuta el siguiente comando para crear un clúster de Kubernetes. Confirma que el valor de la zona esté debajo de la región que usaste para crear el repositorio de Artifact Registry. Cambia el valor de zona us-central1-f
si la región de tu repositorio no cubre la zona.
gcloud container clusters create otel-trace-codelab --zone us-central1-f \ --num-nodes 1 \ --machine-type e2-highcpu-4
Resultado del comando
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
Configuración de Artifact Registry y Skaffold
Ahora tenemos un clúster de Kubernetes listo para implementar. A continuación, nos prepararemos para un registro de contenedores para implementar y enviar contenedores. En este paso, debemos configurar GAR y Skaffold para usarlos.
Configuración de Artifact Registry
Navega al menú de “Artifact Registry” y presiona el botón HABILITAR.
Después de un momento, verás el navegador del repositorio de GAR. Haz clic en “CREAR REPOSITORIO”. e ingresa el nombre del repositorio.
En este codelab, asignaré el nombre trace-codelab
al nuevo repositorio. El formato del artefacto es “Docker” y el tipo de ubicación es "Región". Elige una región cercana a la que estableciste para la zona predeterminada de Google Compute Engine. Por ejemplo, este ejemplo eligió “us-central1-f” arriba, así que aquí elegimos "us-central1 (Iowa)". Luego, haz clic en "CREATE" .
Ahora verás "trace-codelab" en el navegador del repositorio.
Regresaremos más adelante para verificar la ruta de registro.
Configuración de Skaffold
Skaffold es una herramienta útil cuando trabajas en la compilación de microservicios y ejecución en Kubernetes. Controla el flujo de trabajo de compilación, envío e implementación de contenedores de aplicaciones con un conjunto pequeño de comandos. De forma predeterminada, Skaffold usa Docker Registry como registro de contenedores, por lo que debes configurar Skaffold para que reconozca GAR cuando se envían contenedores.
Vuelve a abrir Cloud Shell y confirma si Skaffold está instalado. (Cloud Shell instala Skaffold en el entorno de forma predeterminada). Ejecuta el siguiente comando y consulta la versión de Skaffold.
skaffold version
Resultado del comando
v1.20.0
Ahora, puedes registrar el repositorio predeterminado para que lo use Skaffold. Para obtener la ruta de acceso del registro, navega hasta el panel de Artifact Registry y haz clic en el nombre del repositorio que acabas de configurar en el paso anterior.
Luego, verás los recorridos de las rutas de navegación en la parte superior de la página. Haz clic en el ícono para copiar la ruta de registro en el portapapeles.
Cuando hagas clic en el botón de copiar, verás un diálogo en la parte inferior del navegador con el siguiente mensaje:
"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" se copió
Regresa a Cloud Shell. Ejecuta el comando skaffold config set default-repo
con el valor que acabas de copiar del panel.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
Resultado del comando
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
Además, debes establecer el registro en la configuración de Docker. Ejecuta el siguiente comando:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
Resultado del comando
{ "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
Ya está todo listo para el próximo paso que te permitirá configurar un contenedor de Kubernetes en GKE.
Resumen
En este paso, configurarás el entorno de tu codelab:
- Configura Cloud Shell
- Creó un repositorio de Artifact Registy para Container Registry
- Configura Skaffold para usar Container Registry
- Creaste un clúster de Kubernetes en el que se ejecutan los microservicios del codelab.
Cuál es el próximo paso
En el siguiente paso, compilarás, enviarás y, luego, implementarás tus microservicios en el clúster
3. Compila, envía e implementa los microservicios
Descarga el material del codelab
En el paso anterior, configuramos todos los requisitos previos para este codelab. Ahora está todo listo para ejecutar microservicios completos sobre ellos. El material del codelab está alojado en GitHub, así que descárgalo en el entorno de Cloud Shell con el siguiente comando de Git.
cd ~ git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git
La estructura de directorios del proyecto es la siguiente:
shakesapp-python ├── LICENSE ├── manifests │ ├── client.yaml │ ├── loadgen.yaml │ └── server.yaml ├── proto │ └── shakesapp.proto ├── skaffold.yaml └── src ├── client ├── loadgen └── server
- Manifiestos: Archivos de manifiesto de Kubernetes
- proto: definición de proto para la comunicación entre el cliente y el servidor
- src: Directorios para el código fuente de cada servicio
- skaffold.yaml: Archivo de configuración de Skaffold
Ejecuta el comando de Skaffold
Por último, estarás listo para compilar, enviar e implementar todo el contenido en el clúster de Kubernetes que acabas de crear. Parece que contiene varios pasos, pero Skaffold hace todo por ti. Probemos eso con el siguiente comando:
cd shakesapp-python skaffold run --tail
En cuanto ejecutes el comando, verás el resultado del registro de docker build
y podrás confirmar que se enviaron correctamente al registro.
Resultado del comando
... ---> 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
Después de enviar todos los contenedores de servicio, las implementaciones de Kubernetes se inician automáticamente.
Resultado del comando
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
Precaución: Si ves el error “No push access to specified image repository”, verifica si el comando de skaffold está intentando enviar imágenes a Docker Hub (docker.io), independientemente de tu configuración en el repositorio predeterminado de Skaffold. En ese caso, intenta agregar “–default-repo”. la opción para ejecutar Skaffold como se muestra a continuación.
$ Skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[ID del proyecto]/[nombre del repositorio]
Después de la implementación, verás los registros de aplicación reales emitidos a stdout en cada contenedor de la siguiente manera:
Resultado del comando
[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"}
Por último, está todo listo para comenzar a instrumentar tu aplicación con OpenTelemetry a fin de realizar un seguimiento distribuido de los servicios.
Resumen
En este paso, preparaste el material del codelab en tu entorno y confirmaste que Skaffold se ejecuta como se esperaba.
Cuál es el próximo paso
En el siguiente paso, modificarás el código fuente del servicio loadgen para instrumentar la información de seguimiento.
4. Instrumentación para HTTP
Concepto de instrumentación y propagación de seguimiento
Antes de editar el código fuente, permíteme explicarte brevemente cómo funcionan los seguimientos distribuidos en un diagrama sencillo.
En este ejemplo, instrumentamos el código para exportar información de Trace y Span a Cloud Trace y propagar el contexto de seguimiento en la solicitud desde el servicio loadgen hasta el servicio del servidor.
La aplicación debe enviar metadatos de Trace, como el ID de seguimiento y el ID de intervalo, para que Cloud Trace ensambla todos los intervalos que tienen el mismo ID de Trace en un solo seguimiento. Además, la aplicación debe propagar contextos de seguimiento (la combinación del ID de seguimiento y el ID de intervalo del intervalo superior) cuando se solicitan servicios downstream, para que puedan saber qué contexto de seguimiento están manejando.
OpenTelemetry te ayuda a hacer lo siguiente:
- para generar un ID de seguimiento y un ID de intervalo únicos
- para exportar el ID de seguimiento y el ID de intervalo al backend
- para propagar contextos de seguimiento a otros servicios
Primer intervalo del instrumento
Servicio de generador de cargas de instrumentos
Para abrir el editor de Cloud Shell, presiona el botón ubicado en la parte superior derecha de Cloud Shell. Abre
src/loadgen/loadgen.py
desde el explorador en el panel izquierdo y busca la función 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)
En la función main
, verás el bucle que llama a la función call_client
. En la implementación actual, la sección tiene 2 líneas de registro que registran el comienzo y el final de la llamada a función. Ahora instrumentaremos la información del intervalo para hacer un seguimiento de la latencia de la llamada a función.
Primero, debes crear un intervalo con un ID de seguimiento y un ID de intervalo únicos. OpenTelemetry proporciona una biblioteca práctica para ello. Agrega las siguientes líneas para importar bibliotecas de OpenTelemetry a tu código.
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
Debido a que el generador de cargas llama a la aplicación cliente en HTTP a través del módulo requests
, usamos el paquete de extensión para requests
y habilitamos la instrumentación.
from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()
Luego, configura la instancia de Tracer que se encarga de la configuración de Trace Contenxt y del exportador.
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}")
Ten en cuenta que, como este es un codelab para comprender cómo funciona la instrumentación de seguimiento, configuramos Tracer para que registre cada solicitud y las envíe al backend. (SimpleSpanProcessor()
) Esto no es adecuado para entornos de producción, así que asegúrate de cambiar esta parte cuando instrumentes tu aplicación de producción.
Ahora puedes instrumentar intervalos con el rastreador. El punto aquí es que lo que debes hacer es generar un Span de manera explícita, ¡y eso es todo! Aunque existen dos líneas que agregan metadatos de eventos al intervalo, no es necesario generar un ID de seguimiento y un ID de intervalo únicos de forma manual y, luego, incorporarlos al intervalo.
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)
Para que la compilación de Docker recupere los paquetes necesarios de OpenTelemetry, ejecuta el siguiente comando:
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-requests=^0.20b0"
Puedes confirmar que la descripción de la dependencia correspondiente esté escrita en pyproject.toml
.
Instrumenta el servicio de cliente
En la sección anterior, instrumentamos la parte delimitada en el rectángulo rojo en el siguiente dibujo. Implementamos la información de intervalo en el servicio del generador de cargas. De manera similar al servicio del generador de cargas, ahora debemos instrumentar el servicio del cliente. La diferencia del servicio de generador de cargas es que el servicio de cliente debe extraer la información del ID de Trace que se propaga del servicio de generador de cargas en el encabezado HTTP y usar el ID para generar intervalos.
Abre el editor de Cloud Shell y agrega los módulos requeridos, como hicimos con el servicio del generador de cargas.
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
Notaste que acabas de importar FlaskInstrumentor
, que habilita la instrumentación automática de la aplicación Flask, en nombre de los usuarios, para extraer encabezados HTTP y obtener contextos de seguimiento con una sola línea de código. La comunidad de OpenTelemetry proporciona integraciones útiles similares con otras bibliotecas importantes. Para obtener más información, puedes consultar la documentación oficial.
app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)
Antes de comenzar con la instrumentación, debe preparar la instancia Tracer de manera similar a como lo hicimos en el servicio del generador de cargas.
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():
....
Ahora está listo para agregar instrumentación en el controlador. Busca main_handler()
y modifica la parte que muestra la solicitud de gRPC al servicio del servidor.
@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
De manera similar al servicio de generador de cargas, agrega los paquetes requeridos a pyproject.toml
con el siguiente comando.
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-flask=^0.20b0"
Luego, intenta iniciar la aplicación con el comando skaffold run
y observa lo que muestra el panel de Cloud Trace:
skaffold run --tail
Después de ver algunos mensajes de compilación, implementación y envío, verás registros de aplicaciones en formatos JSON. Navega a Cloud Trace > Lista de seguimientos para verificar si obtienes la información de seguimiento. Debido a que el servicio de generador de cargas envía solicitudes al servicio de cliente de forma periódica y tú habilitaste los seguimientos para todas las solicitudes, comenzarás a ver muchos puntos en la lista de seguimiento.
Si haces clic en una de ellas, verás un gráfico de cascada como el de abajo que explica la latencia de cada parte durante el proceso de solicitud y respuesta. Busca la casilla de verificación junto a "Mostrar eventos" y, luego, obtendrás las anotaciones dentro del gráfico de cascada. Estas anotaciones son aquellas que instrumentaste en el código con el método span.add_event()
.
Es posible que notes que no ves los intervalos del servicio del servidor. Es correcta, ya que no instrumentamos los intervalos en el servicio del servidor.
Resumen
En este paso, instrumentaste el servicio del generador de cargas y el servicio al cliente, y confirmaste que pudiste propagar correctamente el contexto de seguimiento en todos los servicios y exportar la información del intervalo de ambos servicios a Cloud Trace.
Cuál es el próximo paso
En el siguiente paso, instrumentarás el servicio de cliente y el servicio del servidor para confirmar cómo propagar Trace Context a través de gRPC.
5. Instrumentación para gRPC
En el paso anterior, instrumentamos la primera mitad de la solicitud en estos microservicios. En este paso, intentamos instrumentar la comunicación de gRPC entre el servicio del cliente y el servicio del servidor. (Rectángulos verde y púrpura en la imagen de abajo)
Instrumentación automática para el cliente de gRPC
El ecosistema de OpenTelemetry ofrece una gran cantidad de bibliotecas prácticas que ayudan a los desarrolladores a instrumentar aplicaciones. En el paso anterior, usamos instrumentación automática para "solicitudes" módulo. En este paso, ya que intentamos propagar Trace Context a través de gRPC, usamos la biblioteca para ello.
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()
En cuanto al servicio al cliente, la instrumentación es bastante pequeña. Lo que queremos hacer es propagar el Contexto de seguimiento, que es la combinación del ID de seguimiento y el ID de intervalo del intervalo actual a través de gRPC. Por lo tanto, llamamos a GrpcInstrumentatorClient.instrument()
para que el cliente de gRPC en la función de traspaso pueda incorporar el contexto de seguimiento en el encabezado HTTP que está debajo.
Asegúrate de agregar dependencias nuevas a pyproject.toml
con el comando poetry add
:
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
Instrumentación automática para el servidor gRPC
Al igual que con el cliente de gRPC, llamamos instrumentación automática para el servidor de gRPC. Agrega importaciones, como seguimientos, y llama a GrpcInstrumentationServer().instrument()
en la parte superior del archivo.
Precaución: Asegúrate de llamar
GrpcInstrumentationServe()
en este paso, no
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()
+
A continuación, agregarás el exportador para enviar información de seguimiento al backend de Cloud Trace. Agrega el siguiente código a la función 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)
Asegúrate de agregar los paquetes agregados recientemente en el servicio de servidor.
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"
Ejecuta el microservicio y confirma el seguimiento
Luego, ejecuta el código modificado con el comando de Skaffold.
skaffold run --tail
Ahora, de nuevo, verás un montón de seguimientos en la página de lista de Trace de Cloud Trace. Haz clic en uno de los seguimientos y ahora verás que abarca la solicitud, desde el servicio del generador de cargas hasta el servicio del servidor.
Resumen
En este paso, instrumentaste la comunicación basada en gRPC con la compatibilidad de las bibliotecas del ecosistema de OpenTelemetry. Además, confirmaste que el contexto de seguimiento generado en el servicio de generador de cargas se entregó correctamente al servicio del servidor.
6. Felicitaciones
Creaste correctamente seguimientos distribuidos con OpenTelemery y confirmaste latencias de solicitud en el microservicio de Google Cloud Trace.
Para los ejercicios extendidos, puedes probar los siguientes temas por tu cuenta.
- La implementación actual envía todos los intervalos que genera la verificación de estado. ¿Cómo se filtran esos intervalos de Cloud Trace? Puedes ver una pista aquí.
- Correlaciona los registros de eventos con los intervalos y descubre cómo funcionan en Google Cloud Trace y Google Cloud Logging. Puedes ver una pista aquí.
- Reemplaza algún servicio por el que está en otro idioma y prueba instrumentarlo con OpenTelemetry para ese idioma
Precaución: Google Kubernetes Engine y Google Artifact Registry consumen el recurso constantemente.
Realiza una limpieza
Después de este codelab, detén el clúster de Kubernetes y asegúrate de borrar el proyecto para no recibir cargos inesperados de Google Kubernetes Engine, Google Cloud Trace o Google Artifact Registry.
Primero, borra el clúster con el siguiente comando:
skaffold delete
Resultado del comando
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Después de borrar el clúster, en el panel de menú, selecciona “IAM & Administrador > “Configuración” y, luego, haz clic en “APAGAR” .
Luego, ingresa el ID del proyecto (no el nombre del proyecto) en el formulario del diálogo y confirma el cierre.