gRPC Python'da Temel OpenTelemetry Eklentisini Kurma

1. Giriş

Bu codelab'de, Python ile yazılmış bir rota haritası oluşturma uygulamasının temelini oluşturan bir istemci ve sunucu oluşturmak için gRPC'yi kullanacaksınız.

Eğitimin sonunda, gRPC OpenTelemetry eklentisiyle donatılmış basit bir gRPC HelloWorld uygulamanız olacak ve dışa aktarılan gözlemlenebilirlik metriklerini Prometheus'ta görebileceksiniz.

Neler öğreneceksiniz?

  • Mevcut gRPC Python uygulaması için OpenTelemetry eklentisi nasıl ayarlanır?
  • Yerel bir Prometheus örneği çalıştırma
  • Metrikleri Prometheus'a aktarma
  • Prometheus kontrol panelinden metrikleri görüntüleme

2. Başlamadan önce

İhtiyacınız olanlar

  • git
  • curl
  • build-essential
  • Python 3.9 veya sonraki sürümler Platforma özel Python yükleme talimatları için Python Kurulumu ve Kullanımı başlıklı makaleyi inceleyin. Alternatif olarak, uv veya pyenv gibi araçları kullanarak sistem dışı bir Python yükleyin.
  • Python paketlerini yüklemek için pip sürümü 9.0.1 veya daha yeni bir sürüm.
  • Python sanal ortamları oluşturmak için venv.

Ön koşulları yükleyin:

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

Kodu alın

Bu codelab, öğrenme sürecinizi kolaylaştırmak için başlamanıza yardımcı olacak önceden oluşturulmuş bir kaynak kodu iskeleti sunar. Aşağıdaki adımlar, bir uygulamada gRPC OpenTelemetry eklentisini kullanma konusunda size yol gösterecektir.

grpc-codelabs

Bu codelab'in iskele kaynak kodunu bu GitHub dizininde bulabilirsiniz. Kodu kendiniz uygulamayı tercih etmezseniz tamamlanmış kaynak kodu completed dizininde bulabilirsiniz.

İlk olarak, grpc codelab deposunu klonlayın ve grpc-python-opentelemetry klasörüne gidin:

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

Alternatif olarak, yalnızca codelab dizinini içeren .zip dosyasını indirebilir ve manuel olarak sıkıştırmasını açabilirsiniz.

Öncelikle projenizin bağımlılıklarını sistem paketlerinden ayırmak için yeni bir Python sanal ortamı (venv) oluşturalım:

python3 -m venv --upgrade-deps .venv

Sanal ortamı bash/zsh kabuğunda etkinleştirmek için:

source .venv/bin/activate

Windows ve standart dışı kabuklar için https://docs.python.org/3/library/venv.html#how-venvs-work adresindeki tabloya bakın.

Ardından, ortamdaki bağımlılıkları şu komutu kullanarak yükleyin:

python -m pip install -r requirements.txt

3. OpenTelemetry eklentisini kaydetme

gRPC OpenTelemetry eklentisini eklemek için bir gRPC uygulamasına ihtiyacımız var. Bu codelab'de, gRPC OpenTelemetry eklentisiyle donatacağımız basit bir gRPC HelloWorld istemcisi ve sunucusu kullanacağız.

İlk adımınız, istemcide Prometheus dışa aktarıcısıyla yapılandırılmış OpenTelemetry eklentisini kaydetmektir. start_here/observability_greeter_client.py dosyasını favori düzenleyicinizle açın. Öncelikle ilgili bağımlılıkları ve makroları aşağıdaki gibi ekleyin:

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

Ardından run() öğesini aşağıdaki gibi dönüştürün:

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()

Bir sonraki adım, OpenTelemetry eklentisini sunucuya eklemektir. start_here/observability_greeter_server.py öğesini açın ve ilgili bağımlılıkları ve makroları aşağıdaki gibi görünecek şekilde ekleyin:

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

Ardından run() öğesini aşağıdaki gibi dönüştürün:

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. Örneği çalıştırma ve metrikleri görüntüleme

Sunucuyu çalıştırmak için şunu çalıştırın:

cd start_here
python -m observability_greeter_server

Kurulum başarılı olduğunda sunucu için aşağıdaki çıkışı görürsünüz:

Server started, listening on 50051

Sunucu çalışırken başka bir terminalde istemciyi çalıştırın:

# 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

Başarılı bir çalıştırma şöyle görünür:

Greeter client received: Hello You
Greeter client received: Hello You
Greeter client received: Hello You

Prometheus kullanarak metrikleri dışa aktarmak için gRPC OpenTelemetry eklentisini kurduğumuzdan. Bu metrikler, sunucu için localhost:9464, istemci için ise localhost:9465 adresinde kullanılabilir.

Müşteri metriklerini görmek için:

curl localhost:9465/metrics

Sonuç şu biçimde olur:

# 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

Aynı şekilde, sunucu tarafı metrikleri için:

curl localhost:9464/metrics

5. Prometheus'taki metrikleri görüntüleme

Burada, prometheus kullanarak metrikleri dışa aktaran gRPC örnek istemcimizi ve sunucumuzu kazıyacak bir prometheus örneği kuracağız.

Verilen bağlantıyı kullanarak platformunuz için Prometheus'un en son sürümünü indirin veya aşağıdaki komutu kullanın:

curl -sLO https://github.com/prometheus/prometheus/releases/download/v3.7.3/prometheus-3.7.3.linux-amd64.tar.gz

Ardından, aşağıdaki komutu kullanarak dosyayı çıkarın ve çalıştırın:

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

Aşağıdaki bilgileri içeren bir Prometheus yapılandırma dosyası oluşturun:

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

Prometheus'u yeni yapılandırmayla başlatın:

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

Bu işlem, istemci ve sunucu codelab işlemlerindeki metriklerin 5 saniyede bir kazınacak şekilde yapılandırılmasını sağlar.

Metrikleri görüntülemek için http://localhost:9090/graph adresine gidin. Örneğin, şu sorgu:

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

, nicelik hesaplaması için zaman aralığı olarak 1 dakikanın kullanıldığı, deneme gecikmesinin ortanca değerini gösteren bir grafik gösterir.

Sorgu oranı:

increase(grpc_client_attempt_duration_seconds_bucket[1m])

6. (İsteğe bağlı) Kullanıcı için egzersiz

Prometheus kontrol panellerinde QPS'nin düşük olduğunu görürsünüz. Örnekte, sorgu/saniye sayısını sınırlayan şüpheli bir kod olup olmadığını kontrol edin.

İstekli kullanıcılar için istemci kodu, belirli bir anda yalnızca tek bir bekleyen RPC'ye sahip olacak şekilde sınırlandırılmıştır. Bu, istemcinin önceki RPC'lerin tamamlanmasını beklemeden daha fazla RPC gönderecek şekilde değiştirilebilir. (Bunun çözümü sağlanmadı.)