All posts

E-Ticaret Uygulamasında Gözlemlenebilirlik: Prometheus, Jaeger, OpenTelemetry ve Grafana ile Örnek Uygulama

Bu blog yazısında, bir e-ticaret uygulamasını izlemek için Prometheus, Jaeger, OpenTelemetry ve Grafana’yı nasıl entegre edeceğimizi adım adım inceleyeceğiz. Örneğimizde, bir sipariş oluşturma senaryosunu izleyeceğiz ve servis metriklerini Prometheus’ta görselleştireceğiz.

Servisleri Başlatma Öncelikle, order-service ve payment-service servislerini çalışır hale getirelim. Bu servisler hem izleme hem de metrik verisi üretecek.

Dizin Yapısını Oluşturun:

project/
├── order-service/
│   ├── app.py
│   ├── Dockerfile
│   └── requirements.txt
├── payment-service/
│   ├── app.py
│   ├── Dockerfile
│   └── requirements.txt
├── collector-config.yaml
├── prometheus.yml
└── docker-compose.yml

Kod Dosyalarını Oluşturun:

order-service/app.py:

python


from opentelemetry import trace, metrics
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from flask import Flask, request
import requests
import logging

# Log ekleme
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Tracer'ı yapılandır
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
otlp_trace_exporter = OTLPSpanExporter(endpoint="otel-collector:4317", insecure=True)
trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(otlp_trace_exporter))

# Metrikleri yapılandır
metrics.set_meter_provider(MeterProvider(metric_readers=[PeriodicExportingMetricReader(OTLPMetricExporter(endpoint="otel-collector:4317", insecure=True))]))
meter = metrics.get_meter(__name__)
order_counter = meter.create_counter("order_requests_total", description="Toplam sipariş isteği sayısı")

app = Flask(__name__)

@app.route('/order', methods=['POST'])
def create_order():
    with tracer.start_as_current_span("create-order"):
        logger.info("Order servisi izleme başlatıldı")
        order_counter.add(1)  # Metrik artırımı
        payment_response = requests.post("http://payment-service:5001/pay")
        if payment_response.status_code != 200:
            logger.error(f"Payment servisine istek başarısız: {payment_response.status_code}")
    return "Sipariş oluşturuldu", 200

if __name__ == "__main__":
    logger.info("Order servisi başlatılıyor...")
    app.run(host="0.0.0.0", port=5000)

payment-service/app.py:

python

from opentelemetry import trace, metrics
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from flask import Flask, request
import time
import logging

# Log ekleme
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Tracer'ı yapılandır
trace.set_tracer_provider(TracerProvider())
tracer = trace.get_tracer(__name__)
otlp_trace_exporter = OTLPSpanExporter(endpoint="otel-collector:4317", insecure=True)
trace.get_tracer_provider().add_span_processor(BatchSpanProcessor(otlp_trace_exporter))

# Metrikleri yapılandır
metrics.set_meter_provider(MeterProvider(metric_readers=[PeriodicExportingMetricReader(OTLPMetricExporter(endpoint="otel-collector:4317", insecure=True))]))
meter = metrics.get_meter(__name__)
payment_counter = meter.create_counter("payment_requests_total", description="Toplam ödeme isteği sayısı")

app = Flask(__name__)

@app.route('/pay', methods=['POST'])
def process_payment():
    with tracer.start_as_current_span("process-payment"):
        logger.info("Payment servisi izleme başlatıldı")
        payment_counter.add(1)  # Metrik artırımı
        time.sleep(0.5)  # Ödeme işlemini simüle etmek için gecikme
    return "Ödeme tamamlandı", 200

if __name__ == "__main__":
    logger.info("Payment servisi başlatılıyor...")
    app.run(host="0.0.0.0", port=5001)

Dockerfile’ları Oluşturun:

order-service/Dockerfile:

FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]
payment-service/Dockerfile:
dockerfile


FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["python", "app.py"]

Bağımlılık Dosyalarını Oluşturun:

order-service/requirements.txt ve payment-service/requirements.txt:

flask==2.3.3
requests==2.31.0
opentelemetry-api==1.20.0
opentelemetry-sdk==1.20.0
opentelemetry-exporter-otlp-proto-grpc==1.20.0

Docker Compose Dosyasını Oluşturun:

docker-compose.yml:

version: '3'
services:
  order-service:
    build: ./order-service
    ports:
      - "5000:5000"
    depends_on:
      - otel-collector
  payment-service:
    build: ./payment-service
    ports:
      - "5001:5001"
    depends_on:
      - otel-collector
  otel-collector:
    image: otel/opentelemetry-collector
    volumes:
      - ./collector-config.yaml:/etc/otelcol/config.yaml
    ports:
      - "4317:4317"
      - "9091:9091"
    depends_on:
      - jaeger
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
  jaeger:
    image: jaegertracing/all-in-one
    ports:
      - "16686:16686"
      - "14250:14250"
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"

Yapılandırma Dosyalarını Oluşturun:

collector-config.yaml:




receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "0.0.0.0:4317"

exporters:
  prometheus:
    endpoint: "0.0.0.0:9091"
  otlp/jaeger:
    endpoint: "jaeger:14250"
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [otlp/jaeger]
    metrics:
      receivers: [otlp]
      exporters: [prometheus]
prometheus.yml:
yaml


scrape_configs:
  - job_name: 'otel-collector'
    scrape_interval: 5s
    static_configs:
      - targets: ['otel-collector:9091']

Servisleri Başlatın:

Proje kök dizininde terminal açın ve şu komutu çalıştırın:

docker-compose up --build

Servislerin Çalıştığını Doğrulayın: Endpoint’leri Test Edin: curl -X POST http://localhost:5000/order Jaeger UI: http://localhost:16686 Prometheus UI: http://localhost:9090 Grafana UI: http://localhost:3000 (varsayılan kullanıcı: admin, şifre: admin) Senaryo Uygulama: Python tabanlı bir e-ticaret API’si. Servisler: order-service: Sipariş oluşturur ve ödeme servisine istek gönderir. payment-service: Ödeme işlemini simüle eder. Amaç: Metrikler (örneğin, istek sayıları) Prometheus ile toplanacak. İsteklerin servisler arası akışı Jaeger ile izlenecek. OpenTelemetry telemetri verilerini sağlayacak. Grafana tüm verileri görselleştirecek.

  1. OpenTelemetry ile Veri Toplama Servislerimizde OpenTelemetry hem izleme (traces) hem de metrik verisi üretiyor:

order_requests_total: Toplam sipariş isteği sayısı. payment_requests_total: Toplam ödeme isteği sayısı. 2. OpenTelemetry Collector ile Verileri Yönlendirme Collector, OTLP protokolüyle verileri alır, izlemeleri Jaeger’a (otlp/jaeger), metrikleri Prometheus’a gönderir.

  1. Prometheus ile Metrik Depolama Prometheus, Collector’dan metrikleri çeker.

Örnek Sorgular (PromQL): Toplam sipariş isteği sayısı: order_requests_total Toplam ödeme isteği sayısı: payment_requests_total İstek oranı: rate(order_requests_total[5m]) 4. Jaeger ile Dağıtık İzleme Jaeger, izleme verilerini görselleştirir.

Açıklama: http://localhost:16686 adresinde create-order ve process-payment izlemeleri görünmeli. 5. Grafana ile Görselleştirme Grafana, Prometheus ve Jaeger verilerini birleştirir.

Veri Kaynakları: Prometheus: http://prometheus:9090 Jaeger: http://jaeger:16686 Örnek Panel: Sipariş isteği oranı: rate(order_requests_total[5m]) Test ve Sonuç Test Komutu: curl -X POST http://localhost:5000/order Sonuçlar: Jaeger’da: create-order ve process-payment izlemeleri. Prometheus’ta: order_requests_total ve payment_requests_total metrikleri. Grafana’da: Metrikler ve izlemeler. Hata Giderme 405 Hatası: curl -X POST kullandığınızdan emin olun. Metrikler Görünmüyorsa: docker-compose logs order-service ve payment-service ile metriklerin üretildiğini kontrol edin. Prometheus UI’da order_requests_total ve payment_requests_total metriklerini arayın. Uygulama Bu yapı, performans darboğazlarını tespit eder ve sistem sağlığını izler.