最新の安定バージョンについては、Spring Framework 6.2.8 を使用してください! |
可観測性のサポート
Micrometer はアプリケーションでメトリクスとトレースの両方を可能にする観測コンセプト (英語) を定義します。メトリクスのサポートは、アプリケーションの実行時の動作に関する統計を収集するためのタイマー、ゲージ、カウンターを作成する方法を提供します。メトリクスは、エラー率、使用パターン、パフォーマンスなどを追跡できます。トレースは、アプリケーションの境界を越えて、システム全体の全体的なビューを提供します。特定のユーザーリクエストにズームインし、アプリケーション全体でリクエストの完了を追跡することができます。
Spring Framework は、ObservationRegistry
が構成されている場合、独自のコードベースのさまざまな部分を計測して観測を公開します。Spring Boot でオブザーバビリティインフラストラクチャの構成について詳しく知ることができます。
生成された観測のリスト
Spring Framework は可観測性のためのさまざまな機能を備えています。このセクションの冒頭で概説したように、設定に応じて、監視によってタイマーメトリクスやトレースを生成できます。
観測名 | 説明 |
---|---|
HTTP クライアント交換に費やされた時間 | |
フレームワークレベルでの HTTP サーバー交換の処理時間 |
観測では Micrometer の公式命名規則が使用されていますが、メトリクス名は監視システムのバックエンドで推奨される形式 (Prometheus、Atlas、Graphite、InfluxDB など) (英語) に自動的に変換されます。 |
Micrometer 観測概念
Micrometer 観測に詳しくない場合は、知っておくべき概念の簡単な概要を以下に示します。
Observation
は、アプリケーションで起こっていることの実際の記録です。これは、メトリクスまたはトレースを生成するためにObservationHandler
実装によって処理されます。各観測には、対応する
ObservationContext
実装があります。この型には、メタデータを抽出するためのすべての関連情報が保持されます。HTTP サーバー監視の場合、コンテキスト実装は HTTP リクエスト、HTTP レスポンス、処理中にスローされた例外などを保持できます。各
Observation
はKeyValues
メタデータを保持します。HTTP サーバーの監視の場合、これは HTTP リクエストメソッド、HTTP レスポンスステータスなどになります。このメタデータは、サポートするObservationContext
の型を宣言する必要があるObservationConvention
実装によって提供されます。KeyValue
タプルに取り得る値の数が限られている場合、KeyValues
は「カーディナリティが低い」と言われます (HTTP メソッドが良い例です)。低いカーディナリティ値はメトリクスのみにコントリビュートされます。逆に、「高カーディナリティ」値は制限がなく (HTTP リクエスト URI など)、トレースにのみ提供されます。ObservationDocumentation
は、特定のドメイン内のすべての観測結果をドキュメント化し、予想されるキー名とその意味をリストします。
観測の構成
グローバル構成オプションは、ObservationRegistry#observationConfig()
レベルで使用できます。インストルメント化された各コンポーネントは、次の 2 つの拡張ポイントを提供します。
ObservationRegistry
の設定 ; 設定されていない場合、観測は記録されず、ノーオペレーションになります。デフォルトの観測名と抽出された
KeyValues
を変更するためのカスタムObservationConvention
の提供
カスタム観測規則の使用
ServerHttpObservationFilter
を使用した Spring MVC "http.server.requests" メトリクスインスツルメンテーションの例を見てみましょう。この観測では、ServerRequestObservationConvention
と ServerRequestObservationContext
を使用します。カスタム規則はサーブレットフィルターで構成できます。観測によって生成されたメタデータをカスタマイズしたい場合は、要件に合わせて DefaultServerRequestObservationConvention
を継承できます。
import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues;
import org.springframework.http.server.observation.DefaultServerRequestObservationConvention;
import org.springframework.http.server.observation.ServerRequestObservationContext;
public class ExtendedServerRequestObservationConvention extends DefaultServerRequestObservationConvention {
@Override
public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) {
// here, we just want to have an additional KeyValue to the observation, keeping the default values
return super.getLowCardinalityKeyValues(context).and(custom(context));
}
private KeyValue custom(ServerRequestObservationContext context) {
return KeyValue.of("custom.method", context.getCarrier().getMethod());
}
}
完全に制御したい場合は、関心のある観測に対する規約契約全体を実装できます。
import io.micrometer.common.KeyValue;
import io.micrometer.common.KeyValues;
import org.springframework.http.server.observation.ServerHttpObservationDocumentation;
import org.springframework.http.server.observation.ServerRequestObservationContext;
import org.springframework.http.server.observation.ServerRequestObservationConvention;
public class CustomServerRequestObservationConvention implements ServerRequestObservationConvention {
@Override
public String getName() {
// will be used as the metric name
return "http.server.requests";
}
@Override
public String getContextualName(ServerRequestObservationContext context) {
// will be used for the trace name
return "http " + context.getCarrier().getMethod().toLowerCase();
}
@Override
public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) {
return KeyValues.of(method(context), status(context), exception(context));
}
@Override
public KeyValues getHighCardinalityKeyValues(ServerRequestObservationContext context) {
return KeyValues.of(httpUrl(context));
}
private KeyValue method(ServerRequestObservationContext context) {
// You should reuse as much as possible the corresponding ObservationDocumentation for key names
return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, context.getCarrier().getMethod());
}
// status(), exception(), httpUrl()...
private KeyValue status(ServerRequestObservationContext context) {
return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, String.valueOf(context.getResponse().getStatus()));
}
private KeyValue exception(ServerRequestObservationContext context) {
String exception = (context.getError() != null) ? context.getError().getClass().getSimpleName() : KeyValue.NONE_VALUE;
return KeyValue.of(ServerHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, exception);
}
private KeyValue httpUrl(ServerRequestObservationContext context) {
return KeyValue.of(ServerHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, context.getCarrier().getRequestURI());
}
}
カスタム ObservationFilter
を使用して、観測のキー値を追加または削除するなど、同様のゴールを達成することもできます。フィルターはデフォルトの規則を置き換えるものではなく、後処理コンポーネントとして使用されます。
import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationFilter;
import org.springframework.http.server.observation.ServerRequestObservationContext;
public class ServerRequestObservationFilter implements ObservationFilter {
@Override
public Observation.Context map(Observation.Context context) {
if (context instanceof ServerRequestObservationContext serverContext) {
context.setName("custom.observation.name");
context.addLowCardinalityKeyValue(KeyValue.of("project", "spring"));
String customAttribute = (String) serverContext.getCarrier().getAttribute("customAttribute");
context.addLowCardinalityKeyValue(KeyValue.of("custom.attribute", customAttribute));
}
return context;
}
}
ObservationRegistry
で ObservationFilter
インスタンスを構成できます。
HTTP サーバーの計測
HTTP サーバー交換監視は、サーブレットおよびリアクティブアプリケーション用に "http.server.requests"
という名前で作成されます。
サーブレットアプリケーション
アプリケーションは、アプリケーション内で org.springframework.web.filter.ServerHttpObservationFilter
サーブレットフィルターを構成する必要があります。デフォルトでは org.springframework.http.server.observation.DefaultServerRequestObservationConvention
を使用し、ServerRequestObservationContext
によってサポートされます。
これは、Exception
が Web フレームワークによって処理されず、サーブレットフィルターにバブルアップした場合にのみ、観測をエラーとして記録します。通常、Spring MVC の @ExceptionHandler
および ProblemDetail
サポートによって処理されるすべての例外は、観測結果とともに記録されません。リクエスト処理中のいつでも、ObservationContext
のエラーフィールドを自分で設定できます。
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.filter.ServerHttpObservationFilter;
@Controller
public class UserController {
@ExceptionHandler(MissingUserException.class)
ResponseEntity<Void> handleMissingUser(HttpServletRequest request, MissingUserException exception) {
// We want to record this exception with the observation
ServerHttpObservationFilter.findObservationContext(request)
.ifPresent(context -> context.setError(exception));
return ResponseEntity.notFound().build();
}
static class MissingUserException extends RuntimeException {
}
}
インストルメンテーションはサーブレットフィルターレベルで行われるため、監視スコープは、このフィルターの後に順序付けされたフィルターとリクエストの処理のみをカバーします。通常、サーブレットコンテナーのエラー処理は下位レベルで実行され、アクティブな監視やスパンはありません。この使用例では、Tomcat の org.apache.catalina.Valve などのコンテナー固有の実装が必要です。これはこのプロジェクトの範囲外です。 |
デフォルトでは、次の KeyValues
が作成されます。
名前 | 説明 |
| 交換中にスローされた例外の名前、または例外が発生しなかった場合は |
| HTTP リクエストメソッドの名前、または既知のメソッドでない場合は |
| HTTP サーバー交換の結果。 |
| HTTP レスポンスの raw ステータスコード、またはレスポンスが作成されなかった場合は |
| 一致するハンドラーの URI パターン (使用可能な場合)。3xx レスポンスの場合は |
名前 | 説明 |
| HTTP リクエスト URI。 |
リアクティブアプリケーション
アプリケーションは、アプリケーション内で org.springframework.web.filter.reactive.ServerHttpObservationFilter
リアクティブ WebFilter
を構成する必要があります。デフォルトでは org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention
を使用し、ServerRequestObservationContext
によってサポートされます。
これは、Exception
が Web フレームワークによって処理されず、WebFilter
にバブルアップした場合にのみ、観測をエラーとして記録します。通常、Spring WebFlux の @ExceptionHandler
および ProblemDetail
のサポートによって処理されるすべての例外は、観測では記録されません。リクエスト処理中のいつでも、ObservationContext
のエラーフィールドを自分で設定できます。
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.filter.reactive.ServerHttpObservationFilter;
import org.springframework.web.server.ServerWebExchange;
@Controller
public class UserController {
@ExceptionHandler(MissingUserException.class)
ResponseEntity<Void> handleMissingUser(ServerWebExchange exchange, MissingUserException exception) {
// We want to record this exception with the observation
ServerHttpObservationFilter.findObservationContext(exchange)
.ifPresent(context -> context.setError(exception));
return ResponseEntity.notFound().build();
}
static class MissingUserException extends RuntimeException {
}
}
デフォルトでは、次の KeyValues
が作成されます。
名前 | 説明 |
| 交換中にスローされた例外の名前、または例外が発生しなかった場合は |
| HTTP リクエストメソッドの名前、または既知のメソッドでない場合は |
| HTTP サーバー交換の結果。 |
| HTTP レスポンスの raw ステータスコード、またはレスポンスが作成されなかった場合は |
| 一致するハンドラーの URI パターン (使用可能な場合)。3xx レスポンスの場合は |
名前 | 説明 |
| HTTP リクエスト URI。 |
HTTP クライアントのインストルメンテーション
HTTP クライアント交換監視は、ブロッキングクライアントとリアクティブクライアント用に "http.client.requests"
という名前で作成されます。サーバー版とは異なり、インストルメンテーションはクライアントに直接実装されるため、必要な手順はクライアント上で ObservationRegistry
を構成することだけです。
RestTemplate
アプリケーションは、インストルメンテーションを有効にするために、RestTemplate
インスタンスで ObservationRegistry
を構成する必要があります。それがなければ、観測は「ノーオペレーション」です。Spring Boot は、監視レジストリがすでに設定されている RestTemplateBuilder
Bean を自動構成します。
インストルメンテーションはデフォルトで org.springframework.http.client.observation.ClientRequestObservationConvention
を使用し、ClientRequestObservationContext
によってサポートされます。
名前 | 説明 |
| HTTP リクエストメソッドの名前、または既知のメソッドでない場合は |
| HTTP リクエストに使用される URI テンプレート、または指定されていない場合は |
| リクエスト URI ホストから派生したクライアント名。 |
| HTTP レスポンスの raw ステータスコード、または |
| HTTP クライアント交換の結果。 |
| 交換中にスローされた例外の名前、または例外が発生しなかった場合は |
名前 | 説明 |
| HTTP リクエスト URI。 |
WebClient
インストルメンテーションを有効にするには、アプリケーションは WebClient
ビルダーで ObservationRegistry
を構成する必要があります。それがなければ、観測は「ノーオペレーション」です。Spring Boot は、監視レジストリがすでに設定されている WebClient.Builder
Bean を自動構成します。
インストルメンテーションはデフォルトで org.springframework.web.reactive.function.client.ClientRequestObservationConvention
を使用し、ClientRequestObservationContext
によってサポートされます。
名前 | 説明 |
| HTTP リクエストメソッドの名前、または既知のメソッドでない場合は |
| HTTP リクエストに使用される URI テンプレート、または指定されていない場合は |
| リクエスト URI ホストから派生したクライアント名。 |
| HTTP レスポンスの raw ステータスコード、または |
| HTTP クライアント交換の結果。 |
| 交換中にスローされた例外の名前、または例外が発生しなかった場合は |
名前 | 説明 |
| HTTP リクエスト URI。 |