可観測性

可観測性とは、実行中のシステムの内部状態を外部から観測する機能です。これは、ログ、メトリクス、トレースの 3 つの柱で構成されます。

メトリクスとトレースの場合、Spring Boot は Micrometer Observation (英語) を使用します。独自の観測 (メトリクスとトレースにつながる) を作成するには、ObservationRegistry (英語) を挿入できます。

  • Java

  • Kotlin

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

import org.springframework.stereotype.Component;

@Component
public class MyCustomObservation {

	private final ObservationRegistry observationRegistry;

	public MyCustomObservation(ObservationRegistry observationRegistry) {
		this.observationRegistry = observationRegistry;
	}

	public void doSomething() {
		Observation.createNotStarted("doSomething", this.observationRegistry)
			.lowCardinalityKeyValue("locale", "en-US")
			.highCardinalityKeyValue("userId", "42")
			.observe(() -> {
				// Execute business logic here
			});
	}

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

import org.springframework.stereotype.Component

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

	fun doSomething() {
		Observation.createNotStarted("doSomething", observationRegistry)
			.lowCardinalityKeyValue("locale", "en-US")
			.highCardinalityKeyValue("userId", "42")
			.observe {
				// Execute business logic here
			}
	}

}
カーディナリティの低いタグはメトリクスとトレースに追加されますが、カーディナリティの高いタグはトレースにのみ追加されます。

ObservationPredicate (英語) GlobalObservationConvention (英語) ObservationFilter (英語) ObservationHandler (英語) 型の Bean は、ObservationRegistry (英語) に自動的に登録されます。レジストリをさらに構成するために、任意の数の ObservationRegistryCustomizer (Javadoc) Bean を追加で登録できます。

JDBC の可観測性は、別のプロジェクトを使用して構成できます。データソース Micrometer プロジェクト [GitHub] (英語) は、JDBC 操作が呼び出されたときに自動的にオブザベーションを作成する Spring Boot スターターを提供します。詳細については、リファレンスドキュメント (英語) を参照してください。
R2DBC の可観測性は Spring Boot に組み込まれています。これを有効にするには、プロジェクトに io.r2dbc:r2dbc-proxy 依存関係を追加します。

コンテキストの伝播

可観測性サポートは、スレッドとリアクティブパイプライン間で現在の観測を転送するためにコンテキスト伝播ライブラリ [GitHub] (英語) に依存します。デフォルトでは、ThreadLocal (標準 Javadoc) 値はリアクティブオペレーターで自動的に復元されません。この動作は spring.reactor.context-propagation プロパティで制御され、自動伝播を有効にするには auto に設定できます。

@Async (Javadoc) メソッドを使用していて、AsyncTaskExecutor (Javadoc) が自動構成されている場合は、spring.task.execution.propagate-context プロパティを使用してコンテキスト伝播をオプトインする必要があります。

AsyncTaskExecutor (Javadoc) を自分で構成する場合は、次の例に示すように、ContextPropagatingTaskDecorator (Javadoc) Bean を登録する必要があります。

  • Java

  • Kotlin

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.support.ContextPropagatingTaskDecorator;

@Configuration(proxyBeanMethods = false)
class ContextPropagationConfiguration {

	@Bean
	ContextPropagatingTaskDecorator contextPropagatingTaskDecorator() {
		return new ContextPropagatingTaskDecorator();
	}

}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.task.support.ContextPropagatingTaskDecorator

@Configuration(proxyBeanMethods = false)
class ContextPropagationConfiguration {

	@Bean
	fun contextPropagatingTaskDecorator(): ContextPropagatingTaskDecorator {
		return ContextPropagatingTaskDecorator()
	}

}

観測の詳細については、Micrometer 観測資料 (英語) を参照してください。

共通タグ

共通タグは通常、ホスト、インスタンス、リージョン、スタックなどの動作環境の次元ドリルダウンに使用されます。共通タグは、カーディナリティの低いタグとしてすべての観測値に適用され、次の例に示すように構成できます。

  • プロパティ

  • YAML

management.observations.key-values.region=us-east-1
management.observations.key-values.stack=prod
management:
  observations:
    key-values:
      region: "us-east-1"
      stack: "prod"

前述の例では、すべての観測値に region タグと stack タグをそれぞれ us-east-1 と prod の値で追加します。

観測の防止

一部の観測が報告されるのを防ぎたい場合は、management.observations.enable プロパティを使用できます。

  • プロパティ

  • YAML

management.observations.enable.denied.prefix=false
management.observations.enable.another.denied.prefix=false
management:
  observations:
    enable:
      denied:
        prefix: false
      another:
        denied:
          prefix: false

前述の例では、denied.prefix または another.denied.prefix で始まる名前を持つすべての観測が禁止されます。

Spring Security が観測を報告しないようにするには、プロパティ management.observations.enable.spring.security を false に設定します。

観測の防止をより厳密に制御する必要がある場合は、型 ObservationPredicate (英語) の Bean を登録できます。観測は、すべての ObservationPredicate (英語) Bean がその観測に対して true を返す場合にのみ報告されます。

  • Java

  • Kotlin

import io.micrometer.observation.Observation.Context;
import io.micrometer.observation.ObservationPredicate;

import org.springframework.stereotype.Component;

@Component
class MyObservationPredicate implements ObservationPredicate {

	@Override
	public boolean test(String name, Context context) {
		return !name.contains("denied");
	}

}
import io.micrometer.observation.Observation.Context
import io.micrometer.observation.ObservationPredicate
import org.springframework.stereotype.Component

@Component
class MyObservationPredicate : ObservationPredicate {

	override fun test(name: String, context: Context): Boolean {
		return !name.contains("denied")
	}

}

前述の例では、名前に "denied" が含まれるすべての観測が禁止されます。

Micrometer 観測アノテーションのサポート

@Observed (英語) @Timed (英語) @Counted (英語) @MeterTag (英語) @NewSpan (英語) などの可観測性アノテーションのスキャンを有効にするには、management.observations.annotations.enabled プロパティを true に設定してください。また、spring-boot-starter-aspectj の一部である org.aspectj:aspectjweaver への依存関係も必要です。この機能は Micrometer によって直接サポートされています。Micrometer (英語) Micrometer Observation (英語) Micrometer トレース (英語) のリファレンスドキュメントを参照してください。

すでにインストルメント化されているメソッドまたはクラス (たとえば、Spring Data リポジトリまたは Spring MVC コントローラー ) にアノテーションを付ける場合、重複した観測結果が取得されます。その場合、プロパティまたは ObservationPredicate (英語) を使用して自動インストルメント化を無効にしてアノテーションに依存するか、アノテーションを削除することができます。

OpenTelemetry サポート

アプリケーションで OpenTelemetry (英語) をサポートするには、いくつかの方法があります。OTel コミュニティでサポートされている OpenTelemetry Java エージェント (英語) または OpenTelemetry Spring Boot スターター (英語) を使用できます。メトリクスとトレースは、OTel ライブラリで定義されたセマンティック規則を使用します。このドキュメントでは、Micrometer と OTLP エクスポーターを使用して、Spring チームによって公式にサポートされている OpenTelemetry について説明します。メトリクスとトレースは、Spring Framework などの Spring プロジェクトのドキュメントで説明されているセマンティック規則を使用します。

Spring Boot のアクチュエーターモジュールには、OpenTelemetry の基本サポートが含まれています。

これは、型 OpenTelemetry (英語) の Bean を提供し、アプリケーションコンテキストに型 SdkTracerProvider (英語) ContextPropagators (英語) SdkLoggerProvider (英語) または SdkMeterProvider (英語) の Bean がある場合、自動的に登録されます。さらに、Resource (英語) Bean も提供します。自動構成された Resource (英語) の属性は、management.opentelemetry.resource-attributes 構成プロパティを介して構成できます。自動構成された属性は、OTEL_RESOURCE_ATTRIBUTES および OTEL_SERVICE_NAME 環境変数の属性とマージされ、構成プロパティを介して構成された属性は、環境変数の属性よりも優先されます。

独自の Resource (英語) Bean を定義した場合は、この限りではありません。

Spring Boot は、OpenTelemetry のメトリクスやログの自動エクスポートを提供していません。OpenTelemetry のトレースのエクスポートは、Micrometer トレースと併用した場合にのみ自動構成されます。

OpenTelemetry の無効化

OpenTelemetry のサポートは、management.opentelemetry.enabled プロパティを false に設定することで無効にできます。これは、OTEL_SDK_DISABLED (英語) 環境変数と同様の動作をしますが、逆の動作になります。SDK が無効になっている場合、メトリクス、トレース、ログ記録には何もしない実装が使用されます。コンテキストプロパゲーターは影響を受けず、通常どおり機能し続けます。

Spring Boot は OpenTelemetry のメトリクス機能を使用しないため、OpenTelemetry を無効にした場合でもメトリクスが有効になっている可能性があることに注意してください。

環境変数

Spring Boot は OpenTelemetry SDK の環境変数 (英語) のサブセットをサポートしています。これらの環境変数は、起動時に自動的に Spring Boot 構成プロパティにマッピングされます。環境変数にシグナル固有のバリアント (たとえば、OTEL_EXPORTER_OTLP_TRACES_ENDPOINT) と一般的なバリアント (OTEL_EXPORTER_OTLP_ENDPOINT) がある場合、シグナル固有のバリアントが優先され、そのまま使用されます。一般的なバリアントがフォールバックとして使用されるときは、シグナル固有のパス (v1/tracesv1/metricsv1/logs) がそれに追加されます。例: OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4318 を設定すると、トレースの場合は collector:4318/v1/traces (英語)  になります。

このマッピングは、management.opentelemetry.map-environment-variables を false に設定することで無効にできます。

一般

環境変数 Spring Boot プロパティ

OTEL_SDK_DISABLED

management.opentelemetry.enabled (inverted)

OTEL_PROPAGATORS

management.tracing.propagation.type and management.tracing.baggage.enabled

OTEL_TRACES_SAMPLER

management.opentelemetry.tracing.sampler

OTEL_TRACES_SAMPLER_ARG

management.tracing.sampling.probability

OTEL_METRICS_EXEMPLAR_FILTER

management.tracing.exemplars.include

メトリクスエクスポートツール

環境変数 Spring Boot プロパティ

OTEL_EXPORTER_OTLP_METRICS_ENDPOINT / OTEL_EXPORTER_OTLP_ENDPOINT

management.otlp.metrics.export.url

OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE

management.otlp.metrics.export.aggregation-temporality

OTEL_EXPORTER_OTLP_METRICS_DEFAULT_HISTOGRAM_AGGREGATION

management.otlp.metrics.export.histogram-flavor

OTEL_EXPORTER_OTLP_METRICS_COMPRESSION / OTEL_EXPORTER_OTLP_COMPRESSION

management.otlp.metrics.export.compression-mode

OTEL_EXPORTER_OTLP_METRICS_TIMEOUT / OTEL_EXPORTER_OTLP_TIMEOUT

management.otlp.metrics.export.read-timeout

OTEL_EXPORTER_OTLP_METRICS_HEADERS / OTEL_EXPORTER_OTLP_HEADERS

management.otlp.metrics.export.headers

OTEL_METRIC_EXPORT_INTERVAL

management.otlp.metrics.export.step

OTEL_METRICS_EXPORTER

management.otlp.metrics.export.enabled (only otlp enables OTLP export; other values disable it but do not enable alternative exporters)

OTEL_EXPORTER_OTLP_METRICS_CERTIFICATE / OTEL_EXPORTER_OTLP_CERTIFICATE

management.otlp.metrics.export.ssl.bundle (auto-configured SSL bundle)

OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY / OTEL_EXPORTER_OTLP_CLIENT_KEY

management.otlp.metrics.export.ssl.bundle (auto-configured SSL bundle)

OTEL_EXPORTER_OTLP_METRICS_CLIENT_CERTIFICATE / OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE

management.otlp.metrics.export.ssl.bundle (auto-configured SSL bundle)

Traces Exporter

Environment Variable Spring Boot Property

OTEL_EXPORTER_OTLP_TRACES_ENDPOINT / OTEL_EXPORTER_OTLP_ENDPOINT

management.opentelemetry.tracing.export.otlp.endpoint

OTEL_EXPORTER_OTLP_TRACES_COMPRESSION / OTEL_EXPORTER_OTLP_COMPRESSION

management.opentelemetry.tracing.export.otlp.compression

OTEL_EXPORTER_OTLP_TRACES_TIMEOUT / OTEL_EXPORTER_OTLP_TIMEOUT

management.opentelemetry.tracing.export.otlp.timeout

OTEL_EXPORTER_OTLP_TRACES_PROTOCOL / OTEL_EXPORTER_OTLP_PROTOCOL

management.opentelemetry.tracing.export.otlp.transport

OTEL_EXPORTER_OTLP_TRACES_HEADERS / OTEL_EXPORTER_OTLP_HEADERS

management.opentelemetry.tracing.export.otlp.headers

OTEL_BSP_SCHEDULE_DELAY

management.opentelemetry.tracing.export.schedule-delay

OTEL_BSP_EXPORT_TIMEOUT

management.opentelemetry.tracing.export.timeout

OTEL_BSP_MAX_QUEUE_SIZE

management.opentelemetry.tracing.export.max-queue-size

OTEL_BSP_MAX_EXPORT_BATCH_SIZE

management.opentelemetry.tracing.export.max-batch-size

OTEL_TRACES_EXPORTER

management.tracing.export.otlp.enabled (only otlp enables OTLP export; other values disable it but do not enable alternative exporters)

OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT / OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT

management.opentelemetry.tracing.limits.max-attribute-value-length

OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT / OTEL_ATTRIBUTE_COUNT_LIMIT

management.opentelemetry.tracing.limits.max-attributes

OTEL_SPAN_EVENT_COUNT_LIMIT

management.opentelemetry.tracing.limits.max-events

OTEL_SPAN_LINK_COUNT_LIMIT

management.opentelemetry.tracing.limits.max-links

OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT

management.opentelemetry.tracing.limits.max-attributes-per-event

OTEL_LINK_ATTRIBUTE_COUNT_LIMIT

management.opentelemetry.tracing.limits.max-attributes-per-link

OTEL_EXPORTER_OTLP_TRACES_CERTIFICATE / OTEL_EXPORTER_OTLP_CERTIFICATE

management.opentelemetry.tracing.export.otlp.ssl.bundle (auto-configured SSL bundle)

OTEL_EXPORTER_OTLP_TRACES_CLIENT_KEY / OTEL_EXPORTER_OTLP_CLIENT_KEY

management.opentelemetry.tracing.export.otlp.ssl.bundle (auto-configured SSL bundle)

OTEL_EXPORTER_OTLP_TRACES_CLIENT_CERTIFICATE / OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE

management.opentelemetry.tracing.export.otlp.ssl.bundle (auto-configured SSL bundle)

Logs Exporter

Environment Variable Spring Boot Property

OTEL_EXPORTER_OTLP_LOGS_ENDPOINT / OTEL_EXPORTER_OTLP_ENDPOINT

management.opentelemetry.logging.export.otlp.endpoint

OTEL_EXPORTER_OTLP_LOGS_COMPRESSION / OTEL_EXPORTER_OTLP_COMPRESSION

management.opentelemetry.logging.export.otlp.compression

OTEL_EXPORTER_OTLP_LOGS_TIMEOUT / OTEL_EXPORTER_OTLP_TIMEOUT

management.opentelemetry.logging.export.otlp.timeout

OTEL_EXPORTER_OTLP_LOGS_PROTOCOL / OTEL_EXPORTER_OTLP_PROTOCOL

management.opentelemetry.logging.export.otlp.transport

OTEL_EXPORTER_OTLP_LOGS_HEADERS / OTEL_EXPORTER_OTLP_HEADERS

management.opentelemetry.logging.export.otlp.headers

OTEL_BLRP_SCHEDULE_DELAY

management.opentelemetry.logging.export.schedule-delay

OTEL_BLRP_EXPORT_TIMEOUT

management.opentelemetry.logging.export.timeout

OTEL_BLRP_MAX_QUEUE_SIZE

management.opentelemetry.logging.export.max-queue-size

OTEL_BLRP_MAX_EXPORT_BATCH_SIZE

management.opentelemetry.logging.export.max-batch-size

OTEL_LOGS_EXPORTER

management.logging.export.otlp.enabled (only otlp enables OTLP export; other values disable it but do not enable alternative exporters)

OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT / OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT

management.opentelemetry.logging.limits.max-attribute-value-length

OTEL_LOGRECORD_ATTRIBUTE_COUNT_LIMIT / OTEL_ATTRIBUTE_COUNT_LIMIT

management.opentelemetry.logging.limits.max-attributes

OTEL_EXPORTER_OTLP_LOGS_CERTIFICATE / OTEL_EXPORTER_OTLP_CERTIFICATE

management.opentelemetry.logging.export.otlp.ssl.bundle (auto-configured SSL bundle)

OTEL_EXPORTER_OTLP_LOGS_CLIENT_KEY / OTEL_EXPORTER_OTLP_CLIENT_KEY

management.opentelemetry.logging.export.otlp.ssl.bundle (auto-configured SSL bundle)

OTEL_EXPORTER_OTLP_LOGS_CLIENT_CERTIFICATE / OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE

management.opentelemetry.logging.export.otlp.ssl.bundle (自動構成 SSL バンドル)

リソース

以下の環境変数は、OpenTelemetry リソースを設定します。

OTEL_RESOURCE_ATTRIBUTES 環境変数は、キーと値のペアのリストで構成されます。例: key1=value1,key2=value2,key3=spring%20boot。すべての属性値は文字列として扱われ、バゲッジオクテット範囲外の文字はパーセントエンコードする必要があります。

サポートされていない環境変数

OpenTelemetry ドキュメント (英語) に記載されているその他の環境変数はサポートされていません。

OpenTelemetry の SDK で指定されているすべての環境変数を有効にするには、独自の OpenTelemetry Bean を用意する必要があります。

これを行うと、Spring Boot の OpenTelemetry 自動構成がオフになり、組み込みの監視機能が壊れる可能性があります。

まず、io.opentelemetry:opentelemetry-sdk-extension-autoconfigure に依存関係を追加して OpenTelemetry のゼロコード SDK 自動構成モジュール (英語) を取得し、次に次の構成を追加します。

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
class AutoConfiguredOpenTelemetrySdkConfiguration {

	@Bean
	OpenTelemetry autoConfiguredOpenTelemetrySdk() {
		return AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();
	}

}

ログ

OpenTelemetryLoggingAutoConfiguration (Javadoc) は OpenTelemetry の SdkLoggerProvider (英語) を構成します。OTLP 経由のログのエクスポートは OtlpLoggingAutoConfiguration (Javadoc) を通じてサポートされ、HTTP または gRPC 経由の OTLP ログのエクスポートが可能になります。

OTLP ログレコードエクスポーターに高度なカスタマイズを適用する必要がある場合は、OtlpHttpLogRecordExporterBuilderCustomizer (Javadoc) または OtlpGrpcLogRecordExporterBuilderCustomizer (Javadoc) Bean の登録を検討してください。これらの Bean は、OtlpHttpLogRecordExporter (英語) または OtlpGrpcLogRecordExporter (英語) の作成前に呼び出されます。これらのカスタマイザーは、自動構成によって適用されるものよりも優先されます。

ただし、SdkLoggerProvider Bean はありますが、Spring Boot は標準ではこの Bean へのログブリッジをサポートしていません。これは、OpenTelemetry によるログ記録のセクションに従って、サードパーティ製のログブリッジを使用することで実現できます。

メトリクス

Spring ポートフォリオでは Micrometer がメトリクスとして選択されており、これは OpenTelemetry の SdkMeterProvider (英語) を介してメトリクスが収集・エクスポートされないことを意味します。Spring Boot は SdkMeterProvider Bean を提供しません。

ただし、Micrometer メトリクスは、OTLP を使用したメトリクスセクションに従って、OtlpMeterRegistry (英語) を使用して、OTLP 経由で任意の OpenTelemetry 対応バックエンドにエクスポートできます。

Micrometer の OTLP レジストリは Resource Bean を使用しませんが、OTEL_RESOURCE_ATTRIBUTESOTEL_SERVICE_NAME または management.opentelemetry.resource-attributes の設定は機能します。

OpenTelemetry API および SDK 経由のメトリクス

ユーザーまたはユーザーが含める依存関係が OpenTelemetry の MeterProvider (英語) を利用している場合、それらのメトリクスはエクスポートされません。

メトリクスのレポートには Micrometer を使用することを強くお勧めします。OpenTelemetry の MeterProvider を使用する依存関係を組み込む場合は、以下の設定をアプリケーションに組み込むことで MeterProvider Bean を設定できます。その後、この設定を依存関係に組み込む必要があります。

import java.time.Duration;

import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.metrics.export.MetricReader;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import io.opentelemetry.sdk.resources.Resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
class OpenTelemetryMetricsConfiguration {

	@Bean
	OtlpHttpMetricExporter metricExporter() {
		String endpoint = "http://localhost:4318/v1/metrics";
		return OtlpHttpMetricExporter.builder().setEndpoint(endpoint).build();
	}

	@Bean
	PeriodicMetricReader metricReader(MetricExporter exporter) {
		Duration interval = Duration.ofMinutes(1);
		return PeriodicMetricReader.builder(exporter).setInterval(interval).build();
	}

	@Bean
	SdkMeterProvider meterProvider(Resource resource, MetricReader metricReader) {
		return SdkMeterProvider.builder().registerMetricReader(metricReader).setResource(resource).build();
	}

}

この構成により、HTTP 経由の OTLP によるメトリクスのエクスポートも可能になります。

トレース

Micrometer トレースを使用する場合、OpenTelemetryTracingAutoConfiguration (Javadoc) は OpenTelemetry の SdkTracerProvider (英語) を構成します。OTLP を介したトレースのエクスポートは、HTTP または gRPC 経由の OTLP によるトレースのエクスポートをサポートする OtlpTracingAutoConfiguration (Javadoc) によって有効になります。

OpenTelemetry API を直接使用するのではなく、Micrometer 観測またはトレース API を使用することを強くお勧めします。