Reorganize HTTP Observation types
Closes gh-29334
This commit is contained in:
@@ -22,12 +22,13 @@ import io.micrometer.observation.ObservationConvention;
|
||||
import io.micrometer.observation.docs.ObservationDocumentation;
|
||||
|
||||
/**
|
||||
* Documented {@link io.micrometer.common.KeyValue KeyValues} for the {@link WebClient} observations.
|
||||
* Documented {@link io.micrometer.common.KeyValue KeyValues} for the {@link WebClient HTTP client} observations.
|
||||
* <p>This class is used by automated tools to document KeyValues attached to the HTTP client observations.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 6.0
|
||||
*/
|
||||
public enum ClientObservationDocumentation implements ObservationDocumentation {
|
||||
public enum ClientHttpObservationDocumentation implements ObservationDocumentation {
|
||||
|
||||
/**
|
||||
* Observation created for an HTTP client exchange.
|
||||
@@ -35,17 +36,17 @@ public enum ClientObservationDocumentation implements ObservationDocumentation {
|
||||
HTTP_REQUEST {
|
||||
@Override
|
||||
public Class<? extends ObservationConvention<? extends Observation.Context>> getDefaultConvention() {
|
||||
return DefaultClientObservationConvention.class;
|
||||
return DefaultClientRequestObservationConvention.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyName[] getLowCardinalityKeyNames() {
|
||||
return ClientObservationDocumentation.LowCardinalityKeyNames.values();
|
||||
return ClientHttpObservationDocumentation.LowCardinalityKeyNames.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyName[] getHighCardinalityKeyNames() {
|
||||
return ClientObservationDocumentation.HighCardinalityKeyNames.values();
|
||||
return ClientHttpObservationDocumentation.HighCardinalityKeyNames.values();
|
||||
}
|
||||
|
||||
};
|
||||
@@ -22,12 +22,12 @@ import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Context that holds information for metadata collection
|
||||
* during the HTTP client observations.
|
||||
* during the {@link ClientHttpObservationDocumentation#HTTP_REQUEST HTTP client exchange observations}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 6.0
|
||||
*/
|
||||
public class ClientObservationContext extends RequestReplySenderContext<ClientRequest, ClientResponse> {
|
||||
public class ClientRequestObservationContext extends RequestReplySenderContext<ClientRequest, ClientResponse> {
|
||||
|
||||
@Nullable
|
||||
private String uriTemplate;
|
||||
@@ -35,8 +35,8 @@ public class ClientObservationContext extends RequestReplySenderContext<ClientRe
|
||||
private boolean aborted;
|
||||
|
||||
|
||||
public ClientObservationContext() {
|
||||
super(ClientObservationContext::setRequestHeader);
|
||||
public ClientRequestObservationContext() {
|
||||
super(ClientRequestObservationContext::setRequestHeader);
|
||||
}
|
||||
|
||||
private static void setRequestHeader(@Nullable ClientRequest request, String name, String value) {
|
||||
@@ -20,15 +20,17 @@ import io.micrometer.observation.Observation;
|
||||
import io.micrometer.observation.ObservationConvention;
|
||||
|
||||
/**
|
||||
* Interface for an {@link ObservationConvention} related to client HTTP exchanges.
|
||||
* Interface for an {@link ObservationConvention} related to
|
||||
* {@link ClientHttpObservationDocumentation#HTTP_REQUEST HTTP client exchange observations}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 6.0
|
||||
*/
|
||||
public interface ClientObservationConvention extends ObservationConvention<ClientObservationContext> {
|
||||
public interface ClientRequestObservationConvention extends ObservationConvention<ClientRequestObservationContext> {
|
||||
|
||||
@Override
|
||||
default boolean supportsContext(Observation.Context context) {
|
||||
return context instanceof ClientObservationContext;
|
||||
return context instanceof ClientRequestObservationContext;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.reactive.function.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.micrometer.common.KeyValue;
|
||||
import io.micrometer.common.KeyValues;
|
||||
import io.micrometer.observation.ObservationConvention;
|
||||
|
||||
import org.springframework.http.client.observation.ClientHttpObservationDocumentation;
|
||||
import org.springframework.http.observation.HttpOutcome;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Default implementation for a {@code WebClient} {@link ObservationConvention},
|
||||
* extracting information from the {@link ClientObservationContext}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 6.0
|
||||
*/
|
||||
public class DefaultClientObservationConvention implements ClientObservationConvention {
|
||||
|
||||
private static final String DEFAULT_NAME = "http.client.requests";
|
||||
|
||||
private static final KeyValue URI_NONE = KeyValue.of(ClientObservationDocumentation.LowCardinalityKeyNames.URI, "none");
|
||||
|
||||
private static final KeyValue METHOD_NONE = KeyValue.of(ClientObservationDocumentation.LowCardinalityKeyNames.METHOD, "none");
|
||||
|
||||
private static final KeyValue STATUS_IO_ERROR = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "IO_ERROR");
|
||||
|
||||
private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "CLIENT_ERROR");
|
||||
|
||||
private static final KeyValue EXCEPTION_NONE = KeyValue.of(ClientObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, "none");
|
||||
|
||||
private static final KeyValue HTTP_URL_NONE = KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, "none");
|
||||
|
||||
private static final KeyValue CLIENT_NAME_NONE = KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, "none");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
/**
|
||||
* Create a convention with the default name {@code "http.client.requests"}.
|
||||
*/
|
||||
public DefaultClientObservationConvention() {
|
||||
this(DEFAULT_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a convention with a custom name.
|
||||
* @param name the observation name
|
||||
*/
|
||||
public DefaultClientObservationConvention(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextualName(ClientObservationContext context) {
|
||||
return "http " + context.getCarrier().method().name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyValues getLowCardinalityKeyValues(ClientObservationContext context) {
|
||||
return KeyValues.of(uri(context), method(context), status(context), exception(context), outcome(context));
|
||||
}
|
||||
|
||||
protected KeyValue uri(ClientObservationContext context) {
|
||||
if (context.getUriTemplate() != null) {
|
||||
return KeyValue.of(ClientObservationDocumentation.LowCardinalityKeyNames.URI, context.getUriTemplate());
|
||||
}
|
||||
return URI_NONE;
|
||||
}
|
||||
|
||||
protected KeyValue method(ClientObservationContext context) {
|
||||
if (context.getCarrier() != null) {
|
||||
return KeyValue.of(ClientObservationDocumentation.LowCardinalityKeyNames.METHOD, context.getCarrier().method().name());
|
||||
}
|
||||
else {
|
||||
return METHOD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
protected KeyValue status(ClientObservationContext context) {
|
||||
if (context.isAborted()) {
|
||||
return STATUS_CLIENT_ERROR;
|
||||
}
|
||||
ClientResponse response = context.getResponse();
|
||||
if (response != null) {
|
||||
return KeyValue.of(ClientObservationDocumentation.LowCardinalityKeyNames.STATUS, String.valueOf(response.statusCode().value()));
|
||||
}
|
||||
if (context.getError() != null && context.getError() instanceof IOException) {
|
||||
return STATUS_IO_ERROR;
|
||||
}
|
||||
return STATUS_CLIENT_ERROR;
|
||||
}
|
||||
|
||||
protected KeyValue exception(ClientObservationContext context) {
|
||||
Throwable error = context.getError();
|
||||
if (error != null) {
|
||||
String simpleName = error.getClass().getSimpleName();
|
||||
return KeyValue.of(ClientObservationDocumentation.LowCardinalityKeyNames.EXCEPTION,
|
||||
StringUtils.hasText(simpleName) ? simpleName : error.getClass().getName());
|
||||
}
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
protected KeyValue outcome(ClientObservationContext context) {
|
||||
if (context.isAborted()) {
|
||||
return HttpOutcome.UNKNOWN.asKeyValue();
|
||||
}
|
||||
if (context.getResponse() != null) {
|
||||
HttpOutcome httpOutcome = HttpOutcome.forStatus(context.getResponse().statusCode());
|
||||
return httpOutcome.asKeyValue();
|
||||
}
|
||||
return HttpOutcome.UNKNOWN.asKeyValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyValues getHighCardinalityKeyValues(ClientObservationContext context) {
|
||||
return KeyValues.of(httpUrl(context), clientName(context));
|
||||
}
|
||||
|
||||
protected KeyValue httpUrl(ClientObservationContext context) {
|
||||
if (context.getCarrier() != null) {
|
||||
return KeyValue.of(ClientObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, context.getCarrier().url().toASCIIString());
|
||||
}
|
||||
return HTTP_URL_NONE;
|
||||
}
|
||||
|
||||
protected KeyValue clientName(ClientObservationContext context) {
|
||||
if (context.getCarrier() != null && context.getCarrier().url().getHost() != null) {
|
||||
return KeyValue.of(ClientObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, context.getCarrier().url().getHost());
|
||||
}
|
||||
return CLIENT_NAME_NONE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.reactive.function.client;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import io.micrometer.common.KeyValue;
|
||||
import io.micrometer.common.KeyValues;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Default implementation for a {@link ClientRequestObservationConvention},
|
||||
* extracting information from the {@link ClientRequestObservationContext}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 6.0
|
||||
*/
|
||||
public class DefaultClientRequestObservationConvention implements ClientRequestObservationConvention {
|
||||
|
||||
private static final String DEFAULT_NAME = "http.client.requests";
|
||||
|
||||
private static final KeyValue URI_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.URI, "none");
|
||||
|
||||
private static final KeyValue METHOD_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, "none");
|
||||
|
||||
private static final KeyValue STATUS_IO_ERROR = KeyValue.of(org.springframework.http.client.observation.ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "IO_ERROR");
|
||||
|
||||
private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(org.springframework.http.client.observation.ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, "CLIENT_ERROR");
|
||||
|
||||
private static final KeyValue HTTP_OUTCOME_SUCCESS = KeyValue.of(org.springframework.http.client.observation.ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, "SUCCESS");
|
||||
|
||||
private static final KeyValue HTTP_OUTCOME_UNKNOWN = KeyValue.of(org.springframework.http.client.observation.ClientHttpObservationDocumentation.LowCardinalityKeyNames.OUTCOME, "UNKNOWN");
|
||||
|
||||
private static final KeyValue EXCEPTION_NONE = KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION, "none");
|
||||
|
||||
private static final KeyValue HTTP_URL_NONE = KeyValue.of(org.springframework.http.client.observation.ClientHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, "none");
|
||||
|
||||
private static final KeyValue CLIENT_NAME_NONE = KeyValue.of(org.springframework.http.client.observation.ClientHttpObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, "none");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
/**
|
||||
* Create a convention with the default name {@code "http.client.requests"}.
|
||||
*/
|
||||
public DefaultClientRequestObservationConvention() {
|
||||
this(DEFAULT_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a convention with a custom name.
|
||||
* @param name the observation name
|
||||
*/
|
||||
public DefaultClientRequestObservationConvention(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextualName(ClientRequestObservationContext context) {
|
||||
return "http " + context.getCarrier().method().name().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyValues getLowCardinalityKeyValues(ClientRequestObservationContext context) {
|
||||
return KeyValues.of(uri(context), method(context), status(context), exception(context), outcome(context));
|
||||
}
|
||||
|
||||
protected KeyValue uri(ClientRequestObservationContext context) {
|
||||
if (context.getUriTemplate() != null) {
|
||||
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.URI, context.getUriTemplate());
|
||||
}
|
||||
return URI_NONE;
|
||||
}
|
||||
|
||||
protected KeyValue method(ClientRequestObservationContext context) {
|
||||
if (context.getCarrier() != null) {
|
||||
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.METHOD, context.getCarrier().method().name());
|
||||
}
|
||||
else {
|
||||
return METHOD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
protected KeyValue status(ClientRequestObservationContext context) {
|
||||
if (context.isAborted()) {
|
||||
return STATUS_CLIENT_ERROR;
|
||||
}
|
||||
ClientResponse response = context.getResponse();
|
||||
if (response != null) {
|
||||
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.STATUS, String.valueOf(response.statusCode().value()));
|
||||
}
|
||||
if (context.getError() != null && context.getError() instanceof IOException) {
|
||||
return STATUS_IO_ERROR;
|
||||
}
|
||||
return STATUS_CLIENT_ERROR;
|
||||
}
|
||||
|
||||
protected KeyValue exception(ClientRequestObservationContext context) {
|
||||
Throwable error = context.getError();
|
||||
if (error != null) {
|
||||
String simpleName = error.getClass().getSimpleName();
|
||||
return KeyValue.of(ClientHttpObservationDocumentation.LowCardinalityKeyNames.EXCEPTION,
|
||||
StringUtils.hasText(simpleName) ? simpleName : error.getClass().getName());
|
||||
}
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
protected KeyValue outcome(ClientRequestObservationContext context) {
|
||||
if (context.isAborted()) {
|
||||
return HTTP_OUTCOME_UNKNOWN;
|
||||
}
|
||||
if (context.getResponse() != null) {
|
||||
return HttpOutcome.forStatus(context.getResponse().statusCode());
|
||||
}
|
||||
return HTTP_OUTCOME_UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyValues getHighCardinalityKeyValues(ClientRequestObservationContext context) {
|
||||
return KeyValues.of(httpUrl(context), clientName(context));
|
||||
}
|
||||
|
||||
protected KeyValue httpUrl(ClientRequestObservationContext context) {
|
||||
if (context.getCarrier() != null) {
|
||||
return KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.HTTP_URL, context.getCarrier().url().toASCIIString());
|
||||
}
|
||||
return HTTP_URL_NONE;
|
||||
}
|
||||
|
||||
protected KeyValue clientName(ClientRequestObservationContext context) {
|
||||
if (context.getCarrier() != null && context.getCarrier().url().getHost() != null) {
|
||||
return KeyValue.of(ClientHttpObservationDocumentation.HighCardinalityKeyNames.CLIENT_NAME, context.getCarrier().url().getHost());
|
||||
}
|
||||
return CLIENT_NAME_NONE;
|
||||
}
|
||||
|
||||
static class HttpOutcome {
|
||||
|
||||
static KeyValue forStatus(HttpStatusCode statusCode) {
|
||||
if (statusCode.is2xxSuccessful()) {
|
||||
return HTTP_OUTCOME_SUCCESS;
|
||||
}
|
||||
else if (statusCode instanceof HttpStatus status){
|
||||
return KeyValue.of("outcome", status.series().name());
|
||||
}
|
||||
else {
|
||||
return HTTP_OUTCOME_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -73,7 +73,7 @@ class DefaultWebClient implements WebClient {
|
||||
private static final Mono<ClientResponse> NO_HTTP_CLIENT_RESPONSE_ERROR = Mono.error(
|
||||
() -> new IllegalStateException("The underlying HTTP client completed without emitting a response."));
|
||||
|
||||
private static final DefaultClientObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultClientObservationConvention();
|
||||
private static final DefaultClientRequestObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultClientRequestObservationConvention();
|
||||
|
||||
private final ExchangeFunction exchangeFunction;
|
||||
|
||||
@@ -92,7 +92,7 @@ class DefaultWebClient implements WebClient {
|
||||
|
||||
private final ObservationRegistry observationRegistry;
|
||||
|
||||
private final ClientObservationConvention observationConvention;
|
||||
private final ClientRequestObservationConvention observationConvention;
|
||||
|
||||
private final DefaultWebClientBuilder builder;
|
||||
|
||||
@@ -101,7 +101,7 @@ class DefaultWebClient implements WebClient {
|
||||
@Nullable HttpHeaders defaultHeaders, @Nullable MultiValueMap<String, String> defaultCookies,
|
||||
@Nullable Consumer<RequestHeadersSpec<?>> defaultRequest,
|
||||
@Nullable Map<Predicate<HttpStatusCode>, Function<ClientResponse, Mono<? extends Throwable>>> statusHandlerMap,
|
||||
ObservationRegistry observationRegistry, ClientObservationConvention observationConvention,
|
||||
ObservationRegistry observationRegistry, ClientRequestObservationConvention observationConvention,
|
||||
DefaultWebClientBuilder builder) {
|
||||
|
||||
this.exchangeFunction = exchangeFunction;
|
||||
@@ -449,12 +449,12 @@ class DefaultWebClient implements WebClient {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Mono<ClientResponse> exchange() {
|
||||
ClientObservationContext observationContext = new ClientObservationContext();
|
||||
ClientRequestObservationContext observationContext = new ClientRequestObservationContext();
|
||||
ClientRequest request = (this.inserter != null ?
|
||||
initRequestBuilder().body(this.inserter).build() :
|
||||
initRequestBuilder().build());
|
||||
return Mono.defer(() -> {
|
||||
Observation observation = ClientObservationDocumentation.HTTP_REQUEST.observation(observationConvention,
|
||||
Observation observation = ClientHttpObservationDocumentation.HTTP_REQUEST.observation(observationConvention,
|
||||
DEFAULT_OBSERVATION_CONVENTION, () -> observationContext, observationRegistry).start();
|
||||
observationContext.setCarrier(request);
|
||||
observationContext.setUriTemplate((String) request.attribute(URI_TEMPLATE_ATTRIBUTE).orElse(null));
|
||||
|
||||
@@ -113,7 +113,7 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
|
||||
private ObservationRegistry observationRegistry = ObservationRegistry.NOOP;
|
||||
|
||||
@Nullable
|
||||
private ClientObservationConvention observationConvention;
|
||||
private ClientRequestObservationConvention observationConvention;
|
||||
|
||||
|
||||
public DefaultWebClientBuilder() {
|
||||
@@ -288,7 +288,7 @@ final class DefaultWebClientBuilder implements WebClient.Builder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebClient.Builder observationConvention(ClientObservationConvention observationConvention) {
|
||||
public WebClient.Builder observationConvention(ClientRequestObservationConvention observationConvention) {
|
||||
Assert.notNull(observationConvention, "observationConvention must not be null");
|
||||
this.observationConvention = observationConvention;
|
||||
return this;
|
||||
|
||||
@@ -347,12 +347,12 @@ public interface WebClient {
|
||||
|
||||
/**
|
||||
* Provide an {@link ObservationConvention} to use for collecting
|
||||
* metadata for the current observation. Will use {@link DefaultClientObservationConvention}
|
||||
* metadata for the request observation. Will use {@link DefaultClientRequestObservationConvention}
|
||||
* if none provided.
|
||||
* @param observationConvention the observation convention to use
|
||||
* @since 6.0
|
||||
*/
|
||||
Builder observationConvention(ClientObservationConvention observationConvention);
|
||||
Builder observationConvention(ClientRequestObservationConvention observationConvention);
|
||||
|
||||
/**
|
||||
* Apply the given {@code Consumer} to this builder instance.
|
||||
|
||||
@@ -28,13 +28,13 @@ import org.springframework.http.HttpStatus;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link DefaultClientObservationConvention}.
|
||||
* Tests for {@link DefaultClientRequestObservationConvention}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class DefaultClientObservationConventionTests {
|
||||
class DefaultClientRequestObservationConventionTests {
|
||||
|
||||
private final DefaultClientObservationConvention observationConvention = new DefaultClientObservationConvention();
|
||||
private final DefaultClientRequestObservationConvention observationConvention = new DefaultClientRequestObservationConvention();
|
||||
|
||||
@Test
|
||||
void shouldHaveName() {
|
||||
@@ -43,20 +43,20 @@ class DefaultClientObservationConventionTests {
|
||||
|
||||
@Test
|
||||
void shouldHaveContextualName() {
|
||||
ClientObservationContext context = new ClientObservationContext();
|
||||
ClientRequestObservationContext context = new ClientRequestObservationContext();
|
||||
context.setCarrier(ClientRequest.create(HttpMethod.GET, URI.create("/test")).build());
|
||||
assertThat(this.observationConvention.getContextualName(context)).isEqualTo("http get");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldOnlySupportWebClientObservationContext() {
|
||||
assertThat(this.observationConvention.supportsContext(new ClientObservationContext())).isTrue();
|
||||
assertThat(this.observationConvention.supportsContext(new ClientRequestObservationContext())).isTrue();
|
||||
assertThat(this.observationConvention.supportsContext(new Observation.Context())).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAddKeyValuesForNullExchange() {
|
||||
ClientObservationContext context = new ClientObservationContext();
|
||||
ClientRequestObservationContext context = new ClientRequestObservationContext();
|
||||
assertThat(this.observationConvention.getLowCardinalityKeyValues(context)).hasSize(5)
|
||||
.contains(KeyValue.of("method", "none"), KeyValue.of("uri", "none"), KeyValue.of("status", "CLIENT_ERROR"),
|
||||
KeyValue.of("exception", "none"), KeyValue.of("outcome", "UNKNOWN"));
|
||||
@@ -66,7 +66,7 @@ class DefaultClientObservationConventionTests {
|
||||
|
||||
@Test
|
||||
void shouldAddKeyValuesForExchangeWithException() {
|
||||
ClientObservationContext context = new ClientObservationContext();
|
||||
ClientRequestObservationContext context = new ClientRequestObservationContext();
|
||||
context.setError(new IllegalStateException("Could not create client request"));
|
||||
assertThat(this.observationConvention.getLowCardinalityKeyValues(context)).hasSize(5)
|
||||
.contains(KeyValue.of("method", "none"), KeyValue.of("uri", "none"), KeyValue.of("status", "CLIENT_ERROR"),
|
||||
@@ -79,7 +79,7 @@ class DefaultClientObservationConventionTests {
|
||||
void shouldAddKeyValuesForRequestWithUriTemplate() {
|
||||
ClientRequest request = ClientRequest.create(HttpMethod.GET, URI.create("/resource/42"))
|
||||
.attribute(WebClient.class.getName() + ".uriTemplate", "/resource/{id}").build();
|
||||
ClientObservationContext context = createContext(request);
|
||||
ClientRequestObservationContext context = createContext(request);
|
||||
context.setUriTemplate("/resource/{id}");
|
||||
assertThat(this.observationConvention.getLowCardinalityKeyValues(context))
|
||||
.contains(KeyValue.of("exception", "none"), KeyValue.of("method", "GET"), KeyValue.of("uri", "/resource/{id}"),
|
||||
@@ -90,7 +90,7 @@ class DefaultClientObservationConventionTests {
|
||||
|
||||
@Test
|
||||
void shouldAddKeyValuesForRequestWithoutUriTemplate() {
|
||||
ClientObservationContext context = createContext(ClientRequest.create(HttpMethod.GET, URI.create("/resource/42")).build());
|
||||
ClientRequestObservationContext context = createContext(ClientRequest.create(HttpMethod.GET, URI.create("/resource/42")).build());
|
||||
assertThat(this.observationConvention.getLowCardinalityKeyValues(context))
|
||||
.contains(KeyValue.of("method", "GET"), KeyValue.of("uri", "none"));
|
||||
assertThat(this.observationConvention.getHighCardinalityKeyValues(context)).hasSize(2).contains(KeyValue.of("http.url", "/resource/42"));
|
||||
@@ -98,12 +98,12 @@ class DefaultClientObservationConventionTests {
|
||||
|
||||
@Test
|
||||
void shouldAddClientNameKeyValueForRequestWithHost() {
|
||||
ClientObservationContext context = createContext(ClientRequest.create(HttpMethod.GET, URI.create("https://localhost:8080/resource/42")).build());
|
||||
ClientRequestObservationContext context = createContext(ClientRequest.create(HttpMethod.GET, URI.create("https://localhost:8080/resource/42")).build());
|
||||
assertThat(this.observationConvention.getHighCardinalityKeyValues(context)).contains(KeyValue.of("client.name", "localhost"));
|
||||
}
|
||||
|
||||
private ClientObservationContext createContext(ClientRequest request) {
|
||||
ClientObservationContext context = new ClientObservationContext();
|
||||
private ClientRequestObservationContext createContext(ClientRequest request) {
|
||||
ClientRequestObservationContext context = new ClientRequestObservationContext();
|
||||
context.setCarrier(request);
|
||||
context.setResponse(ClientResponse.create(HttpStatus.OK).build());
|
||||
return context;
|
||||
Reference in New Issue
Block a user