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.
Aynı temel uygulamayı kullanacağım: Kotlin'de kodlanmış basit bir Spring Boot uygulaması. Tek bir uç nokta sunuyor.
entry()
olarak adlandırılırintermediate()
adında başka bir fonksiyonu çağırırRestTemplate
yerine geçen bir WebClient
örneği kullanırentry()
fonksiyonu bunu bulursa, daha fazla ilerlemez
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, "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 İzlemeye başlamak için birkaç bağımlılığın eklenmesi gerekir:
org.springframework.boot:spring-boot-starter-actuator
io.micrometer:micrometer-tracing
io.micrometer:micrometer-tracing-bridge-otel
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
İşte sonuç:
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.
İş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:
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"
/v1/traces
ekler
Herhangi bir yapılandırma yapmadan aşağıdaki izleri elde ederiz:
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.
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:
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.
Önceki versiyonda olduğu gibi, @WithSpan
anotasyonuyla izleri ekleyebiliriz. Tek fark, entry()
fonksiyonunu da anotlamamız gerektiğidir. Varsayılan olarak izlenmemektedir.
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ı