1. Introduction
Dans cet atelier de programmation, vous allez utiliser gRPC pour créer un client et un serveur qui constituent la base d'une application de mappage d'itinéraires écrite en Python.
À la fin de ce tutoriel, vous disposerez d'une application gRPC HelloWorld simple instrumentée avec le plug-in gRPC OpenTelemetry et vous pourrez afficher les métriques d'observabilité exportées dans Prometheus.
Points abordés
- Configurer le plug-in OpenTelemetry pour une application gRPC Python existante
- Exécuter une instance Prometheus locale
- Exporter des métriques vers Prometheus
- Afficher les métriques à partir du tableau de bord Prometheus
2. Avant de commencer
Ce dont vous avez besoin
- git
- curl
- build-essential
- Python 3.9 ou version ultérieure. Pour obtenir des instructions d'installation de Python spécifiques à la plate-forme, consultez Configuration et utilisation de Python. Vous pouvez également installer une version de Python non système à l'aide d'outils tels que uv ou pyenv.
- pip version 9.0.1 ou ultérieure pour installer des packages Python.
- venv pour créer des environnements virtuels Python.
Installez les prérequis :
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install -y git curl build-essential clang
sudo apt install python3
sudo apt install python3-pip python3-venv
Obtenir le code
Pour simplifier votre apprentissage, cet atelier de programmation propose une structure de code source prédéfinie pour vous aider à démarrer. Les étapes suivantes vous guideront dans l'instrumentation du plug-in gRPC OpenTelemetry dans une application.
grpc-codelabs
Le code source de la structure de cet atelier de programmation est disponible dans ce répertoire GitHub directory. Si vous préférez ne pas implémenter le code vous-même, le code source complet est disponible dans le répertoire completed.
Commencez par cloner le dépôt de l'atelier de programmation gRPC et accédez au dossier grpc-python-opentelemetry :
git clone -b v1 https://github.com/grpc-ecosystem/grpc-codelabs.git
cd grpc-codelabs/codelabs/grpc-python-opentelemetry/
Vous pouvez également télécharger le fichier .zip contenant uniquement le répertoire de l'atelier de programmation et le décompresser manuellement.
Commençons par créer un nouvel environnement virtuel Python (venv) pour isoler les dépendances de votre projet des packages système :
python3 -m venv --upgrade-deps .venv
Pour activer l'environnement virtuel dans le shell bash/zsh :
source .venv/bin/activate
Pour Windows et les shells non standards, consultez le tableau à l'adresse https://docs.python.org/3/library/venv.html#how-venvs-work.
Ensuite, installez les dépendances dans l'environnement à l'aide de la commande suivante :
python -m pip install -r requirements.txt
3. Enregistrer le plug-in OpenTelemetry
Nous avons besoin d'une application gRPC pour ajouter le plug-in gRPC OpenTelemetry. Dans cet atelier de programmation, nous allons utiliser un client et un serveur gRPC HelloWorld simples que nous allons instrumenter avec le plug-in gRPC OpenTelemetry.
La première étape consiste à enregistrer le plug-in OpenTelemetry configuré avec un exportateur Prometheus dans le client. Ouvrez start_here/observability_greeter_client.py avec votre éditeur préféré. Commencez par ajouter des dépendances et des macros associées pour obtenir le résultat suivant :
import logging
import time
import grpc
import grpc_observability
import helloworld_pb2
import helloworld_pb2_grpc
from opentelemetry.exporter.prometheus import PrometheusMetricReader
from opentelemetry.sdk.metrics import MeterProvider
from prometheus_client import start_http_server
_SERVER_PORT = "50051"
_PROMETHEUS_PORT = 9465
Ensuite, transformez run() pour obtenir le résultat suivant :
def run():
# Start Prometheus client
start_http_server(port=_PROMETHEUS_PORT, addr="0.0.0.0")
meter_provider = MeterProvider(metric_readers=[PrometheusMetricReader()])
otel_plugin = grpc_observability.OpenTelemetryPlugin(
meter_provider=meter_provider
)
otel_plugin.register_global()
with grpc.insecure_channel(target=f"localhost:{_SERVER_PORT}") as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
# Continuously send RPCs every second.
while True:
try:
response = stub.SayHello(helloworld_pb2.HelloRequest(name="You"))
print(f"Greeter client received: {response.message}")
time.sleep(1)
except grpc.RpcError as rpc_error:
print("Call failed with code: ", rpc_error.code())
# Deregister is not called in this example, but this is required to clean up.
otel_plugin.deregister_global()
L'étape suivante consiste à ajouter le plug-in OpenTelemetry au serveur. Ouvrez start_here/observability_greeter_server.py et ajoutez des dépendances et des macros associées pour obtenir le résultat suivant :
from concurrent import futures
import logging
import time
import grpc
import grpc_observability
import helloworld_pb2
import helloworld_pb2_grpc
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.exporter.prometheus import PrometheusMetricReader
from prometheus_client import start_http_server
_SERVER_PORT = "50051"
_PROMETHEUS_PORT = 9464
Ensuite, transformez run() pour obtenir le résultat suivant :
def serve():
# Start Prometheus client
start_http_server(port=_PROMETHEUS_PORT, addr="0.0.0.0")
meter_provider = MeterProvider(metric_readers=[PrometheusMetricReader()])
otel_plugin = grpc_observability.OpenTelemetryPlugin(
meter_provider=meter_provider
)
otel_plugin.register_global()
server = grpc.server(
thread_pool=futures.ThreadPoolExecutor(max_workers=10),
)
helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), server)
server.add_insecure_port("[::]:" + _SERVER_PORT)
server.start()
print("Server started, listening on " + _SERVER_PORT)
server.wait_for_termination()
# Deregister is not called in this example, but this is required to clean up.
otel_plugin.deregister_global()
4. Exécuter l'exemple et afficher les métriques
Pour exécuter le serveur, exécutez la commande suivante :
cd start_here
python -m observability_greeter_server
Si la configuration est réussie, le résultat suivant s'affiche pour le serveur :
Server started, listening on 50051
Pendant que le serveur est en cours d'exécution, exécutez le client sur un autre terminal :
# Run the below commands to cd to the working directory and activate virtual environment in the new terminal
cd grpc-codelabs/codelabs/grpc-python-opentelemetry/
source .venv/bin/activate
cd start_here
python -m observability_greeter_client
Si l'exécution est réussie, le résultat suivant s'affiche :
Greeter client received: Hello You
Greeter client received: Hello You
Greeter client received: Hello You
Nous avons configuré le plug-in gRPC OpenTelemetry pour exporter des métriques à l'aide de Prometheus. Ces métriques seront disponibles sur localhost:9464 pour le serveur et localhost:9465 pour le client.
Pour afficher les métriques du client :
curl localhost:9465/metrics
Le résultat se présente sous la forme suivante :
# HELP python_gc_objects_collected_total Objects collected during gc
# TYPE python_gc_objects_collected_total counter
python_gc_objects_collected_total{generation="0"} 241.0
python_gc_objects_collected_total{generation="1"} 163.0
python_gc_objects_collected_total{generation="2"} 0.0
# HELP python_gc_objects_uncollectable_total Uncollectable objects found during GC
# TYPE python_gc_objects_uncollectable_total counter
python_gc_objects_uncollectable_total{generation="0"} 0.0
python_gc_objects_uncollectable_total{generation="1"} 0.0
python_gc_objects_uncollectable_total{generation="2"} 0.0
# HELP python_gc_collections_total Number of times this generation was collected
# TYPE python_gc_collections_total counter
python_gc_collections_total{generation="0"} 78.0
python_gc_collections_total{generation="1"} 7.0
python_gc_collections_total{generation="2"} 0.0
# HELP python_info Python platform information
# TYPE python_info gauge
python_info{implementation="CPython",major="3",minor="10",patchlevel="9",version="3.10.9"} 1.0
# HELP process_virtual_memory_bytes Virtual memory size in bytes.
# TYPE process_virtual_memory_bytes gauge
process_virtual_memory_bytes 1.868988416e+09
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 4.1680896e+07
# TYPE process_resident_memory_bytes gauge 21:20:16 [154/966]
process_resident_memory_bytes 4.1680896e+07
# HELP process_start_time_seconds Start time of the process since unix epoch in seconds.
# TYPE process_start_time_seconds gauge
process_start_time_seconds 1.72375679833e+09
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
process_cpu_seconds_total 0.38
# HELP process_open_fds Number of open file descriptors.
# TYPE process_open_fds gauge
process_open_fds 9.0
# HELP process_max_fds Maximum number of open file descriptors.
# TYPE process_max_fds gauge
process_max_fds 4096.0
# HELP target_info Target metadata
# TYPE target_info gauge
target_info{service_name="unknown_service",telemetry_sdk_language="python",telemetry_sdk_name="opentelemetry",telemetry_sdk_version="1.26.0"} 1.0
# HELP grpc_client_attempt_started_total Number of client call attempts started
# TYPE grpc_client_attempt_started_total counter
grpc_client_attempt_started_total{grpc_method="other",grpc_target="localhost:50051"} 18.0
# HELP grpc_client_attempt_sent_total_compressed_message_size_bytes Compressed message bytes sent per client call attempt
# TYPE grpc_client_attempt_sent_total_compressed_message_size_bytes histogram
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="0.0"} 0.0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="5.0"} 18.0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="10.0"} 18.0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="25.0"} 18.0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="50.0"} 18.0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="75.0"} 18.0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="100.0"} 18.0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="other",grpc_status="OK",grpc_target="localhost:50051",le="250.0"} 18.0
De même, pour les métriques côté serveur :
curl localhost:9464/metrics
5. Afficher les métriques dans Prometheus
Nous allons ici configurer une instance Prometheus qui récupérera notre exemple de client et de serveur gRPC qui exportent des métriques à l'aide de Prometheus.
Téléchargez la dernière version de Prometheus pour votre plate-forme à l'aide du lien fourni ou utilisez la commande suivante :
curl -sLO https://github.com/prometheus/prometheus/releases/download/v3.7.3/prometheus-3.7.3.linux-amd64.tar.gz
Ensuite, extrayez-la et exécutez-la à l'aide de la commande suivante :
tar xvfz prometheus-*.tar.gz
cd prometheus-*
Créez un fichier de configuration Prometheus avec le contenu suivant :
cat > grpc_otel_python_prometheus.yml <<EOF
scrape_configs:
- job_name: "prometheus"
scrape_interval: 5s
static_configs:
- targets: ["localhost:9090"]
- job_name: "grpc-otel-python"
scrape_interval: 5s
static_configs:
- targets: ["localhost:9464", "localhost:9465"]
EOF
Démarrez Prometheus avec la nouvelle configuration :
./prometheus --config.file=grpc_otel_python_prometheus.yml
Les métriques des processus de l'atelier de programmation client et serveur seront récupérées toutes les cinq secondes.
Accédez à http://localhost:9090/graph pour afficher les métriques. Par exemple, la requête suivante :
histogram_quantile(0.5, rate(grpc_client_attempt_duration_seconds_bucket[1m]))
affiche un graphique avec la latence médiane des tentatives, en utilisant une minute comme fenêtre temporelle pour le calcul des quantiles.
Taux de requêtes :
increase(grpc_client_attempt_duration_seconds_bucket[1m])
6. (Facultatif) Exercice pour l'utilisateur
Dans les tableaux de bord Prometheus, vous remarquerez que le QPS est faible. Essayez d'identifier du code suspect dans l'exemple qui limite le QPS.
Pour les plus enthousiastes, le code client se limite à une seule RPC en attente à un moment donné. Vous pouvez le modifier pour que le client envoie plus de RPC sans attendre la fin des précédentes. (La solution n'est pas fournie.)