paint-brush
Spring Boot'ta OpenTelemetry İzleme: Java Agent ve Micrometer Arasında Seçim Yapmakile@nfrankel
205 okumalar

Spring Boot'ta OpenTelemetry İzleme: Java Agent ve Micrometer Arasında Seçim Yapmak

ile Nicolas Fränkel8m2024/08/11
Read on Terminal Reader

Çok uzun; Okumak

Bu gönderi, Java Agent v1, Java Agent v2 ve Micrometer Tracing kullanan bir Spring Boot uygulamasındaki OpenTelemetry izleme çözümlerini karşılaştırır. Yapılandırma, işlevsellik ve izleme yeteneklerindeki farklılıkları vurgulayarak, her yaklaşımın gözlemlenebilirlik için etkinliği ve uygulaması hakkında içgörüler sunar.
featured image - Spring Boot'ta OpenTelemetry İzleme: Java Agent ve Micrometer Arasında Seçim Yapmak
Nicolas Fränkel HackerNoon profile picture

OpenTelemetry Tracing demom iki Spring Boot bileşeni içeriyor. Biri Java aracısını kullanıyor ve yakın zamanda v1.x'ten v2.x'e yükselttiğimde farklı bir davranış fark ettim. Diğerinde, GraalVM yereline derlediğim için Micrometer Tracing kullanıyorum ve Java aracılarını işleyemiyor.



Bu yazımda bu üç yaklaşımı karşılaştırmak istiyorum: Java Agent v1, Java Agent v2 ve Micrometer Tracing.

Temel uygulama ve altyapısı

Aynı temel uygulamayı kullanacağım: Kotlin'de kodlanmış basit bir Spring Boot uygulaması. Tek bir uç nokta sunuyor.


  • Uç noktanın ötesindeki fonksiyon entry() olarak adlandırılır
  • intermediate() adında başka bir fonksiyonu çağırır
  • İkincisi, yukarıdaki uç noktaya bir çağrı yapmak için RestTemplate yerine geçen bir WebClient örneği kullanır
  • Sonsuz döngüden kaçınmak için özel bir istek başlığı geçiriyorum: entry() fonksiyonu bunu bulursa, daha fazla ilerlemez


Örnek uygulama sıra diyagramı


Aşağıdaki koda çevrilir:


 @SpringBootApplication class Agent1xApplication @RestController class MicrometerController { private val logger = LoggerFactory.getLogger(MicrometerController::class.java) @GetMapping("/{message}") fun entry(@PathVariable message: String, @RequestHeader("X-done") done: String?) { logger.info("entry: $message") if (done == null) intermediate() } fun intermediate() { logger.info("intermediate") RestClient.builder() .baseUrl("http://localhost:8080/done") .build() .get() .header("X-done", "true") .retrieve() .toBodilessEntity() } }


Her kurulum için iki aşamayı kontrol edeceğim: OpenTelemetry'nin etkinleştirildiği birincil aşama ve ek dahili aralıklar oluşturmak için bir özelleştirme aşaması.

Mikrometre İzleme

Mikrometre İzleme, "tedarikçiden bağımsız bir uygulama gözlemlenebilirlik cephesi" olan Mikrometre'den kaynaklanmaktadır.


Micrometer Tracing, en popüler izleyici kütüphaneleri için basit bir cephe sunar ve JVM tabanlı uygulama kodunuzu satıcıya bağlı kalmadan enstrümanlamanıza olanak tanır. İzleme toplama etkinliğinize çok az veya hiç ek yük eklemeden izleme çabanızın taşınabilirliğini en üst düzeye çıkarmak için tasarlanmıştır.


-- Mikrometre İzleme sitesi


Mikrometre İzlemeye başlamak için birkaç bağımlılığın eklenmesi gerekir:


  • Spring Boot Aktüatörü, org.springframework.boot:spring-boot-starter-actuator
  • Mikrometre İzlemenin kendisi, io.micrometer:micrometer-tracing
  • Hedef izleme arka uç API'sine bir "köprü". Benim durumumda, bu OpenTelemetry'dir, dolayısıyla io.micrometer:micrometer-tracing-bridge-otel
  • Arka uç için somut bir ihracatçı, io.opentelemetry:opentelemetry-exporter-otlp


Spring Boot ebeveyninde sürümler zaten tanımlı olduğundan bir BOM'a ihtiyacımız yok.


Yine de, iki çalışma zamanı yapılandırma parametresine ihtiyacımız var: İzler nereye gönderilmeli ve bileşenin adı nedir. Bunlar MANAGEMENT_OTLP_TRACING_ENDPOINT ve SPRING_APPLICATION_NAME değişkenleri tarafından yönetilir.


 services: jaeger: image: jaegertracing/all-in-one:1.55 environment: - COLLECTOR_OTLP_ENABLED=true #1 ports: - "16686:16686" micrometer-tracing: build: dockerfile: Dockerfile-micrometer environment: MANAGEMENT_OTLP_TRACING_ENDPOINT: http://jaeger:4318/v1/traces #2 SPRING_APPLICATION_NAME: micrometer-tracing #3
  1. Jaeger için OpenTelemetry toplayıcısını etkinleştirin
  2. Jaeger OpenTelemetry gRPC uç noktasına tam URL
  3. OpenTelemetry'nin hizmet adını ayarlayın


İşte sonuç:

Jaeger'de özelleştirmeye gerek kalmadan mikrometre izleri


Micrometer, herhangi bir özelleştirmeye gerek kalmadan HTTP isteklerini alırken ve gönderirken aralıklar oluşturur.


Çerçevenin RestClient gönderim için sihir enjekte etmesi gerekir. Bunun için birincisinin ikincisini örneklendirmesine izin vermeliyiz:


 @SpringBootApplication class MicrometerTracingApplication { @Bean fun restClient(builder: RestClient.Builder) = builder.baseUrl("http://localhost:8080/done").build() }


Manuel aralıkları birkaç şekilde oluşturabiliriz, bunlardan biri OpenTelemetry API'sinin kendisidir. Ancak kurulum çok sayıda hazır kod gerektirir. En basit yol Micrometer'ın Observation API'sidir . Başlıca faydası hem ölçümleri hem de izleri yöneten tek bir API kullanmaktır.


Gözlem API sınıf diyagramı

İşte güncellenmiş kod:


 class MicrometerController( private val restClient: RestClient, private val registry: ObservationRegistry ) { @GetMapping("/{message}") fun entry(@PathVariable message: String, @RequestHeader("X-done") done: String?) { logger.info("entry: $message") val observation = Observation.start("entry", registry) if (done == null) intermediate(observation) observation.stop() } fun intermediate(parent: Observation) { logger.info("intermediate") val observation = Observation.createNotStarted("intermediate", registry) .parentObservation(parent) .start() restClient.get() .header("X-done", "true") .retrieve() .toBodilessEntity() observation.stop() } }


Eklenen gözlem çağrıları oluşturulan izlere yansır:


Observation API ile Jaeger'de mikrometre izleri

OpenTelemetry Aracısı v1

Micrometer Tracing'e bir alternatif, genel OpenTelemetry Java Agent'tır . Başlıca faydası, ne kodu ne de geliştiricileri etkilememesidir; ajan, saf bir çalışma zamanı kapsamlı endişedir.


 java -javaagent:opentelemetry-javaagent.jar agent-one-1.0-SNAPSHOT.jar


Ajan, ortam değişkenleriyle OpenTelemetry'nin yapılandırmasına uyar:


 services: agent-1x: build: dockerfile: Dockerfile-agent1 environment: OTEL_EXPORTER_OTLP_ENDPOINT: http://jaeger:4317 #1 OTEL_RESOURCE_ATTRIBUTES: service.name=agent-1x #2 OTEL_METRICS_EXPORTER: none #3 OTEL_LOGS_EXPORTER: none #4 ports: - "8081:8080"
  1. Protokolü, etki alanını ve portu ayarlayın. Kütüphane /v1/traces ekler
  2. OpenTelemetry'nin hizmet adını ayarlayın
  3. Ne ölçümleri ne de günlükleri dışa aktarın


Herhangi bir yapılandırma yapmadan aşağıdaki izleri elde ederiz:


Agent v1, Jaeger'da özelleştirme olmaksızın izler


Aracı, alınan ve gönderilen istekleri ve Spring ile ilgili açıklamalarla işaretlenmiş işlevleri otomatik olarak izler. İzler, çağrı yığınına göre birbirlerinin içine doğru şekilde yerleştirilmiştir. Ek işlevleri izlemek için kod tabanımıza bir bağımlılık eklememiz gerekir, io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations . Artık daha önce izlenmeyen işlevleri @WithSpan açıklamasıyla açıklayabiliriz.

@WithSpan sınıf diyagramı


value() kısmı, trace'in etiketini yönetirken, kind bir span.kind niteliği olarak çevrilir. Değer, varsayılan olan boş bir dizeye ayarlanırsa, işlevin adını çıktı olarak verir. Benim amaçlarım için, varsayılan değerler yeterince iyidir.


 @WithSpan fun intermediate() { logger.info("intermediate") RestClient.builder() .baseUrl("http://localhost:8080/done") .build() .get() .header("X-done", "true") .retrieve() .toBodilessEntity() }


Beklenen yeni intermediate() izini verir:

Ajan v1, Jaeger'da açıklamalarla izler

OpenTelemetry Aracısı v2

OpenTelemetry bu yılın Ocak ayında ajanın yeni bir ana sürümünü yayınladı. Demomu bununla güncelledim; izler artık yalnızca uygulama istek aldığında ve gönderdiğinde oluşturuluyor.

Jaeger'da Agent v2 izleri özelleştirme olmadan


Önceki versiyonda olduğu gibi, @WithSpan anotasyonuyla izleri ekleyebiliriz. Tek fark, entry() fonksiyonunu da anotlamamız gerektiğidir. Varsayılan olarak izlenmemektedir.

Jaeger'da açıklamalarla Agent v2 izleri


Tartışma

Spring iki nedenden ötürü başarılı oldu: karmaşık çözümleri basitleştirdi, yani EJBs 2 ve rakip kütüphaneler üzerinde bir soyutlama katmanı sağladı. Micrometer Tracing, Zipkin ve Jaeger üzerinde bir soyutlama katmanı olarak başladı ve tamamen mantıklıydı. OpenTelemetry'nin programlama dilleri ve iz toplayıcıları genelindeki çoğu kütüphane tarafından desteklenmesiyle bu argüman tartışmalı hale geldi. Observation API, Metrics ve Traces üzerinde tek bir API kullandığı için Micrometer Tracing'in hala önemli bir faydasıdır.


Java Agent tarafında, OpenTelemetry yapılandırması tüm teknoloji yığınları ve kütüphaneler arasında benzerdir - ortam değişkenleri. v1'den v2'ye yükselttiğimde biraz hayal kırıklığına uğradım, çünkü yeni ajan Spring'i algılamıyor: Spring açıklamalı işlevler varsayılan olarak izlenmiyor.


Sonuç olarak, bu akıllıca bir karardır. Görmek istemediğiniz bazı bölümleri kaldırmaktansa, istediğiniz bölümleri açıkça belirtmek çok daha iyidir.


Yardımı ve yorumu için Jonatan Ivanov'a teşekkürler .


Bu yazının tam kaynak koduna GitHub'dan ulaşabilirsiniz:

Daha ileri gitmek gerekirse:


İlk olarak 3 Ağustos 2024'te A Java Geek'te yayınlandı