uv sync Sonrası OpenTelemetry Auto-Instrumentation Sorunları
Selamlar, bu yazımda son dönemde Python tarafına gelen sevimli paket yöneticisi uv ile OpenTelemetry'nin auto-instrumentation'ı arasındaki o sinir bozucu sürtüşmeye bakacağız. Konu basit gibi duruyor ama bir CI runner'da iz kayboldu mu, üç saatiniz nereye gittiğini anlamadan uçup gidiyor. Hadi sebepleri sırayla açalım.
Olay genelde şöyle başlıyor: Lokalde her şey güzel çalışıyor, span'ler Jaeger'a düşüyor, hayat güzel. Sonra biri uv sync çalıştırıyor (ya da pipeline kendi başına yapıyor) ve aniden opentelemetry-instrument python app.py komutu hiç span üretmemeye başlıyor. Worse, bazen şu hatayı alıyorsunuz:
ModuleNotFoundError: No module named 'opentelemetry.instrumentation.flask'
uv sync Neden Sessizce Paketleri Siliyor?
Burada kritik nokta uv'nin felsefesi. uv sync, pyproject.toml ve uv.lock dosyasında ne yazıyorsa onu kurar, geri kalan ne varsa siler. Bu davranış aslında bir lütuf, çünkü artık 'benim makinemde çalışıyor' krizinin yarısı buradan çıkmıyor. Ama OpenTelemetry'nin opentelemetry-bootstrap -a install komutuyla kurulan instrumentation paketlerini de aynı acımasızlıkla siliyor, çünkü onlar pyproject.toml'da yazmıyor.
Yani problem uv'de değil, alışkanlıklarımızda. Eskiden pip'in gevşekliğine güvenip 'bir kez kurarım, dururlar' derdik. Artık böyle bir lüksümüz yok.
Çözüm 1: Bootstrap'ı Listeye Çevirin
Bence en temiz yol bu. opentelemetry-bootstrap size lazım olan paketleri zaten söylüyor; biz de bu listeyi alıp pyproject.toml'a doğrudan yazıyoruz. Önce bootstrap aracını geçici olarak kuralım:
uv pip install opentelemetry-instrumentation
uv run opentelemetry-bootstrap --action=requirements
Çıktı şuna benzeyecek:
opentelemetry-instrumentation-flask==0.46b0
opentelemetry-instrumentation-requests==0.46b0
opentelemetry-instrumentation-sqlalchemy==0.46b0
Bu listeyi pyproject.toml'a açık açık ekliyoruz:
[project]
name = "<Svc>"
version = '0.1.0'
dependencies = [
'flask>=3.0',
'opentelemetry-api>=1.27',
'opentelemetry-sdk>=1.27',
'opentelemetry-exporter-otlp-proto-http>=1.27',
'opentelemetry-instrumentation-flask>=0.46b0',
'opentelemetry-instrumentation-requests>=0.46b0',
'opentelemetry-instrumentation-sqlalchemy>=0.46b0',
]
Sonrasında uv sync çalıştırın; bir daha bu paketler kaybolmaz, lock dosyasına da girer, CI'da reproducibility sağlam kalır.
Çözüm 2: Optional Dependencies Grubu
Bazı ortamlarda (özellikle local geliştirmede) tracing'i istemeyebilirsiniz. O zaman optional bir grup açıp telemetry paketlerini oraya koymak çok daha temiz duruyor:
[project.optional-dependencies]
telemetry = [
'opentelemetry-api>=1.27',
'opentelemetry-sdk>=1.27',
'opentelemetry-exporter-otlp-proto-http>=1.27',
'opentelemetry-instrumentation-flask>=0.46b0',
'opentelemetry-instrumentation-requests>=0.46b0',
]
Production'da:
uv sync --extra telemetry
uv run opentelemetry-instrument python app.py
Lokalde sadece uv sync deyip OTEL'siz çalıştırabiliyorsunuz. Şahsi tercihim bu yön; telemetri prod'a aitse pyproject.toml da bunu söylesin.
Çözüm 3 (Geçici): uv pip install
Acil bir durumda uv pip install opentelemetry-instrumentation-flask deyip devam edebilirsiniz. Ama unutmayın, bir sonraki uv sync bunları yine süpürür. Bu yöntemi sadece 'hemen şimdi prod'da görmek istiyorum, sonra düzelteceğim' diyorsanız kullanın. Aksi hâlde aynı çukura iki gün sonra tekrar düşersiniz.
Doğrulama
Kurulum sonrası her şeyin yerinde olduğunu görmek için şunlar yeter:
uv run opentelemetry-instrument --help
uv run pip list | grep opentelemetry
uv run opentelemetry-bootstrap --action=requirements
Son komut boş liste dönerse her şey tıkır tıkır demektir; çünkü bootstrap 'sana lazım olup da kurulmamış bir şey yok' diyor. --help çıktısı geliyorsa CLI da virtualenv içinden bulunabiliyor.
Çalıştırırken uv run prefix'ini unutmayın, yoksa sistem Python'ı devreye girer ve hâlâ aynı modül hatasını yersiniz:
OTEL_SERVICE_NAME=<Svc> \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 \
uv run opentelemetry-instrument python app.py
Docker Tarafı
Container içinde --frozen flag'i ile lock'a sadık kalın; sürpriz upgrade istemiyoruz:
FROM python:3.12-slim
WORKDIR /app
RUN pip install uv
COPY pyproject.toml uv.lock ./
RUN uv sync --extra telemetry --frozen
COPY . .
CMD ['uv', 'run', 'opentelemetry-instrument', 'python', 'app.py']
Sık Karşılaşılan Hatalar
- Bootstrap'ı pyproject'e yazmamak: En sık tuzak.
opentelemetry-bootstrap -a installçalıştırılır, paketler gelir,uv syncgelir, paketler gider. Döngü. - uv run unutmak:
opentelemetry-instrumentPATH'te görünüyor olabilir ama sistem Python'ından geliyordur.uv runile virtualenv içine girin. - Versiyon karışıklığı:
opentelemetry-apiileopentelemetry-instrumentation-*paketleri uyumlu olmalı. Birini güncelleyip diğerini bırakırsanız import zinciri bozulur; bootstrap çıktısını referans alın. - CI'da --frozen kullanmamak: Lock var, frozen yok, sürpriz minor upgrade gelir, instrumentation API kırılır. Üretimde her zaman
--frozen.
Kapanış
Özetle, uv size 'sadece dediğini kurarım' diyor; biz de OpenTelemetry'ye bunu yazılı olarak söyleyeceğiz. Bence en sağlıklı yol bootstrap çıktısını alıp optional telemetry extras'ına koymak; hem prod sağlam kalıyor, hem lokal hızlı açılıyor. Umarım faydalı olur, bir sonraki yazıda görüşmek üzere.
