Thiết lập trình bổ trợ OpenTelemetry cơ bản trong gRPC Python

1. Giới thiệu

Trong lớp học lập trình này, bạn sẽ sử dụng gRPC để tạo một máy khách và máy chủ tạo thành nền tảng của một ứng dụng lập bản đồ tuyến đường được viết bằng Python.

Khi kết thúc hướng dẫn này, bạn sẽ có một ứng dụng gRPC HelloWorld đơn giản được đo bằng trình bổ trợ gRPC OpenTelemetry và có thể xem các chỉ số quan sát được đã xuất trong Prometheus.

Kiến thức bạn sẽ học được

  • Cách thiết lập Trình bổ trợ OpenTelemetry cho ứng dụng Python gRPC hiện có
  • Chạy một phiên bản Prometheus cục bộ
  • Xuất chỉ số sang Prometheus
  • Xem các chỉ số trên trang tổng quan Prometheus

2. Trước khi bắt đầu

Bạn cần có

  • git
  • curl
  • build-essential
  • Python 3.9 trở lên. Để biết hướng dẫn cài đặt Python theo từng nền tảng, hãy xem phần Thiết lập và sử dụng Python. Ngoài ra, hãy cài đặt Python không phải là hệ thống bằng các công cụ như uv hoặc pyenv.
  • pip phiên bản 9.0.1 trở lên để cài đặt các gói Python.
  • venv để tạo môi trường ảo Python.

Cài đặt các điều kiện tiên quyết:

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

Lấy mã

Để đơn giản hoá quá trình học tập, lớp học lập trình này cung cấp một khung mã nguồn được tạo sẵn để giúp bạn bắt đầu. Các bước sau đây sẽ hướng dẫn bạn cách đo lường bằng Trình bổ trợ OpenTelemetry gRPC trong một ứng dụng.

grpc-codelabs

Mã nguồn của giàn giáo cho lớp học lập trình này có trong thư mục này trên GitHub. Nếu bạn không muốn tự triển khai mã, thì mã nguồn hoàn chỉnh có trong thư mục completed.

Trước tiên, hãy sao chép kho lưu trữ lớp học lập trình grpc và chuyển đến thư mục grpc-python-opentelemetry:

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

Ngoài ra, bạn có thể tải tệp .zip chỉ chứa thư mục codelab xuống rồi giải nén theo cách thủ công.

Trước tiên, hãy tạo một môi trường ảo Python (venv) mới để tách biệt các phần phụ thuộc của dự án với các gói hệ thống:

python3 -m venv --upgrade-deps .venv

Cách kích hoạt môi trường ảo trong trình bao bash/zsh:

source .venv/bin/activate

Đối với Windows và các shell không theo chuẩn, hãy xem bảng tại https://docs.python.org/3/library/venv.html#how-venvs-work.

Tiếp theo, hãy cài đặt các phần phụ thuộc trong môi trường bằng cách sử dụng:

python -m pip install -r requirements.txt

3. Đăng ký trình bổ trợ OpenTelemetry

Chúng ta cần một ứng dụng gRPC để thêm trình bổ trợ gRPC OpenTelemetry. Trong lớp học lập trình này, chúng ta sẽ sử dụng một máy chủ và ứng dụng gRPC HelloWorld đơn giản mà chúng ta sẽ đo bằng trình bổ trợ gRPC OpenTelemetry.

Bước đầu tiên là đăng ký OpenTelemetry Plugin được định cấu hình bằng một trình xuất Prometheus trong ứng dụng. Mở start_here/observability_greeter_client.py bằng trình chỉnh sửa bạn yêu thích. Trước tiên, hãy thêm các phần phụ thuộc và macro có liên quan để trông như thế này:

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

Sau đó, hãy biến đổi run() để có dạng như sau:

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

Bước tiếp theo là thêm trình bổ trợ OpenTelemetry vào máy chủ. Mở start_here/observability_greeter_server.py rồi thêm các phần phụ thuộc và macro có liên quan để có dạng như sau:

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

Sau đó, hãy biến đổi run() để có dạng như sau:

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. Chạy ví dụ và xem các chỉ số

Để chạy máy chủ, hãy chạy –

cd start_here
python -m observability_greeter_server

Nếu thiết lập thành công, bạn sẽ thấy kết quả sau cho máy chủ –

Server started, listening on 50051

Trong khi máy chủ đang chạy, trên một thiết bị đầu cuối khác, hãy chạy ứng dụng –

# 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

Một lần chạy thành công sẽ có dạng như sau:

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

Vì chúng ta đã thiết lập trình bổ trợ gRPC OpenTelemetry để xuất các chỉ số bằng Prometheus. Các chỉ số đó sẽ có trên localhost:9464 cho máy chủ và localhost:9465 cho ứng dụng.

Cách xem các chỉ số về khách hàng:

curl localhost:9465/metrics

Kết quả sẽ có dạng –

# 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

Tương tự, đối với các chỉ số phía máy chủ:

curl localhost:9464/metrics

5. Xem các chỉ số trên Prometheus

Ở đây, chúng ta sẽ thiết lập một phiên bản prometheus để thu thập dữ liệu từ máy chủ và máy khách ví dụ gRPC đang xuất các chỉ số bằng prometheus.

Tải bản phát hành mới nhất của Prometheus cho nền tảng của bạn bằng đường liên kết đã cho hoặc sử dụng lệnh sau:

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

Sau đó, hãy trích xuất và chạy tệp này bằng lệnh sau:

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

Tạo một tệp cấu hình prometheus có nội dung sau:

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

Khởi động prometheus bằng cấu hình mới –

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

Thao tác này sẽ định cấu hình các chỉ số từ quy trình lớp học lập trình máy khách và máy chủ để được thu thập sau mỗi 5 giây.

Truy cập vào http://localhost:9090/graph để xem các chỉ số. Ví dụ: truy vấn –

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

sẽ cho thấy một biểu đồ có độ trễ trung bình của lượt thử bằng cách sử dụng 1 phút làm khung thời gian để tính toán phân vị.

Tỷ lệ truy vấn –

increase(grpc_client_attempt_duration_seconds_bucket[1m])

6. (Không bắt buộc) Bài tập cho người dùng

Trong trang tổng quan prometheus, bạn sẽ nhận thấy QPS thấp. Hãy xem liệu bạn có thể xác định một số mã đáng ngờ trong ví dụ đang giới hạn QPS hay không.

Đối với những người có hứng thú, mã ứng dụng khách chỉ có một RPC đang chờ xử lý tại một thời điểm nhất định. Bạn có thể sửa đổi để máy khách gửi nhiều RPC hơn mà không cần đợi các RPC trước đó hoàn tất. (Chúng tôi chưa cung cấp giải pháp cho vấn đề này.)