From a59b6cb1f38bbb44117fd0318e60385435a09385 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 25 Oct 2022 17:04:05 -0700 Subject: [PATCH] Polish --- ...mpositeHealthContributorConfiguration.java | 47 ++++++++++++------ .../ObservationAutoConfiguration.java | 4 +- .../ObservationHandlerGrouping.java | 9 ++-- .../ObservationRegistryConfigurer.java | 6 +-- ...lientHttpObservationConventionAdapter.java | 2 +- .../ClientObservationConventionAdapter.java | 16 +++--- ...tpClientObservationsAutoConfiguration.java | 12 +++-- ...erRequestObservationConventionAdapter.java | 2 +- .../WebFluxObservationAutoConfiguration.java | 29 ++++++----- ...erRequestObservationConventionAdapter.java | 2 +- .../tracing/BraveAutoConfiguration.java | 8 +-- .../wavefront/MeterRegistrySpanMetrics.java | 7 ++- .../tracing/zipkin/ZipkinConfigurations.java | 12 +++-- .../tracing/zipkin/ZipkinWebClientSender.java | 9 +++- .../WavefrontSenderConfiguration.java | 10 ++-- .../management/HeapDumpWebEndpoint.java | 6 +-- .../amqp/RabbitStreamConfiguration.java | 10 ++-- .../data/mongo/MongoDataConfiguration.java | 4 +- .../flyway/NativeImageResourceProvider.java | 40 +++++++++------ .../HazelcastSessionConfiguration.java | 2 +- .../session/JdbcSessionConfiguration.java | 2 +- .../MongoReactiveSessionConfiguration.java | 2 +- .../RedisReactiveSessionConfiguration.java | 2 +- .../session/RedisSessionConfiguration.java | 8 +-- .../docs/asciidoc/actuator/http-tracing.adoc | 6 +-- .../src/docs/asciidoc/actuator/tracing.adoc | 35 ++++++++----- .../MockServerRestTemplateCustomizer.java | 10 ++++ .../plugin/NativeImagePluginAction.java | 7 ++- .../boot/StartupInfoLogger.java | 1 + .../logback/SpringBootJoranConfigurator.java | 49 +++++++++---------- ...backConfigurationAotContributionTests.java | 2 - 31 files changed, 208 insertions(+), 153 deletions(-) diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.java index 0b0d583711..1628446456 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/health/AbstractCompositeHealthContributorConfiguration.java @@ -47,21 +47,8 @@ public abstract class AbstractCompositeHealthContributorConfiguration indicatorType = type.resolveGeneric(1); - Class beanType = type.resolveGeneric(2); - this.indicatorFactory = (bean) -> { - try { - @SuppressWarnings("unchecked") - Constructor constructor = (Constructor) indicatorType.getDeclaredConstructor(beanType); - return BeanUtils.instantiateClass(constructor, bean); - } - catch (Exception ex) { - throw new IllegalStateException( - "Unable to create health indicator " + indicatorType + " for bean type " + beanType, ex); - } - }; + this.indicatorFactory = new ReflectionIndicatorFactory( + ResolvableType.forClass(AbstractCompositeHealthContributorConfiguration.class, getClass())); } /** @@ -88,4 +75,34 @@ public abstract class AbstractCompositeHealthContributorConfiguration { + + private final Class indicatorType; + + private final Class beanType; + + ReflectionIndicatorFactory(ResolvableType type) { + this.indicatorType = type.resolveGeneric(1); + this.beanType = type.resolveGeneric(2); + } + + @Override + public I apply(B bean) { + try { + return BeanUtils.instantiateClass(getConstructor(), bean); + } + catch (Exception ex) { + throw new IllegalStateException("Unable to create health indicator %s for bean type %s" + .formatted(this.indicatorType, this.beanType), ex); + } + + } + + @SuppressWarnings("unchecked") + private Constructor getConstructor() throws NoSuchMethodException { + return (Constructor) this.indicatorType.getDeclaredConstructor(this.beanType); + } + + } + } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java index a00a6080c6..d7c531aa0e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationAutoConfiguration.java @@ -132,8 +132,8 @@ public class ObservationAutoConfiguration { @Bean TracingAwareMeterObservationHandler tracingAwareMeterObservationHandler( MeterRegistry meterRegistry, Tracer tracer) { - return new TracingAwareMeterObservationHandler<>(new DefaultMeterObservationHandler(meterRegistry), - tracer); + DefaultMeterObservationHandler delegate = new DefaultMeterObservationHandler(meterRegistry); + return new TracingAwareMeterObservationHandler<>(delegate, tracer); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java index fcdbd5fb2f..163186947e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationHandlerGrouping.java @@ -16,16 +16,15 @@ package org.springframework.boot.actuate.autoconfigure.observation; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import io.micrometer.observation.ObservationHandler; import io.micrometer.observation.ObservationHandler.FirstMatchingCompositeObservationHandler; import io.micrometer.observation.ObservationRegistry.ObservationConfig; import org.springframework.util.CollectionUtils; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; /** * Groups {@link ObservationHandler ObservationHandlers} by type. @@ -46,11 +45,11 @@ class ObservationHandlerGrouping { } void apply(List> handlers, ObservationConfig config) { - Map, List>> groupings = new HashMap<>(); + MultiValueMap, ObservationHandler> groupings = new LinkedMultiValueMap<>(); for (ObservationHandler handler : handlers) { Class category = findCategory(handler); if (category != null) { - groupings.computeIfAbsent(category, (c) -> new ArrayList<>()).add(handler); + groupings.add(category, handler); } else { config.observationHandler(handler); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationRegistryConfigurer.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationRegistryConfigurer.java index 6c5bbba97c..e99288ed95 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationRegistryConfigurer.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/ObservationRegistryConfigurer.java @@ -73,13 +73,11 @@ class ObservationRegistryConfigurer { } private void registerObservationPredicates(ObservationRegistry registry) { - this.observationPredicates.orderedStream().forEach( - (observationPredicate) -> registry.observationConfig().observationPredicate(observationPredicate)); + this.observationPredicates.orderedStream().forEach(registry.observationConfig()::observationPredicate); } private void registerGlobalObservationConventions(ObservationRegistry registry) { - this.observationConventions.orderedStream() - .forEach((convention) -> registry.observationConfig().observationConvention(convention)); + this.observationConventions.orderedStream().forEach(registry.observationConfig()::observationConvention); } @SuppressWarnings("unchecked") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientHttpObservationConventionAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientHttpObservationConventionAdapter.java index 9f9d5e7063..5eb0177267 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientHttpObservationConventionAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientHttpObservationConventionAdapter.java @@ -44,9 +44,9 @@ class ClientHttpObservationConventionAdapter implements ClientRequestObservation @Override @SuppressWarnings("deprecation") public KeyValues getLowCardinalityKeyValues(ClientRequestObservationContext context) { - KeyValues keyValues = KeyValues.empty(); Iterable tags = this.tagsProvider.getTags(context.getUriTemplate(), context.getCarrier(), context.getResponse()); + KeyValues keyValues = KeyValues.empty(); for (Tag tag : tags) { keyValues = keyValues.and(tag.getKey(), tag.getValue()); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientObservationConventionAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientObservationConventionAdapter.java index 09b26818a4..36b29a3426 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientObservationConventionAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/ClientObservationConventionAdapter.java @@ -21,6 +21,7 @@ import io.micrometer.core.instrument.Tag; import io.micrometer.observation.Observation; import org.springframework.boot.actuate.metrics.web.reactive.client.WebClientExchangeTagsProvider; +import org.springframework.core.Conventions; import org.springframework.web.reactive.function.client.ClientRequest; import org.springframework.web.reactive.function.client.ClientRequestObservationContext; import org.springframework.web.reactive.function.client.ClientRequestObservationConvention; @@ -32,10 +33,11 @@ import org.springframework.web.reactive.function.client.WebClient; * * @author Brian Clozel */ -@SuppressWarnings({ "deprecation", "removal" }) +@SuppressWarnings("removal") class ClientObservationConventionAdapter implements ClientRequestObservationConvention { - private static final String URI_TEMPLATE_ATTRIBUTE = WebClient.class.getName() + ".uriTemplate"; + private static final String URI_TEMPLATE_ATTRIBUTE = Conventions.getQualifiedAttributeName(WebClient.class, + "uriTemplate"); private final String metricName; @@ -53,20 +55,18 @@ class ClientObservationConventionAdapter implements ClientRequestObservationConv @Override public KeyValues getLowCardinalityKeyValues(ClientRequestObservationContext context) { - KeyValues keyValues = KeyValues.empty(); mutateClientRequest(context); Iterable tags = this.tagsProvider.tags(context.getCarrier(), context.getResponse(), context.getError()); + KeyValues keyValues = KeyValues.empty(); for (Tag tag : tags) { keyValues = keyValues.and(tag.getKey(), tag.getValue()); } return keyValues; } - /* - * {@link WebClientExchangeTagsProvider} relies on a request attribute to get the URI - * template, we need to adapt to that. - */ - private static void mutateClientRequest(ClientRequestObservationContext context) { + private void mutateClientRequest(ClientRequestObservationContext context) { + // WebClientExchangeTagsProvider relies on a request attribute to get the URI + // template, we need to adapt to that. ClientRequest clientRequest = ClientRequest.from(context.getCarrier()) .attribute(URI_TEMPLATE_ATTRIBUTE, context.getUriTemplate()).build(); context.setCarrier(clientRequest); diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/HttpClientObservationsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/HttpClientObservationsAutoConfiguration.java index 6d35ea6050..8886d48b45 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/HttpClientObservationsAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/client/HttpClientObservationsAutoConfiguration.java @@ -23,6 +23,7 @@ import io.micrometer.observation.ObservationRegistry; import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties.Web.Client; import org.springframework.boot.actuate.autoconfigure.metrics.OnlyOnceLoggingDenyMeterFilter; import org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties; @@ -67,13 +68,14 @@ public class HttpClientObservationsAutoConfiguration { @SuppressWarnings("removal") MeterFilter metricsHttpClientUriTagFilter(ObservationProperties observationProperties, MetricsProperties metricsProperties) { - String metricName = metricsProperties.getWeb().getClient().getRequest().getMetricName(); + Client clientProperties = metricsProperties.getWeb().getClient(); + String metricName = clientProperties.getRequest().getMetricName(); String observationName = observationProperties.getHttp().getClient().getRequests().getName(); String name = (observationName != null) ? observationName : metricName; - MeterFilter denyFilter = new OnlyOnceLoggingDenyMeterFilter(() -> String - .format("Reached the maximum number of URI tags for '%s'. Are you using 'uriVariables'?", name)); - return MeterFilter.maximumAllowableTags(name, "uri", metricsProperties.getWeb().getClient().getMaxUriTags(), - denyFilter); + MeterFilter denyFilter = new OnlyOnceLoggingDenyMeterFilter( + () -> "Reached the maximum number of URI tags for '%s'. Are you using 'uriVariables'?" + .formatted(name)); + return MeterFilter.maximumAllowableTags(name, "uri", clientProperties.getMaxUriTags(), denyFilter); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/ServerRequestObservationConventionAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/ServerRequestObservationConventionAdapter.java index 3b3890e910..8b2138617c 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/ServerRequestObservationConventionAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/ServerRequestObservationConventionAdapter.java @@ -58,8 +58,8 @@ class ServerRequestObservationConventionAdapter implements ServerRequestObservat @Override public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) { - KeyValues keyValues = KeyValues.empty(); Iterable tags = this.tagsProvider.httpRequestTags(context.getServerWebExchange(), context.getError()); + KeyValues keyValues = KeyValues.empty(); for (Tag tag : tags) { keyValues = keyValues.and(tag.getKey(), tag.getValue()); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/WebFluxObservationAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/WebFluxObservationAutoConfiguration.java index b5343633b0..5c15a3958a 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/WebFluxObservationAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/reactive/WebFluxObservationAutoConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.ObjectProvider; 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.MetricsProperties.Web.Server; 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; @@ -80,22 +81,26 @@ public class WebFluxObservationAutoConfiguration { public ServerHttpObservationFilter webfluxObservationFilter(ObservationRegistry registry, ObjectProvider tagConfigurer, ObjectProvider contributorsProvider) { - String observationName = this.observationProperties.getHttp().getServer().getRequests().getName(); String metricName = this.metricsProperties.getWeb().getServer().getRequest().getMetricName(); String name = (observationName != null) ? observationName : metricName; WebFluxTagsProvider tagsProvider = tagConfigurer.getIfAvailable(); List tagsContributors = contributorsProvider.orderedStream().toList(); - ServerRequestObservationConvention convention = new DefaultServerRequestObservationConvention(name); - if (tagsProvider != null) { - convention = new ServerRequestObservationConventionAdapter(name, tagsProvider); - } - else if (!tagsContributors.isEmpty()) { - convention = new ServerRequestObservationConventionAdapter(name, tagsContributors); - } + ServerRequestObservationConvention convention = extracted(name, tagsProvider, tagsContributors); return new ServerHttpObservationFilter(registry, convention); } + private ServerRequestObservationConvention extracted(String name, WebFluxTagsProvider tagsProvider, + List tagsContributors) { + if (tagsProvider != null) { + return new ServerRequestObservationConventionAdapter(name, tagsProvider); + } + if (!tagsContributors.isEmpty()) { + return new ServerRequestObservationConventionAdapter(name, tagsContributors); + } + return new DefaultServerRequestObservationConvention(name); + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass(MeterRegistry.class) @ConditionalOnBean(MeterRegistry.class) @@ -104,11 +109,11 @@ public class WebFluxObservationAutoConfiguration { @Bean @Order(0) MeterFilter metricsHttpServerUriTagFilter(MetricsProperties properties) { - String metricName = properties.getWeb().getServer().getRequest().getMetricName(); + Server serverProperties = properties.getWeb().getServer(); + String metricName = serverProperties.getRequest().getMetricName(); MeterFilter filter = new OnlyOnceLoggingDenyMeterFilter( - () -> String.format("Reached the maximum number of URI tags for '%s'.", metricName)); - return MeterFilter.maximumAllowableTags(metricName, "uri", properties.getWeb().getServer().getMaxUriTags(), - filter); + () -> "Reached the maximum number of URI tags for '%s'.".formatted(metricName)); + return MeterFilter.maximumAllowableTags(metricName, "uri", serverProperties.getMaxUriTags(), filter); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/servlet/ServerRequestObservationConventionAdapter.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/servlet/ServerRequestObservationConventionAdapter.java index dfc6427ae1..22f2cd819e 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/servlet/ServerRequestObservationConventionAdapter.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/observation/web/servlet/ServerRequestObservationConventionAdapter.java @@ -64,9 +64,9 @@ class ServerRequestObservationConventionAdapter implements ServerRequestObservat @Override public KeyValues getLowCardinalityKeyValues(ServerRequestObservationContext context) { - KeyValues keyValues = KeyValues.empty(); Iterable tags = this.tagsProvider.getTags(context.getCarrier(), context.getResponse(), getHandler(context), context.getError()); + KeyValues keyValues = KeyValues.empty(); for (Tag tag : tags) { keyValues = keyValues.and(tag.getKey(), tag.getValue()); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.java index 1d32b20d35..a0ad63ca9f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/BraveAutoConfiguration.java @@ -110,9 +110,7 @@ public class BraveAutoConfiguration { Builder builder = Tracing.newBuilder().currentTraceContext(currentTraceContext).traceId128Bit(true) .supportsJoin(false).propagationFactory(propagationFactory).sampler(sampler) .localServiceName(applicationName); - for (SpanHandler spanHandler : spanHandlers) { - builder.addSpanHandler(spanHandler); - } + spanHandlers.forEach(builder::addSpanHandler); for (TracingCustomizer tracingCustomizer : tracingCustomizers) { tracingCustomizer.customize(builder); } @@ -130,9 +128,7 @@ public class BraveAutoConfiguration { public CurrentTraceContext braveCurrentTraceContext(List scopeDecorators, List currentTraceContextCustomizers) { ThreadLocalCurrentTraceContext.Builder builder = ThreadLocalCurrentTraceContext.newBuilder(); - for (ScopeDecorator scopeDecorator : scopeDecorators) { - builder.addScopeDecorator(scopeDecorator); - } + scopeDecorators.forEach(builder::addScopeDecorator); for (CurrentTraceContextCustomizer currentTraceContextCustomizer : currentTraceContextCustomizers) { currentTraceContextCustomizer.customize(builder); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/MeterRegistrySpanMetrics.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/MeterRegistrySpanMetrics.java index 1f9d4e0325..4b39d822de 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/MeterRegistrySpanMetrics.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/wavefront/MeterRegistrySpanMetrics.java @@ -66,8 +66,11 @@ class MeterRegistrySpanMetrics implements SpanMetrics { @Override public void registerQueueRemainingCapacity(BlockingQueue queue) { - this.meterRegistry.gauge("wavefront.reporter.queue.remaining_capacity", queue, - (q) -> (double) q.remainingCapacity()); + this.meterRegistry.gauge("wavefront.reporter.queue.remaining_capacity", queue, this::remainingCapacity); + } + + private double remainingCapacity(BlockingQueue queue) { + return queue.remainingCapacity(); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java index 72c196ceb5..7bd8584a0d 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinConfigurations.java @@ -60,9 +60,11 @@ class ZipkinConfigurations { @Bean @ConditionalOnMissingBean(Sender.class) URLConnectionSender urlConnectionSender(ZipkinProperties properties) { - return URLConnectionSender.newBuilder().connectTimeout((int) properties.getConnectTimeout().toMillis()) - .readTimeout((int) properties.getReadTimeout().toMillis()).endpoint(properties.getEndpoint()) - .build(); + URLConnectionSender.Builder builder = URLConnectionSender.newBuilder(); + builder.connectTimeout((int) properties.getConnectTimeout().toMillis()); + builder.readTimeout((int) properties.getReadTimeout().toMillis()); + builder.endpoint(properties.getEndpoint()); + return builder.build(); } } @@ -78,7 +80,7 @@ class ZipkinConfigurations { ObjectProvider customizers) { RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder() .setConnectTimeout(properties.getConnectTimeout()).setReadTimeout(properties.getReadTimeout()); - customizers.orderedStream().forEach((c) -> c.customize(restTemplateBuilder)); + customizers.orderedStream().forEach((customizer) -> customizer.customize(restTemplateBuilder)); return new ZipkinRestTemplateSender(properties.getEndpoint(), restTemplateBuilder.build()); } @@ -94,7 +96,7 @@ class ZipkinConfigurations { ZipkinWebClientSender webClientSender(ZipkinProperties properties, ObjectProvider customizers) { WebClient.Builder builder = WebClient.builder(); - customizers.orderedStream().forEach((c) -> c.customize(builder)); + customizers.orderedStream().forEach((customizer) -> customizer.customize(builder)); return new ZipkinWebClientSender(properties.getEndpoint(), builder.build()); } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java index 0ea45e3052..2db94cbe59 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinWebClientSender.java @@ -20,6 +20,7 @@ import reactor.core.publisher.Mono; import zipkin2.Call; import zipkin2.Callback; +import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.web.reactive.function.client.WebClient; @@ -73,8 +74,12 @@ class ZipkinWebClientSender extends HttpSender { } private Mono> sendRequest() { - return this.webClient.post().uri(this.endpoint).headers((headers) -> headers.addAll(getDefaultHeaders())) - .bodyValue(getBody()).retrieve().toBodilessEntity(); + return this.webClient.post().uri(this.endpoint).headers(this::addDefaultHeaders).bodyValue(getBody()) + .retrieve().toBodilessEntity(); + } + + private void addDefaultHeaders(HttpHeaders headers) { + headers.addAll(getDefaultHeaders()); } } diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java index 565be4c913..eb14940697 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/wavefront/WavefrontSenderConfiguration.java @@ -48,12 +48,12 @@ public class WavefrontSenderConfiguration { @ConditionalOnMissingBean public WavefrontSender wavefrontSender(WavefrontProperties properties) { Builder builder = new Builder(properties.getEffectiveUri().toString(), properties.getApiTokenOrThrow()); - PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull(); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); WavefrontProperties.Sender sender = properties.getSender(); - mapper.from(sender.getMaxQueueSize()).to(builder::maxQueueSize); - mapper.from(sender.getFlushInterval()).asInt(Duration::getSeconds).to(builder::flushIntervalSeconds); - mapper.from(sender.getMessageSize()).asInt(DataSize::toBytes).to(builder::messageSizeBytes); - mapper.from(sender.getBatchSize()).to(builder::batchSize); + map.from(sender.getMaxQueueSize()).to(builder::maxQueueSize); + map.from(sender.getFlushInterval()).asInt(Duration::getSeconds).to(builder::flushIntervalSeconds); + map.from(sender.getMessageSize()).asInt(DataSize::toBytes).to(builder::messageSizeBytes); + map.from(sender.getBatchSize()).to(builder::batchSize); return builder.build(); } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java index ab608ee224..044b950f6d 100644 --- a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/management/HeapDumpWebEndpoint.java @@ -43,6 +43,7 @@ import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; @@ -208,10 +209,7 @@ public class HeapDumpWebEndpoint { @Override public File dumpHeap(Boolean live) throws IOException, InterruptedException { - if (live != null) { - throw new IllegalArgumentException( - "OpenJ9DiagnosticsMXBean does not support live parameter when dumping the heap"); - } + Assert.isNull(live, "OpenJ9DiagnosticsMXBean does not support live parameter when dumping the heap"); return new File( (String) ReflectionUtils.invokeMethod(this.dumpHeapMethod, this.diagnosticMXBean, "heap", null)); } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitStreamConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitStreamConfiguration.java index 49715a78c3..6547cfdc4e 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitStreamConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/amqp/RabbitStreamConfiguration.java @@ -99,11 +99,11 @@ class RabbitStreamConfiguration { static EnvironmentBuilder configure(EnvironmentBuilder builder, RabbitProperties properties) { builder.lazyInitialization(true); RabbitProperties.Stream stream = properties.getStream(); - PropertyMapper mapper = PropertyMapper.get(); - mapper.from(stream.getHost()).to(builder::host); - mapper.from(stream.getPort()).to(builder::port); - mapper.from(stream.getUsername()).as(withFallback(properties::getUsername)).whenNonNull().to(builder::username); - mapper.from(stream.getPassword()).as(withFallback(properties::getPassword)).whenNonNull().to(builder::password); + PropertyMapper map = PropertyMapper.get(); + map.from(stream.getHost()).to(builder::host); + map.from(stream.getPort()).to(builder::port); + map.from(stream.getUsername()).as(withFallback(properties::getUsername)).whenNonNull().to(builder::username); + map.from(stream.getPassword()).as(withFallback(properties::getPassword)).whenNonNull().to(builder::password); return builder; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.java index 7b5e56c116..898b4bc7e9 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataConfiguration.java @@ -52,9 +52,9 @@ class MongoDataConfiguration { @ConditionalOnMissingBean MongoMappingContext mongoMappingContext(MongoProperties properties, MongoCustomConversions conversions, MongoManagedTypes managedTypes) { - PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull(); + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); MongoMappingContext context = new MongoMappingContext(); - mapper.from(properties.isAutoIndexCreation()).to(context::setAutoIndexCreation); + map.from(properties.isAutoIndexCreation()).to(context::setAutoIndexCreation); context.setManagedTypes(managedTypes); Class strategyClass = properties.getFieldNamingStrategy(); if (strategyClass != null) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/NativeImageResourceProvider.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/NativeImageResourceProvider.java index 5c84a754c7..37baef8637 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/NativeImageResourceProvider.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/NativeImageResourceProvider.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Predicate; import org.flywaydb.core.api.FlywayException; import org.flywaydb.core.api.Location; @@ -57,7 +58,7 @@ class NativeImageResourceProvider implements ResourceProvider { private final boolean failOnMissingLocations; - private final List resources = new ArrayList<>(); + private final List locatedResources = new ArrayList<>(); private final Lock lock = new ReentrantLock(); @@ -93,14 +94,21 @@ class NativeImageResourceProvider implements ResourceProvider { return this.scanner.getResources(prefix, suffixes); } ensureInitialized(); - List result = new ArrayList<>(this.scanner.getResources(prefix, suffixes)); - this.resources.stream().filter((r) -> StringUtils.startsAndEndsWith(r.resource.getFilename(), prefix, suffixes)) - .map((r) -> (LoadableResource) new ClassPathResource(r.location(), - r.location().getPath() + "/" + r.resource().getFilename(), this.classLoader, this.encoding)) + Predicate matchesPrefixAndSuffixes = (locatedResource) -> StringUtils + .startsAndEndsWith(locatedResource.resource.getFilename(), prefix, suffixes); + List result = new ArrayList<>(); + result.addAll(this.scanner.getResources(prefix, suffixes)); + this.locatedResources.stream().filter(matchesPrefixAndSuffixes).map(this::asClassPathResource) .forEach(result::add); return result; } + private ClassPathResource asClassPathResource(LocatedResource locatedResource) { + Location location = locatedResource.location(); + String fileNameWithAbsolutePath = location.getPath() + "/" + locatedResource.resource().getFilename(); + return new ClassPathResource(location, fileNameWithAbsolutePath, this.classLoader, this.encoding); + } + private void ensureInitialized() { this.lock.lock(); try { @@ -127,20 +135,24 @@ class NativeImageResourceProvider implements ResourceProvider { } continue; } - Resource[] resources; - try { - resources = resolver.getResources(root.getURI() + "/*"); - } - catch (IOException ex) { - throw new UncheckedIOException("Failed to list resources for " + location.getDescriptor(), ex); - } + Resource[] resources = getResources(resolver, location, root); for (Resource resource : resources) { - this.resources.add(new ResourceWithLocation(resource, location)); + this.locatedResources.add(new LocatedResource(resource, location)); } } } - private record ResourceWithLocation(Resource resource, Location location) { + private Resource[] getResources(PathMatchingResourcePatternResolver resolver, Location location, Resource root) { + try { + return resolver.getResources(root.getURI() + "/*"); + } + catch (IOException ex) { + throw new UncheckedIOException("Failed to list resources for " + location.getDescriptor(), ex); + } + } + + private record LocatedResource(Resource resource, Location location) { + } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java index 113b290680..108da8ac47 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/HazelcastSessionConfiguration.java @@ -52,8 +52,8 @@ class HazelcastSessionConfiguration { SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, HazelcastSessionProperties hazelcastSessionProperties, ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); return (sessionRepository) -> { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(sessionProperties.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) .to(sessionRepository::setDefaultMaxInactiveInterval); map.from(hazelcastSessionProperties::getMapName).to(sessionRepository::setSessionMapName); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java index 07470b06ea..24bca4a40b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/JdbcSessionConfiguration.java @@ -67,8 +67,8 @@ class JdbcSessionConfiguration { SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, JdbcSessionProperties jdbcSessionProperties, ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); return (sessionRepository) -> { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(sessionProperties.determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) .to(sessionRepository::setDefaultMaxInactiveInterval); map.from(jdbcSessionProperties::getTableName).to(sessionRepository::setTableName); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java index 449530cbec..ade685ee33 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/MongoReactiveSessionConfiguration.java @@ -50,8 +50,8 @@ class MongoReactiveSessionConfiguration { ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, MongoSessionProperties mongoSessionProperties, ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); return (sessionRepository) -> { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(sessionProperties.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) .to(sessionRepository::setDefaultMaxInactiveInterval); map.from(mongoSessionProperties::getCollectionName).to(sessionRepository::setCollectionName); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java index 3415e8f64c..200d74817a 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisReactiveSessionConfiguration.java @@ -50,8 +50,8 @@ class RedisReactiveSessionConfiguration { ReactiveSessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); return (sessionRepository) -> { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(sessionProperties.determineTimeout(() -> serverProperties.getReactive().getSession().getTimeout())) .to(sessionRepository::setDefaultMaxInactiveInterval); map.from(redisSessionProperties::getNamespace).to(sessionRepository::setRedisKeyNamespace); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java index 96b1307408..5f51a81741 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/session/RedisSessionConfiguration.java @@ -67,11 +67,11 @@ class RedisSessionConfiguration { String cleanupCron = redisSessionProperties.getCleanupCron(); if (cleanupCron != null) { throw new InvalidConfigurationPropertyValueException("spring.session.redis.cleanup-cron", cleanupCron, - "Cron-based cleanup is only supported when spring.session.redis.repository-type is set to " - + "indexed."); + "Cron-based cleanup is only supported when " + + "spring.session.redis.repository-type is set to indexed."); } - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); return (sessionRepository) -> { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(sessionProperties .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) .to(sessionRepository::setDefaultMaxInactiveInterval); @@ -101,8 +101,8 @@ class RedisSessionConfiguration { SessionRepositoryCustomizer springBootSessionRepositoryCustomizer( SessionProperties sessionProperties, RedisSessionProperties redisSessionProperties, ServerProperties serverProperties) { - PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); return (sessionRepository) -> { + PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull(); map.from(sessionProperties .determineTimeout(() -> serverProperties.getServlet().getSession().getTimeout())) .to(sessionRepository::setDefaultMaxInactiveInterval); diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/http-tracing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/http-tracing.adoc index 30709752db..8282dd2e49 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/http-tracing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/http-tracing.adoc @@ -1,6 +1,5 @@ [[actuator.tracing]] == HTTP Tracing - You can enable HTTP Tracing by providing a bean of type `HttpTraceRepository` in your application's configuration. For convenience, Spring Boot offers `InMemoryHttpTraceRepository`, which stores traces for the last 100 (the default) request-response exchanges. `InMemoryHttpTraceRepository` is limited compared to other tracing solutions, and we recommend using it only for development environments. @@ -9,8 +8,9 @@ Alternatively, you can create your own `HttpTraceRepository`. You can use the `httptrace` endpoint to obtain information about the request-response exchanges that are stored in the `HttpTraceRepository`. -[[actuator.tracing.custom]] -=== Custom HTTP tracing + +[[actuator.tracing.custom]] +=== Custom HTTP Tracing To customize the items that are included in each trace, use the configprop:management.trace.http.include[] configuration property. For advanced customization, consider registering your own `HttpExchangeTracer` implementation. diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/tracing.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/tracing.adoc index a5ca682248..7f4509da1f 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/tracing.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/tracing.adoc @@ -1,22 +1,23 @@ [[actuator.micrometer-tracing]] == Tracing - Spring Boot Actuator provides dependency management and auto-configuration for https://micrometer.io/docs/tracing[Micrometer Tracing], a facade for popular tracer libraries. Micrometer Tracing hooks into Micrometer's `ObservationHandler`, which means a https://micrometer.io/docs/tracing#_glossary[span] is reported for every completed observation. TIP: To learn more about Micrometer Tracing capabilities, see its https://micrometer.io/docs/tracing[reference documentation]. -[[actuator.micrometer-tracing.tracers]] -=== Supported tracers + +[[actuator.micrometer-tracing.tracers]] +=== Supported Tracers Spring Boot ships auto-configuration for the following tracers: * https://opentelemetry.io/[OpenTelemetry] with https://zipkin.io/[Zipkin] or https://docs.wavefront.com/[Wavefront] * https://github.com/openzipkin/brave[OpenZipkin Brave] with https://zipkin.io/[Zipkin] or https://docs.wavefront.com/[Wavefront] + + [[actuator.micrometer-tracing.getting-started]] === Getting Started - We need an example application that we can use to getting started with tracing. For our purposes, the simple "`Hello World!`" web application that's covered in the "`<>`" section will suffice. We're going to use the OpenTelemetry tracer with Zipkin as trace backend. @@ -64,42 +65,52 @@ Press the "Show" button to see the details of that trace. TIP: You can include the current trace and span id in the logs by setting the `logging.pattern.level` property to `%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]` -[[actuator.micrometer-tracing.tracer-implementations]] -=== Tracer implementations + +[[actuator.micrometer-tracing.tracer-implementations]] +=== Tracer Implementations As Micrometer Tracer supports multiple tracer implementations, there are multiple dependency combinations possible with Spring Boot. All tracer implementations need the `org.springframework.boot:spring-boot-starter-actuator` dependency. + + [[actuator.micrometer-tracing.tracer-implementations.otel-zipkin]] -==== OpenTelemetry with Zipkin +==== OpenTelemetry With Zipkin * `io.micrometer:micrometer-tracing-bridge-otel` - which is needed to bride the Micrometer Observation API to OpenTelemetry. * `io.opentelemetry:opentelemetry-exporter-zipkin` - which is needed to report traces to Zipkin. + + [[actuator.micrometer-tracing.tracer-implementations.otel-wavefront]] -==== OpenTelemetry with Wavefront +==== OpenTelemetry With Wavefront * `io.micrometer:micrometer-tracing-bridge-otel` - which is needed to bride the Micrometer Observation API to OpenTelemetry. * `io.micrometer:micrometer-tracing-reporter-wavefront` - which is needed to report traces to Wavefront. + + [[actuator.micrometer-tracing.tracer-implementations.brave-zipkin]] -==== OpenZipkin Brave with Zipkin +==== OpenZipkin Brave With Zipkin * `io.micrometer:micrometer-tracing-bridge-brave` - which is needed to bridge the Micrometer Observation API to Brave. * `io.zipkin.reporter2:zipkin-reporter-brave` - which is needed to report traces to Zipkin. NOTE: If your project doesn't use Spring MVC or Spring WebFlux, the `io.zipkin.reporter2:zipkin-sender-urlconnection` dependency is needed, too. + + [[actuator.micrometer-tracing.tracer-implementations.brave-wavefront]] -==== OpenZipkin Brave with Wavefront +==== OpenZipkin Brave With Wavefront * `io.micrometer:micrometer-tracing-bridge-brave` - which is needed to bridge the Micrometer Observation API to Brave. * `io.micrometer:micrometer-tracing-reporter-wavefront` - which is needed to report traces to Wavefront. -[[actuator.micrometer-tracing.creating-spans]] -=== Creating custom spans + +[[actuator.micrometer-tracing.creating-spans]] +=== Creating Custom Spans You can create your own spans by starting an observation. For this, inject `ObservationRegistry` into your component: diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/MockServerRestTemplateCustomizer.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/MockServerRestTemplateCustomizer.java index 3e3f53c3e1..45f95ee538 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/MockServerRestTemplateCustomizer.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/client/MockServerRestTemplateCustomizer.java @@ -67,11 +67,21 @@ public class MockServerRestTemplateCustomizer implements RestTemplateCustomizer this(SimpleRequestExpectationManager::new); } + /** + * Crate a new {@link MockServerRestTemplateCustomizer} instance. + * @param expectationManager the expectation manager class to use + */ public MockServerRestTemplateCustomizer(Class expectationManager) { this(() -> BeanUtils.instantiateClass(expectationManager)); Assert.notNull(expectationManager, "ExpectationManager must not be null"); } + /** + * Crate a new {@link MockServerRestTemplateCustomizer} instance. + * @param expectationManagerSupplier a supplier that provides the + * {@link RequestExpectationManager} to use + * @since 3.0.0 + */ public MockServerRestTemplateCustomizer(Supplier expectationManagerSupplier) { Assert.notNull(expectationManagerSupplier, "ExpectationManagerSupplier must not be null"); this.expectationManagerSupplier = expectationManagerSupplier; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java index 100c601836..3e2eabc889 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/NativeImagePluginAction.java @@ -76,11 +76,14 @@ class NativeImagePluginAction implements PluginApplicationAction { } private Iterable removeDevelopmentOnly(Set configurations) { - return configurations.stream().filter(( - configuration) -> !SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME.equals(configuration.getName())) + return configurations.stream().filter(this::isNotDevelopmentOnly) .collect(Collectors.toCollection(LinkedHashSet::new)); } + private boolean isNotDevelopmentOnly(Configuration configuration) { + return !SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME.equals(configuration.getName()); + } + private void configureTestNativeBinaryClasspath(SourceSetContainer sourceSets, GraalVMExtension graalVmExtension, String sourceSetName) { SourceSetOutput output = sourceSets.getByName(SpringBootAotPlugin.AOT_TEST_SOURCE_SET_NAME).getOutput(); diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/StartupInfoLogger.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/StartupInfoLogger.java index 0bb3b69ab3..06ffc52a0f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/StartupInfoLogger.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/StartupInfoLogger.java @@ -38,6 +38,7 @@ import org.springframework.util.StringUtils; * * @author Phillip Webb * @author Dave Syer + * @author Moritz Halbritter */ class StartupInfoLogger { diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootJoranConfigurator.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootJoranConfigurator.java index eca2312f0e..be1a949921 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootJoranConfigurator.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootJoranConfigurator.java @@ -222,44 +222,39 @@ class SpringBootJoranConfigurator extends JoranConfigurator { } private Class determineType(Model model, Supplier parentSupplier) { - String className = null; - if (model instanceof ComponentModel) { - className = ((ComponentModel) model).getClassName(); - } - if (className == null) { - String tag = model.getTag(); - if (tag != null) { - className = this.modelInterpretationContext.getDefaultNestedComponentRegistry() - .findDefaultComponentTypeByTag(tag); - if (className == null) { - Class type = inferTypeFromParent(parentSupplier, tag); - if (type != null) { - return type; - } - } - } - } + String className = (model instanceof ComponentModel componentModel) ? componentModel.getClassName() : null; if (className != null) { - className = this.modelInterpretationContext.getImport(className); - return loadComponentType(className); + return loadImportType(className); + } + String tag = model.getTag(); + if (tag != null) { + className = this.modelInterpretationContext.getDefaultNestedComponentRegistry() + .findDefaultComponentTypeByTag(tag); + if (className != null) { + return loadImportType(className); + } + return inferTypeFromParent(parentSupplier, tag); } return null; } + private Class loadImportType(String className) { + return loadComponentType(this.modelInterpretationContext.getImport(className)); + } + private Class inferTypeFromParent(Supplier parentSupplier, String tag) { Object parent = parentSupplier.get(); if (parent != null) { try { - Class typeFromSetter = new PropertySetter( - this.modelInterpretationContext.getBeanDescriptionCache(), parent) - .getClassNameViaImplicitRules(tag, AggregationType.AS_COMPLEX_PROPERTY, - this.modelInterpretationContext.getDefaultNestedComponentRegistry()); - if (typeFromSetter != null) { - return typeFromSetter; - } + PropertySetter propertySetter = new PropertySetter( + this.modelInterpretationContext.getBeanDescriptionCache(), parent); + Class typeFromPropertySetter = propertySetter.getClassNameViaImplicitRules(tag, + AggregationType.AS_COMPLEX_PROPERTY, + this.modelInterpretationContext.getDefaultNestedComponentRegistry()); + return typeFromPropertySetter; } catch (Exception ex) { - // Continue + return null; } } return null; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackConfigurationAotContributionTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackConfigurationAotContributionTests.java index 976aa1e833..0eca197fda 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackConfigurationAotContributionTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackConfigurationAotContributionTests.java @@ -234,7 +234,6 @@ class LogbackConfigurationAotContributionTests { public static class Outer { public void setImplementation(Implementation implementation) { - } } @@ -243,7 +242,6 @@ class LogbackConfigurationAotContributionTests { @DefaultClass(Implementation.class) public void setContract(Contract contract) { - } }