トレース

Spring Boot Actuator は、一般的なトレーサーライブラリのファサードである Micrometer トレース (英語) の依存関係管理と自動構成を提供します。

Micrometer トレース機能の詳細については、リファレンスドキュメント (英語) を参照してください。

サポートされているトレーサー

Spring Boot には、次のトレーサーの自動構成が同梱されています。

入門

トレースを始めるには、サンプルアプリケーションが必要です。今回の目的には、初めての Spring Boot アプリケーションの開発セクションで紹介されているシンプルな "Hello World!" Web アプリケーションで十分です。Brave トレーサーを使用し、トレースバックエンドには Zipkin を使用します。

要約すると、メインのアプリケーションコードは次のようになります。

  • Java

  • Kotlin

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@SpringBootApplication
public class MyApplication {

	private static final Log logger = LogFactory.getLog(MyApplication.class);

	@RequestMapping("/")
	String home() {
		logger.info("home() has been called");
		return "Hello World!";
	}

	public static void main(String[] args) {
		SpringApplication.run(MyApplication.class, args);
	}

}
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@SpringBootApplication
class MyApplication {

	private val logger: Log = LogFactory.getLog(MyApplication::class.java)

	@RequestMapping("/")
	fun home(): String {
		logger.info("home() has been called")
		return "Hello, World!"
	}

}

fun main(args: Array<String>) {
	runApplication<MyApplication>(*args)
}
home() メソッドには logger ステートメントが追加されていますが、これは後で重要になります。

ここで、org.springframework.boot:spring-boot-starter-zipkin 依存関係を追加する必要があります。

次に、次のアプリケーションプロパティを追加します。

  • プロパティ

  • YAML

management.tracing.sampling.probability=1
management:
  tracing:
    sampling:
      probability: 1.0

デフォルトでは、Spring Boot はリクエストの 10% のみをサンプリングして、トレースバックエンドがオーバーロードになるのを防ぎます。このプロパティは、すべてのリクエストがトレースバックエンドに送信されるように、100% に切り替えます。

トレースを収集して視覚化するには、実行中のトレースバックエンドが必要です。ここではトレースバックエンドとして Zipkin を使用します。Zipkin クイックスタートガイド (英語) は、Zipkin をローカルで開始する方法を説明します。

Zipkin が実行されたら、アプリケーションを開始できます。

Web ブラウザーを localhost:8080 で開くと、次の出力が表示されるはずです。

Hello World!

バックグラウンドでは、HTTP リクエストの観測が作成され、それが Brave にブリッジされ、Zipkin に新しいトレースが報告されます。

次に、localhost:9411 で Zipkin UI を開き、クエリの実行 ボタンを押して、収集されたすべてのトレースを一覧表示します。トレースが 1 つ表示されるはずです。「表示」ボタンを押すと、そのトレースの詳細が表示されます。

相関 ID のログ記録

相関 ID は、ログファイル内の行をスパン / トレースにリンクする便利な方法を提供します。Micrometer トレースを使用している場合、Spring Boot はデフォルトでログに相関 ID を含めます。

デフォルトの相関 ID は、traceId および spanId MDC (英語) 値から構築されます。例: Micrometer トレースが 803B448A0489F84084905D3093480352 の MDC traceId と 3425F23BB2432450 の MDC spanId を追加した場合、ログ出力には相関 ID [803B448A0489F84084905D3093480352-3425F23BB2432450] が含まれます。

相関 ID に別の形式を使用したい場合は、logging.pattern.correlation プロパティを使用して相関 ID を定義できます。例: 以下は、以前に Spring Cloud Sleuth で使用されていた形式で Logback の相関 ID を提供します。

  • プロパティ

  • YAML

logging.pattern.correlation=[${spring.application.name:},%X{traceId:-},%X{spanId:-}] 
logging.include-application-name=false
logging:
  pattern:
    correlation: "[${spring.application.name:},%X{traceId:-},%X{spanId:-}] "
  include-application-name: false
上の例では、ログメッセージ内でアプリケーション名が重複するのを避けるために、logging.include-application-name が false に設定されています (logging.pattern.correlation にはすでにアプリケーション名が含まれています)。logging.pattern.correlation には、デフォルトで直後に来るロガー名と区別されるように、末尾にスペースが含まれていることにもメンションする価値があります。
相関 ID はコンテキストの伝播に依存します。詳細については、このドキュメントを参照してください。

トレースの伝播

ネットワーク経由でトレースを自動的に伝播するには、自動構成された RestTemplateBuilderRestClient.BuilderWebClient.Builder を使用してクライアントを構築します。

自動構成されたビルダーを使用せずに RestTemplate (Javadoc) RestClient (Javadoc) WebClient (Javadoc) を作成すると、自動トレース伝播は機能しません。

トレーサーの実装

Micrometer Tracer は複数のトレーサー実装をサポートしているため、Spring Boot との依存関係は複数可能です。OpenTelemetry と OTLP、Brave と Zipkin の組み合わせは一般的であり、専用のスターターが用意されています。

OpenTelemetry と OTLP

OpenTelemetry を使用したトレースと OTLP を使用したレポートには、次の依存関係が必要です。

  • org.springframework.boot:spring-boot-starter-opentelemetry

management.opentelemetry.tracing.export.otlp.* 構成プロパティを使用して、OTLP を使用したレポートを構成します。

OTLP スパンエクスポーターに高度なカスタマイズを適用する必要がある場合は、OtlpHttpSpanExporterBuilderCustomizer (Javadoc) または OtlpGrpcSpanExporterBuilderCustomizer (Javadoc) Bean の登録を検討してください。これらは、OtlpHttpSpanExporter または OtlpGrpcSpanExporter の作成前に呼び出されます。カスタマイザーは、自動構成によって適用されるものよりも優先されます。

OpenTelemetry と Zipkin

OpenTelemetry を使用したトレースと Zipkin へのレポートには、次の依存関係が必要です。

  • org.springframework.boot:spring-boot-micrometer-tracing-opentelemetry - Spring Boot は OpenTelemetry 経由の Micrometer トレースをサポートします。

  • io.micrometer:micrometer-tracing-bridge-otel - Micrometer Observation API を OpenTelemetry にブリッジします。

  • org.springframework.boot:spring-boot-zipkin - Spring Boot による Zipkin のサポート。

  • io.opentelemetry:opentelemetry-exporter-zipkin - トレースを Zipkin に報告する OpenTelemetry エクスポータ。

management.tracing.export.zipkin.* 構成プロパティを使用して、Zipkin へのレポートを構成します。

OpenZipkin Brave と Zipkin

OpenZipkin Brave を使用したトレースと Zipkin へのレポートには、次の依存関係が必要です。

  • org.springframework.boot:spring-boot-starter-zipkin

management.tracing.export.zipkin.* 構成プロパティを使用して、Zipkin へのレポートを構成します。

Micrometer Observation との統合

TracingAwareMeterObservationHandler (英語) ObservationRegistry (英語) に自動的に登録され、完了した観測ごとにスパンが作成されます。

カスタムスパンの作成

観測を開始することで、独自のスパンを作成できます。そのためには、コンポーネントに ObservationRegistry (英語) を挿入します。

  • Java

  • Kotlin

import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationRegistry;

import org.springframework.stereotype.Component;

@Component
class CustomObservation {

	private final ObservationRegistry observationRegistry;

	CustomObservation(ObservationRegistry observationRegistry) {
		this.observationRegistry = observationRegistry;
	}

	void someOperation() {
		Observation observation = Observation.createNotStarted("some-operation", this.observationRegistry);
		observation.lowCardinalityKeyValue("some-tag", "some-value");
		observation.observe(() -> {
			// Business logic ...
		});
	}

}
import io.micrometer.observation.Observation
import io.micrometer.observation.ObservationRegistry
import org.springframework.stereotype.Component

@Component
class CustomObservation(private val observationRegistry: ObservationRegistry) {

	fun someOperation() {
		Observation.createNotStarted("some-operation", observationRegistry)
			.lowCardinalityKeyValue("some-tag", "some-value")
			.observe {
				// Business logic ...
			}
	}

}

これにより、タグ "some-tag=some-value" を持つ "some-operation" という名前の観測が作成されます。

メトリクスを作成せずにスパンを作成する場合は、Micrometer の下位レベルの Tracer API (英語) を使用する必要があります。

バゲッジ

Tracer (英語) API を使用してバゲッジを作成できます。

  • Java

  • Kotlin

import io.micrometer.tracing.BaggageInScope;
import io.micrometer.tracing.Tracer;

import org.springframework.stereotype.Component;

@Component
class CreatingBaggage {

	private final Tracer tracer;

	CreatingBaggage(Tracer tracer) {
		this.tracer = tracer;
	}

	void doSomething() {
		try (BaggageInScope scope = this.tracer.createBaggageInScope("baggage1", "value1")) {
			// Business logic
		}
	}

}
import io.micrometer.tracing.Tracer
import org.springframework.stereotype.Component

@Component
class CreatingBaggage(private val tracer: Tracer) {

	fun doSomething() {
		tracer.createBaggageInScope("baggage1", "value1").use {
			// Business logic
		}
	}

}

この例では、値 value1 を持つ baggage1 という名前のバゲッジを作成します。W3C 伝播を使用している場合、バゲッジはネットワーク上で自動的に伝播されます。B3 伝播を使用している場合、バゲッジは自動的には伝播されません。ネットワーク上でバゲージを手動で伝播するには、management.tracing.baggage.remote-fields 構成プロパティを使用します (これは W3C にも機能します)。上の例では、このプロパティを baggage1 に設定すると、HTTP ヘッダー baggage1: value1 が生成されます。

バゲージを MDC に伝播する場合は、management.tracing.baggage.correlation.fields 構成プロパティを使用します。上の例では、このプロパティを baggage1 に設定すると、baggage1 という名前の MDC エントリが作成されます。

テスト

@SpringBootTest (Javadoc) を使用する場合、データをレポートしているトレースコンポーネントは自動的に構成されません。詳細については、トレースの使用を参照してください。