mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Add support for SslBundles to OTLP traces export
Closes gh-49584
This commit is contained in:
+11
@@ -19,6 +19,7 @@ package org.springframework.boot.micrometer.tracing.opentelemetry.docker.compose
|
||||
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.OtlpTracingConnectionDetails;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.Transport;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -35,6 +36,16 @@ class GrafanaOpenTelemetryTracingDockerComposeConnectionDetailsFactoryIntegratio
|
||||
void runCreatesConnectionDetails(OtlpTracingConnectionDetails connectionDetails) {
|
||||
assertThat(connectionDetails.getUrl(Transport.HTTP)).startsWith("http://").endsWith("/v1/traces");
|
||||
assertThat(connectionDetails.getUrl(Transport.GRPC)).startsWith("http://").endsWith("/v1/traces");
|
||||
assertThat(connectionDetails.getSslBundle()).isNull();
|
||||
}
|
||||
|
||||
@DockerComposeTest(composeFile = "otlp-ssl-compose.yaml", image = TestImage.GRAFANA_OTEL_LGTM,
|
||||
additionalResources = "ca.crt")
|
||||
void runWithSslCreatesConnectionDetails(OtlpTracingConnectionDetails connectionDetails) {
|
||||
assertThat(connectionDetails.getUrl(Transport.HTTP)).startsWith("https://").endsWith("/v1/traces");
|
||||
assertThat(connectionDetails.getUrl(Transport.GRPC)).startsWith("https://").endsWith("/v1/traces");
|
||||
SslBundle sslBundle = connectionDetails.getSslBundle();
|
||||
assertThat(sslBundle).isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
@@ -19,6 +19,7 @@ package org.springframework.boot.micrometer.tracing.opentelemetry.docker.compose
|
||||
import org.springframework.boot.docker.compose.service.connection.test.DockerComposeTest;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.OtlpTracingConnectionDetails;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.Transport;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -35,6 +36,16 @@ class OpenTelemetryTracingDockerComposeConnectionDetailsFactoryIntegrationTests
|
||||
void runCreatesConnectionDetails(OtlpTracingConnectionDetails connectionDetails) {
|
||||
assertThat(connectionDetails.getUrl(Transport.HTTP)).startsWith("http://").endsWith("/v1/traces");
|
||||
assertThat(connectionDetails.getUrl(Transport.GRPC)).startsWith("http://").endsWith("/v1/traces");
|
||||
assertThat(connectionDetails.getSslBundle()).isNull();
|
||||
}
|
||||
|
||||
@DockerComposeTest(composeFile = "otlp-ssl-compose.yaml", image = TestImage.OTEL_COLLECTOR,
|
||||
additionalResources = "ca.crt")
|
||||
void runWithSslCreatesConnectionDetails(OtlpTracingConnectionDetails connectionDetails) {
|
||||
assertThat(connectionDetails.getUrl(Transport.HTTP)).startsWith("https://").endsWith("/v1/traces");
|
||||
assertThat(connectionDetails.getUrl(Transport.GRPC)).startsWith("https://").endsWith("/v1/traces");
|
||||
SslBundle sslBundle = connectionDetails.getSslBundle();
|
||||
assertThat(sslBundle).isNotNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -55,6 +55,7 @@ class GrafanaOpenTelemetryTracingContainerConnectionDetailsFactoryIntegrationTes
|
||||
.isEqualTo("%s/v1/traces".formatted(container.getOtlpHttpUrl()));
|
||||
assertThat(this.connectionDetails.getUrl(Transport.GRPC))
|
||||
.isEqualTo("%s/v1/traces".formatted(container.getOtlpGrpcUrl()));
|
||||
assertThat(this.connectionDetails.getSslBundle()).isNull();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
+1
@@ -56,6 +56,7 @@ class OpenTelemetryTracingContainerConnectionDetailsFactoryIntegrationTests {
|
||||
.isEqualTo("http://" + container.getHost() + ":" + container.getMappedPort(4318) + "/v1/traces");
|
||||
assertThat(this.connectionDetails.getUrl(Transport.GRPC))
|
||||
.isEqualTo("http://" + container.getHost() + ":" + container.getMappedPort(4317) + "/v1/traces");
|
||||
assertThat(this.connectionDetails.getSslBundle()).isNull();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
Dyno/RVFR/rUL5091gjGRXhLsi1oUHKdEzU=
|
||||
-----END CERTIFICATE-----
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
services:
|
||||
otlp:
|
||||
image: '{imageName}'
|
||||
ports:
|
||||
- '4317'
|
||||
- '4318'
|
||||
labels:
|
||||
- 'org.springframework.boot.sslbundle.pem.truststore.certificate=ca.crt'
|
||||
+52
-3
@@ -18,20 +18,28 @@ package org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
|
||||
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder;
|
||||
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
|
||||
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.micrometer.tracing.autoconfigure.ConditionalOnEnabledTracingExport;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.ssl.SslBundles;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Configurations imported by {@link OtlpTracingAutoConfiguration}.
|
||||
@@ -47,8 +55,9 @@ final class OtlpTracingConfigurations {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty("management.opentelemetry.tracing.export.otlp.endpoint")
|
||||
OtlpTracingConnectionDetails otlpTracingConnectionDetails(OtlpTracingProperties properties) {
|
||||
return new PropertiesOtlpTracingConnectionDetails(properties);
|
||||
OtlpTracingConnectionDetails otlpTracingConnectionDetails(OtlpTracingProperties properties,
|
||||
ObjectProvider<SslBundles> sslBundles) {
|
||||
return new PropertiesOtlpTracingConnectionDetails(properties, sslBundles.getIfAvailable());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,8 +67,11 @@ final class OtlpTracingConfigurations {
|
||||
|
||||
private final OtlpTracingProperties properties;
|
||||
|
||||
PropertiesOtlpTracingConnectionDetails(OtlpTracingProperties properties) {
|
||||
private final @Nullable SslBundles sslBundles;
|
||||
|
||||
PropertiesOtlpTracingConnectionDetails(OtlpTracingProperties properties, @Nullable SslBundles sslBundles) {
|
||||
this.properties = properties;
|
||||
this.sslBundles = sslBundles;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,6 +84,16 @@ final class OtlpTracingConfigurations {
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SslBundle getSslBundle() {
|
||||
String bundleName = this.properties.getSsl().getBundle();
|
||||
if (StringUtils.hasLength(bundleName)) {
|
||||
Assert.notNull(this.sslBundles, "SSL bundle name has been set but no SSL bundles found in context");
|
||||
return this.sslBundles.getBundle(bundleName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -95,6 +117,7 @@ final class OtlpTracingConfigurations {
|
||||
.setCompression(properties.getCompression().name().toLowerCase(Locale.ROOT));
|
||||
properties.getHeaders().forEach(builder::addHeader);
|
||||
meterProvider.ifAvailable(builder::setMeterProvider);
|
||||
configureSsl(connectionDetails, builder::setSslContext);
|
||||
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||
return builder.build();
|
||||
}
|
||||
@@ -111,10 +134,36 @@ final class OtlpTracingConfigurations {
|
||||
.setCompression(properties.getCompression().name().toLowerCase(Locale.ROOT));
|
||||
properties.getHeaders().forEach(builder::addHeader);
|
||||
meterProvider.ifAvailable(builder::setMeterProvider);
|
||||
configureSsl(connectionDetails, builder::setSslContext);
|
||||
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private void configureSsl(OtlpTracingConnectionDetails connectionDetails,
|
||||
SslContextConfigurer sslContextConfigurer) {
|
||||
SslBundle sslBundle = connectionDetails.getSslBundle();
|
||||
if (sslBundle != null) {
|
||||
SSLContext sslContext = sslBundle.createSslContext();
|
||||
X509TrustManager trustManager = extractTrustManager(sslBundle);
|
||||
sslContextConfigurer.configure(sslContext, trustManager);
|
||||
}
|
||||
}
|
||||
|
||||
private X509TrustManager extractTrustManager(SslBundle sslBundle) {
|
||||
for (TrustManager trustManager : sslBundle.getManagers().getTrustManagers()) {
|
||||
if (trustManager instanceof X509TrustManager x509TrustManager) {
|
||||
return x509TrustManager;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No X509TrustManager found in the SSL bundle trust managers");
|
||||
}
|
||||
|
||||
private interface SslContextConfigurer {
|
||||
|
||||
void configure(SSLContext sslContext, X509TrustManager trustManager);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
|
||||
/**
|
||||
* Details required to establish a connection to an OpenTelemetry service.
|
||||
@@ -34,4 +37,13 @@ public interface OtlpTracingConnectionDetails extends ConnectionDetails {
|
||||
*/
|
||||
String getUrl(Transport transport);
|
||||
|
||||
/**
|
||||
* SSL bundle to use.
|
||||
* @return the SSL bundle to use or {@code null}
|
||||
* @since 4.1.0
|
||||
*/
|
||||
default @Nullable SslBundle getSslBundle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+23
@@ -66,6 +66,8 @@ public class OtlpTracingProperties {
|
||||
*/
|
||||
private Map<String, String> headers = new HashMap<>();
|
||||
|
||||
private final Ssl ssl = new Ssl();
|
||||
|
||||
public @Nullable String getEndpoint() {
|
||||
return this.endpoint;
|
||||
}
|
||||
@@ -114,6 +116,27 @@ public class OtlpTracingProperties {
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
|
||||
public static class Ssl {
|
||||
|
||||
/**
|
||||
* SSL bundle name.
|
||||
*/
|
||||
private @Nullable String bundle;
|
||||
|
||||
public @Nullable String getBundle() {
|
||||
return this.bundle;
|
||||
}
|
||||
|
||||
public void setBundle(@Nullable String bundle) {
|
||||
this.bundle = bundle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum Compression {
|
||||
|
||||
/**
|
||||
|
||||
+13
-1
@@ -16,11 +16,14 @@
|
||||
|
||||
package org.springframework.boot.micrometer.tracing.opentelemetry.docker.compose.otlp;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.docker.compose.core.RunningService;
|
||||
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionDetailsFactory;
|
||||
import org.springframework.boot.docker.compose.service.connection.DockerComposeConnectionSource;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.OtlpTracingConnectionDetails;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.Transport;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
|
||||
/**
|
||||
* {@link DockerComposeConnectionDetailsFactory} to create
|
||||
@@ -58,11 +61,14 @@ class OpenTelemetryTracingDockerComposeConnectionDetailsFactory
|
||||
|
||||
private final int httpPort;
|
||||
|
||||
private final @Nullable SslBundle sslBundle;
|
||||
|
||||
private OpenTelemetryTracingDockerComposeConnectionDetails(RunningService source) {
|
||||
super(source);
|
||||
this.host = source.host();
|
||||
this.grpcPort = source.ports().get(OTLP_GRPC_PORT);
|
||||
this.httpPort = source.ports().get(OTLP_HTTP_PORT);
|
||||
this.sslBundle = getSslBundle(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,7 +77,13 @@ class OpenTelemetryTracingDockerComposeConnectionDetailsFactory
|
||||
case HTTP -> this.httpPort;
|
||||
case GRPC -> this.grpcPort;
|
||||
};
|
||||
return "http://%s:%d/v1/traces".formatted(this.host, port);
|
||||
String scheme = (this.sslBundle != null) ? "https" : "http";
|
||||
return "%s://%s:%d/v1/traces".formatted(scheme, this.host, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SslBundle getSslBundle() {
|
||||
return this.sslBundle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -16,10 +16,12 @@
|
||||
|
||||
package org.springframework.boot.micrometer.tracing.opentelemetry.testcontainers.otlp;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.testcontainers.grafana.LgtmStackContainer;
|
||||
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.OtlpTracingConnectionDetails;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.Transport;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
|
||||
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
@@ -59,9 +61,17 @@ class GrafanaOpenTelemetryTracingContainerConnectionDetailsFactory
|
||||
case HTTP -> getContainer().getOtlpHttpUrl();
|
||||
case GRPC -> getContainer().getOtlpGrpcUrl();
|
||||
};
|
||||
if (getSslBundle() != null) {
|
||||
url = url.replaceFirst("^http://", "https://");
|
||||
}
|
||||
return "%s/v1/traces".formatted(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SslBundle getSslBundle() {
|
||||
return super.getSslBundle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-1
@@ -16,11 +16,13 @@
|
||||
|
||||
package org.springframework.boot.micrometer.tracing.opentelemetry.testcontainers.otlp;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.testcontainers.containers.Container;
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.OtlpTracingConnectionDetails;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.Transport;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
|
||||
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
@@ -64,7 +66,14 @@ class OpenTelemetryTracingContainerConnectionDetailsFactory
|
||||
case HTTP -> OTLP_HTTP_PORT;
|
||||
case GRPC -> OTLP_GRPC_PORT;
|
||||
};
|
||||
return "http://%s:%d/v1/traces".formatted(getContainer().getHost(), getContainer().getMappedPort(port));
|
||||
String scheme = (getSslBundle() != null) ? "https" : "http";
|
||||
return "%s://%s:%d/v1/traces".formatted(scheme, getContainer().getHost(),
|
||||
getContainer().getMappedPort(port));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable SslBundle getSslBundle() {
|
||||
return super.getSslBundle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+59
@@ -20,6 +20,8 @@ import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import io.opentelemetry.api.metrics.MeterProvider;
|
||||
import io.opentelemetry.exporter.internal.compression.GzipCompressor;
|
||||
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
|
||||
@@ -30,13 +32,18 @@ import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration;
|
||||
import org.springframework.boot.micrometer.tracing.opentelemetry.autoconfigure.otlp.OtlpTracingConfigurations.ConnectionDetails.PropertiesOtlpTracingConnectionDetails;
|
||||
import org.springframework.boot.ssl.SslBundle;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link OtlpTracingAutoConfiguration}.
|
||||
@@ -269,6 +276,58 @@ class OtlpTracingAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHasSslBundleConfiguresHttpExporter() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(SslAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"management.opentelemetry.tracing.export.otlp.endpoint=https://localhost:4318/v1/traces",
|
||||
"management.opentelemetry.tracing.export.otlp.ssl.bundle=mybundle",
|
||||
"spring.ssl.bundle.jks.mybundle.truststore.location=classpath:test.jks")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(OtlpHttpSpanExporter.class);
|
||||
OtlpHttpSpanExporter exporter = context.getBean(OtlpHttpSpanExporter.class);
|
||||
assertThat(exporter).extracting("delegate.httpSender.client.sslSocketFactoryOrNull").isNotNull();
|
||||
assertThat(exporter).extracting("delegate.httpSender.client.x509TrustManager")
|
||||
.isInstanceOf(X509TrustManager.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHasSslBundleConfiguresGrpcExporter() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(SslAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"management.opentelemetry.tracing.export.otlp.endpoint=https://localhost:4318/v1/traces",
|
||||
"management.opentelemetry.tracing.export.otlp.transport=grpc",
|
||||
"management.opentelemetry.tracing.export.otlp.ssl.bundle=mybundle",
|
||||
"spring.ssl.bundle.jks.mybundle.truststore.location=classpath:test.jks")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(OtlpGrpcSpanExporter.class);
|
||||
OtlpGrpcSpanExporter exporter = context.getBean(OtlpGrpcSpanExporter.class);
|
||||
assertThat(exporter).extracting("delegate.grpcSender.client.sslSocketFactoryOrNull").isNotNull();
|
||||
assertThat(exporter).extracting("delegate.grpcSender.client.x509TrustManager")
|
||||
.isInstanceOf(X509TrustManager.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenCustomConnectionDetailsProvidesSslBundleConfiguresHttpExporter() {
|
||||
SslBundle sslBundle = SslBundle.systemDefault();
|
||||
OtlpTracingConnectionDetails connectionDetails = mock(OtlpTracingConnectionDetails.class);
|
||||
given(connectionDetails.getUrl(Transport.HTTP)).willReturn("https://localhost:4318/v1/traces");
|
||||
given(connectionDetails.getSslBundle()).willReturn(sslBundle);
|
||||
this.contextRunner
|
||||
.withBean("customOtlpTracingConnectionDetails", OtlpTracingConnectionDetails.class, () -> connectionDetails)
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(OtlpHttpSpanExporter.class);
|
||||
OtlpHttpSpanExporter exporter = context.getBean(OtlpHttpSpanExporter.class);
|
||||
assertThat(exporter).extracting("delegate.httpSender.client.sslSocketFactoryOrNull").isNotNull();
|
||||
assertThat(exporter).extracting("delegate.httpSender.client.x509TrustManager")
|
||||
.isInstanceOf(X509TrustManager.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
private static final class MeterProviderConfiguration {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user