Skip to content

Commit

Permalink
Disable HTTP Observations for Actuator
Browse files Browse the repository at this point in the history
There's something weird with test using WebTestClient,
see the two failing tests in WebFluxObservationAutoConfigurationTests:
- whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomWebfluxBasePath
- whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomWebfluxBasePathAndCustomEndpointBasePath

Closes spring-projectsgh-34801
  • Loading branch information
jonatan-ivanov committed Jun 28, 2023
1 parent 7d019c6 commit c2e5352
Show file tree
Hide file tree
Showing 9 changed files with 436 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
*
* @author Brian Clozel
* @author Moritz Halbritter
* @author Jonatan Ivanov
* @since 3.0.0
*/
@ConfigurationProperties("management.observations")
Expand Down Expand Up @@ -113,6 +114,8 @@ public static class Server {

private final Filter filter = new Filter();

private final Actuator actuator = new Actuator();

public ServerRequests getRequests() {
return this.requests;
}
Expand All @@ -121,6 +124,10 @@ public Filter getFilter() {
return this.filter;
}

public Actuator getActuator() {
return this.actuator;
}

public static class ServerRequests {

/**
Expand Down Expand Up @@ -159,4 +166,21 @@ public void setOrder(int order) {

}

public static class Actuator {

/**
* Enables HTTP observations for actuator.
*/
private boolean enabled = true;

public boolean isEnabled() {
return this.enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,32 @@
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationPredicate;
import io.micrometer.observation.ObservationRegistry;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties;
import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention;
import org.springframework.http.server.reactive.observation.ServerRequestObservationContext;
import org.springframework.http.server.reactive.observation.ServerRequestObservationConvention;
import org.springframework.web.filter.reactive.ServerHttpObservationFilter;

Expand All @@ -51,14 +56,15 @@
* @author Jon Schneider
* @author Dmytro Nosan
* @author Moritz Halbritter
* @author Jonatan Ivanov
* @since 3.0.0
*/
@AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, ObservationAutoConfiguration.class })
@ConditionalOnClass(Observation.class)
@ConditionalOnBean(ObservationRegistry.class)
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
@EnableConfigurationProperties({ MetricsProperties.class, ObservationProperties.class })
@EnableConfigurationProperties({ MetricsProperties.class, ObservationProperties.class, WebEndpointProperties.class })
@SuppressWarnings("removal")
public class WebFluxObservationAutoConfiguration {

Expand Down Expand Up @@ -97,4 +103,21 @@ MeterFilter metricsHttpServerUriTagFilter(MetricsProperties metricsProperties,

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "management.observations.http.server.actuator.enabled", havingValue = "false")
static class ActuatorWebEndpointObservationConfiguration {

@Bean
ObservationPredicate actuatorWebEndpointObservationPredicate(PathMappedEndpoints pathMappedEndpoints) {
return (name, context) -> {
if (context instanceof ServerRequestObservationContext serverContext) {
return !serverContext.getCarrier().getURI().getPath().startsWith(pathMappedEndpoints.getBasePath());
}
return true;
};

}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.observation.Observation;
import io.micrometer.observation.ObservationPredicate;
import io.micrometer.observation.ObservationRegistry;
import jakarta.servlet.DispatcherType;

Expand All @@ -30,18 +31,24 @@
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties;
import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties.Servlet;
import org.springframework.boot.autoconfigure.web.servlet.ConditionalOnMissingFilterBean;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.server.observation.DefaultServerRequestObservationConvention;
import org.springframework.http.server.observation.ServerRequestObservationContext;
import org.springframework.http.server.observation.ServerRequestObservationConvention;
import org.springframework.web.filter.ServerHttpObservationFilter;
import org.springframework.web.servlet.DispatcherServlet;
Expand All @@ -54,14 +61,15 @@
* @author Jon Schneider
* @author Dmytro Nosan
* @author Moritz Halbritter
* @author Jonatan Ivanov
* @since 3.0.0
*/
@AutoConfiguration(after = { MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class,
SimpleMetricsExportAutoConfiguration.class, ObservationAutoConfiguration.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
@ConditionalOnClass({ DispatcherServlet.class, Observation.class })
@ConditionalOnBean(ObservationRegistry.class)
@EnableConfigurationProperties({ MetricsProperties.class, ObservationProperties.class })
@EnableConfigurationProperties({ MetricsProperties.class, ObservationProperties.class, ServerProperties.class })
public class WebMvcObservationAutoConfiguration {

@Bean
Expand Down Expand Up @@ -97,4 +105,37 @@ MeterFilter metricsHttpServerUriTagFilter(ObservationProperties observationPrope

}

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(value = "management.observations.http.server.actuator.enabled", havingValue = "false")
static class ActuatorWebEndpointObservationConfiguration {

@Bean
ObservationPredicate actuatorWebEndpointObservationPredicate(ServerProperties serverProperties,
WebMvcProperties webMvcProperties, PathMappedEndpoints pathMappedEndpoints) {
return (name, context) -> {
if (context instanceof ServerRequestObservationContext serverContext) {
String contextPath = getContextPath(serverProperties);
String servletPath = getServletPath(webMvcProperties);
String endpointPath = contextPath + servletPath + pathMappedEndpoints.getBasePath();
return !serverContext.getCarrier().getRequestURI().startsWith(endpointPath);
}
return true;
};
}

private static String getContextPath(ServerProperties serverProperties) {
Servlet servlet = serverProperties.getServlet();
return (servlet.getContextPath() != null) ? servlet.getContextPath() : "";
}

private static String getServletPath(WebMvcProperties webMvcProperties) {
WebMvcProperties.Servlet servletProperties = webMvcProperties.getServlet();
if (servletProperties.getPath() == null || "/".equals(servletProperties.getPath())) {
return "";
}
return servletProperties.getPath();
}

}

}
Loading

0 comments on commit c2e5352

Please sign in to comment.