Menyiapkan Plugin OpenTelemetry Dasar di gRPC Java

1. Pengantar

Dalam codelab ini, Anda akan menggunakan gRPC untuk membuat klien dan server yang membentuk dasar aplikasi pemetaan rute yang ditulis dalam java.

Di akhir tutorial, Anda akan memiliki aplikasi gRPC HelloWorld sederhana yang diinstrumentasikan dengan plugin gRPC OpenTelemetry dan dapat melihat metrik kemampuan observasi yang diekspor di Prometheus.

Yang akan Anda pelajari

  • Cara menyiapkan Plugin OpenTelemetry untuk aplikasi Java gRPC yang sudah ada
  • Menjalankan instance Prometheus lokal
  • Mengekspor metrik ke Prometheus
  • Melihat metrik dari dasbor Prometheus

2. Sebelum memulai

Yang Anda butuhkan

  • git
  • curl
  • JDK v8 atau yang lebih tinggi

Instal prasyarat:

sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install -y git curl

Mendapatkan kode

Untuk menyederhanakan pembelajaran Anda, codelab ini menawarkan struktur kode sumber bawaan untuk membantu Anda memulai. Langkah-langkah berikut akan memandu Anda menginstrumentasi Plugin OpenTelemetry gRPC dalam aplikasi.

grpc-codelabs

Kode sumber scaffold untuk codelab ini tersedia di direktori GitHub ini. Jika Anda memilih untuk tidak menerapkan kode sendiri, kode sumber yang sudah selesai tersedia di direktori completed.

Pertama, clone repo codelab grpc dan cd ke folder grpc-java-opentelemetry:

git clone https://github.com/grpc-ecosystem/grpc-codelabs.git
cd grpc-codelabs/codelabs/grpc-java-opentelemetry/

Atau, Anda dapat mendownload file .zip yang hanya berisi direktori codelab dan mengekstraknya secara manual.

3. Mendaftarkan Plugin OpenTelemetry

Kita memerlukan aplikasi gRPC untuk menambahkan plugin OpenTelemetry gRPC. Dalam codelab ini, kita akan menggunakan klien dan server gRPC HelloWorld sederhana yang akan kita instrumentasikan dengan plugin gRPC OpenTelemetry.

Langkah pertama Anda adalah mendaftarkan Plugin OpenTelemetry yang dikonfigurasi dengan pengekspor Prometheus di klien. Buka codelabs/grpc-java-opentelemetry/start_here/src/main/java/io/grpc/codelabs/opentelemetry/OpenTelemetryClient.java dengan editor favorit Anda, lalu ubah main untuk menambahkan kode guna menyiapkan gRPC Java OpenTelemetry API.

Menyiapkan instrumentasi di klien

Buat eksportir Prometheus

Buat PrometheusHttpServer untuk mengonversi metrik OpenTelemetry ke format Prometheus dan mengeksposnya melalui HttpServer. Cuplikan kode berikut membuat Prometheus Exporter baru.

// Default prometheus port i.e `prometheusPort` has been initialized to 9465
 
PrometheusHttpServer prometheusExporter = PrometheusHttpServer.builder()
        .setPort(prometheusPort)         
        .build();

Buat instance SDK OpenTelemetry

Daftarkan prometheusExporter di atas sebagai MetricReader untuk membaca metrik dari SdkMeterProvider. SdkMeterProvider digunakan untuk mengonfigurasi setelan metrik.

SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder()
        .registerMetricReader(prometheusExporter)
        .build();

Buat instance OpenTelemetrySdk dengan sdkMeterProvider yang dibuat di atas untuk penerapan SDK OpenTelemetry.

OpenTelemetrySdk openTelemetrySdk =OpenTelemetrySdk.builder()
        .setMeterProvider(sdkMeterProvider)
        .build();

Buat instance GrpcOpenTelemetry

Dengan menggunakan API GrpcOpenTelemetry, tetapkan SDK OpenTelemetry yang menggunakan eksportir Metrik Prometheus.

GrpcOpenTelemetry grpcOpenTelmetry = GrpcOpenTelemetry.newBuilder()
        .sdk(openTelemetrySdk)
        .build();

// Registers gRPC OpenTelemetry globally.
grpcOpenTelmetry.registerGlobal();

Setelah instance GrpcOpenTelemetry didaftarkan secara global menggunakan registerGlobal, semua klien dan server gRPC yang dibuat setelahnya akan diinstrumentasikan dengan OpenTelemetry.

Menonaktifkan OpenTelemetry SDK

Penonaktifan harus terjadi di dalam ShutDownHook. openTelemetrySdk.close() mematikan SDK dan juga memanggil shutdown di SdkMeterProvider.

Menyiapkan instrumentasi di server

Demikian pula, mari kita tambahkan GrpcOpenTelemetry ke server juga. Buka codelabs/grpc-java-opentelemetry/start_here/src/main/java/io/grpc/codelabs/opentelemetry/OpenTelemetryServer.java dan tambahkan kode untuk menginisialisasi GrpcOpenTelemetry.

Buat eksportir Prometheus

Karena codelab ini mungkin dijalankan dari mesin yang sama, kita menggunakan port yang berbeda untuk menghosting metrik sisi server gRPC guna menghindari konflik port saat membuat PrometheusHttpServer.

// Default prometheus port i.e `prometheusPort` has been set to 9464

PrometheusHttpServer prometheusExporter = PrometheusHttpServer.builder()
        .setPort(prometheusPort)
        .build();

Buat instance SDK OpenTelemetry

SdkMeterProvider sdkMeterProvider = SdkMeterProvider.builder()
        .registerMetricReader(prometheusExporter)
        .build();

Lakukan inisialisasi GrpcOpenTelemetry dengan OpenTelemetry SDK

OpenTelemetrySdk openTelemetrySdk =OpenTelemetrySdk.builder()
        .setMeterProvider(sdkMeterProvider)
        .build();

Buat instance GrpcOpenTelemetry

GrpcOpenTelemetry grpcOpenTelmetry = GrpcOpenTelemetry.newBuilder()
        .sdk(openTelemetrySdk)
        .build();
    // Registers gRPC OpenTelemetry globally.
grpcOpenTelmetry.registerGlobal();

Menonaktifkan OpenTelemetry SDK

Setelah saluran gRPC dimatikan. Memanggil openTelemetrySdk.close() akan mematikan SDK dan juga memanggil shutdown di SdkMeterProvider.

4. Menjalankan contoh dan melihat metrik

Untuk menjalankan server, jalankan -

cd start_here
../gradlew installDist
./build/install/start_here/bin/opentelemetry-server

Jika penyiapan berhasil, Anda akan melihat output berikut untuk server -

[date and time] io.grpc.codelabs.opentelemetry.OpenTelemetryServer start
INFO: Server started, listening on 50051

Saat server berjalan, di terminal lain, jalankan klien -

./build/install/start_here/bin/opentelemetry-client world

Eksekusi yang berhasil akan terlihat seperti -

[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

Karena kita telah menyiapkan plugin gRPC OpenTelemetry untuk mengekspor metrik menggunakan Prometheus. Metrik tersebut akan tersedia di localhost:9464 untuk server dan localhost:9465 untuk klien.

Untuk melihat metrik klien -

curl localhost:9465/metrics

Hasilnya akan dalam bentuk -

# 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

Demikian pula, untuk metrik sisi server -

curl localhost:9464/metrics

5. Melihat metrik di Prometheus

Di sini, kita akan menyiapkan instance prometheus yang akan meng-scrape klien dan server contoh gRPC yang mengekspor metrik menggunakan prometheus.

Download rilis terbaru Prometheus untuk platform Anda, lalu ekstrak dan jalankan:

tar xvfz prometheus-*.tar.gz
cd prometheus-*

Buat file konfigurasi prometheus dengan -

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

Mulai prometheus dengan konfigurasi baru -

./prometheus --config.file=grpc_otel_java_prometheus.yml

Tindakan ini akan mengonfigurasi metrik dari proses codelab klien dan server agar di-scrape setiap 5 detik.

Buka http://localhost:9090/graph untuk melihat metrik. Misalnya, kueri -

histogram_quantile(0.5, rate(grpc_client_attempt_duration_seconds_bucket[1m]))

akan menampilkan grafik dengan latensi upaya median menggunakan 1 menit sebagai jangka waktu untuk penghitungan kuantil.

Rasio kueri -

increase(grpc_client_attempt_duration_seconds_bucket[1m])

6. (Opsional) Latihan untuk Pengguna

Di dasbor Prometheus, Anda akan melihat bahwa QPS rendah. Lihat apakah Anda dapat mengidentifikasi beberapa kode mencurigakan dalam contoh yang membatasi QPS.

Untuk yang antusias, kode klien membatasi dirinya hanya untuk memiliki satu RPC yang tertunda pada saat tertentu. Hal ini dapat diubah sehingga klien mengirim lebih banyak RPC tanpa menunggu RPC sebelumnya selesai. (Solusi untuk masalah ini belum diberikan.)