OpenTelemetry nedir ve neden şimdi?
Modern uygulamalar mikroservisler, HTTP çağrıları, mesaj kuyrukları ve veritabanı etkileşimleriyle dolu. Bir isteğin nerede yavaşladığını veya neden hata verdiğini anlamak için klasik loglar tek başına yetmiyor. OpenTelemetry (OTel), dil bağımsız bir standart ve SDK seti olarak uygulama içinde otomatik enstrümantasyon sağlar; iz (trace), span, metrik ve log verilerini toplayıp OTLP gibi açık protokollerle istediğiniz araca yollar. Bu rehberde, Node.js bir servise OTel entegre ederek izleri Jaeger üzerinden görselleştireceğiz.
Hedef
Amaç: Node.js uygulamanızdaki HTTP isteklerinin uçtan uca izlenmesini 15 dakikada etkinleştirmek. İzleri toplamak için OpenTelemetry Node SDK’sını kullanacağız, çıktıyı OTLP üzerinden gönderecek ve Jaeger All-in-One ile arayüzde görüntüleyeceğiz.
Önkoşullar
- Node.js 16+ ve npm yüklü olmalı. - Docker çalışıyor olmalı. - Uygulama Express, Fastify veya yerleşik HTTP modülü kullanıyor olabilir; OTel, otomatik enstrümantasyonla bu kütüphaneleri tanır.
Adım 1: Paketleri yükleyin
Projeye OpenTelemetry bağımlılıklarını ekleyin: npm i @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/auto-instrumentations-node @opentelemetry/resources @opentelemetry/semantic-conventions @opentelemetry/exporter-trace-otlp-http
Bu paketler; API yüzeyi, Node SDK, otomatik enstrümantasyon, kaynak (resource) nitelikleri ve OTLP HTTP trace exporter içerir. İhtiyaca göre gRPC tabanlı exporter da tercih edebilirsiniz fakat yerelde HTTP pratik ve hızlıdır.
Adım 2: Tracing başlatıcısını oluşturun
Proje köküne tracing.js isminde bir dosya ekleyin ve SDK’yı minimum ayarlarla başlatın. Ana fikir: servis adını tanımlayın, OTLP exporter’ı 4318 portuna yönlendirin ve otomatik enstrümantasyon modüllerini etkinleştirin.
Örnek yapılandırma (özet): const { NodeSDK } = require('@opentelemetry/sdk-node'); const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node'); const { Resource } = require('@opentelemetry/resources'); const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions'); const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http'); const sdk = new NodeSDK({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: 'orders-api', [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0' }), traceExporter: new OTLPTraceExporter({ url: 'http://localhost:4318/v1/traces' }), instrumentations: [getNodeAutoInstrumentations()] }); sdk.start(); process.on('SIGTERM', () => sdk.shutdown());
Burada service.name gelecekteki sorgular için kritik; Jaeger’de projeyi bu ad üzerinden bulacaksınız. Versiyon alanı, sürüm bazlı karşılaştırmalar için faydalıdır.
Adım 3: Uygulamayı OTel ile çalıştırın
Node sürecini tracing başlatıcısı ile preload ederek başlatın: node -r ./tracing.js app.js
Eğer bir test isteği göndermek isterseniz, uygulama ayağa kalktıktan sonra örneğin curl http://localhost:3000/health gibi basit bir çağrı yapın. OTel, HTTP istemci ve sunucu katmanlarını, Express route’larını ve veritabanı sürücülerini otomatik olarak span’lere dönüştürür.
Adım 4: Jaeger All-in-One’ı başlatın
Jaeger’i tek komutla çalıştırabilirsiniz. Bu imaj, OTLP HTTP alıcısı ve web arayüzünü içerir: docker run -d --name jaeger -p 16686:16686 -p 4318:4318 jaegertracing/all-in-one:1.56
- 16686: Jaeger UI portu. - 4318: OTLP HTTP endpoint’i. Uygulamanızdaki exporter URL’si ile eşleşir. Arayüze tarayıcıdan erişip (localhost:16686) “services” alanında orders-api servisini seçerek izleri görüntüleyebilirsiniz.
Adım 5: Manuel span eklemek (opsiyonel)
Otomatik enstrümantasyon çoğu senaryo için yeterli olsa da domain mantığınızı daha iyi anlamak için manuel span eklemek değerlidir. Örneğin kritik bir iş kuralını ölçmek için: const { context, trace } = require('@opentelemetry/api'); const tracer = trace.getTracer('orders-business'); await tracer.startActiveSpan('price-calculation', span => { // iş mantığı ... span.setAttribute('discount.applied', true); span.end(); });
Bu şekilde, Jaeger’de sadece altyapı çağrılarını değil, iş süreçlerinizi de okunaklı şekilde takip edebilirsiniz.
Üretim için en iyi uygulamalar
- Örnekleme (sampling): Trafiğiniz yüksekse, varsayılan oranı düşürün. Çevresel değişkenle kontrol etmek pratik: OTEL_TRACES_SAMPLER=traceidratio ve OTEL_TRACES_SAMPLER_ARG=0.1 (yüzde 10). - Kaynak nitelikleri: Ortam bilgilerini ekleyin: deployment.environment=prod, cloud.region=eu-central-1. - Veri güvenliği: Hassas verileri span attribute veya event’lerde taşımayın. Maskleme/sansürleme katmanı ekleyin. - Bağımlılık izleme: HTTP client timeouts, retry politikaları ve hataları span event’lerinde açıkça belirtin. - Başlatma düzeni: Tracing dosyanızı uygulama kodundan önce yüklediğinizden emin olun; aksi halde ilk istekler enstrümanlanmayabilir.
Sorun giderme
- İzler gelmiyor: Exporter URL’sini ve portu doğrulayın (http://localhost:4318/v1/traces). - CORS/agent hatası: Sunucu tarafında çalıştığınızdan emin olun; tarayıcı için farklı SDK gerekir. - Servis görünmüyor: service.name niteliği boşsa Jaeger listede göstermeyebilir. - Ağ çakışmaları: 4318 portu başka bir süreç tarafından kullanılıyorsa, Jaeger’i farklı portla çalıştırın ve exporter URL’sini eşitleyin.
Sonuç
OpenTelemetry ile Node.js uygulamanıza dakikalar içinde dağıtık izleme ekleyebilir, Jaeger üzerinden gecikmeleri, hata oranlarını ve bağımlılık zincirlerini şeffaf biçimde görebilirsiniz. Daha ileri kullanımda OpenTelemetry Collector ekleyip verileri birden fazla hedefe (ör. Tempo, Zipkin) yönlendirebilir; metrik ve log’ları aynı bağlamda zenginleştirerek tam kapsamlı gözlemlenebilirlik elde edebilirsiniz. Başlangıç için bu kurulum, üretimde dahi temel ihtiyaçları karşılayacak kadar hafif ve esnektir.