diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointHandlerMapping.java index f8e1811adc4..58c381ef5e3 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/reactive/CloudFoundryWebFluxEndpointHandlerMapping.java @@ -38,7 +38,6 @@ import org.springframework.boot.actuate.endpoint.web.reactive.AbstractWebFluxEnd import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.reactive.result.method.RequestMappingInfoHandlerMapping; import org.springframework.web.server.ServerWebExchange; @@ -49,6 +48,7 @@ import org.springframework.web.server.ServerWebExchange; * * @author Madhura Bhave * @author Phillip Webb + * @author Brian Clozel */ class CloudFoundryWebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandlerMapping { @@ -75,34 +75,47 @@ class CloudFoundryWebFluxEndpointHandlerMapping } @Override - @ResponseBody - protected Publisher> links(ServerWebExchange exchange) { - ServerHttpRequest request = exchange.getRequest(); - return this.securityInterceptor.preHandle(exchange, "") - .map((securityResponse) -> { - if (!securityResponse.getStatus().equals(HttpStatus.OK)) { - return new ResponseEntity<>(securityResponse.getStatus()); - } - AccessLevel accessLevel = exchange - .getAttribute(AccessLevel.REQUEST_ATTRIBUTE); - Map links = this.linksResolver - .resolveLinks(request.getURI().toString()); - return new ResponseEntity<>( - Collections.singletonMap("_links", - getAccessibleLinks(accessLevel, links)), - HttpStatus.OK); - }); + protected LinksHandler getLinksHandler() { + return new CloudFoundryLinksHandler(); } - private Map getAccessibleLinks(AccessLevel accessLevel, - Map links) { - if (accessLevel == null) { - return new LinkedHashMap<>(); + class CloudFoundryLinksHandler implements LinksHandler { + + @Override + public Publisher> links(ServerWebExchange exchange) { + ServerHttpRequest request = exchange.getRequest(); + return CloudFoundryWebFluxEndpointHandlerMapping.this.securityInterceptor + .preHandle(exchange, "").map((securityResponse) -> { + if (!securityResponse.getStatus().equals(HttpStatus.OK)) { + return new ResponseEntity<>(securityResponse.getStatus()); + } + AccessLevel accessLevel = exchange + .getAttribute(AccessLevel.REQUEST_ATTRIBUTE); + Map links = CloudFoundryWebFluxEndpointHandlerMapping.this.linksResolver + .resolveLinks(request.getURI().toString()); + return new ResponseEntity<>( + Collections.singletonMap("_links", + getAccessibleLinks(accessLevel, links)), + HttpStatus.OK); + }); } - return links.entrySet().stream() - .filter((entry) -> entry.getKey().equals("self") - || accessLevel.isAccessAllowed(entry.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + private Map getAccessibleLinks(AccessLevel accessLevel, + Map links) { + if (accessLevel == null) { + return new LinkedHashMap<>(); + } + return links.entrySet().stream() + .filter((entry) -> entry.getKey().equals("self") + || accessLevel.isAccessAllowed(entry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + @Override + public String toString() { + return "Actuator root web endpoint"; + } + } /** diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java index 5b20e0fcbf0..430ce78e062 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/cloudfoundry/servlet/CloudFoundryWebEndpointServletHandlerMapping.java @@ -47,6 +47,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi * * @author Madhura Bhave * @author Phillip Webb + * @author Brian Clozel */ class CloudFoundryWebEndpointServletHandlerMapping extends AbstractWebMvcEndpointHandlerMapping { @@ -73,38 +74,52 @@ class CloudFoundryWebEndpointServletHandlerMapping } @Override - @ResponseBody - protected Map> links(HttpServletRequest request, - HttpServletResponse response) { - SecurityResponse securityResponse = this.securityInterceptor.preHandle(request, - null); - if (!securityResponse.getStatus().equals(HttpStatus.OK)) { - sendFailureResponse(response, securityResponse); - } - AccessLevel accessLevel = (AccessLevel) request - .getAttribute(AccessLevel.REQUEST_ATTRIBUTE); - Map links = this.linksResolver - .resolveLinks(request.getRequestURL().toString()); - Map filteredLinks = new LinkedHashMap<>(); - if (accessLevel == null) { - return Collections.singletonMap("_links", filteredLinks); - } - filteredLinks = links.entrySet().stream() - .filter((e) -> e.getKey().equals("self") - || accessLevel.isAccessAllowed(e.getKey())) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - return Collections.singletonMap("_links", filteredLinks); + protected LinksHandler getLinksHandler() { + return new CloudFoundryLinksHandler(); } - private void sendFailureResponse(HttpServletResponse response, - SecurityResponse securityResponse) { - try { - response.sendError(securityResponse.getStatus().value(), - securityResponse.getMessage()); + class CloudFoundryLinksHandler implements LinksHandler { + + @Override + @ResponseBody + public Map> links(HttpServletRequest request, + HttpServletResponse response) { + SecurityResponse securityResponse = CloudFoundryWebEndpointServletHandlerMapping.this.securityInterceptor + .preHandle(request, null); + if (!securityResponse.getStatus().equals(HttpStatus.OK)) { + sendFailureResponse(response, securityResponse); + } + AccessLevel accessLevel = (AccessLevel) request + .getAttribute(AccessLevel.REQUEST_ATTRIBUTE); + Map links = CloudFoundryWebEndpointServletHandlerMapping.this.linksResolver + .resolveLinks(request.getRequestURL().toString()); + Map filteredLinks = new LinkedHashMap<>(); + if (accessLevel == null) { + return Collections.singletonMap("_links", filteredLinks); + } + filteredLinks = links.entrySet().stream() + .filter((e) -> e.getKey().equals("self") + || accessLevel.isAccessAllowed(e.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + return Collections.singletonMap("_links", filteredLinks); } - catch (Exception ex) { - this.logger.debug("Failed to send error response", ex); + + @Override + public String toString() { + return "Actuator root web endpoint"; } + + private void sendFailureResponse(HttpServletResponse response, + SecurityResponse securityResponse) { + try { + response.sendError(securityResponse.getStatus().value(), + securityResponse.getMessage()); + } + catch (Exception ex) { + logger.debug("Failed to send error response", ex); + } + } + } /** diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java index 060ae160b8b..a4a9c84ba46 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/AbstractWebFluxEndpointHandlerMapping.java @@ -55,6 +55,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.result.condition.ConsumesRequestCondition; import org.springframework.web.reactive.result.condition.PatternsRequestCondition; @@ -73,6 +74,7 @@ import org.springframework.web.util.pattern.PathPatternParser; * @author Andy Wilkinson * @author Madhura Bhave * @author Phillip Webb + * @author Brian Clozel * @since 2.0.0 */ public abstract class AbstractWebFluxEndpointHandlerMapping @@ -88,9 +90,6 @@ public abstract class AbstractWebFluxEndpointHandlerMapping private final CorsConfiguration corsConfiguration; - private final Method linksMethod = ReflectionUtils.findMethod(getClass(), "links", - ServerWebExchange.class); - private final Method handleWriteMethod = ReflectionUtils.findMethod( WriteOperationHandler.class, "handle", ServerWebExchange.class, Map.class); @@ -127,14 +126,17 @@ public abstract class AbstractWebFluxEndpointHandlerMapping } } + @Override + protected HandlerMethod createHandlerMethod(Object handler, Method method) { + HandlerMethod handlerMethod = super.createHandlerMethod(handler, method); + return new WebFluxEndpointHandlerMethod(handlerMethod.getBean(), + handlerMethod.getMethod()); + } + private void registerMappingForOperation(ExposableWebEndpoint endpoint, WebOperation operation) { - OperationInvoker invoker = operation::invoke; - if (operation.isBlocking()) { - invoker = new ElasticSchedulerInvoker(invoker); - } ReactiveWebOperation reactiveWebOperation = wrapReactiveWebOperation(endpoint, - operation, new ReactiveWebOperationAdapter(invoker)); + operation, new ReactiveWebOperationAdapter(operation)); if (operation.getType() == OperationType.WRITE) { registerMapping(createRequestMappingInfo(operation), new WriteOperationHandler((reactiveWebOperation)), @@ -183,7 +185,9 @@ public abstract class AbstractWebFluxEndpointHandlerMapping StringUtils.toStringArray(this.endpointMediaTypes.getProduced())); RequestMappingInfo mapping = new RequestMappingInfo(patterns, methods, null, null, null, produces, null); - registerMapping(mapping, this, this.linksMethod); + LinksHandler linksHandler = getLinksHandler(); + registerMapping(mapping, linksHandler, ReflectionUtils + .findMethod(linksHandler.getClass(), "links", ServerWebExchange.class)); } @Override @@ -203,7 +207,11 @@ public abstract class AbstractWebFluxEndpointHandlerMapping return null; } - protected abstract Object links(ServerWebExchange exchange); + /** + * Return the Handler providing actuator links at the root endpoint. + * @return the links handler + */ + protected abstract LinksHandler getLinksHandler(); /** * Return the web endpoints being mapped. @@ -243,6 +251,16 @@ public abstract class AbstractWebFluxEndpointHandlerMapping } + /** + * Reactive handler providing actuator links at the root endpoint. + */ + @FunctionalInterface + protected interface LinksHandler { + + Object links(ServerWebExchange exchange); + + } + /** * A reactive web operation that can be handled by WebFlux. */ @@ -263,13 +281,24 @@ public abstract class AbstractWebFluxEndpointHandlerMapping private final OperationInvoker invoker; + private final String operationId; + private final Supplier> securityContextSupplier; - private ReactiveWebOperationAdapter(OperationInvoker invoker) { - this.invoker = invoker; + private ReactiveWebOperationAdapter(WebOperation operation) { + this.invoker = getInvoker(operation); + this.operationId = operation.getId(); this.securityContextSupplier = getSecurityContextSupplier(); } + private OperationInvoker getInvoker(WebOperation operation) { + OperationInvoker invoker = operation::invoke; + if (operation.isBlocking()) { + invoker = new ElasticSchedulerInvoker(invoker); + } + return invoker; + } + private Supplier> getSecurityContextSupplier() { if (ClassUtils.isPresent( "org.springframework.security.core.context.ReactiveSecurityContextHolder", @@ -337,6 +366,11 @@ public abstract class AbstractWebFluxEndpointHandlerMapping HttpStatus.valueOf(webEndpointResponse.getStatus())); } + @Override + public String toString() { + return "Actuator web endpoint '" + this.operationId + "'"; + } + } /** @@ -376,6 +410,26 @@ public abstract class AbstractWebFluxEndpointHandlerMapping } + private static class WebFluxEndpointHandlerMethod extends HandlerMethod { + + WebFluxEndpointHandlerMethod(Object bean, Method method) { + super(bean, method); + } + + @Override + public String toString() { + return getBean().toString(); + } + + @Override + public HandlerMethod createWithResolvedBean() { + HandlerMethod handlerMethod = super.createWithResolvedBean(); + return new WebFluxEndpointHandlerMethod(handlerMethod.getBean(), + handlerMethod.getMethod()); + } + + } + private static final class ReactiveSecurityContext implements SecurityContext { private final RoleVoter roleVoter = new RoleVoter(); diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointHandlerMapping.java index 42bd357b2b2..8dc6cd79e13 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/reactive/WebFluxEndpointHandlerMapping.java @@ -38,6 +38,7 @@ import org.springframework.web.util.UriComponentsBuilder; * * @author Andy Wilkinson * @author Phillip Webb + * @author Brian Clozel * @since 2.0.0 */ public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandlerMapping @@ -64,12 +65,31 @@ public class WebFluxEndpointHandlerMapping extends AbstractWebFluxEndpointHandle } @Override - @ResponseBody - protected Map> links(ServerWebExchange exchange) { - String requestUri = UriComponentsBuilder.fromUri(exchange.getRequest().getURI()) - .replaceQuery(null).toUriString(); - return Collections.singletonMap("_links", - this.linksResolver.resolveLinks(requestUri)); + protected LinksHandler getLinksHandler() { + return new WebFluxLinksHandler(); + } + + /** + * Handler for root endpoint providing links. + */ + class WebFluxLinksHandler implements LinksHandler { + + @Override + @ResponseBody + public Map> links(ServerWebExchange exchange) { + String requestUri = UriComponentsBuilder + .fromUri(exchange.getRequest().getURI()).replaceQuery(null) + .toUriString(); + return Collections.singletonMap("_links", + WebFluxEndpointHandlerMapping.this.linksResolver + .resolveLinks(requestUri)); + } + + @Override + public String toString() { + return "Actuator root web endpoint"; + } + } } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/AbstractWebMvcEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/AbstractWebMvcEndpointHandlerMapping.java index dd0f620f606..c9a9c10648a 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/AbstractWebMvcEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/AbstractWebMvcEndpointHandlerMapping.java @@ -49,6 +49,7 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.handler.MatchableHandlerMapping; import org.springframework.web.servlet.handler.RequestMatchResult; @@ -66,6 +67,7 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMappi * @author Andy Wilkinson * @author Madhura Bhave * @author Phillip Webb + * @author Brian Clozel * @since 2.0.0 */ public abstract class AbstractWebMvcEndpointHandlerMapping @@ -80,9 +82,6 @@ public abstract class AbstractWebMvcEndpointHandlerMapping private final CorsConfiguration corsConfiguration; - private final Method linksMethod = ReflectionUtils.findMethod(getClass(), "links", - HttpServletRequest.class, HttpServletResponse.class); - private final Method handleMethod = ReflectionUtils.findMethod(OperationHandler.class, "handle", HttpServletRequest.class, Map.class); @@ -131,6 +130,13 @@ public abstract class AbstractWebMvcEndpointHandlerMapping } } + @Override + protected HandlerMethod createHandlerMethod(Object handler, Method method) { + HandlerMethod handlerMethod = super.createHandlerMethod(handler, method); + return new WebMvcEndpointHandlerMethod(handlerMethod.getBean(), + handlerMethod.getMethod()); + } + @Override public RequestMatchResult match(HttpServletRequest request, String pattern) { RequestMappingInfo info = RequestMappingInfo.paths(pattern).options(builderConfig) @@ -156,9 +162,8 @@ public abstract class AbstractWebMvcEndpointHandlerMapping private void registerMappingForOperation(ExposableWebEndpoint endpoint, WebOperation operation) { - OperationInvoker invoker = operation::invoke; ServletWebOperation servletWebOperation = wrapServletWebOperation(endpoint, - operation, new ServletWebOperationAdapter(invoker)); + operation, new ServletWebOperationAdapter(operation)); registerMapping(createRequestMappingInfo(operation), new OperationHandler(servletWebOperation), this.handleMethod); } @@ -171,7 +176,6 @@ public abstract class AbstractWebMvcEndpointHandlerMapping * @param servletWebOperation the servlet web operation to wrap * @return a wrapped servlet web operation */ - protected ServletWebOperation wrapServletWebOperation(ExposableWebEndpoint endpoint, WebOperation operation, ServletWebOperation servletWebOperation) { return servletWebOperation; @@ -200,7 +204,10 @@ public abstract class AbstractWebMvcEndpointHandlerMapping .toStringArray(this.endpointMediaTypes.getProduced()))); RequestMappingInfo mapping = new RequestMappingInfo(patterns, methods, null, null, null, produces, null); - registerMapping(mapping, this, this.linksMethod); + LinksHandler linksHandler = getLinksHandler(); + registerMapping(mapping, linksHandler, + ReflectionUtils.findMethod(linksHandler.getClass(), "links", + HttpServletRequest.class, HttpServletResponse.class)); } private PatternsRequestCondition patternsRequestConditionForPattern(String path) { @@ -232,8 +239,11 @@ public abstract class AbstractWebMvcEndpointHandlerMapping interceptors.add(new SkipPathExtensionContentNegotiation()); } - protected abstract Object links(HttpServletRequest request, - HttpServletResponse response); + /** + * Return the Handler providing actuator links at the root endpoint. + * @return the links handler + */ + protected abstract LinksHandler getLinksHandler(); /** * Return the web endpoints being mapped. @@ -243,6 +253,16 @@ public abstract class AbstractWebMvcEndpointHandlerMapping return this.endpoints; } + /** + * Handler providing actuator links at the root endpoint. + */ + @FunctionalInterface + protected interface LinksHandler { + + Object links(HttpServletRequest request, HttpServletResponse response); + + } + /** * A servlet web operation that can be handled by Spring MVC. */ @@ -259,10 +279,10 @@ public abstract class AbstractWebMvcEndpointHandlerMapping */ private class ServletWebOperationAdapter implements ServletWebOperation { - private final OperationInvoker invoker; + private final WebOperation operation; - ServletWebOperationAdapter(OperationInvoker invoker) { - this.invoker = invoker; + ServletWebOperationAdapter(WebOperation operation) { + this.operation = operation; } @Override @@ -271,7 +291,7 @@ public abstract class AbstractWebMvcEndpointHandlerMapping Map arguments = getArguments(request, body); try { return handleResult( - this.invoker.invoke(new InvocationContext( + this.operation.invoke(new InvocationContext( new ServletSecurityContext(request), arguments)), HttpMethod.valueOf(request.getMethod())); } @@ -280,6 +300,11 @@ public abstract class AbstractWebMvcEndpointHandlerMapping } } + @Override + public String toString() { + return "Actuator web endpoint '" + this.operation.getId() + "'"; + } + private Map getArguments(HttpServletRequest request, Map body) { Map arguments = new LinkedHashMap<>(); @@ -330,6 +355,32 @@ public abstract class AbstractWebMvcEndpointHandlerMapping return this.operation.handle(request, body); } + @Override + public String toString() { + return this.operation.toString(); + } + + } + + /** + * {@link HandlerMethod} subclass for endpoint information logging. + */ + private static class WebMvcEndpointHandlerMethod extends HandlerMethod { + + WebMvcEndpointHandlerMethod(Object bean, Method method) { + super(bean, method); + } + + @Override + public String toString() { + return getBean().toString(); + } + + @Override + public HandlerMethod createWithResolvedBean() { + return this; + } + } @ResponseStatus(code = HttpStatus.BAD_REQUEST) diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcEndpointHandlerMapping.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcEndpointHandlerMapping.java index ca1aae006d6..f0e8a736cc7 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcEndpointHandlerMapping.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/servlet/WebMvcEndpointHandlerMapping.java @@ -63,11 +63,29 @@ public class WebMvcEndpointHandlerMapping extends AbstractWebMvcEndpointHandlerM } @Override - @ResponseBody - protected Map> links(HttpServletRequest request, - HttpServletResponse response) { - return Collections.singletonMap("_links", - this.linksResolver.resolveLinks(request.getRequestURL().toString())); + protected LinksHandler getLinksHandler() { + return new WebMvcLinksHandler(); + } + + /** + * Handler for root endpoint providing links. + */ + class WebMvcLinksHandler implements LinksHandler { + + @Override + @ResponseBody + public Map> links(HttpServletRequest request, + HttpServletResponse response) { + return Collections.singletonMap("_links", + WebMvcEndpointHandlerMapping.this.linksResolver + .resolveLinks(request.getRequestURL().toString())); + } + + @Override + public String toString() { + return "Actuator root web endpoint"; + } + } } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/logging/LoggingApplicationListener.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/logging/LoggingApplicationListener.java index cb180b2d357..a83951eb525 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/logging/LoggingApplicationListener.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/logging/LoggingApplicationListener.java @@ -130,6 +130,7 @@ public class LoggingApplicationListener implements GenericApplicationListener { loggers.add("web", "org.springframework.core.codec"); loggers.add("web", "org.springframework.http"); loggers.add("web", "org.springframework.web"); + loggers.add("web", "org.springframework.boot.actuate.endpoint.web"); loggers.add("sql", "org.springframework.jdbc.core"); loggers.add("sql", "org.hibernate.SQL"); DEFAULT_GROUP_LOGGERS = Collections.unmodifiableMap(loggers); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java index 58fbba16de5..7cafdd7a4eb 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/logging/LoggingApplicationListenerTests.java @@ -569,6 +569,7 @@ public class LoggingApplicationListenerTests { assertTraceEnabled("org.springframework.core.codec", true); assertTraceEnabled("org.springframework.http", true); assertTraceEnabled("org.springframework.web", true); + assertTraceEnabled("org.springframework.boot.actuate.endpoint.web", true); } @Test