OpenTelemetry ile Tracing

Ahmet Şenlik
SabancıDx
Published in
5 min readDec 1, 2022

--

Muhtemelen OpenCensus ve OpenTracing’i duymuşsunuzdur, peki OpenTelemetry?

Dağıtık mimaride uygulama performansını izlemek zorlaşır. Sisteminizin davranışını anlamak istiyorsanız telemetri verilerini toplamak çok önemlidir. Sorun şu ki, piyasadaki hiçbir ürün, uygulamalar ve sistemlerdeki bu verileri toplamak için tek bir araca sahip değildi ta ki OpenTelemetry piyasaya çıkana kadar.

OpenTelemetry Nedir?

OpenTelemetry, servis enstrümantasyonu için açık kaynaklı bir projedir, dağıtık uygulamaları ölçüm yapmaya olanak tanıyan bir dizi API ve SDK’dır. Cloud Native Computing Foundation (CNCF) sponsorluğunda, OpenCensus ve OpenTracing’in dağıtılmış izleme teknolojisinin tek bir araçta birleştirilmesiyle ortaya çıkmıştır.

OpenTelemetry, izlemeler, günlükler ve ölçümler gibi tüm gözlemlenebilirlik sinyalleri için tek bir standart sağlamayı amaçlar.

Sağladığı SDK’lar, entegrasyonlar ve servisler telemetri verilerini toplayıp izleme araçlarına göndermenize olanak tanır.

Enstrümantasyon, uygulama kodunuzun telemetri verileri oluşturmasını sağlama işlemidir.

OpenTelemetry kod enstrümantasyonu, birçok popüler programlama dili için desteklenir:

  • C++
  • .Net
  • Erlang/Elixir
  • Go
  • Java
  • JavaScript
  • PHP
  • Python
  • Ruby
  • Rust
  • Swift

Telemetri Verisi Nedir?

Telemetri verileri, uygulamalarınız tarafından oluşturulan tüm günlükleri, ölçümleri, olayları ve izleri kapsar. Bu verileri yakalamak, uygulamalarınızın ve altyapınızın (t) anında nasıl performans gösterdiğini anlamak için kritik öneme sahiptir.

Telemetre verileri üç ana başlıktan toplanır:

Logs: Yapılandırılmış (önerilen) veya yapılandırılmamış, meta veriler içeren, zaman damgalı bir metin kaydıdır.

Metrics: Çalışma zamanında yakalanan servisle ilgili bir ölçümdür . Mantıksal olarak, bu ölçümlerden birinin yakalanma anı, yalnızca ölçümün kendisinden değil, yakalandığı zamandan ve ilişkili meta verilerden oluşan bir metrik olay olarak bilinir.

Tracing: Kullanıcı veya uygulama tarafından bir istek yapıldığında, servislerin hangi sırayla tetiklendiğine dair bize bilgi verir.

OpenTelemetry(OTEL) Collector

Otel Collector telemetre verilerini alabilen, işleyen ve dışarı aktarabilen bir proxy’dir. Aldığı verileri Jaeger, Prometheus veya Zipkin gibi desteklenen uygulamalara gönderebilir. OpenTelemetry Collector, birden çok veri biçimini yönetme esnekliği sağlar ve telemetri verilerini yönetmek için uygulamadan sorumluluğu alır.

Collector’ün üç ana bileşeni vardır:

Receivers: Verilerin toplayıcıya gelmesini sağlayan bir bileşendir. Birden çok veri kaynağından (OTLP , Jaeger ve Zipkin) gelen verileri alır.

Processors: Telemetre verilerinizi izleme araçlarına aktarmadan hemen önce manipüle etmemizi sağlar.

Exporters: Kullanıcının belirttiğine bağlı olarak telemetri verilerini OTLP, Prometheus ve Jaeger bir veya birden fazla izleme aracına gönderir.

Otel Collector hakkında daha fazla bilgi için aşağıdaki linki inceleyebilirsiniz.

OpenTelemetry Protocol (OTLP)

OTLP, OpenTelemetry tarafından kullanılan telemetri verilerini aktarmak için varsayılan protokoldür. Bu protokol, verilerin her biri için uygulama kodunu değiştirmeye gerek kalmadan çeşitli izleme araçlarına gönderilmesini sağlar.

Şu anda desteklenen iki iletişim protokolü vardır.

  • OTLP/HTTP(protobuf)
  • gRPC

OTLP, telemetri verilerini seri hale getirmek için Protocol Buffers(Protobuf) ve verileri göndermek için gRPC veya HTTP’yi kullanır.

.NET Distrubuted Tracing

Enstrümantasyon katmanınız olarak OpenTelemetry, izleme verilerini depolamak ve görselleştirmek için Jaeger’ı kullanabiliriz.

OpenTelemetry .Net ve .Net Framework’ün resmi olarak desteklenen tüm sürümlerini destekler.

Şimdi iki adet Webapi projesi oluşturup bu projelerden birinin diğerine istek atacak şekilde endpoint oluşturuyoruz.

Dağıtılmış olarak Tracing verilerini toplamak için iki projeye de aşağıdaki OpenTelemetry paketlerini ekliyoruz.

<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.0.0-rc9.9" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.0.0-rc9.9" />
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.9" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.4.0-beta.3" />
<PackageReference Include="OpenTelemetry.Exporter.Jaeger" Version="1.4.0-beta.3" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.4.0-beta.3" />
  • OpenTelemetry.Extensions.Hosting: .NET OpenTelemetry sağlayıcısını kaydeder.
  • OpenTelemetry.Instrumentation.AspNetCore: Gelen web istekleri hakkında telemetri verilerini toplar.
  • OpenTelemetry.Instrumentation.Http: Giden web istekleri hakkında telemetri verilerini toplar.
  • OpenTelemetry.Exporter.Console: Oluşan trace verilerini konsola yazar.
  • OpenTelemetry.Exporter.Jaeger: Oluşan trace verilerini Jaeger’a yazar.
  • OpenTelemetry.Exporter.OpenTelemetryProtocol: Oluşan trace verilerini OTLP protokolü ile gönderir.

Burada bulunan dışında daha bir çok enstürmantasyon paketi mevcut;

MassTransit, EntityFrameworkCore, AWS, Elasticsearch, Redis, SQL Server, PostgreSQL vb.

Daha sonra iki api için program.cs dosyalarına aşağıdaki satırları ekliyoruz.

using OpenTelemetry;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using System.Diagnostics;

var serviceName = "ServiceA";
var serviceVersion = "1.0";
builder.Services.AddOpenTelemetryTracing((b)=>
{
b.AddSource(serviceName)
.SetResourceBuilder(
ResourceBuilder.CreateDefault()
.AddService(serviceName: serviceName, serviceVersion: serviceVersion));
b.AddAspNetCoreInstrumentation();
b.AddHttpClientInstrumentation();
b.AddConsoleExporter();
b.AddJaegerExporter(opt =>
{
//Varsayılan değer ExportProcessorType.Batch
//Diğer seçenek ExportProcessorType.Simple
opt.ExportProcessorType = ExportProcessorType.Batch;
opt.BatchExportProcessorOptions = new BatchExportProcessorOptions<Activity>()
{
//Maksimum kuyruk boyutu, sınıra ulaştığında veri bırakılır
MaxQueueSize = 2048,
//İki veri arasındaki geçikme süresi
ScheduledDelayMilliseconds = 5000,
//Export işleminin zaman aşımı süresi
ExporterTimeoutMilliseconds = 30000,
//Her export işleminin maksimum boyutu
MaxExportBatchSize = 512,
};
});
});

OpenTelemetry de iki adet ExportProcessorType ayarlanabilir:

  • Simple processor: Telemetre verisi oluştuğu anda dışarı aktarılır.
  • Batching processor: Telemetre verileri toplu halde dışarı aktarılır. Bu seçenek işlemin ne sıklıkla ne kadar bir boyutta dışarı aktarılacağına ilişkin ayarlamaları yapabilirsiniz. (Production ortamında daha faydalı olabilir.)

Console Çıktısı:

Activity.TraceId:            97b1158896691315231b1620565ea969
Activity.SpanId: 4199f7e6a8223737
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: OpenTelemetry.Instrumentation.AspNetCore
Activity.DisplayName: WeatherForecast
Activity.Kind: Server
Activity.StartTime: 2022-11-22T20:44:02.7117670Z
Activity.Duration: 00:00:00.0713592
Activity.Tags:
http.host: localhost:7118
http.method: GET
http.scheme: https
http.target: /WeatherForecast
http.url: https://localhost:7118/WeatherForecast
http.flavor: 2.0
http.user_agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36
http.route: WeatherForecast
http.status_code: 200
Resource associated with Activity:
service.name: ServiceA
service.version: 1.0
service.instance.id: 529dd858-d66d-48ac-b670-0fc0f7f5ad53

OTLP kullanarak da verileri dışarı aktarabilirsiniz:

b.AddOtlpExporter(opt =>
{
opt.Protocol = OtlpExportProtocol.Grpc;
opt.Endpoint = new Uri("http://localhost:4317");
});

Trace verilerimiz oluştu fakat bu verileri görsel olarak görmek istersek ne yapmalıyız tam burada Jaeger devreye giriyor.

Jaeger

Dapper ve OpenZipkin’den ilham alan Jaeger, Uber Technologies tarafından açık kaynak olarak Go dilinde yazılmış bir dağıtık sistem izleme aracıdır.

Jaeger All-in-one image’ini aşağıdaki komutla ayağı kaldıralım.

Not: Jaeger All-in-one, varsayılan olarak in-memory depolamayı kullanacak şekilde yapılandırılmıştır. Bu genellikle bellek boyutuyla ilgili sorunlara ve yeniden başlatmalarda tüm verileri kaybolmasına neden olur. Production ortamlarda kurulum yapılırken depolama olarak Cassandra veya ElasticSearch kullanılmasına dikkat edilmelidir. Bunları kullanmak için “SPAN_STORAGE_TYPE=elasticsearch” şeklinde tanımlanabilir.

docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-e COLLECTOR_OTLP_ENABLED=true \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 4317:4317 \
-p 4318:4318 \
-p 14250:14250 \
-p 14268:14268 \
-p 14269:14269 \
-p 9411:9411 \
jaegertracing/all-in-one:1.39

Jaeger arayüzüne http://localhost:16686 adresinden erişilebilir.

Sol taraftan servisimizi seçip “Find Traces” butonuna bastığımızda atılan isteğin gerçekleşmesinin ne sürdüğünü, hangi endpoint üzerinden geldiğini ve ne zaman yapıldığını görüntülenebiliyor.

Seçtiğimiz isteğin detaylarına ve servislerin birbirleriyle etkileşimini trace etmek istediğimiz verilere ait detayları sırasıyla görüntülemiş oluyoruz.

Projenin kaynak kodlarına github üzerinden ulaşabilirsiniz.

Kaynaklar

--

--