Reorganize HTTP Observation types

Closes gh-29334
This commit is contained in:
Brian Clozel
2022-10-17 21:54:04 +02:00
parent 4d44aaf81b
commit 001b2636d6
42 changed files with 762 additions and 849 deletions

View File

@@ -34,15 +34,15 @@ import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link DefaultClientHttpObservationConvention}.
* Tests for {@link DefaultClientRequestObservationConvention}.
*
* @author Brian Clozel
*/
class DefaultClientHttpObservationConventionTests {
class DefaultClientRequestObservationConventionTests {
private final MockClientHttpRequest request = new MockClientHttpRequest(HttpMethod.GET, "/test");
private final DefaultClientHttpObservationConvention observationConvention = new DefaultClientHttpObservationConvention();
private final DefaultClientRequestObservationConvention observationConvention = new DefaultClientRequestObservationConvention();
@Test
void shouldHaveName() {
@@ -51,20 +51,20 @@ class DefaultClientHttpObservationConventionTests {
@Test
void shouldHaveContextualName() {
ClientHttpObservationContext context = new ClientHttpObservationContext(this.request);
ClientRequestObservationContext context = new ClientRequestObservationContext(this.request);
assertThat(this.observationConvention.getContextualName(context)).isEqualTo("http get");
}
@Test
void supportsOnlyClientHttpObservationContext() {
ClientHttpObservationContext context = new ClientHttpObservationContext(this.request);
ClientRequestObservationContext context = new ClientRequestObservationContext(this.request);
assertThat(this.observationConvention.supportsContext(context)).isTrue();
assertThat(this.observationConvention.supportsContext(new Observation.Context())).isFalse();
}
@Test
void addsKeyValuesForRequestWithUriTemplate() {
ClientHttpObservationContext context = createContext(
ClientRequestObservationContext context = createContext(
new MockClientHttpRequest(HttpMethod.GET, "/resource/{id}", 42), new MockClientHttpResponse());
context.setUriTemplate("/resource/{id}");
assertThat(this.observationConvention.getLowCardinalityKeyValues(context))
@@ -76,7 +76,7 @@ class DefaultClientHttpObservationConventionTests {
@Test
void addsKeyValuesForRequestWithoutUriTemplate() {
ClientHttpObservationContext context = createContext(
ClientRequestObservationContext context = createContext(
new MockClientHttpRequest(HttpMethod.GET, "/resource/42"), new MockClientHttpResponse());
assertThat(this.observationConvention.getLowCardinalityKeyValues(context))
.contains(KeyValue.of("method", "GET"), KeyValue.of("uri", "none"));
@@ -86,7 +86,7 @@ class DefaultClientHttpObservationConventionTests {
@Test
void addsClientNameForRequestWithHost() {
ClientHttpObservationContext context = createContext(
ClientRequestObservationContext context = createContext(
new MockClientHttpRequest(HttpMethod.GET, "https://localhost:8080/resource/42"),
new MockClientHttpResponse());
assertThat(this.observationConvention.getHighCardinalityKeyValues(context)).contains(KeyValue.of("client.name", "localhost"));
@@ -94,15 +94,15 @@ class DefaultClientHttpObservationConventionTests {
@Test
void addsKeyValueForNonResolvableStatus() throws Exception {
ClientHttpObservationContext context = new ClientHttpObservationContext(this.request);
ClientRequestObservationContext context = new ClientRequestObservationContext(this.request);
ClientHttpResponse response = mock(ClientHttpResponse.class);
context.setResponse(response);
given(response.getStatusCode()).willThrow(new IOException("test error"));
assertThat(this.observationConvention.getLowCardinalityKeyValues(context)).contains(KeyValue.of("status", "IO_ERROR"));
}
private ClientHttpObservationContext createContext(ClientHttpRequest request, ClientHttpResponse response) {
ClientHttpObservationContext context = new ClientHttpObservationContext(request);
private ClientRequestObservationContext createContext(ClientHttpRequest request, ClientHttpResponse response) {
ClientRequestObservationContext context = new ClientRequestObservationContext(request);
context.setResponse(response);
return context;
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.web.observation;
package org.springframework.http.observation;
import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
@@ -26,18 +26,18 @@ import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultHttpRequestsObservationConvention}.
* Tests for {@link DefaultServerRequestObservationConvention}.
* @author Brian Clozel
*/
class DefaultHttpRequestsObservationConventionTests {
class DefaultServerRequestObservationConventionTests {
private final DefaultHttpRequestsObservationConvention convention = new DefaultHttpRequestsObservationConvention();
private final DefaultServerRequestObservationConvention convention = new DefaultServerRequestObservationConvention();
private final MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test/resource");
private final MockHttpServletResponse response = new MockHttpServletResponse();
private final HttpRequestsObservationContext context = new HttpRequestsObservationContext(this.request, this.response);
private final ServerRequestObservationContext context = new ServerRequestObservationContext(this.request, this.response);
@Test

View File

@@ -1,83 +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.http.observation;
import io.micrometer.common.KeyValue;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.springframework.http.HttpStatusCode;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link HttpOutcome}.
*
* @author Brian Clozel
*/
class HttpOutcomeTests {
@ParameterizedTest
@ValueSource(ints = {100, 101, 102})
void shouldResolveInformational(int code) {
HttpOutcome httpOutcome = HttpOutcome.forStatus(HttpStatusCode.valueOf(code));
assertThat(httpOutcome).isEqualTo(HttpOutcome.INFORMATIONAL);
assertThat(httpOutcome.asKeyValue()).isEqualTo(KeyValue.of("outcome", "INFORMATIONAL"));
}
@ParameterizedTest
@ValueSource(ints = {200, 202, 226})
void shouldResolveSuccess(int code) {
HttpOutcome httpOutcome = HttpOutcome.forStatus(HttpStatusCode.valueOf(code));
assertThat(httpOutcome).isEqualTo(HttpOutcome.SUCCESS);
assertThat(httpOutcome.asKeyValue()).isEqualTo(KeyValue.of("outcome", "SUCCESS"));
}
@ParameterizedTest
@ValueSource(ints = {300, 302, 303})
void shouldResolveRedirection(int code) {
HttpOutcome httpOutcome = HttpOutcome.forStatus(HttpStatusCode.valueOf(code));
assertThat(httpOutcome).isEqualTo(HttpOutcome.REDIRECTION);
assertThat(httpOutcome.asKeyValue()).isEqualTo(KeyValue.of("outcome", "REDIRECTION"));
}
@ParameterizedTest
@ValueSource(ints = {400, 404, 405})
void shouldResolveClientError(int code) {
HttpOutcome httpOutcome = HttpOutcome.forStatus(HttpStatusCode.valueOf(code));
assertThat(httpOutcome).isEqualTo(HttpOutcome.CLIENT_ERROR);
assertThat(httpOutcome.asKeyValue()).isEqualTo(KeyValue.of("outcome", "CLIENT_ERROR"));
}
@ParameterizedTest
@ValueSource(ints = {500, 502, 503})
void shouldResolveServerError(int code) {
HttpOutcome httpOutcome = HttpOutcome.forStatus(HttpStatusCode.valueOf(code));
assertThat(httpOutcome).isEqualTo(HttpOutcome.SERVER_ERROR);
assertThat(httpOutcome.asKeyValue()).isEqualTo(KeyValue.of("outcome", "SERVER_ERROR"));
}
@ParameterizedTest
@ValueSource(ints = {600, 799, 855})
void shouldResolveUnknown(int code) {
HttpOutcome httpOutcome = HttpOutcome.forStatus(HttpStatusCode.valueOf(code));
assertThat(httpOutcome).isEqualTo(HttpOutcome.UNKNOWN);
assertThat(httpOutcome.asKeyValue()).isEqualTo(KeyValue.of("outcome", "UNKNOWN"));
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.web.observation.reactive;
package org.springframework.http.observation.reactive;
import io.micrometer.common.KeyValue;
import io.micrometer.observation.Observation;
@@ -29,12 +29,12 @@ import org.springframework.web.util.pattern.PathPatternParser;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultHttpRequestsObservationConvention}.
* Tests for {@link DefaultServerRequestObservationConvention}.
* @author Brian Clozel
*/
class DefaultHttpRequestsObservationConventionTests {
class DefaultServerRequestObservationConventionTests {
private final DefaultHttpRequestsObservationConvention convention = new DefaultHttpRequestsObservationConvention();
private final DefaultServerRequestObservationConvention convention = new DefaultServerRequestObservationConvention();
@Test
@@ -45,14 +45,14 @@ class DefaultHttpRequestsObservationConventionTests {
@Test
void shouldHaveContextualName() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test/resource"));
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
assertThat(convention.getContextualName(context)).isEqualTo("http get");
}
@Test
void supportsOnlyHttpRequestsObservationContext() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post("/test/resource"));
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
assertThat(this.convention.supportsContext(context)).isTrue();
assertThat(this.convention.supportsContext(new Observation.Context())).isFalse();
}
@@ -61,7 +61,7 @@ class DefaultHttpRequestsObservationConventionTests {
void addsKeyValuesForExchange() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post("/test/resource"));
exchange.getResponse().setRawStatusCode(201);
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
assertThat(this.convention.getLowCardinalityKeyValues(context)).hasSize(5)
.contains(KeyValue.of("method", "POST"), KeyValue.of("uri", "UNKNOWN"), KeyValue.of("status", "201"),
@@ -74,7 +74,7 @@ class DefaultHttpRequestsObservationConventionTests {
void addsKeyValuesForExchangeWithPathPattern() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test/resource"));
exchange.getResponse().setRawStatusCode(200);
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
PathPattern pathPattern = getPathPattern("/test/{name}");
context.setPathPattern(pathPattern);
@@ -89,7 +89,7 @@ class DefaultHttpRequestsObservationConventionTests {
@Test
void addsKeyValuesForErrorExchange() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test/resource"));
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
context.setError(new IllegalArgumentException("custom error"));
exchange.getResponse().setRawStatusCode(500);
@@ -103,7 +103,7 @@ class DefaultHttpRequestsObservationConventionTests {
@Test
void addsKeyValuesForRedirectExchange() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test/redirect"));
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
exchange.getResponse().setRawStatusCode(302);
exchange.getResponse().getHeaders().add("Location", "https://example.org/other");
@@ -117,7 +117,7 @@ class DefaultHttpRequestsObservationConventionTests {
@Test
void addsKeyValuesForNotFoundExchange() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test/notFound"));
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
exchange.getResponse().setRawStatusCode(404);
assertThat(this.convention.getLowCardinalityKeyValues(context)).hasSize(5)
@@ -130,7 +130,7 @@ class DefaultHttpRequestsObservationConventionTests {
@Test
void addsKeyValuesForCancelledExchange() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test/resource"));
HttpRequestsObservationContext context = new HttpRequestsObservationContext(exchange);
ServerRequestObservationContext context = new ServerRequestObservationContext(exchange);
context.setConnectionAborted(true);
exchange.getResponse().setRawStatusCode(200);

View File

@@ -37,7 +37,7 @@ import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.observation.ClientHttpObservationContext;
import org.springframework.http.client.observation.ClientRequestObservationContext;
import org.springframework.http.converter.HttpMessageConverter;
import static org.assertj.core.api.Assertions.assertThat;
@@ -192,15 +192,15 @@ class RestTemplateObservationTests {
.hasObservationWithNameEqualTo("http.client.requests").that();
}
static class ContextAssertionObservationHandler implements ObservationHandler<ClientHttpObservationContext> {
static class ContextAssertionObservationHandler implements ObservationHandler<ClientRequestObservationContext> {
@Override
public boolean supportsContext(Observation.Context context) {
return context instanceof ClientHttpObservationContext;
return context instanceof ClientRequestObservationContext;
}
@Override
public void onStart(ClientHttpObservationContext context) {
public void onStart(ClientRequestObservationContext context) {
assertThat(context.getCarrier()).isNotNull();
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.web.observation;
package org.springframework.web.filter;
import io.micrometer.observation.tck.TestObservationRegistry;
import io.micrometer.observation.tck.TestObservationRegistryAssert;
@@ -23,6 +23,7 @@ import jakarta.servlet.ServletException;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.observation.ServerRequestObservationContext;
import org.springframework.web.testfixture.servlet.MockFilterChain;
import org.springframework.web.testfixture.servlet.MockHttpServletRequest;
import org.springframework.web.testfixture.servlet.MockHttpServletResponse;
@@ -31,14 +32,14 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Tests for {@link HttpRequestsObservationFilter}.
* Tests for {@link ServerHttpObservationFilter}.
* @author Brian Clozel
*/
class HttpRequestsObservationFilterTests {
class ServerHttpObservationFilterTests {
private final TestObservationRegistry observationRegistry = TestObservationRegistry.create();
private final HttpRequestsObservationFilter filter = new HttpRequestsObservationFilter(this.observationRegistry);
private final ServerHttpObservationFilter filter = new ServerHttpObservationFilter(this.observationRegistry);
private final MockFilterChain mockFilterChain = new MockFilterChain();
@@ -51,8 +52,8 @@ class HttpRequestsObservationFilterTests {
void filterShouldFillObservationContext() throws Exception {
this.filter.doFilter(this.request, this.response, this.mockFilterChain);
HttpRequestsObservationContext context = (HttpRequestsObservationContext) this.request
.getAttribute(HttpRequestsObservationFilter.CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE);
ServerRequestObservationContext context = (ServerRequestObservationContext) this.request
.getAttribute(ServerHttpObservationFilter.CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE);
assertThat(context).isNotNull();
assertThat(context.getCarrier()).isEqualTo(this.request);
assertThat(context.getResponse()).isEqualTo(this.response);
@@ -66,8 +67,8 @@ class HttpRequestsObservationFilterTests {
this.request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, customError);
this.filter.doFilter(this.request, this.response, this.mockFilterChain);
HttpRequestsObservationContext context = (HttpRequestsObservationContext) this.request
.getAttribute(HttpRequestsObservationFilter.CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE);
ServerRequestObservationContext context = (ServerRequestObservationContext) this.request
.getAttribute(ServerHttpObservationFilter.CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE);
assertThat(context.getError()).isEqualTo(customError);
assertThatHttpObservation().hasLowCardinalityKeyValue("outcome", "SERVER_ERROR");
}
@@ -81,8 +82,8 @@ class HttpRequestsObservationFilterTests {
throw new ServletException(customError);
});
}).isInstanceOf(ServletException.class);
HttpRequestsObservationContext context = (HttpRequestsObservationContext) this.request
.getAttribute(HttpRequestsObservationFilter.CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE);
ServerRequestObservationContext context = (ServerRequestObservationContext) this.request
.getAttribute(ServerHttpObservationFilter.CURRENT_OBSERVATION_CONTEXT_ATTRIBUTE);
assertThat(context.getError()).isEqualTo(customError);
assertThatHttpObservation().hasLowCardinalityKeyValue("outcome", "SUCCESS");
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.web.observation.reactive;
package org.springframework.web.filter.reactive;
import java.util.Optional;
@@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import org.springframework.http.observation.reactive.ServerRequestObservationContext;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpRequest;
@@ -34,22 +35,22 @@ import org.springframework.web.testfixture.server.MockServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link HttpRequestsObservationWebFilter}.
* Tests for {@link ServerHttpObservationFilter}.
*
* @author Brian Clozel
*/
class HttpRequestsObservationWebFilterTests {
class ServerHttpObservationFilterTests {
private final TestObservationRegistry observationRegistry = TestObservationRegistry.create();
private final HttpRequestsObservationWebFilter filter = new HttpRequestsObservationWebFilter(this.observationRegistry);
private final ServerHttpObservationFilter filter = new ServerHttpObservationFilter(this.observationRegistry);
@Test
void filterShouldFillObservationContext() {
ServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.post("/test/resource"));
exchange.getResponse().setRawStatusCode(200);
WebFilterChain filterChain = createFilterChain(filterExchange -> {
Optional<HttpRequestsObservationContext> observationContext = HttpRequestsObservationWebFilter.findObservationContext(filterExchange);
Optional<ServerRequestObservationContext> observationContext = ServerHttpObservationFilter.findObservationContext(filterExchange);
assertThat(observationContext).isPresent();
assertThat(observationContext.get().getCarrier()).isEqualTo(exchange.getRequest());
assertThat(observationContext.get().getResponse()).isEqualTo(exchange.getResponse());
@@ -68,7 +69,7 @@ class HttpRequestsObservationWebFilterTests {
StepVerifier.create(this.filter.filter(exchange, filterChain))
.expectError(IllegalArgumentException.class)
.verify();
Optional<HttpRequestsObservationContext> observationContext = HttpRequestsObservationWebFilter.findObservationContext(exchange);
Optional<ServerRequestObservationContext> observationContext = ServerHttpObservationFilter.findObservationContext(exchange);
assertThat(observationContext.get().getError()).isInstanceOf(IllegalArgumentException.class);
assertThatHttpObservation().hasLowCardinalityKeyValue("outcome", "SERVER_ERROR");
}