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 Java.
À 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 Java 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
gitcurlJDKversion 8 ou ultérieure
Installez les prérequis :
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install -y git curl
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.
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-java-opentelemetry :
git clone -b v1 https://github.com/grpc-ecosystem/grpc-codelabs.git
cd grpc-codelabs/codelabs/grpc-java-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.
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 codelabs/grpc-java-opentelemetry/start_here/src/main/java/io/grpc/codelabs/opentelemetry/OpenTelemetryClient.java avec votre éditeur préféré, puis modifiez main pour ajouter du code afin de configurer l'API gRPC Java OpenTelemetry.
Configurer l'instrumentation sur le client
Créer un exportateur Prometheus
Créez un PrometheusHttpServer pour convertir les métriques OpenTelemetry au format Prometheus et les exposer via un HttpServer. L'extrait de code suivant crée un nouvel exportateur Prometheus.
// Default prometheus port i.e `prometheusPort` has been initialized to 9465
PrometheusHttpServer prometheusExporter = PrometheusHttpServer.builder()
.setPort(prometheusPort)
.build();
Créer une instance du SDK OpenTelemetry
Enregistrez la création ci-dessus prometheusExporter en tant que MetricReader pour lire les métriques à partir d'un SdkMeterProvider. SdkMeterProvider permet de configurer les paramètres des métriques.
SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder()
.registerMetricReader(prometheusExporter)
.build();
Créez une instance d'OpenTelemetrySdk avec le sdkMeterProvider créé ci-dessus pour l'implémentation du SDK de OpenTelemetry.
OpenTelemetrySdk openTelemetrySdk =OpenTelemetrySdk.builder()
.setMeterProvider(sdkMeterProvider)
.build();
Créer une instance GrpcOpenTelemetry
À l'aide de l'API GrpcOpenTelemetry API, définissez le SDK OpenTelemetry qui utilise l'exportateur de métriques Prometheus.
GrpcOpenTelemetry grpcOpenTelmetry = GrpcOpenTelemetry.newBuilder()
.sdk(openTelemetrySdk)
.build();
// Registers gRPC OpenTelemetry globally.
grpcOpenTelmetry.registerGlobal();
Une fois qu'une instance GrpcOpenTelemetry est enregistrée globalement à l'aide de registerGlobal, tous les clients et serveurs gRPC créés par la suite seront instrumentés avec OpenTelemetry.
Arrêter le SDK OpenTelemetry
La mise hors service doit avoir lieu dans le ShutDownHook. openTelemetrySdk.close() arrête le SDK et appelle également l'arrêt sur le SdkMeterProvider.
Configurer l'instrumentation sur le serveur
De même, ajoutons également GrpcOpenTelemetry au serveur. Ouvrez codelabs/grpc-java-opentelemetry/start_here/src/main/java/io/grpc/codelabs/opentelemetry/OpenTelemetryServer.java et ajoutez du code pour initialiser GrpcOpenTelemetry.
Créer un exportateur Prometheus
Étant donné que cet atelier de programmation peut être exécuté à partir de la même machine, nous utilisons un port différent pour héberger les métriques côté serveur gRPC afin d'éviter les conflits de ports lors de la création de PrometheusHttpServer.
// Default prometheus port i.e `prometheusPort` has been set to 9464
PrometheusHttpServer prometheusExporter = PrometheusHttpServer.builder()
.setPort(prometheusPort)
.build();
Créer une instance du SDK OpenTelemetry
SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder()
.registerMetricReader(prometheusExporter)
.build();
Initialiser GrpcOpenTelemetry avec le SDK OpenTelemetry
OpenTelemetrySdk openTelemetrySdk =OpenTelemetrySdk.builder()
.setMeterProvider(sdkMeterProvider)
.build();
Créer une instance GrpcOpenTelemetry
GrpcOpenTelemetry grpcOpenTelmetry = GrpcOpenTelemetry.newBuilder()
.sdk(openTelemetrySdk)
.build();
// Registers gRPC OpenTelemetry globally.
grpcOpenTelmetry.registerGlobal();
Arrêter le SDK OpenTelemetry
Une fois le canal gRPC arrêté. L'appel de openTelemetrySdk.close() arrête le SDK et appelle également l'arrêt sur le SdkMeterProvider.
4. Exécuter l'exemple et afficher les métriques
Pour exécuter le serveur, exécutez -
cd start_here
../gradlew installDist
./build/install/start_here/bin/opentelemetry-server
Si la configuration est correcte, la sortie suivante s'affiche pour le serveur :
[date and time] io.grpc.codelabs.opentelemetry.OpenTelemetryServer start
INFO: Server started, listening on 50051
Pendant que le serveur est en cours d'exécution, exécutez le client sur un autre terminal :
./build/install/start_here/bin/opentelemetry-client world
Une exécution réussie se présente comme suit :
[date and time]io.grpc.codelabs.opentelemetry.OpenTelemetryClient greet
INFO: Greeting: Hello world
[date and time] io.grpc.codelabs.opentelemetry.OpenTelemetryClient greet
INFO: Will try to greet world ...
[date and time]io.grpc.codelabs.opentelemetry.OpenTelemetryClient greet
INFO: Greeting: Hello world
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 grpc_client_attempt_duration_seconds Time taken to complete a client call attempt
# TYPE grpc_client_attempt_duration_seconds histogram
grpc_client_attempt_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.002"} 0
grpc_client_attempt_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.003"} 2
grpc_client_attempt_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.004"} 14
grpc_client_attempt_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.005"} 29
grpc_client_attempt_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.1"} 33
grpc_client_attempt_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="+Inf"} 34
grpc_client_attempt_duration_seconds_count{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0"} 34
grpc_client_attempt_duration_seconds_sum{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0"} 0.46512665300000006
# HELP grpc_client_attempt_rcvd_total_compressed_message_size_bytes Compressed message bytes received per call attempt
# TYPE grpc_client_attempt_rcvd_total_compressed_message_size_bytes histogram
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.0"} 0
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_sum{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0"} 442.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="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.0"} 0
grpc_client_attempt_sent_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="1024.0"} 34
grpc_client_attempt_sent_total_compressed_message_size_bytes_sum{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0"} 238.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="helloworld.Greeter/SayHello",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0"} 34.0
# HELP grpc_client_call_duration_seconds Time taken by gRPC to complete an RPC from application's perspective
# TYPE grpc_client_call_duration_seconds histogram
grpc_client_call_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.0"} 0
grpc_client_call_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="0.003"} 2
grpc_client_call_duration_seconds_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0",le="+Inf"} 34
grpc_client_call_duration_seconds_count{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0"} 34
grpc_client_call_duration_seconds_sum{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-java",otel_scope_version="1.66.0"} 0.512708707
# TYPE target_info gauge
target_info{service_name="unknown_service:java",telemetry_sdk_language="java",telemetry_sdk_name="opentelemetry",telemetry_sdk_version="1.40.0"} 1
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 va extraire 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, puis extrayez-la et exécutez-la :
tar xvfz prometheus-*.tar.gz
cd prometheus-*
Créez un fichier de configuration Prometheus avec les éléments suivants :
cat > grpc_otel_java_prometheus.yml <<EOF
scrape_configs:
- job_name: "prometheus"
scrape_interval: 5s
static_configs:
- targets: ["localhost:9090"]
- job_name: "grpc-otel-java"
scrape_interval: 5s
static_configs:
- targets: ["localhost:9464", "localhost:9465"]
EOF
Démarrez Prometheus avec la nouvelle configuration :
./prometheus --config.file=grpc_otel_java_prometheus.yml
Les métriques des processus de l'atelier de programmation client et serveur seront extraites toutes les 5 secondes.
Accédez à http://localhost:9090/graph pour afficher les métriques. Par exemple, la requête -
histogram_quantile(0.5, rate(grpc_client_attempt_duration_seconds_bucket[1m]))
affiche un graphique avec la latence médiane des tentatives, en utilisant 1 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.)