【Java(Kotlin)編】OTel のドキュメントを読む

OpenTelemetry Java 入門
特に実装することがないのと、現時点で読んでも理解できない部分が多いのでスキップ。

サンプルによる入門
Java エージェントによる計装。
OTel のサンプルコードによくある Dice を使ったサンプルアプリケーション。

Spring Boot starter
API&SDKを順番に読み進めてもわかりづらいので、Spring Boot のゼロコード計装をさきにやる。

Getting started
以下を追加することで、自動的に OTel の計装がされていた
dependencies {
// otel まわりで必要なパッケージ
implementation(platform(SpringBootPlugin.BOM_COORDINATES))
implementation(platform("io.opentelemetry:opentelemetry-bom:1.44.0"))
implementation(platform("io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:2.10.0"))
implementation("io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter")
}
@RestController
class Controller {
@GetMapping("/ping")
fun ping(): String {
return "pong"
}
}

Extending instrumentations with the API
Span
span の切り方。
package com.example.opentelemetry_zero_code_instrumentation_practice
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.trace.Tracer
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class Controller(openTelemetry: OpenTelemetry) {
private val tracer: Tracer = openTelemetry.getTracer("application")
@GetMapping("/ping")
fun ping(): String {
this.pingSpan()
return "pong"
}
fun pingSpan() {
val span = tracer.spanBuilder("pingSpan").startSpan()
span.end()
return
}
}
Meter
Java API & SDK で実装するためスキップ

Meter
Java API & SDK で実装するためスキップ

SDK configuration
General configuration
dependencies {
// 中略
// 用途
// Propagator Distribution(tracecontext、b3)に必要
// - https://opentelemetry.io/docs/specs/otel/context/api-propagators/#propagators-distribution
// 変更点
// - application.yaml(application.properties)に otel.propagators=tracecontext,b3 を追加するとき
implementation("io.opentelemetry:opentelemetry-extension-trace-propagators")
}
spring:
application:
name: opentelemetry-zero-code-instrumentation-practice
otel:
propagators:
- tracecontext
- b3
Overriding Resource Attributes
Resource Attribute の上書き。スキップ。
Disable the OpenTelemetry Starter
OTEL の SDK を無効化する。これを設定するとシグナルが送信されなくなる。
Programmatic configuration
Exclude actuator endpoints from tracing
Sampler の設定。これを設定すると、トレースがサンプリングされなくなる。
ドキュメントのサンプルでは、actuator を drop する。
dependencies {
// 中略
// 名前
// - opentelemetry-samplers
// Maven Repository の URL
// - https://mvnrepository.com/artifact/io.opentelemetry.contrib/opentelemetry-samplers
// 用途
// - サンプリングのカスタマイズに必要
// - このリポジトリでは、actuator の drop に使用する
implementation("io.opentelemetry.contrib:opentelemetry-samplers:1.33.0-alpha")
implementation("org.springframework.boot:spring-boot-starter-actuator")
}
package com.example.opentelemetry_zero_code_instrumentation_practice
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.contrib.sampler.RuleBasedRoutingSampler
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider
import io.opentelemetry.semconv.UrlAttributes
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class FilterPaths {
// actuator パスをフィルタリングするカスタマイズ
@Bean
fun otelCustomizer(): AutoConfigurationCustomizerProvider {
return AutoConfigurationCustomizerProvider { p ->
p.addSamplerCustomizer { fallback, config ->
RuleBasedRoutingSampler.builder(SpanKind.SERVER, fallback)
.drop(UrlAttributes.URL_PATH, "^/actuator")
.build()
}
}
}
}
たとえば、↓のような actuator が表示されなくなる。
Configure the exporter programmatically
OTLP exporter に設定を追加する。
今回の例だと、認証用の設定を追加する。
戦術の otelCustomizer
を使い回すと起動しなくなるので注意。
package com.example.opentelemetry_zero_code_instrumentation_practice
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class CustomAuth {
@Bean
fun otelCustomizer(): AutoConfigurationCustomizerProvider {
return AutoConfigurationCustomizerProvider { p ->
p.addSpanExporterCustomizer { exporter, _ ->
if (exporter is OtlpHttpSpanExporter) {
exporter.toBuilder()
.setHeaders { headers() }
.build()
} else {
exporter
}
}
}
}
private fun headers(): Map<String, String> {
return mapOf("Authorization" to "Bearer ${refreshToken()}")
}
private fun refreshToken(): String {
// e.g. read the token from a kubernetes secret
return "token"
}
}
Resource Providers
OpenTelemetry Starter を利用すると、以下の Resource が自動的に付与される。
- Distribution Resource Provider
- telemetry.distro.name
- telemetry.distro.version
下記の項目は、所定の箇所に設定(application.yaml、build.gradle.kts、etc...)することで、反映される。
- Spring Resource Provider
- service.name
- service.version
application.yaml
の設定例
// 略
otel:
// 略
resource:
attributes:
deployment.environment: dev
service:
name: zero-code-instrumentation-practice
version: 0.0.1
画像は反映後の例。
Service name
Resource の Service の反映の優先順位について記載。

Out of the box instrumentation
Spring Boot starter によって自動計装されるライブラリ一覧。
ライブラリによっては追加の設定が必要。

Annotations
WithSpan アノテーションを利用すると、AOP で Span を生成できる。
package com.example.opentelemetry_zero_code_instrumentation_practice
import io.opentelemetry.api.trace.Span
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.instrumentation.annotations.SpanAttribute
import io.opentelemetry.instrumentation.annotations.WithSpan
import org.springframework.stereotype.Component
@Component
class TracedClass {
@WithSpan
fun tracedMethod() {}
@WithSpan(value = "TracedClass span name")
fun tracedMethodWithSpanName() {
val currentSpan = Span.current()
currentSpan.addEvent("ADD EVENT TO tracedMethodWithName SPAN");
currentSpan.setAttribute("isTestAttribute", true);
}
@WithSpan(kind = SpanKind.CLIENT)
fun tracedMethodWithoutAnnotation() {}
@WithSpan
fun tracedMethodWithAttribute(@SpanAttribute("attributeName") parameter: String) {}
}
dependencies {
// 中略
// 名前
// - spring-boot-starter-aop
// Maven Repository の URL
// - https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop
// 用途
// - アノテーションを利用したトレースに必要
// - AOP であるため、アノテーションを付与しただけでは動作せず、Constructor Injection などでインスタンス化する必要がある
implementation("org.springframework.boot:spring-boot-starter-aop")
}
ただし、AOP で動作するため、DI しなければ利用できないことに注意。
package com.example.opentelemetry_zero_code_instrumentation_practice
import io.opentelemetry.api.OpenTelemetry
import io.opentelemetry.api.trace.Tracer
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class Controller(
openTelemetry: OpenTelemetry,
private val tracedClass: TracedClass
) {
private val tracer: Tracer = openTelemetry.getTracer("application")
@GetMapping("/ping")
fun ping(): String {
this.pingSpan()
return "pong"
}
fun pingSpan() {
val span = tracer.spanBuilder("pingSpan").startSpan()
span.end()
return
}
@GetMapping("/ping2")
fun ping2(): String {
tracedClass.tracedMethod()
tracedClass.tracedMethodWithSpanName()
tracedClass.tracedMethodWithoutAnnotation()
tracedClass.tracedMethodWithAttribute("attributeValue")
return "pong2"
}
}

Additional instrumentation
log4j2 の OTel instrumentation について。
多分、ログのブリッジ機能について言っているはず。

Other Spring autoconfiguration
Zipkin の話。よくわからないからスキップ。