OpenTelemetry Giriş ve ASP.NET Core Entegrasyonu
OpenTelemetry ile dağıtık sistemlerde izleme, metrik ve logları nasıl entegre edebileceğinizi öğrenin. ASP.NET Core örneğiyle adım adım.
İçindekiler·15 bölümBölümler arasında hızlı geçiş yapın
⏱️ ~19 dk okuma
Bölümler arasında hızlı geçiş yapın
OpenTelemetry (OTel) uygulamalarımızda gözlemlenebilirlik (observability) verilerini (izlemeler, metrikler ve loglar) toplamak, işlemek ve dağıtmak için kullanılan bir satıcı bağımsız açık kaynak projesidir. Kendi içinde API’ler, SDK’lar ve farklı araçlar ile bize uygulamalarımızın iç işleyişini anlamamıza ve performans sorunlarını, hataları veya darboğazları tespit etmenize yardımcı olur.
OpenTelemetry’nin Tanımı ve Amacı:
OpenTelemetry (kısaca OTel), uygulamalarımızın loglarını, metrik bilgilerini ve akışlarının izlemek için kullanacağımız bir açık kaynak projedir. Özellikle mikro servis gibi dağıtık mimariye sahip sistemlerde bir çağırım (request) birden fazla servis üzerinden geçebilmektedir. Böyle bir durumda bu akışın izini sürmek, bu akış esnasındaki çağırımların performanslarının incelemek ve hata alınan noktaların tespit edilmesi zor olacaktır. OTel bu konuda bize yardımcı olacak ve bize sunduğu araçlar ile verileri incelememizi sağlayacaktır.
Özet olarak ürünün temel amacı, uygulamalarınızdan gözlemlenebilirlik (observability) verileri toplamaktır.
OTel bu verileri üç ana veri türü aracılığıyla sağlar.
-
Traces (İzlemeler) : Bir kullanıcının isteğinin dağıtık mimariye sahip olab sistemde nasıl ilerlediğini gösterir. Hangi serviste ne kadar zaman harcandığını, bu servislerde bir hata olup olmadığı konusunda bilgileri toplar.
-
Metrics (Metrikler) : Uygulamanızın performansı hakkında sayısal verilerdir. CPU kullanımı, bellek kullanımı, istek sayısı, hata oranları gibi değerleri izlemenizi sağlar.
-
Logs (Loglar) : Uygulamamızdaki belirli olaylar ve durumlar konusunda kayıt altına alınması istenen mesajlardır. Hata, bilgi mesajları ve uyarılar gibi bilgileri içerir.
OpenTelemetry, bu üç tür veriyi standart bir şekilde toplamanızı sağlar. Bu da, uygulamanızda bir sorun olduğunda (örneğin, bir istek yavaşladığında), izlemelere bakarak hangi servisin soruna neden olduğunu bulmanıza, metriklerle o servisin genel durumunu kontrol etmenize ve ilgili loglarla hatanın detayını görmenize olanak tanır.
Modern Uygulamalarda Gözlemlenebilirliğin Önemi
Günümüzde uygulamaları talepler ve istekler doğrultusunda monolit yapıdan dağıtık mimarilere, bulut altyapılarına ve mikro servislere doğru yönlenmekte. Bu değişim avantajlar sunsa da, beraberinde karmaşıklığı da getirmektedir.
Bu karışıklığın içerisinde sorunların çözümü için gözlemlenebilirlik büyük önem taşıyor.
Gözlemlenebilirliğin önemine bakacak olursak;
-
Performans Optimizasyonu: Performans optimizasyonu, servis hızları, veri tabanı sorgu performansı ve darboğazları belirleyerek uygulama performansını artırır.
-
Sorunları Hızlı Tespit ve Giderme: Dağıtık sistemlerde hata kaynağını bulmak zor olabilir. Ancak gözlemlenebilirlik verileri (izlemeler, metrikler, loglar) sayesinde hatanın başlangıç noktası, etkilediği servisler ve nedeni hızlıca tespit edilerek kesinti süresi azaltılır.
-
Sistem Sağlığını Anlama: Metriklerle CPU, bellek ve ağ kullanımını sürekli izleyerek sorunları erken tespit edebilirsiniz.
-
Kullanıcı Deneyimini İyileştirme: Kullanıcıların hatalarını ve yavaşlıkları tespit ederek deneyimlerini iyileştirirsiniz.
-
Geliştirme Sürecini Hızlandırma: Geliştiriciler, kodlarının üretim ortamındaki davranışını gözlemleyerek daha bilinçli kararlar alır ve sorunlar karşısında hızlı aksiyon alabilirler.
Kısacası modern ve dağıtık yapıdaki uygulamaları etkili bir şekilde yönetmek, performanslarını izlemek ve sorunları çözmek için gözlemlemek önemli bir rol oynamaktadır. OTel gibi araçlar bizlere bu sorunların önüne geçme ve uygulamalarımızı yönetme yeteneğini kazandırırlar.
Satıcı Bağımsız, Açık Kaynak
OTel’in önemli özelliklerin birisi de belirli bir ticari ürüne veya satıcıya bağlı olmamasıdır. Neden böyle bir şey var ? Bakalım.
Genelde bu metrik ve izleme verilerini toplamak için piyasada yaygın olarak kullanılan APM (Application Performance Monitoring) araçlarından yararlanırız. Uygulamamız ile entegrasyon için de bu aracın kendi kütüphanelerini kullanmamız gerekir. Böyle bir durumda başka bir araca geçmek istersek tüm kodumuzu değiştirmemiz gerekebilir. Bu da aslında vendor-lock dediğimiz bir durumu ortaya çıkarmaktadır.
OpenTelemetry ise vendor-bağımsız bir durum sunar. OTel kütüphanelerini kullandığınız zaman uygulamanızdan alınan veriler (izlemeler, metrikler, loglar) OpenTelemetry Collector aracılığı ile veya doğrudan, OpenTelemetry standartlarının destekleyen herhangi bir backend sistemine aktarılabilir. (Jaeger, Zipkin, Prometheus vb.) Böyle bir durumda kazanacağınız esneklik ile backend uygulamasındaki yapacağınız sistemsel değişikliklerden (ürün değiştirme vb.) mevcut uygulama kodunuz etkilenmeyecektir.
Ayrıca, OpenTelemetry Cloud Native Computing Foundation (CNCF) altında bulunan çok büyük topluluğa sahiptir. Bu da topluluk tarafından desteklenen hem yardım hem de yeni geliştirmelerin aktif bir şekilde olduğunu göstermektedir.
İzlemeler, Metrikler ve Loglar
Dağıtık İzleme (Distributed Tracing)
Dağıtık izleme, bir isteğin dağıtık bir mimari içinde nasıl hareket ettiğini izlemeye yaramaktadır.
Dağıtık izlemede iki önemli terim vardır:
-
Span: Bir izlemenin en küçük yapısıdır. Bir Span, bir istekteki tek bir birimi veya iş adımını temsil etmektedir. Bir istek alındığı zaman bir span olacaktır. Yine aynı istek akışı sırasında bir veri tabanı çağırımı yapacak olur ise o da ayrı bir span olarak kayıt edilecektir. Her Span’in bir başlama ve bitiş zamanı, adı ve ilgili olduğu servis bilgisi vardır.
-
Trace: İsteğin tamamlanması için oluşan Span’lerin bir araya gelerek oluşturdukları akışında kendisidir. Trace o akış içerisindeki tüm Span’lerin hiyerarşik ve sıralı bir şekilde tüm akışı gösterir.
Burada Context Propagation (bağlam aktarımı) OpenTelemetry için önemli kavramlardan biridir. Bir istek farklı servis ve bileşenlere yayıldıkça OpenTelemetry bu Span’leri birbirine bağlamak için TraceId bilgisini diğer servislere de taşır. Böylelikle tüm akış tek TraceId altında Span’ler şeklinde kayıt altına alınmış olur.
Dağıtık izleme sayesinde, bu karmaşık süreçte hangi adımın yavaşladığını veya nerede bir hata oluştuğunu görsel olarak net bir şekilde görebilirsiniz.
Metrics (Metrikler) :
Metrikler uygulamamızın veya sistemimizin zamanla performansının ve sağlığını anlamak için topladığımız sayısal ölçümlerdir. Trace bilgileri isteklerin tekil akışlarına odaklanırken, metrikler sistemin genel durumu hakkında bilgi sahibi olmamızı sağlar.
OpenTelemetry metrikleri genellikle dört ana türde toplar:
-
Sayaçlar (Counters): Sadece artan veya bazen azalan kümülatif değerleri ölçer. Toplam istek, hata veya tamamlanan işlem sayısı gibi değerler için kullanılır. Sayılar sadece yükselir veya sabit kalır.
-
Göstergeler (Gauges): Anlık değerler, bir sistemin o andaki durumunu gösterir. CPU kullanımı yüzdesi, mevcut bellek miktarı, kuyruktaki mesaj sayısı veya bir servise bağlı aktif kullanıcı sayısı gibi değerler bu kapsamdadır. Bu değerler zamanla artabilir veya azalabilir.
-
Histogramlar (Histograms): Bir değerin (örn. istek gecikmesi, işlem süresi) dağılımını ölçer. Değerleri önceden belirlenmiş gruplara (bucket) ayırıp, her gruptaki örnek sayısını kaydeder. Bu, ortalama değerin ötesinde, değerlerin çoğunluğunun hangi aralıkta olduğunu ve uç değerlerin sıklığını görmenizi sağlar. Örneğin, isteklerin %95’inin 200 ms’den hızlı yanıt verdiğini böyle anlayabilirsiniz.
-
Özetler (Summaries): Özetler, histogramlara benzer şekilde dağılımı ölçer ancak belirli yüzdelikleri (medyan, 95., 99. yüzdelik gibi) hesaplar. Histogramlar daha fazla veri toplarken, özetler genellikle daha fazla arka uç hesaplama gerektirir.
Metrikler, sisteminizin genel olarak durumunu görmek için kullanılan ölçüm değerleridir. Zaman içindeki değişiklikleri görselleştirerek hızlı bir şekilde sorunları tespit etmemizi sağlar.
Logs (Loglar) :
Loglar, bir uygulamanın çalışması sırasında meydana gelen belirli olaylar, durumlar veya işlemler hakkında yazılan metinsel kayıtlardır. Geliştiricilerin ve operasyon ekiplerinin uygulamanın iç işleyişi hakkında bilgi edinmeleri, hataları görmeleri ve sorunları tespit etmeleri için kullanılmaktadır.
Loglar genellikle iki ana türle olabilir:
-
Yapılandırılmamış Loglar (Unstructured Logs): En yaygın kullanılan tiptir. Okunması en kolay log kayıtları olarak tutulmaktadırlar. Genellikle serbest yazı şeklinde tutulurlar. (
[ERROR] 2025-04-17 22:30:15 - Veri tabanı bağlantı hatası: Connection timed out.) -
Yapılandırılmış Loglar (Structured Logs): JSON, XML veya key-value çiftleri gibi makine tarafından kolayca ayrıştırılabilen yapıdalardır. Her log kaydı, belirli anahtarlar (alanlar) ve değerler içerir. (
"timestamp": "2023-10-27T10:30:15Z", "level": "ERROR", "message": "Veritabanı bağlantı hatası", "error_type": "Connection timed out", "service": "auth-service"}. Yapılandırılmış loglar, log yönetim sistemlerinde daha kolay aranabilir, filtrelenebilir ve analiz edilebilir.
OpenTelemetry bir log kaydı oluştuğu zaman Context Correlation kullanarak o olan TraceId ve SpanId bilgisini kullanarak bu logu kayıt altına alır. Böylelikle bütünlük özel atılan loglarda da bozulmamış olur.
Özet olarak anlatmak istersek;
-
Metrikler: Size sistemin genel sağlığı ve performansı hakkında yüksek seviyeli, toplanmış sayılar sunar (“İstek oranımız yüksek”, “CPU kullanımı %80”). Bunlar size bir şeylerin yanlış olduğunu veya olağandışı bir durum yaşandığını ilk fark etmenizi sağlar.
-
İzlemeler: Bir istek veya işlem neden yavaş veya hatalı davrandı sorusuna cevap vermenize yardımcı olur. Metriklerde bir anormallik gördüğünüzde, o anormallik sırasında gerçekleşen tekil isteklerin izlemelerine bakarak sorunun nerede olduğunu tespit edebiliriz.
-
Loglar: Bir hatanın veya anormalliğin detaylarını ve nedenini anlamanızı sağlar. İzlemede sorunun nerede olduğunu bulduğunuzda, o Span ile ilişkili loglara bakarak hatanın tam olarak ne olduğunu, hangi hata mesajını verdiğini, belki hangi parametrelerle çağrıldığını görürsünüz.
OpenTelemetry Mimarisi ve Bileşenleri
OpenTelemetry mimarisi bir pipeline gibi çalışmaktadır. En baştan verinin kayıt altına alındığı ve gösteriminin sağlandığı en sona kadar bileşenler şu şekildedir.
-
Enstrümantasyon (Instrumentation): Uygulamanızın içine yerleştirilen kod parçacıkları veya kütüphanelerdir. Bunlar uygulamanız çalışırken gözlemlenebilirlik verilerini (izlemeler, metrikler, loglar) toplar.
-
SDK (Software Development Kit): Enstrümantasyonun kullanıldığı, uygulamanızın içinde çalışan OpenTelemetry kütüphanesidir. Toplanan veriyi işler, standart OTel formatına dönüştürür ve bir sonraki adıma (genellikle Collector’e) gönderir.
-
Collector: Toplanan gözlemlenebilirlik verilerini (izlemeler, metrikler, loglar) farklı kaynaklardan (uygulamalar, altyapı vb.) alan, işleyen (filtreleme, dönüştürme, gruplama) ve çeşitli backendlere yönlendiren bir aracıdır.
-
Exporter (Dışa Aktarıcı): Toplanan ve işlenen veriyi belirli bir backend sisteminin anlayacağı formata dönüştürüp o sisteme gönderen bileşendir. Veriyi doğru adrese ve doğru dilde gönderen “postacı” gibidir.
-
Backend: Toplanan gözlemlenebilirlik verilerinin depolandığı, analiz edildiği ve görselleştirildiği son noktadır. Bu, bir APM aracı (Datadog, New Relic), bir izleme sistemi (Jaeger, Zipkin), bir metrik veritabanı (Prometheus, InfluxDB) veya bir log yönetim sistemi (ELK Stack, Splunk) olabilir.

Enstrümantasyonun Rolü
Enstrümantasyon, uygulamanızın içine eklediğiniz ve uygulamanız çalışırken gözlemlenebilirlik verilerini (izlemeler, metrikler, loglar) toplayan kod veya yapılandırmadır. Bir sensör gibi çalışarak bu verileri kayıt altına alır.
OpenTelemetry’de enstrümantasyon iki şekilde yapılabilir:
-
Otomatik Enstrümantasyon (Automatic Instrumentation): Bu kullanım kodunuzda hiç bir değişiklik yapmadan otomatik olarak verileri toplayan yöntemdir. Genellikle özel kütüphaneler aracılığı ile yapılır. Bu kütüphaneler, yaygın kullanılan framework’leri, veri tabanı sürücülerini veya HTTP istemcilerini hedefler ve bu bileşenler etkileşime girdiğinde otomatik olarak Spanler oluşturur, metrikleri günceller veya log bağlamını ekler.
-
Manuel Enstrümantasyon (Manual Instrumentation): Bu yöntemde, uygulamanızın koduna OpenTelemetry SDK’sını kullanarak gözlemlenebilirlik verisi toplamak için açıkça kod yazabiliriz. Belirli bir iş metodunun ne kadar sürdüğünü ölçmek, özel bir iş akışının adımlarını izlemek veya uygulamamıza özel metrikler tanımlamak istediğimizde bu yöntemi kullanabiliriz.
OpenTelemetry SDK’ları ise, bu yapıların topladığı ham veriyi alan ve OTel standardına uygun hale getiren, işleyen ve bir sonraki adıma hazır hale getiren kütüphanelerdir.
OpenTelemetry Collector
Collector uygulamalarımızdan gelen gözlemlenebilirlik verilerini (izlemeler, metrikler, loglar) alan, bu veriyi işleyen ve farklı backendlere gönderen bağımsız bir araç olarak hizmet vermektedir.
Collertor’un üç ana işlevi vardır:
-
Alma (Receiving): Farklı kaynaklardan çeşitli formatlarda gözlemlenebilirlik verisi alabilir. OpenTelemetry Protocol (OTLP) en yaygın kullanılan format olsa da, Jaeger, Zipkin, Prometheus gibi diğer popüler formatları da alabilir.
-
İşleme (Processing): Collector aldığı veriler üzerinde farklı işlemler yapabilmektedir. - Filtereleme: Belirli alanları istenildiği zaman kayıt edilen verilerden çıkarabilir. - Dönüştürme: Berilere ek metadata ekleyebilir. - Gruplama / Toplu İşleme: Küçük veri parçalarının birleştirerel aktarım maliyetini düşürür. - Örnekleme: Tüm izleme verilerini değil, yalnızca belirli bir yüzdesini veya belirli kriterlere uyanları saklayabilir.
Collector kullanmanın yararları
-
Ayrıştırma (Decoupling): Uygulamalarımızın direkt olarak backend’e bağımlı olmasının engeller. Uygulama verileri sadece Collector’e gönderir, Collector ise veriyi nereye gönderceğini kendisi bilir. Böylelikle bir gün backend yapımızı değiştirmek istersek Collector üzerinden düzenleme ile değişikliği yapabiliriz. Bu noktada mevcut uygulama kodumuzda hiç bir değişiklik yapmamıza gerek kalmayacaktır.
-
Toplu İşleme ve Sıkıştırma (Batching & Compression): Veriyi toplu halde göndererek ağ trafiğini ve dışa aktarma yükünü azaltır.
-
Yönlendirme ve Çoğaltma (Routing & Multiplexing): Farklı kaynaklardan gelen veriyi farklı backendlere yönlendirebilir veya aynı veriyi birden çok backende kopyalayabilir.
-
Veri İşleme Yetenekleri: Uygulamalarda yapmak istemeyeceğiniz filtreleme, zenginleştirme gibi işlemleri merkezi olarak yapar.
-
Güvenlik: Verinin hassas kısımlarını filtreleyebilir veya maskeleyebilir.
Collector, özellikle mikro servis veya dağıtık sistemlerde gözlemlenebilirlik stratejisinin omurgasıdır.
Exporterlar (Dışa Aktarıcılar)
Exporter’ların görevi toplanan gözlemlenebilirlik verisini (izlemeler, metrikler ve loglar) berlirli bir backend sisteminin anlayacağı formata çevirerek göndermektir.
Bu yapılar genellikle Collector içinde bir bileşen olarak yapılandırılır ve çalışırlar. Collector veriyi işledikten sonra ilgili Exporter’a teslim eder. OpenTelemetry projesi, bir çok popüler backend sistemi için Exportar’lar sunmaktadır. İhtiyaca uygun olanı projemize ekleyerek kullanabiliriz.
Backend Sistemleri
Bu sistemler OpenTelemetry veri toplama akışının son durağıdır. Exporterlar tarafından gönderilen gözlemlenebilirlik verilerinin (izlemeler, metrikler, loglar) depolandığı, indekslendiği, analiz edildiği ve görselleştirildiği yerlerdir.
Verilerin aktarıldığı backend sistemleri sayesinde;
-
Trace bilgilerini görselleştirerek isteklerin servisler arasındaki akışını görebiliriz.
-
Metrik bilgilerini dashboard’lar sayesinde toplu analiz edebiliriz.
-
Loglar üzerinde filtreleme ve arama yaparak hataları analiz edebiliriz.
-
TraceId bilgisi üzerinden logları eşleyerek hataların özel nedenlerini bulabiliriz.
Backend sistemleri de kullanımlarına göre farklı tiplere ayrılmaktadır. Bunlar;
-
APM (Application Performance Monitoring) Araçları: İzleme, metrik ve log bilgilerini genellikle tek bir platformda birleştirip sunarlar. Böylelikle kapsamlı bir performans izleme aracı olarak bize yardımcı olurlar. Dynatrace bu ürünlere güzel bir örnek olabilir.
-
Dağıtık İzleme Sistemleri: Özellikle izleme verilerini görselleştirmeye odanlanan uygulamalardır. Jaeger bu tip uygulamalara örnek olarak verilebilir.
-
Metrik Veri Tabanları ve Görselleştirme Araçları: Metrik verilerini depolamak ve sorgulamak için kullanılan uygulamalardır. Örnek olarak Prometheus verilebilir.
-
Log Yönetim Sistemler: Logları toplamak, depolamak, aramak ve analiz etmek için kullanılan araçlardır. ELK Stack (Elasticsearch, Logstash, Kibana) bu uygulamalar için örnek verilebilir.
OpenTelemetry, veri toplama (Enstrümantasyon, SDK, Collector) ve veri dışa aktarma (Exporter) işlevlerini backend seçiminden bağımsız olarak sunar, böylece istediğiniz backend çözümünü seçme özgürlüğü sağlar ve vendor lock-in problemlerini ortadan kaldırır.
ASP.NET Core Api OpenTelemetry Entegrasyonu
OpenTelemetry’nin özelliklerine, mimarisine ve çalışma biçimine baktık. Şimdi de bir Api projemize nasıl entegre edeceğiz? Nasıl logları göreceğiz? Bu konuları beraber inceleyelim.
Öncelikle gözlemlenebilirlik verilerimizi kayıt altına alacağımız Collector ve Jaeger kurulumlarımızı yapalım. Bunun için Docker kullanacağız ve container olarak uygulamaları ayağa kaldıracağız. Sonrasında Bir api projesi oluşturup entegrasyonumuzu yapacağız. Sonrasında ise verilerimizin akışını kontrol edeceğiz.
Bu kurulumları yapmanın en kolay yolu Docker Compose kullanmaktır. Öncelikle belirli bir klasör oluşturup docker-compose.yaml dosyamızı bu klasör içinde oluşturalım.
version: "3.8"
services:
# OpenTelemetry Collector (Contrib sürümü, daha fazla bileşen içerir)
otel-collector:
image: otel/opentelemetry-collector-contrib:latest # Contrib sürümünü kullanıyoruz
command: ["--config=/etc/otel-collector-config.yaml"] # Yapılandırma dosyasını belirtiyoruz
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml # Yerel yapılandırma dosyasını bind mount ediyoruz
ports:
- "4317:4317" # OTLP gRPC standard port
- "4318:4318" # OTLP HTTP standard port
- "13133:13133" # Sağlık kontrolü (health check) portu
- "8888:8888" # İç metrikler için port
depends_on:
- jaeger # Jaeger servisi çalıştıktan sonra başlasın
# Jaeger All-in-One (İzleme görselleştirme için)
jaeger:
image: jaegertracing/all-in-one:latest # Tek bir containerda Jaeger
ports:
- "16686:16686" # Jaeger UI portu
- "14250:14250" # Jaeger gRPC alıcı portu (Collector buraya gönderecek)
- "14268:14268" # Jaeger HTTP alıcı portu
- "6831:6831/udp" # Jaeger Thrift compact UDP (eski formatlar için)
- "6832:6832/udp" # Jaeger Thrift binary UDP (eski formatlar için)
Bu docker-compose.yml dosyası iki servis tanımlar: otel-collector ve jaeger. Collector, yerel bir yapılandırma dosyasını (otel-collector-config.yaml) kullanacak şekilde ayarlanmıştır.
Şimdi Collector için basit bir otel-collector-config.yaml dosyası oluşturalım (bu dosyayı docker-compose.yml ile aynı klasöre koymamız gerekiyor):
receivers:
# Uygulamanızdan OTLP verisi alacak
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317 # gRPC üzerinden alma
processors:
# Basit bir batch processor (opsiyonel ama iyi pratik)
batch:
exporters:
# İzleme verisini Jaeger'a gönderecek
otlp:
endpoint: jaeger:4317 # Jaeger containerının adını ve gRPC portunu kullanıyoruz
tls:
insecure: true # Yerel test için TLS'i kapatıyoruz
service:
pipelines:
traces: # İzleme veri hattı
receivers: [otlp] # otlp receiver'dan al
processors: [batch] # batch processor'dan geçir
exporters: [otlp] # otlp exporter'a gönder
Ardından docker-compose.yml dosyamızın bulunduğu klasöre giderek aşağıdaki komutu çalıştıracağız ve container içinde uygulamalarımız ayağa kalkacaktır.
docker compose -f 'docker-compose.yml' up -d --build
Eğer işlem başarılı bir şekilde tamamlanırsa http://localhost:16686/search adresi üzerinden Jaeger uygulamamıza ulaşabiliriz.

Şimdi de bir ASPNET Core Web Api projesi oluşturarak OpenTelemetry uyarlamamızı yapacağız. Ardından hem otomatik olarak hem de kendimiz loglarımızı ekleyerek Jaeger üzerinden bu logların akışının kontrol edeceğiz.
Yeni bir ASPNET Core Web Api oluşturup ismini OpenTelemetryWebApi olarak veriyoruz.

İlk olarak projemize OpenTelemetry paketlerini ekleyelim. Ardından bu paketlerin uyarlamalarının yapacağız.
Ekleyeceğimiz paketler aşağıdaki gibi olacaklar. Paketleri aşağıdaki gibi csproj dosyasına ekleyebilir veya npm ile tek tek ekleyebilirsiniz.
<PackageReference Include="OpenTelemetry" Version="1.11.2" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.11.2" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.11.2" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.11.2" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.11.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.11.1" />
<PackageReference Include="OpenTelemetry.Instrumentation.SqlClient" Version="1.11.0-beta.2" />
OpenTelemetry’nin güzel özelliklerinden bir tanesi de otomatik olarak eklediğiniz paketlere göre logları toplamasıdır. Örnek olarak ismi http ile biten paket eklediğimiz ve tanımı yaptığımız zaman uygulamamızdan yapılan HTTP istekleri otomatik olarak loglanacaktır. Böylelikle, otomatik loglar dışında hata ve akışlarımızı kontrol altına alabilmek için ek logları kendimiz ekleyecek her metot ve işlem için tek tek loglama kodları yazmanın da önüne geçmiş oluyoruz.
Şimdi, eklediğimiz paketler çin uygulamamızda bir configurasyon yapalım. Program.cs (Startup.cs) içinde bu konfigurasyonu yapacağız. Yalnız, konfigürasyon için gerekli bilgileri de appsettings.json dosyamızda tanımladığımız key’ler üzerinden alacağız. Böylelikle, OTel ayarlarını istediğiniz zaman kod değişikliği yapmadan appsettings.json üzerinden değiştirebileceksiniz.
Biz biraz az veri ile bunu yapacağız fakat siz isterseniz çeşitlendirebilirsiniz.
appsettings.json dosyamıza tanımları ekledikten sonra aşağıdaki gibi olacaktır.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"OpenTelemetry": {
"ServiceName": "OpenTelemetryWebApi",
"ResourceAttributes": {
"Environment": "Development",
"Version": "1.0.0"
},
"Tracing": {
"Enabled": true,
"Sources": [
"OpenTelemetryWebApi"
]
},
"Instrumentation": {
"AspNetCore": {
"Enabled": true
},
"HttpClient": {
"Enabled": true
},
"SqlClient": {
"Enabled": false
}
},
"Exporters": {
"Console": {
"Enabled": true
},
"OTLP": {
"Enabled": true,
"Endpoint": "http://localhost:4317",
"Protocol": "Grpc"
}
}
}
}
Burada OpenTelemetry’i yönetebilmek için gerekli bazı bilgileri eklemiş olduk. Şimdi öncelikle Options Pattern kullanarak bu bilgileri uygulamamız üzerinden nasıl kullanacağımıza bakalım.
Eklediğimiz appsettings.json bilgilerine uygun şekilde bir sınıf yapısı ekliyoruz projemize.
public class OpenTelemetryOptions
{
public string ServiceName { get; set; } = string.Empty;
public ResourceAttributesOptions ResourceAttributes { get; set; } = new();
public TracingOptions Tracing { get; set; } = new ();
public InstrumentationOptions Instrumentation { get; set; } = new();
public ExportersOptions Exporters { get; set; } = new();
}
public class ResourceAttributesOptions
{
public string Environment { get; set; } = string.Empty;
public string Version { get; set; } = string.Empty;
}
public class TracingOptions
{
public bool Enabled { get; set; }
public List<string> Sources { get; set; } = new();
}
public class HttpClientOptions
{
public bool Enabled { get; set; } = false;
}
public class SqlClientOptions
{
public bool Enabled { get; set; } = false;
}
public class AspNetCoreOptions
{
public bool Enabled { get; set; } = false;
}
public class InstrumentationOptions
{
public HttpClientOptions HttpClient { get; set; } = new();
public SqlClientOptions SqlClient { get; set; } = new();
public AspNetCoreOptions AspNetCore { get; set; } = new();
}
public class ConsoleOptions
{
public bool Enabled { get; set; } = true;
}
public class OtlpOptions
{
public bool Enabled { get; set; } = false;
public string Endpoint { get; set; } = string.Empty;
public string Protocol { get; set; } = string.Empty;
}
public class ExportersOptions
{
public ConsoleOptions Console { get; set; } = new();
public OtlpOptions Otlp { get; set; } = new();
}
Şimdi, eklediğimiz konfigürasyon ayarları ile birlikte OpenTelemetry yapısını uygulamamıza uyarlayalım.
Program.cs sınıfımızı aşağıdaki şekilde düzenliyoruz.
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Configure OpenTelemetryOptions
builder.Services.Configure<OpenTelemetryOptions>(builder.Configuration.GetSection("OpenTelemetry"));
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<OpenTelemetryOptions>>().Value;
builder.Services.AddOpenTelemetry()
.ConfigureResource(resource =>
{
resource.AddService(options.ServiceName).AddAttributes(new Dictionary<string, object>
{
{ "environment", options.ResourceAttributes.Environment },
{ "version", options.ResourceAttributes.Version }
});
})
.WithTracing(tracing =>
{
if (!options.Tracing.Enabled)
{
return;
}
if (options.Instrumentation.AspNetCore.Enabled)
{
tracing.AddAspNetCoreInstrumentation(tracing => tracing.RecordException = true);
}
if (options.Instrumentation.HttpClient.Enabled)
{
tracing.AddHttpClientInstrumentation(tracing => { tracing.RecordException = true; });
}
if (options.Instrumentation.SqlClient.Enabled)
{
tracing.AddSqlClientInstrumentation(tracing => { tracing.RecordException = true; });
}
foreach (var source in options.Tracing.Sources)
{
tracing.AddSource(source);
}
if (options.Exporters.Console.Enabled)
{
tracing.AddConsoleExporter();
}
if (options.Exporters.Otlp.Enabled)
{
tracing.AddOtlpExporter(otlpOptions =>
{
otlpOptions.Endpoint = new Uri(options.Exporters.Otlp.Endpoint);
otlpOptions.Protocol = options.Exporters.Otlp.Protocol switch
{
"Grpc" => OpenTelemetry.Exporter.OtlpExportProtocol.Grpc,
"HttpProtobuf" => OpenTelemetry.Exporter.OtlpExportProtocol.HttpProtobuf,
_ => OpenTelemetry.Exporter.OtlpExportProtocol.Grpc
};
});
}
});
// Add services to the container.
builder.Services.AddHttpClient();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
}
Aşağıdaki satırlar ile appsettings.json içerisinde tanımlamış olduğumuz konfigürasyon tanımlarının alabiliyor ve kodumuzda kullanılabilir hale getiriyoruz.
builder.Services.Configure<OpenTelemetryOptions>(builder.Configuration.GetSection("OpenTelemetry"));
var options = builder.Services.BuildServiceProvider().GetRequiredService<IOptions<OpenTelemetryOptions>>().Value;jemize OpenTelemetryController adında yeni bir controller ekliyoruz ve iki adet yeni metot ekliyoruz.
Eklediğimiz OTel özelliklerinin bazılarını açıklamak gerekirse;
AddOpenTelemetry(): OpenTelemetry yapılandırmasını başlatır.
WithTracing(): İzleme (Tracing) özel yapılandırmasını başlatır.
AddSource(): Kendi kodunuzda tanımlayacağınız ActivitySource nesnelerini belirtir. Manuel izleme için gereklidir.
Add...Instrumentation(): Otomatik enstrümantasyon paketlerini etkinleştirir. Eklediğiniz her ilgili NuGet paketi için burada Add[PackageName]Instrumentation() metodunu çağırmanız gerekir.
AddOtlpExporter() veya AddConsoleExporter() gibi metodlarla toplanan izleme verisinin nereye gönderileceğini belirlersiniz.
Son olarak projemize OpenTelemetryController.cs adında bir controller ekleyerek aşağıdaki şekilde düzenliyoruz.
using Microsoft.AspNetCore.Mvc;
using System.Diagnostics;
namespace OpenTelemetryWebApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class OpenTelemetryController : ControllerBase
{
private static readonly ActivitySource ActivitySource = new ActivitySource("OpenTelemetryWebApi");
private readonly IHttpClientFactory _httpClientFactory;
public OpenTelemetryController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet("ApiCall")]
public IActionResult ApiCall()
{
var httpClient = _httpClientFactory.CreateClient();
var response = httpClient.GetAsync("https://jsonplaceholder.typicode.com/users/1").Result;
if (response.IsSuccessStatusCode)
{
var data = response.Content.ReadAsStringAsync().Result;
return Ok(data);
}
else
{
return StatusCode((int)response.StatusCode, "Error fetching data");
}
}
[HttpGet("ManuelLog")]
public IActionResult ManueLog(string customerValue)
{
using (var activity = ActivitySource.StartActivity("ManualLogOperation"))
{
activity?.SetTag("customerValue", customerValue);
activity?.SetTag("operation", "manual_logging");
activity?.SetTag("timestamp", DateTime.UtcNow);
activity?.AddEvent(new ActivityEvent("Start processing"));
System.Threading.Thread.Sleep(500);
activity?.AddEvent(new ActivityEvent("End processing"));
}
return Ok("Metrics data with manual logging");
}
}
Burada iki adet api endpoint eklemiş olduk. ApiCall ismindeki endpoint bir http rest çağırımı yapacak. OTel bu çağırımı otomatik olarak öncelikle console üzerinde loglayacak ve sonra bunu Otlp ile Jaeger UI’a gönderecek.
İkinci ManuelLog isimli endpoint ise standart bir akışı uyguluyor ve biz kendi istediğimiz gibi bir özel log atıyoruz. Bu log içerisine SetTag ile istediğimzi akış içerisinde kullanılan verileri ekleyebiliriz. Bu bilgis de yine console üzerinden izlenebilecek ve ardından Jaeger UI’a gönderilecektir.
Şimdi oluşturduğumuz bu endpointler üzerinden oluşan logları kontrol edelim.
Projemizi çalıştırıp her iki endpoint çağırımını yapıyoruz.

Ardından console üzerinde oluşan logları görebiliriz.


Burada dikkat ederseniz kırmızı ile işaretlenmiş satırlarda bizim özellikle akış içerisinde olan özel olarak loglamak istediğimiz bilgilerin de loglandığını görebilirsiniz.
Şimdi de Jaeger UI üzerinden bu logları kontrol edelim.

Gördüğünüz gibi Jaeger UI üzerinden de aynı logları görüntüleyebiliriz. Otlp aracılığı ile uygulamamız üzerinden gönderilen log bilgileri Jaeger UI’ın anlayacağı şekle dönüştürülerek kayıt altına alınmış durumda.
Beraber OpenTelemetry nedir? Temel olarak nasıl kullanılır? öğrenmeye çalıştık. Umarım OTel kullanımı ile ilgili temel bilgileri anlatabilmişimdir.
Okuduğunuz için teşekkür ediyorum.
Yazı sırasında oluşturduğumuz projeye aşağıdaki bağlantıdan ulaşabilirsiniz.
GitHub - onurkarakus/OpenTelemetryWebApi: ASPNET Core Web Api Open Telemetry Example *ASPNET Core Web Api Open Telemetry Example. Contribute to onurkarakus/OpenTelemetryWebApi development by creating an…*github.com