Refine actuator httpexhanges naming
See gh-32885
This commit is contained in:
@@ -40,7 +40,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@ConditionalOnWebApplication
|
||||
@ConditionalOnProperty(prefix = "management.httpexchanges", name = "record", matchIfMissing = true)
|
||||
@ConditionalOnProperty(prefix = "management.httpexchanges.recording", name = "enabled", matchIfMissing = true)
|
||||
@ConditionalOnBean(HttpExchangeRepository.class)
|
||||
@EnableConfigurationProperties(HttpExchangesProperties.class)
|
||||
public class HttpExchangesAutoConfiguration {
|
||||
@@ -52,7 +52,7 @@ public class HttpExchangesAutoConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
HttpExchangesFilter httpExchangesFilter(HttpExchangeRepository repository, HttpExchangesProperties properties) {
|
||||
return new HttpExchangesFilter(repository, properties.getInclude());
|
||||
return new HttpExchangesFilter(repository, properties.getRecording().getInclude());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class HttpExchangesAutoConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
HttpExchangesWebFilter httpExchangesWebFilter(HttpExchangeRepository repository,
|
||||
HttpExchangesProperties properties) {
|
||||
return new HttpExchangesWebFilter(repository, properties.getInclude());
|
||||
return new HttpExchangesWebFilter(repository, properties.getRecording().getInclude());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,19 +35,34 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ConfigurationProperties(prefix = "management.httpexchanges")
|
||||
public class HttpExchangesProperties {
|
||||
|
||||
/**
|
||||
* Items to be included in the exchange recording. Defaults to request headers
|
||||
* (excluding Authorization and Cookie), response headers (excluding Set-Cookie), and
|
||||
* time taken.
|
||||
*/
|
||||
private Set<Include> include = new HashSet<>(Include.defaultIncludes());
|
||||
private final Recording recording = new Recording();
|
||||
|
||||
public Set<Include> getInclude() {
|
||||
return this.include;
|
||||
public Recording getRecording() {
|
||||
return this.recording;
|
||||
}
|
||||
|
||||
public void setInclude(Set<Include> include) {
|
||||
this.include = include;
|
||||
/**
|
||||
* Recording properties.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public static class Recording {
|
||||
|
||||
/**
|
||||
* Items to be included in the exchange recording. Defaults to request headers
|
||||
* (excluding Authorization and Cookie), response headers (excluding Set-Cookie),
|
||||
* and time taken.
|
||||
*/
|
||||
private Set<Include> include = new HashSet<>(Include.defaultIncludes());
|
||||
|
||||
public Set<Include> getInclude() {
|
||||
return this.include;
|
||||
}
|
||||
|
||||
public void setInclude(Set<Include> include) {
|
||||
this.include = include;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -240,19 +240,19 @@
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "management.httpexchanges.include",
|
||||
"name": "management.httpexchanges.recording.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable HTTP request-response exchange recording.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "management.httpexchanges.recording.include",
|
||||
"defaultValue": [
|
||||
"request-headers",
|
||||
"response-headers",
|
||||
"errors"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "management.httpexchanges.record",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to record HTTP request-response exchanges.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "management.influx.metrics.export.consistency",
|
||||
"defaultValue": "one"
|
||||
@@ -2141,21 +2141,21 @@
|
||||
{
|
||||
"name": "management.trace.http.enabled",
|
||||
"deprecation": {
|
||||
"replacement": "management.httpexchanges.record",
|
||||
"replacement": "management.httpexchanges.recording.enabled",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.trace.http.include",
|
||||
"deprecation": {
|
||||
"replacement": "management.httpexchanges.include",
|
||||
"replacement": "management.httpexchanges.recording.include",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.trace.include",
|
||||
"deprecation": {
|
||||
"replacement": "management.httpexchanges.include",
|
||||
"replacement": "management.httpexchanges.recording.include",
|
||||
"level": "error"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -33,8 +33,8 @@ import org.springframework.boot.actuate.web.exchanges.HttpExchange;
|
||||
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
|
||||
import org.springframework.boot.actuate.web.exchanges.HttpExchangesEndpoint;
|
||||
import org.springframework.boot.actuate.web.exchanges.Include;
|
||||
import org.springframework.boot.actuate.web.exchanges.SourceHttpRequest;
|
||||
import org.springframework.boot.actuate.web.exchanges.SourceHttpResponse;
|
||||
import org.springframework.boot.actuate.web.exchanges.RecordableHttpRequest;
|
||||
import org.springframework.boot.actuate.web.exchanges.RecordableHttpResponse;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -62,12 +62,12 @@ class HttpExchangesEndpointDocumentationTests extends MockMvcEndpointDocumentati
|
||||
|
||||
@Test
|
||||
void httpExchanges() throws Exception {
|
||||
SourceHttpRequest request = mock(SourceHttpRequest.class);
|
||||
RecordableHttpRequest request = mock(RecordableHttpRequest.class);
|
||||
given(request.getUri()).willReturn(URI.create("https://api.example.com"));
|
||||
given(request.getMethod()).willReturn("GET");
|
||||
given(request.getHeaders())
|
||||
.willReturn(Collections.singletonMap(HttpHeaders.ACCEPT, Arrays.asList("application/json")));
|
||||
SourceHttpResponse response = mock(SourceHttpResponse.class);
|
||||
RecordableHttpResponse response = mock(RecordableHttpResponse.class);
|
||||
given(response.getStatus()).willReturn(200);
|
||||
given(response.getHeaders())
|
||||
.willReturn(Collections.singletonMap(HttpHeaders.CONTENT_TYPE, Arrays.asList("application/json")));
|
||||
|
||||
@@ -91,7 +91,7 @@ class HttpExchangesAutoConfigurationTests {
|
||||
@Test
|
||||
void backsOffWhenNotRecording() {
|
||||
this.contextRunner.withUserConfiguration(CustomHttpExchangesRepositoryConfiguration.class)
|
||||
.withPropertyValues("management.httpexchanges.record=false")
|
||||
.withPropertyValues("management.httpexchanges.recording.enabled=false")
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(InMemoryHttpExchangeRepository.class)
|
||||
.doesNotHaveBean(HttpExchangesFilter.class));
|
||||
}
|
||||
@@ -134,7 +134,7 @@ class HttpExchangesAutoConfigurationTests {
|
||||
@Bean
|
||||
CustomHttpExchangesWebFilter customWebFilter(HttpExchangeRepository repository,
|
||||
HttpExchangesProperties properties) {
|
||||
return new CustomHttpExchangesWebFilter(repository, properties.getInclude());
|
||||
return new CustomHttpExchangesWebFilter(repository, properties.getRecording().getInclude());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -125,21 +125,21 @@ public final class HttpExchange {
|
||||
|
||||
/**
|
||||
* Start a new {@link Started} from the given source request.
|
||||
* @param sourceHttpRequest the source HTTP request
|
||||
* @param request the recordable HTTP request
|
||||
* @return an in-progress request
|
||||
*/
|
||||
public static Started start(SourceHttpRequest sourceHttpRequest) {
|
||||
return start(Clock.systemUTC(), sourceHttpRequest);
|
||||
public static Started start(RecordableHttpRequest request) {
|
||||
return start(Clock.systemUTC(), request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new {@link Started} from the given source request.
|
||||
* @param clock the clock to use
|
||||
* @param sourceHttpRequest the source HTTP request
|
||||
* @param request the recordable HTTP request
|
||||
* @return an in-progress request
|
||||
*/
|
||||
public static Started start(Clock clock, SourceHttpRequest sourceHttpRequest) {
|
||||
return new Started(clock, sourceHttpRequest);
|
||||
public static Started start(Clock clock, RecordableHttpRequest request) {
|
||||
return new Started(clock, request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,76 +150,74 @@ public final class HttpExchange {
|
||||
|
||||
private final Instant timestamp;
|
||||
|
||||
private final SourceHttpRequest sourceRequest;
|
||||
private final RecordableHttpRequest request;
|
||||
|
||||
private Started(Clock clock, SourceHttpRequest sourceRequest) {
|
||||
private Started(Clock clock, RecordableHttpRequest request) {
|
||||
this.timestamp = Instant.now(clock);
|
||||
this.sourceRequest = sourceRequest;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the request and return a new {@link HttpExchange} instance.
|
||||
* @param sourceHttpResponse the source HTTP response
|
||||
* @param response the recordable HTTP response
|
||||
* @param principalSupplier a supplier to provide the principal
|
||||
* @param sessionIdSupplier a supplier to provide the session ID
|
||||
* @param includes the options to include
|
||||
* @return a new {@link HttpExchange} instance
|
||||
*/
|
||||
public HttpExchange finish(SourceHttpResponse sourceHttpResponse,
|
||||
Supplier<java.security.Principal> principalSupplier, Supplier<String> sessionIdSupplier,
|
||||
Include... includes) {
|
||||
return finish(Clock.systemUTC(), sourceHttpResponse, principalSupplier, sessionIdSupplier, includes);
|
||||
public HttpExchange finish(RecordableHttpResponse response, Supplier<java.security.Principal> principalSupplier,
|
||||
Supplier<String> sessionIdSupplier, Include... includes) {
|
||||
return finish(Clock.systemUTC(), response, principalSupplier, sessionIdSupplier, includes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the request and return a new {@link HttpExchange} instance.
|
||||
* @param clock the clock to use
|
||||
* @param sourceHttpResponse the source HTTP response
|
||||
* @param response the recordable HTTP response
|
||||
* @param principalSupplier a supplier to provide the principal
|
||||
* @param sessionIdSupplier a supplier to provide the session ID
|
||||
* @param includes the options to include
|
||||
* @return a new {@link HttpExchange} instance
|
||||
*/
|
||||
public HttpExchange finish(Clock clock, SourceHttpResponse sourceHttpResponse,
|
||||
public HttpExchange finish(Clock clock, RecordableHttpResponse response,
|
||||
Supplier<java.security.Principal> principalSupplier, Supplier<String> sessionIdSupplier,
|
||||
Include... includes) {
|
||||
return finish(clock, sourceHttpResponse, principalSupplier, sessionIdSupplier,
|
||||
return finish(clock, response, principalSupplier, sessionIdSupplier,
|
||||
new HashSet<>(Arrays.asList(includes)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the request and return a new {@link HttpExchange} instance.
|
||||
* @param sourceHttpResponse the source HTTP response
|
||||
* @param response the recordable HTTP response
|
||||
* @param principalSupplier a supplier to provide the principal
|
||||
* @param sessionIdSupplier a supplier to provide the session ID
|
||||
* @param includes the options to include
|
||||
* @return a new {@link HttpExchange} instance
|
||||
*/
|
||||
public HttpExchange finish(SourceHttpResponse sourceHttpResponse,
|
||||
Supplier<java.security.Principal> principalSupplier, Supplier<String> sessionIdSupplier,
|
||||
Set<Include> includes) {
|
||||
return finish(Clock.systemUTC(), sourceHttpResponse, principalSupplier, sessionIdSupplier, includes);
|
||||
public HttpExchange finish(RecordableHttpResponse response, Supplier<java.security.Principal> principalSupplier,
|
||||
Supplier<String> sessionIdSupplier, Set<Include> includes) {
|
||||
return finish(Clock.systemUTC(), response, principalSupplier, sessionIdSupplier, includes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the request and return a new {@link HttpExchange} instance.
|
||||
* @param clock the clock to use
|
||||
* @param sourceHttpResponse the source HTTP response
|
||||
* @param response the recordable HTTP response
|
||||
* @param principalSupplier a supplier to provide the principal
|
||||
* @param sessionIdSupplier a supplier to provide the session ID
|
||||
* @param includes the options to include
|
||||
* @return a new {@link HttpExchange} instance
|
||||
*/
|
||||
public HttpExchange finish(Clock clock, SourceHttpResponse sourceHttpResponse,
|
||||
public HttpExchange finish(Clock clock, RecordableHttpResponse response,
|
||||
Supplier<java.security.Principal> principalSupplier, Supplier<String> sessionIdSupplier,
|
||||
Set<Include> includes) {
|
||||
Request request = new Request(this.sourceRequest, includes);
|
||||
Response response = new Response(sourceHttpResponse, includes);
|
||||
Request exchangeRequest = new Request(this.request, includes);
|
||||
Response exchangeResponse = new Response(response, includes);
|
||||
Principal principal = getIfIncluded(includes, Include.PRINCIPAL, () -> Principal.from(principalSupplier));
|
||||
Session session = getIfIncluded(includes, Include.SESSION_ID, () -> Session.from(sessionIdSupplier));
|
||||
Duration duration = getIfIncluded(includes, Include.TIME_TAKEN,
|
||||
() -> Duration.between(this.timestamp, Instant.now(clock)));
|
||||
return new HttpExchange(this.timestamp, request, response, principal, session, duration);
|
||||
return new HttpExchange(this.timestamp, exchangeRequest, exchangeResponse, principal, session, duration);
|
||||
}
|
||||
|
||||
private <T> T getIfIncluded(Set<Include> includes, Include include, Supplier<T> supplier) {
|
||||
@@ -241,11 +239,11 @@ public final class HttpExchange {
|
||||
|
||||
private final Map<String, List<String>> headers;
|
||||
|
||||
private Request(SourceHttpRequest source, Set<Include> includes) {
|
||||
this.uri = source.getUri();
|
||||
this.remoteAddress = (includes.contains(Include.REMOTE_ADDRESS)) ? source.getRemoteAddress() : null;
|
||||
this.method = source.getMethod();
|
||||
this.headers = Collections.unmodifiableMap(filterHeaders(source.getHeaders(), includes));
|
||||
private Request(RecordableHttpRequest request, Set<Include> includes) {
|
||||
this.uri = request.getUri();
|
||||
this.remoteAddress = (includes.contains(Include.REMOTE_ADDRESS)) ? request.getRemoteAddress() : null;
|
||||
this.method = request.getMethod();
|
||||
this.headers = Collections.unmodifiableMap(filterHeaders(request.getHeaders(), includes));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,9 +312,9 @@ public final class HttpExchange {
|
||||
|
||||
private final Map<String, List<String>> headers;
|
||||
|
||||
private Response(SourceHttpResponse source, Set<Include> includes) {
|
||||
this.status = source.getStatus();
|
||||
this.headers = Collections.unmodifiableMap(filterHeaders(source.getHeaders(), includes));
|
||||
private Response(RecordableHttpResponse request, Set<Include> includes) {
|
||||
this.status = request.getStatus();
|
||||
this.headers = Collections.unmodifiableMap(filterHeaders(request.getHeaders(), includes));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,14 +21,14 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The source of an HTTP request that will result in an {@link HttpExchange}.
|
||||
* The recordable parts of an HTTP request used when creating an {@link HttpExchange}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.0.0
|
||||
* @see SourceHttpResponse
|
||||
* @see RecordableHttpResponse
|
||||
*/
|
||||
public interface SourceHttpRequest {
|
||||
public interface RecordableHttpRequest {
|
||||
|
||||
/**
|
||||
* Returns the URI of the request.
|
||||
@@ -20,13 +20,13 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The source of an HTTP response that will result in an {@link HttpExchange}.
|
||||
* The recordable parts of an HTTP response used when creating an {@link HttpExchange}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.0.0
|
||||
* @see SourceHttpRequest
|
||||
* @see RecordableHttpRequest
|
||||
*/
|
||||
public interface SourceHttpResponse {
|
||||
public interface RecordableHttpResponse {
|
||||
|
||||
/**
|
||||
* The status of the response.
|
||||
@@ -82,10 +82,10 @@ public class HttpExchangesWebFilter implements WebFilter, Ordered {
|
||||
}
|
||||
|
||||
private void addExchangeOnCommit(ServerWebExchange exchange, PrincipalAndSession principalAndSession) {
|
||||
SourceServerHttpRequest sourceRequest = new SourceServerHttpRequest(exchange.getRequest());
|
||||
RecordableServerHttpRequest sourceRequest = new RecordableServerHttpRequest(exchange.getRequest());
|
||||
HttpExchange.Started startedHtppExchange = HttpExchange.start(sourceRequest);
|
||||
exchange.getResponse().beforeCommit(() -> {
|
||||
SourceServerHttpResponse sourceResponse = new SourceServerHttpResponse(exchange.getResponse());
|
||||
RecordableServerHttpResponse sourceResponse = new RecordableServerHttpResponse(exchange.getResponse());
|
||||
HttpExchange finishedExchange = startedHtppExchange.finish(sourceResponse,
|
||||
principalAndSession::getPrincipal, principalAndSession::getSessionId, this.includes);
|
||||
this.repository.add(finishedExchange);
|
||||
|
||||
@@ -23,16 +23,15 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.web.exchanges.SourceHttpRequest;
|
||||
import org.springframework.boot.actuate.web.exchanges.RecordableHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
/**
|
||||
* A {@link SourceHttpRequest} backed by a {@link ServerWebExchange}.
|
||||
* A {@link RecordableHttpRequest} backed by a {@link ServerHttpRequest}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class SourceServerHttpRequest implements SourceHttpRequest {
|
||||
class RecordableServerHttpRequest implements RecordableHttpRequest {
|
||||
|
||||
private final String method;
|
||||
|
||||
@@ -42,7 +41,7 @@ class SourceServerHttpRequest implements SourceHttpRequest {
|
||||
|
||||
private final String remoteAddress;
|
||||
|
||||
SourceServerHttpRequest(ServerHttpRequest request) {
|
||||
RecordableServerHttpRequest(ServerHttpRequest request) {
|
||||
this.method = request.getMethod().name();
|
||||
this.headers = request.getHeaders();
|
||||
this.uri = request.getURI();
|
||||
@@ -20,22 +20,23 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.actuate.web.exchanges.SourceHttpResponse;
|
||||
import org.springframework.boot.actuate.web.exchanges.RecordableHttpResponse;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
|
||||
/**
|
||||
* An adapter that exposes a {@link ServerHttpResponse} as a {@link SourceHttpResponse}.
|
||||
* An adapter that exposes a {@link ServerHttpResponse} as a
|
||||
* {@link RecordableHttpResponse}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
class SourceServerHttpResponse implements SourceHttpResponse {
|
||||
class RecordableServerHttpResponse implements RecordableHttpResponse {
|
||||
|
||||
private final int status;
|
||||
|
||||
private final Map<String, List<String>> headers;
|
||||
|
||||
SourceServerHttpResponse(ServerHttpResponse response) {
|
||||
RecordableServerHttpResponse(ServerHttpResponse response) {
|
||||
this.status = (response.getStatusCode() != null) ? response.getStatusCode().value() : HttpStatus.OK.value();
|
||||
this.headers = new LinkedHashMap<>(response.getHeaders());
|
||||
}
|
||||
@@ -82,7 +82,7 @@ public class HttpExchangesFilter extends OncePerRequestFilter implements Ordered
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
ServletSourceHttpRequest sourceRequest = new ServletSourceHttpRequest(request);
|
||||
RecordableServletHttpRequest sourceRequest = new RecordableServletHttpRequest(request);
|
||||
HttpExchange.Started startedHtppExchange = HttpExchange.start(sourceRequest);
|
||||
int status = HttpStatus.INTERNAL_SERVER_ERROR.value();
|
||||
try {
|
||||
@@ -90,7 +90,7 @@ public class HttpExchangesFilter extends OncePerRequestFilter implements Ordered
|
||||
status = response.getStatus();
|
||||
}
|
||||
finally {
|
||||
SourceServletHttpResponse sourceResponse = new SourceServletHttpResponse(response, status);
|
||||
RecordableServletHttpResponse sourceResponse = new RecordableServletHttpResponse(response, status);
|
||||
HttpExchange finishedExchange = startedHtppExchange.finish(sourceResponse, request::getUserPrincipal,
|
||||
() -> getSessionId(request), this.includes);
|
||||
this.repository.add(finishedExchange);
|
||||
|
||||
@@ -27,20 +27,21 @@ import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.boot.actuate.web.exchanges.SourceHttpRequest;
|
||||
import org.springframework.boot.actuate.web.exchanges.RecordableHttpRequest;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriUtils;
|
||||
|
||||
/**
|
||||
* An adapter that exposes an {@link HttpServletRequest} as a {@link SourceHttpRequest}.
|
||||
* An adapter that exposes an {@link HttpServletRequest} as a
|
||||
* {@link RecordableHttpRequest}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class ServletSourceHttpRequest implements SourceHttpRequest {
|
||||
final class RecordableServletHttpRequest implements RecordableHttpRequest {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
|
||||
ServletSourceHttpRequest(HttpServletRequest request) {
|
||||
RecordableServletHttpRequest(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@@ -23,20 +23,21 @@ import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.boot.actuate.web.exchanges.SourceHttpResponse;
|
||||
import org.springframework.boot.actuate.web.exchanges.RecordableHttpResponse;
|
||||
|
||||
/**
|
||||
* An adapter that exposes an {@link HttpServletResponse} as a {@link SourceHttpResponse}.
|
||||
* An adapter that exposes an {@link HttpServletResponse} as a
|
||||
* {@link RecordableHttpResponse}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
final class SourceServletHttpResponse implements SourceHttpResponse {
|
||||
final class RecordableServletHttpResponse implements RecordableHttpResponse {
|
||||
|
||||
private final HttpServletResponse delegate;
|
||||
|
||||
private final int status;
|
||||
|
||||
SourceServletHttpResponse(HttpServletResponse response, int status) {
|
||||
RecordableServletHttpResponse(HttpServletResponse response, int status) {
|
||||
this.delegate = response;
|
||||
this.status = status;
|
||||
}
|
||||
@@ -293,12 +293,12 @@ class HttpExchangeTests {
|
||||
assertThat(exchange.getResponse().getHeaders()).containsOnlyKeys(HttpHeaders.CONTENT_LENGTH);
|
||||
}
|
||||
|
||||
private SourceHttpRequest createRequest() {
|
||||
private RecordableHttpRequest createRequest() {
|
||||
return createRequest(Collections.singletonMap(HttpHeaders.ACCEPT, Arrays.asList("application/json")));
|
||||
}
|
||||
|
||||
private SourceHttpRequest createRequest(Map<String, List<String>> headers) {
|
||||
SourceHttpRequest request = mock(SourceHttpRequest.class);
|
||||
private RecordableHttpRequest createRequest(Map<String, List<String>> headers) {
|
||||
RecordableHttpRequest request = mock(RecordableHttpRequest.class);
|
||||
given(request.getMethod()).willReturn("GET");
|
||||
given(request.getUri()).willReturn(URI.create("https://api.example.com"));
|
||||
given(request.getHeaders()).willReturn(new HashMap<>(headers));
|
||||
@@ -306,12 +306,12 @@ class HttpExchangeTests {
|
||||
return request;
|
||||
}
|
||||
|
||||
private SourceHttpResponse createResponse() {
|
||||
private RecordableHttpResponse createResponse() {
|
||||
return createResponse(Collections.singletonMap(HttpHeaders.CONTENT_TYPE, Arrays.asList("application/json")));
|
||||
}
|
||||
|
||||
private SourceHttpResponse createResponse(Map<String, List<String>> headers) {
|
||||
SourceHttpResponse response = mock(SourceHttpResponse.class);
|
||||
private RecordableHttpResponse createResponse(Map<String, List<String>> headers) {
|
||||
RecordableHttpResponse response = mock(RecordableHttpResponse.class);
|
||||
given(response.getStatus()).willReturn(204);
|
||||
given(response.getHeaders()).willReturn(new HashMap<>(headers));
|
||||
return response;
|
||||
|
||||
@@ -48,14 +48,14 @@ class HttpExchangesEndpointTests {
|
||||
assertThat(exchange.getRequest().getMethod()).isEqualTo("GET");
|
||||
}
|
||||
|
||||
private SourceHttpRequest createRequest(String method) {
|
||||
SourceHttpRequest request = mock(SourceHttpRequest.class);
|
||||
private RecordableHttpRequest createRequest(String method) {
|
||||
RecordableHttpRequest request = mock(RecordableHttpRequest.class);
|
||||
given(request.getMethod()).willReturn(method);
|
||||
return request;
|
||||
}
|
||||
|
||||
private SourceHttpResponse createResponse() {
|
||||
return mock(SourceHttpResponse.class);
|
||||
private RecordableHttpResponse createResponse() {
|
||||
return mock(RecordableHttpResponse.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,9 +66,9 @@ class InMemoryHttpExchangeRepositoryTests {
|
||||
}
|
||||
|
||||
private HttpExchange createHttpExchange(String method) {
|
||||
SourceHttpRequest request = mock(SourceHttpRequest.class);
|
||||
RecordableHttpRequest request = mock(RecordableHttpRequest.class);
|
||||
given(request.getMethod()).willReturn(method);
|
||||
SourceHttpResponse response = mock(SourceHttpResponse.class);
|
||||
RecordableHttpResponse response = mock(RecordableHttpResponse.class);
|
||||
return HttpExchange.start(request).finish(response, NO_PRINCIPAL, NO_SESSION_ID);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,11 +34,11 @@ import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link SourceServerHttpRequest}.
|
||||
* Tests for {@link RecordableServerHttpRequest}.
|
||||
*
|
||||
* @author Dmytro Nosan
|
||||
*/
|
||||
class SourceServerHttpRequestTests {
|
||||
class RecordableServerHttpRequestTests {
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
@@ -54,7 +54,7 @@ class SourceServerHttpRequestTests {
|
||||
|
||||
@Test
|
||||
void getMethod() {
|
||||
SourceServerHttpRequest sourceRequest = new SourceServerHttpRequest(this.request);
|
||||
RecordableServerHttpRequest sourceRequest = new RecordableServerHttpRequest(this.request);
|
||||
assertThat(sourceRequest.getMethod()).isEqualTo("GET");
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class SourceServerHttpRequestTests {
|
||||
void getUri() {
|
||||
URI uri = URI.create("http://localhost:8080/");
|
||||
given(this.request.getURI()).willReturn(uri);
|
||||
SourceServerHttpRequest sourceRequest = new SourceServerHttpRequest(this.request);
|
||||
RecordableServerHttpRequest sourceRequest = new RecordableServerHttpRequest(this.request);
|
||||
assertThat(sourceRequest.getUri()).isSameAs(uri);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ class SourceServerHttpRequestTests {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.add("name", "value");
|
||||
given(this.request.getHeaders()).willReturn(httpHeaders);
|
||||
SourceServerHttpRequest sourceRequest = new SourceServerHttpRequest(this.request);
|
||||
RecordableServerHttpRequest sourceRequest = new RecordableServerHttpRequest(this.request);
|
||||
assertThat(sourceRequest.getHeaders()).containsOnly(entry("name", Collections.singletonList("value")));
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class SourceServerHttpRequestTests {
|
||||
void getUnresolvedRemoteAddress() {
|
||||
InetSocketAddress socketAddress = InetSocketAddress.createUnresolved("unresolved.example.com", 8080);
|
||||
given(this.request.getRemoteAddress()).willReturn(socketAddress);
|
||||
SourceServerHttpRequest sourceRequest = new SourceServerHttpRequest(this.request);
|
||||
RecordableServerHttpRequest sourceRequest = new RecordableServerHttpRequest(this.request);
|
||||
assertThat(sourceRequest.getRemoteAddress()).isNull();
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ class SourceServerHttpRequestTests {
|
||||
void getRemoteAddress() {
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(0);
|
||||
given(this.request.getRemoteAddress()).willReturn(socketAddress);
|
||||
SourceServerHttpRequest sourceRequest = new SourceServerHttpRequest(this.request);
|
||||
RecordableServerHttpRequest sourceRequest = new RecordableServerHttpRequest(this.request);
|
||||
assertThat(sourceRequest.getRemoteAddress()).isEqualTo(socketAddress.getAddress().toString());
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ServletSourceHttpRequest}.
|
||||
* Tests for {@link RecordableServletHttpRequest}.
|
||||
*
|
||||
* @author Madhura Bhave
|
||||
*/
|
||||
class ServletSourceHttpRequestTests {
|
||||
class RecordableServletHttpRequestTests {
|
||||
|
||||
private MockHttpServletRequest request;
|
||||
|
||||
@@ -61,7 +61,7 @@ class ServletSourceHttpRequestTests {
|
||||
}
|
||||
|
||||
private void validate(String expectedUri) {
|
||||
ServletSourceHttpRequest sourceRequest = new ServletSourceHttpRequest(this.request);
|
||||
RecordableServletHttpRequest sourceRequest = new RecordableServletHttpRequest(this.request);
|
||||
assertThat(sourceRequest.getUri().toString()).isEqualTo(expectedUri);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,6 @@ You can use the `httpexchanges` endpoint to obtain information about the request
|
||||
|
||||
[[actuator.http-exchanges.custom]]
|
||||
=== Custom HTTP Exchange Recording
|
||||
To customize the items that are included in each recorded exchange, use the configprop:management.httpexchanges.include[] configuration property.
|
||||
To customize the items that are included in each recorded exchange, use the configprop:management.httpexchanges.recording.include[] configuration property.
|
||||
|
||||
To disable recoding entirely, set configprop:management.httpexchanges.record[] to `false`.
|
||||
To disable recoding entirely, set configprop:management.httpexchanges.recording.enabled[] to `false`.
|
||||
|
||||
@@ -17,7 +17,7 @@ spring.jmx.enabled=true
|
||||
|
||||
spring.jackson.serialization.write_dates_as_timestamps=false
|
||||
|
||||
management.httpexchanges.include=request-headers,response-headers,principal,remote-address,session-id
|
||||
management.httpexchanges.recording.include=request-headers,response-headers,principal,remote-address,session-id
|
||||
|
||||
management.endpoint.health.show-details=always
|
||||
management.endpoint.health.group.ready.include=db,diskSpace
|
||||
|
||||
Reference in New Issue
Block a user