Rename web observation documentation

Prior to this commit, several variants of observation documentation
would share the same name; for example HTTP client observations for both
blocking and reactive clients would have the same name.

While it is required that they have the same metric name for dashboards,
the observation documentation names should be different so that they can
be documented without confusing developers.

This commit renames the observation documentation names to avoid that.

Closes gh-29431
This commit is contained in:
Brian Clozel 2022-11-04 15:38:32 +01:00
parent d492086c76
commit 6022065ad3
18 changed files with 60 additions and 54 deletions

View File

@ -35,9 +35,9 @@ import org.springframework.http.client.ClientHttpRequestFactory;
public enum ClientHttpObservationDocumentation implements ObservationDocumentation {
/**
* Observation created for a client HTTP exchange.
* HTTP exchanges observations for clients.
*/
HTTP_REQUEST {
HTTP_CLIENT_EXCHANGES {
@Override
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
return DefaultClientRequestObservationConvention.class;

View File

@ -24,7 +24,7 @@ import org.springframework.lang.Nullable;
/**
* Context that holds information for metadata collection
* during the {@link ClientHttpObservationDocumentation#HTTP_REQUEST client HTTP exchanges} observations.
* during the {@link ClientHttpObservationDocumentation#HTTP_CLIENT_EXCHANGES client HTTP exchanges} observations.
* <p>This context also extends {@link RequestReplySenderContext} for propagating tracing
* information with the HTTP client exchange.
* @author Brian Clozel

View File

@ -21,7 +21,7 @@ import io.micrometer.observation.ObservationConvention;
/**
* Interface for an {@link ObservationConvention} for
* {@link ClientHttpObservationDocumentation#HTTP_REQUEST client HTTP exchanges}.
* {@link ClientHttpObservationDocumentation#HTTP_CLIENT_EXCHANGES client HTTP exchanges}.
*
* @author Brian Clozel
* @since 6.0

View File

@ -26,6 +26,9 @@ import org.springframework.http.HttpStatusCode;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.StringUtils;
import static org.springframework.http.client.observation.ClientHttpObservationDocumentation.HighCardinalityKeyNames;
import static org.springframework.http.client.observation.ClientHttpObservationDocumentation.LowCardinalityKeyNames;
/**
* Default implementation for a {@link ClientRequestObservationConvention},
* extracting information from the {@link ClientRequestObservationContext}.
@ -37,23 +40,23 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
private static final String DEFAULT_NAME = "http.client.requests";
private static final KeyValue URI_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.URI, KeyValue.NONE_VALUE);
private static final KeyValue URI_NONE = KeyValue.of(LowCardinalityKeyNames.URI, KeyValue.NONE_VALUE);
private static final KeyValue METHOD_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, KeyValue.NONE_VALUE);
private static final KeyValue METHOD_NONE = KeyValue.of(LowCardinalityKeyNames.METHOD, KeyValue.NONE_VALUE);
private static final KeyValue STATUS_IO_ERROR = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "IO_ERROR");
private static final KeyValue STATUS_IO_ERROR = KeyValue.of(LowCardinalityKeyNames.STATUS, "IO_ERROR");
private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "CLIENT_ERROR");
private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(LowCardinalityKeyNames.STATUS, "CLIENT_ERROR");
private static final KeyValue HTTP_OUTCOME_SUCCESS = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, "SUCCESS");
private static final KeyValue HTTP_OUTCOME_SUCCESS = KeyValue.of(LowCardinalityKeyNames.OUTCOME, "SUCCESS");
private static final KeyValue HTTP_OUTCOME_UNKNOWN = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, "UNKNOWN");
private static final KeyValue HTTP_OUTCOME_UNKNOWN = KeyValue.of(LowCardinalityKeyNames.OUTCOME, "UNKNOWN");
private static final KeyValue EXCEPTION_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, KeyValue.NONE_VALUE);
private static final KeyValue EXCEPTION_NONE = KeyValue.of(LowCardinalityKeyNames.EXCEPTION, KeyValue.NONE_VALUE);
private static final KeyValue HTTP_URL_NONE = KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, KeyValue.NONE_VALUE);
private static final KeyValue HTTP_URL_NONE = KeyValue.of(HighCardinalityKeyNames.HTTP_URL, KeyValue.NONE_VALUE);
private static final KeyValue CLIENT_NAME_NONE = KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, KeyValue.NONE_VALUE);
private static final KeyValue CLIENT_NAME_NONE = KeyValue.of(HighCardinalityKeyNames.CLIENT_NAME, KeyValue.NONE_VALUE);
private final String name;
@ -90,14 +93,14 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
protected KeyValue uri(ClientRequestObservationContext context) {
if (context.getUriTemplate() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.URI, context.getUriTemplate());
return KeyValue.of(LowCardinalityKeyNames.URI, context.getUriTemplate());
}
return URI_NONE;
}
protected KeyValue method(ClientRequestObservationContext context) {
if (context.getCarrier() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, context.getCarrier().getMethod().name());
return KeyValue.of(LowCardinalityKeyNames.METHOD, context.getCarrier().getMethod().name());
}
else {
return METHOD_NONE;
@ -110,7 +113,7 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
return STATUS_CLIENT_ERROR;
}
try {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, String.valueOf(response.getStatusCode().value()));
return KeyValue.of(LowCardinalityKeyNames.STATUS, String.valueOf(response.getStatusCode().value()));
}
catch (IOException ex) {
return STATUS_IO_ERROR;
@ -121,7 +124,7 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
Throwable error = context.getError();
if (error != null) {
String simpleName = error.getClass().getSimpleName();
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION,
return KeyValue.of(LowCardinalityKeyNames.EXCEPTION,
StringUtils.hasText(simpleName) ? simpleName : error.getClass().getName());
}
return EXCEPTION_NONE;
@ -146,14 +149,14 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
protected KeyValue requestUri(ClientRequestObservationContext context) {
if (context.getCarrier() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, context.getCarrier().getURI().toASCIIString());
return KeyValue.of(HighCardinalityKeyNames.HTTP_URL, context.getCarrier().getURI().toASCIIString());
}
return HTTP_URL_NONE;
}
protected KeyValue clientName(ClientRequestObservationContext context) {
if (context.getCarrier() != null && context.getCarrier().getURI().getHost() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, context.getCarrier().getURI().getHost());
return KeyValue.of(HighCardinalityKeyNames.CLIENT_NAME, context.getCarrier().getURI().getHost());
}
return CLIENT_NAME_NONE;
}
@ -165,7 +168,7 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
return HTTP_OUTCOME_SUCCESS;
}
else if (statusCode instanceof HttpStatus status) {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, status.series().name());
return KeyValue.of(LowCardinalityKeyNames.OUTCOME, status.series().name());
}
else {
return HTTP_OUTCOME_UNKNOWN;

View File

@ -33,9 +33,9 @@ import io.micrometer.observation.docs.ObservationDocumentation;
public enum ServerHttpObservationDocumentation implements ObservationDocumentation {
/**
* HTTP server request observations.
* HTTP exchanges observations for Servlet-based servers.
*/
HTTP_REQUESTS {
HTTP_SERVLET_SERVER_EXCHANGES {
@Override
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
return DefaultServerRequestObservationConvention.class;

View File

@ -24,7 +24,7 @@ import org.springframework.lang.Nullable;
/**
* Context that holds information for metadata collection during observations
* for {@link ServerHttpObservationDocumentation#HTTP_REQUESTS Servlet HTTP exchanges}.
* for {@link ServerHttpObservationDocumentation#HTTP_SERVLET_SERVER_EXCHANGES Servlet HTTP exchanges}.
* <p>This context also extends {@link RequestReplyReceiverContext} for propagating
* tracing information with the HTTP server exchange.
*

View File

@ -20,7 +20,7 @@ import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;
/**
* Interface for an {@link ObservationConvention} for {@link ServerHttpObservationDocumentation#HTTP_REQUESTS Servlet HTTP exchanges}.
* Interface for an {@link ObservationConvention} for {@link ServerHttpObservationDocumentation#HTTP_SERVLET_SERVER_EXCHANGES Servlet HTTP exchanges}.
*
* @author Brian Clozel
* @since 6.0

View File

@ -33,9 +33,9 @@ import io.micrometer.observation.docs.ObservationDocumentation;
public enum ServerHttpObservationDocumentation implements ObservationDocumentation {
/**
* HTTP server request observations.
* HTTP exchanges observations for reactive servers.
*/
HTTP_REQUESTS {
HTTP_REACTIVE_SERVER_EXCHANGES {
@Override
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
return DefaultServerRequestObservationConvention.class;

View File

@ -26,7 +26,7 @@ import org.springframework.web.util.pattern.PathPattern;
/**
* Context that holds information for metadata collection during observations
* for {@link ServerHttpObservationDocumentation#HTTP_REQUESTS reactive HTTP exchanges}.
* for {@link ServerHttpObservationDocumentation#HTTP_REACTIVE_SERVER_EXCHANGES reactive HTTP exchanges}.
* <p>This context also extends {@link RequestReplyReceiverContext} for propagating
* tracing information with the HTTP server exchange.
*

View File

@ -20,7 +20,7 @@ import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationConvention;
/**
* Interface for an {@link ObservationConvention} for {@link ServerHttpObservationDocumentation#HTTP_REQUESTS reactive HTTP exchanges}.
* Interface for an {@link ObservationConvention} for {@link ServerHttpObservationDocumentation#HTTP_REACTIVE_SERVER_EXCHANGES reactive HTTP exchanges}.
*
* @author Brian Clozel
* @since 6.0

View File

@ -855,7 +855,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
}
ClientRequestObservationContext observationContext = new ClientRequestObservationContext(request);
observationContext.setUriTemplate(uriTemplate);
Observation observation = ClientHttpObservationDocumentation.HTTP_REQUEST.observation(this.observationConvention,
Observation observation = ClientHttpObservationDocumentation.HTTP_CLIENT_EXCHANGES.observation(this.observationConvention,
DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, this.observationRegistry).start();
ClientHttpResponse response = null;
try {

View File

@ -127,7 +127,7 @@ public class ServerHttpObservationFilter extends OncePerRequestFilter {
Observation observation = (Observation) request.getAttribute(CURRENT_OBSERVATION_ATTRIBUTE);
if (observation == null) {
ServerRequestObservationContext context = new ServerRequestObservationContext(request, response);
observation = ServerHttpObservationDocumentation.HTTP_REQUESTS.observation(this.observationConvention,
observation = ServerHttpObservationDocumentation.HTTP_SERVLET_SERVER_EXCHANGES.observation(this.observationConvention,
DEFAULT_OBSERVATION_CONVENTION, () -> context, this.observationRegistry).start();
request.setAttribute(CURRENT_OBSERVATION_ATTRIBUTE, observation);
if (!observation.isNoop()) {

View File

@ -106,7 +106,7 @@ public class ServerHttpObservationFilter implements WebFilter {
}
private Publisher<Void> filter(ServerWebExchange exchange, ServerRequestObservationContext observationContext, Mono<Void> call) {
Observation observation = ServerHttpObservationDocumentation.HTTP_REQUESTS.observation(this.observationConvention,
Observation observation = ServerHttpObservationDocumentation.HTTP_REACTIVE_SERVER_EXCHANGES.observation(this.observationConvention,
DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, this.observationRegistry);
observation.start();
return call.doOnEach(signal -> {

View File

@ -32,9 +32,9 @@ import io.micrometer.observation.docs.ObservationDocumentation;
public enum ClientHttpObservationDocumentation implements ObservationDocumentation {
/**
* Observation created for an HTTP client exchange.
* HTTP exchanges observations for reactive clients.
*/
HTTP_REQUEST {
HTTP_REACTIVE_CLIENT_EXCHANGES {
@Override
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
return DefaultClientRequestObservationConvention.class;
@ -42,12 +42,12 @@ public enum ClientHttpObservationDocumentation implements ObservationDocumentati
@Override
public KeyName[] getLowCardinalityKeyNames() {
return ClientHttpObservationDocumentation.LowCardinalityKeyNames.values();
return LowCardinalityKeyNames.values();
}
@Override
public KeyName[] getHighCardinalityKeyNames() {
return ClientHttpObservationDocumentation.HighCardinalityKeyNames.values();
return HighCardinalityKeyNames.values();
}
};

View File

@ -22,7 +22,7 @@ import org.springframework.lang.Nullable;
/**
* Context that holds information for metadata collection
* during the {@link ClientHttpObservationDocumentation#HTTP_REQUEST HTTP client exchange observations}.
* during the {@link ClientHttpObservationDocumentation#HTTP_REACTIVE_CLIENT_EXCHANGES HTTP client exchange observations}.
* <p>The {@link #getCarrier() tracing context carrier} is a {@link ClientRequest.Builder request builder},
* since the actual request is immutable. For {@code KeyValue} extraction, the {@link #getRequest() actual request}
* should be used instead.

View File

@ -21,7 +21,7 @@ import io.micrometer.observation.ObservationConvention;
/**
* Interface for an {@link ObservationConvention} related to
* {@link ClientHttpObservationDocumentation#HTTP_REQUEST HTTP client exchange observations}.
* {@link ClientHttpObservationDocumentation#HTTP_REACTIVE_CLIENT_EXCHANGES HTTP client exchange observations}.
*
* @author Brian Clozel
* @since 6.0

View File

@ -25,6 +25,9 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.util.StringUtils;
import static org.springframework.web.reactive.function.client.ClientHttpObservationDocumentation.HighCardinalityKeyNames;
import static org.springframework.web.reactive.function.client.ClientHttpObservationDocumentation.LowCardinalityKeyNames;
/**
* Default implementation for a {@link ClientRequestObservationConvention},
* extracting information from the {@link ClientRequestObservationContext}.
@ -36,23 +39,23 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
private static final String DEFAULT_NAME = "http.client.requests";
private static final KeyValue URI_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.URI, KeyValue.NONE_VALUE);
private static final KeyValue URI_NONE = KeyValue.of(LowCardinalityKeyNames.URI, KeyValue.NONE_VALUE);
private static final KeyValue METHOD_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, KeyValue.NONE_VALUE);
private static final KeyValue METHOD_NONE = KeyValue.of(LowCardinalityKeyNames.METHOD, KeyValue.NONE_VALUE);
private static final KeyValue STATUS_IO_ERROR = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "IO_ERROR");
private static final KeyValue STATUS_IO_ERROR = KeyValue.of(LowCardinalityKeyNames.STATUS, "IO_ERROR");
private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "CLIENT_ERROR");
private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(LowCardinalityKeyNames.STATUS, "CLIENT_ERROR");
private static final KeyValue HTTP_OUTCOME_SUCCESS = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, "SUCCESS");
private static final KeyValue HTTP_OUTCOME_SUCCESS = KeyValue.of(LowCardinalityKeyNames.OUTCOME, "SUCCESS");
private static final KeyValue HTTP_OUTCOME_UNKNOWN = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, "UNKNOWN");
private static final KeyValue HTTP_OUTCOME_UNKNOWN = KeyValue.of(LowCardinalityKeyNames.OUTCOME, "UNKNOWN");
private static final KeyValue EXCEPTION_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, KeyValue.NONE_VALUE);
private static final KeyValue EXCEPTION_NONE = KeyValue.of(LowCardinalityKeyNames.EXCEPTION, KeyValue.NONE_VALUE);
private static final KeyValue HTTP_URL_NONE = KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, KeyValue.NONE_VALUE);
private static final KeyValue HTTP_URL_NONE = KeyValue.of(HighCardinalityKeyNames.HTTP_URL, KeyValue.NONE_VALUE);
private static final KeyValue CLIENT_NAME_NONE = KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, KeyValue.NONE_VALUE);
private static final KeyValue CLIENT_NAME_NONE = KeyValue.of(HighCardinalityKeyNames.CLIENT_NAME, KeyValue.NONE_VALUE);
private final String name;
@ -89,14 +92,14 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
protected KeyValue uri(ClientRequestObservationContext context) {
if (context.getUriTemplate() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.URI, context.getUriTemplate());
return KeyValue.of(LowCardinalityKeyNames.URI, context.getUriTemplate());
}
return URI_NONE;
}
protected KeyValue method(ClientRequestObservationContext context) {
if (context.getRequest() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, context.getRequest().method().name());
return KeyValue.of(LowCardinalityKeyNames.METHOD, context.getRequest().method().name());
}
else {
return METHOD_NONE;
@ -109,7 +112,7 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
}
ClientResponse response = context.getResponse();
if (response != null) {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, String.valueOf(response.statusCode().value()));
return KeyValue.of(LowCardinalityKeyNames.STATUS, String.valueOf(response.statusCode().value()));
}
if (context.getError() != null && context.getError() instanceof IOException) {
return STATUS_IO_ERROR;
@ -121,7 +124,7 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
Throwable error = context.getError();
if (error != null) {
String simpleName = error.getClass().getSimpleName();
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION,
return KeyValue.of(LowCardinalityKeyNames.EXCEPTION,
StringUtils.hasText(simpleName) ? simpleName : error.getClass().getName());
}
return EXCEPTION_NONE;
@ -144,14 +147,14 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
protected KeyValue httpUrl(ClientRequestObservationContext context) {
if (context.getRequest() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, context.getRequest().url().toASCIIString());
return KeyValue.of(HighCardinalityKeyNames.HTTP_URL, context.getRequest().url().toASCIIString());
}
return HTTP_URL_NONE;
}
protected KeyValue clientName(ClientRequestObservationContext context) {
if (context.getRequest() != null && context.getRequest().url().getHost() != null) {
return KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, context.getRequest().url().getHost());
return KeyValue.of(HighCardinalityKeyNames.CLIENT_NAME, context.getRequest().url().getHost());
}
return CLIENT_NAME_NONE;
}
@ -163,7 +166,7 @@ public class DefaultClientRequestObservationConvention implements ClientRequestO
return HTTP_OUTCOME_SUCCESS;
}
else if (statusCode instanceof HttpStatus status) {
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, status.series().name());
return KeyValue.of(LowCardinalityKeyNames.OUTCOME, status.series().name());
}
else {
return HTTP_OUTCOME_UNKNOWN;

View File

@ -459,7 +459,7 @@ class DefaultWebClient implements WebClient {
initRequestBuilder().body(this.inserter) :
initRequestBuilder();
return Mono.deferContextual(contextView -> {
Observation observation = ClientHttpObservationDocumentation.HTTP_REQUEST.observation(observationConvention,
Observation observation = ClientHttpObservationDocumentation.HTTP_REACTIVE_CLIENT_EXCHANGES.observation(observationConvention,
DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, observationRegistry);
observationContext.setCarrier(requestBuilder);
observation