You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
221 lines
12 KiB
221 lines
12 KiB
[[observability]] |
|
= Observability Support |
|
|
|
Micrometer defines an https://micrometer.io/docs/observation[Observation concept that enables both Metrics and Traces] in applications. |
|
Metrics support offers a way to create timers, gauges, or counters for collecting statistics about the runtime behavior of your application. |
|
Metrics can help you to track error rates, usage patterns, performance, and more. |
|
Traces provide a holistic view of an entire system, crossing application boundaries; you can zoom in on particular user requests and follow their entire completion across applications. |
|
|
|
Spring Framework instruments various parts of its own codebase to publish observations if an `ObservationRegistry` is configured. |
|
You can learn more about {docs-spring-boot}/html/actuator.html#actuator.metrics[configuring the observability infrastructure in Spring Boot]. |
|
|
|
|
|
[[observability.list]] |
|
== List of produced Observations |
|
|
|
Spring Framework instruments various features for observability. |
|
As outlined xref:integration/observability.adoc[at the beginning of this section], observations can generate timer Metrics and/or Traces depending on the configuration. |
|
|
|
.Observations produced by Spring Framework |
|
[%autowidth] |
|
|=== |
|
|Observation name |Description |
|
|
|
|xref:integration/observability.adoc#http-client[`"http.client.requests"`] |
|
|Time spent for HTTP client exchanges |
|
|
|
|xref:integration/observability.adoc#http-server[`"http.server.requests"`] |
|
|Processing time for HTTP server exchanges at the Framework level |
|
|=== |
|
|
|
NOTE: Observations are using Micrometer's official naming convention, but Metrics names will be automatically converted |
|
https://micrometer.io/docs/concepts#_naming_meters[to the format preferred by the monitoring system backend] |
|
(Prometheus, Atlas, Graphite, InfluxDB...). |
|
|
|
|
|
[[observability.concepts]] |
|
== Micrometer Observation concepts |
|
|
|
If you are not familiar with Micrometer Observation, here's a quick summary of the concepts you should know about. |
|
|
|
* `Observation` is the actual recording of something happening in your application. This is processed by `ObservationHandler` implementations to produce metrics or traces. |
|
* Each observation has a corresponding `ObservationContext` implementation; this type holds all the relevant information for extracting metadata for it. |
|
In the case of an HTTP server observation, the context implementation could hold the HTTP request, the HTTP response, any exception thrown during processing, and so forth. |
|
* Each `Observation` holds `KeyValues` metadata. In the case of an HTTP server observation, this could be the HTTP request method, the HTTP response status, and so forth. |
|
This metadata is contributed by `ObservationConvention` implementations which should declare the type of `ObservationContext` they support. |
|
* `KeyValues` are said to be "low cardinality" if there is a low, bounded number of possible values for the `KeyValue` tuple (HTTP method is a good example). |
|
Low cardinality values are contributed to metrics only. |
|
Conversely, "high cardinality" values are unbounded (for example, HTTP request URIs) and are only contributed to traces. |
|
* An `ObservationDocumentation` documents all observations in a particular domain, listing the expected key names and their meaning. |
|
|
|
|
|
[[observability.config]] |
|
== Configuring Observations |
|
|
|
Global configuration options are available at the `ObservationRegistry#observationConfig()` level. |
|
Each instrumented component will provide two extension points: |
|
|
|
* setting the `ObservationRegistry`; if not set, observations will not be recorded and will be no-ops |
|
* providing a custom `ObservationConvention` to change the default observation name and extracted `KeyValues` |
|
|
|
|
|
[[observability.config.conventions]] |
|
=== Using custom Observation conventions |
|
|
|
Let's take the example of the Spring MVC "http.server.requests" metrics instrumentation with the `ServerHttpObservationFilter`. |
|
This observation uses a `ServerRequestObservationConvention` with a `ServerRequestObservationContext`; custom conventions can be configured on the Servlet filter. |
|
If you would like to customize the metadata produced with the observation, you can extend the `DefaultServerRequestObservationConvention` for your requirements: |
|
|
|
include-code::./ExtendedServerRequestObservationConvention[] |
|
|
|
If you want full control, you can implement the entire convention contract for the observation you're interested in: |
|
|
|
include-code::./CustomServerRequestObservationConvention[] |
|
|
|
You can also achieve similar goals using a custom `ObservationFilter` – adding or removing key values for an observation. |
|
Filters do not replace the default convention and are used as a post-processing component. |
|
|
|
include-code::./ServerRequestObservationFilter[] |
|
|
|
You can configure `ObservationFilter` instances on the `ObservationRegistry`. |
|
|
|
|
|
[[observability.http-server]] |
|
== HTTP Server instrumentation |
|
|
|
HTTP server exchange observations are created with the name `"http.server.requests"` for Servlet and Reactive applications. |
|
|
|
[[observability.http-server.servlet]] |
|
=== Servlet applications |
|
|
|
Applications need to configure the `org.springframework.web.filter.ServerHttpObservationFilter` Servlet filter in their application. |
|
It uses the `org.springframework.http.server.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`. |
|
|
|
This will only record an observation as an error if the `Exception` has not been handled by the web framework and has bubbled up to the Servlet filter. |
|
Typically, all exceptions handled by Spring MVC's `@ExceptionHandler` and xref:web/webmvc/mvc-ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation. |
|
You can, at any point during request processing, set the error field on the `ObservationContext` yourself: |
|
|
|
include-code::./UserController[] |
|
|
|
NOTE: Because the instrumentation is done at the Servlet Filter level, the observation scope only covers the filters ordered after this one as well as the handling of the request. |
|
Typically, Servlet container error handling is performed at a lower level and won't have any active observation or span. |
|
For this use case, a container-specific implementation is required, such as a `org.apache.catalina.Valve` for Tomcat; this is outside of the scope of this project. |
|
|
|
By default, the following `KeyValues` are created: |
|
|
|
.Low cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`exception` _(required)_|Name of the exception thrown during the exchange, or `KeyValue#NONE_VALUE`} if no exception happened. |
|
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method. |
|
|`outcome` _(required)_|Outcome of the HTTP server exchange. |
|
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created. |
|
|`uri` _(required)_|URI pattern for the matching handler if available, falling back to `REDIRECTION` for 3xx responses, `NOT_FOUND` for 404 responses, `root` for requests with no path info, and `UNKNOWN` for all other requests. |
|
|=== |
|
|
|
.High cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`http.url` _(required)_|HTTP request URI. |
|
|=== |
|
|
|
|
|
[[observability.http-server.reactive]] |
|
=== Reactive applications |
|
|
|
Applications need to configure the `org.springframework.web.filter.reactive.ServerHttpObservationFilter` reactive `WebFilter` in their application. |
|
It uses the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`. |
|
|
|
This will only record an observation as an error if the `Exception` has not been handled by the web framework and has bubbled up to the `WebFilter`. |
|
Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and xref:web/webflux/ann-rest-exceptions.adoc[`ProblemDetail` support] will not be recorded with the observation. |
|
You can, at any point during request processing, set the error field on the `ObservationContext` yourself: |
|
|
|
include-code::./UserController[] |
|
|
|
By default, the following `KeyValues` are created: |
|
|
|
.Low cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened. |
|
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method. |
|
|`outcome` _(required)_|Outcome of the HTTP server exchange. |
|
|`status` _(required)_|HTTP response raw status code, or `"UNKNOWN"` if no response was created. |
|
|`uri` _(required)_|URI pattern for the matching handler if available, falling back to `REDIRECTION` for 3xx responses, `NOT_FOUND` for 404 responses, `root` for requests with no path info, and `UNKNOWN` for all other requests. |
|
|=== |
|
|
|
.High cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`http.url` _(required)_|HTTP request URI. |
|
|=== |
|
|
|
|
|
|
|
[[observability.http-client]] |
|
== HTTP Client Instrumentation |
|
|
|
HTTP client exchange observations are created with the name `"http.client.requests"` for blocking and reactive clients. |
|
Unlike their server counterparts, the instrumentation is implemented directly in the client so the only required step is to configure an `ObservationRegistry` on the client. |
|
|
|
[[observability.http-client.resttemplate]] |
|
=== RestTemplate |
|
|
|
Applications must configure an `ObservationRegistry` on `RestTemplate` instances to enable the instrumentation; without that, observations are "no-ops". |
|
Spring Boot will auto-configure `RestTemplateBuilder` beans with the observation registry already set. |
|
|
|
Instrumentation uses the `org.springframework.http.client.observation.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`. |
|
|
|
.Low cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method. |
|
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered. |
|
|`client.name` _(required)_|Client name derived from the request URI host. |
|
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received. |
|
|`outcome` _(required)_|Outcome of the HTTP client exchange. |
|
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened. |
|
|=== |
|
|
|
.High cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`http.url` _(required)_|HTTP request URI. |
|
|=== |
|
|
|
|
|
|
|
[[observability.http-client.webclient]] |
|
=== WebClient |
|
|
|
Applications must configure an `ObservationRegistry` on the `WebClient` builder to enable the instrumentation; without that, observations are "no-ops". |
|
Spring Boot will auto-configure `WebClient.Builder` beans with the observation registry already set. |
|
|
|
Instrumentation uses the `org.springframework.web.reactive.function.client.ClientRequestObservationConvention` by default, backed by the `ClientRequestObservationContext`. |
|
|
|
.Low cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`method` _(required)_|Name of HTTP request method or `"none"` if not a well-known method. |
|
|`uri` _(required)_|URI template used for HTTP request, or `"none"` if none was provided. Only the path part of the URI is considered. |
|
|`client.name` _(required)_|Client name derived from the request URI host. |
|
|`status` _(required)_|HTTP response raw status code, or `"IO_ERROR"` in case of `IOException`, or `"CLIENT_ERROR"` if no response was received. |
|
|`outcome` _(required)_|Outcome of the HTTP client exchange. |
|
|`exception` _(required)_|Name of the exception thrown during the exchange, or `"none"` if no exception happened. |
|
|=== |
|
|
|
.High cardinality Keys |
|
[cols="a,a"] |
|
|=== |
|
|Name | Description |
|
|`http.url` _(required)_|HTTP request URI. |
|
|=== |
|
|
|
|
|
|