Support Otlp Tracing's GRPC port from service connections

Otlp Tracing's exporter is configured using Transport. Current support
for service connections read the mapped port for HTTP transport 4318.
This commits adds support to read port for GRPC transport 4317.

See gh-41333
This commit is contained in:
Eddú Meléndez 2024-07-05 09:43:41 -06:00 committed by Moritz Halbritter
parent f6505f7a18
commit 7baa553760
7 changed files with 51 additions and 10 deletions

View File

@ -23,6 +23,7 @@ import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporterBuilder;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
import org.springframework.boot.actuate.autoconfigure.opentelemetry.otlp.Transport;
import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing; import org.springframework.boot.actuate.autoconfigure.tracing.ConditionalOnEnabledTracing;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -34,6 +35,7 @@ import org.springframework.context.annotation.Configuration;
* Configurations imported by {@link OtlpAutoConfiguration}. * Configurations imported by {@link OtlpAutoConfiguration}.
* *
* @author Moritz Halbritter * @author Moritz Halbritter
* @author Eddú Meléndez
*/ */
class OtlpTracingConfigurations { class OtlpTracingConfigurations {
@ -63,6 +65,11 @@ class OtlpTracingConfigurations {
return this.properties.getEndpoint(); return this.properties.getEndpoint();
} }
@Override
public String getGrpcEndpoint() {
return this.properties.getEndpoint();
}
} }
} }
@ -79,7 +86,7 @@ class OtlpTracingConfigurations {
OtlpHttpSpanExporter otlpHttpSpanExporter(OtlpProperties properties, OtlpHttpSpanExporter otlpHttpSpanExporter(OtlpProperties properties,
OtlpTracingConnectionDetails connectionDetails) { OtlpTracingConnectionDetails connectionDetails) {
OtlpHttpSpanExporterBuilder builder = OtlpHttpSpanExporter.builder() OtlpHttpSpanExporterBuilder builder = OtlpHttpSpanExporter.builder()
.setEndpoint(connectionDetails.getUrl()) .setEndpoint(resolveEndpoint(properties.getTransport(), connectionDetails))
.setTimeout(properties.getTimeout()) .setTimeout(properties.getTimeout())
.setCompression(properties.getCompression().name().toLowerCase()); .setCompression(properties.getCompression().name().toLowerCase());
for (Entry<String, String> header : properties.getHeaders().entrySet()) { for (Entry<String, String> header : properties.getHeaders().entrySet()) {
@ -93,7 +100,7 @@ class OtlpTracingConfigurations {
OtlpGrpcSpanExporter otlpGrpcSpanExporter(OtlpProperties properties, OtlpGrpcSpanExporter otlpGrpcSpanExporter(OtlpProperties properties,
OtlpTracingConnectionDetails connectionDetails) { OtlpTracingConnectionDetails connectionDetails) {
OtlpGrpcSpanExporterBuilder builder = OtlpGrpcSpanExporter.builder() OtlpGrpcSpanExporterBuilder builder = OtlpGrpcSpanExporter.builder()
.setEndpoint(connectionDetails.getUrl()) .setEndpoint(resolveEndpoint(properties.getTransport(), connectionDetails))
.setTimeout(properties.getTimeout()) .setTimeout(properties.getTimeout())
.setCompression(properties.getCompression().name().toLowerCase()); .setCompression(properties.getCompression().name().toLowerCase());
for (Entry<String, String> header : properties.getHeaders().entrySet()) { for (Entry<String, String> header : properties.getHeaders().entrySet()) {
@ -102,6 +109,10 @@ class OtlpTracingConfigurations {
return builder.build(); return builder.build();
} }
private static String resolveEndpoint(Transport transport, OtlpTracingConnectionDetails connectionDetails) {
return (transport == Transport.HTTP) ? connectionDetails.getUrl() : connectionDetails.getGrpcEndpoint();
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -32,4 +32,8 @@ public interface OtlpTracingConnectionDetails extends ConnectionDetails {
*/ */
String getUrl(); String getUrl();
default String getGrpcEndpoint() {
return "http://localhost:4317/v1/traces";
}
} }

View File

@ -32,6 +32,7 @@ class OpenTelemetryTracingDockerComposeConnectionDetailsFactoryIntegrationTests
@DockerComposeTest(composeFile = "otlp-compose.yaml", image = TestImage.OPENTELEMETRY) @DockerComposeTest(composeFile = "otlp-compose.yaml", image = TestImage.OPENTELEMETRY)
void runCreatesConnectionDetails(OtlpTracingConnectionDetails connectionDetails) { void runCreatesConnectionDetails(OtlpTracingConnectionDetails connectionDetails) {
assertThat(connectionDetails.getGrpcEndpoint()).startsWith("http://").endsWith("/v1/traces");
assertThat(connectionDetails.getUrl()).startsWith("http://").endsWith("/v1/traces"); assertThat(connectionDetails.getUrl()).startsWith("http://").endsWith("/v1/traces");
} }

View File

@ -2,4 +2,5 @@ services:
otlp: otlp:
image: '{imageName}' image: '{imageName}'
ports: ports:
- '4317'
- '4318' - '4318'

View File

@ -33,7 +33,9 @@ class OpenTelemetryTracingDockerComposeConnectionDetailsFactory
private static final String[] OPENTELEMETRY_IMAGE_NAMES = { "otel/opentelemetry-collector-contrib", private static final String[] OPENTELEMETRY_IMAGE_NAMES = { "otel/opentelemetry-collector-contrib",
"grafana/otel-lgtm" }; "grafana/otel-lgtm" };
private static final int OTLP_PORT = 4318; private static final int OTLP_GRPC_PORT = 4317;
private static final int OTLP_HTTP_PORT = 4318;
OpenTelemetryTracingDockerComposeConnectionDetailsFactory() { OpenTelemetryTracingDockerComposeConnectionDetailsFactory() {
super(OPENTELEMETRY_IMAGE_NAMES, super(OPENTELEMETRY_IMAGE_NAMES,
@ -50,17 +52,25 @@ class OpenTelemetryTracingDockerComposeConnectionDetailsFactory
private final String host; private final String host;
private final int port; private final int grpcPort;
private final int httPort;
private OpenTelemetryTracingDockerComposeConnectionDetails(RunningService source) { private OpenTelemetryTracingDockerComposeConnectionDetails(RunningService source) {
super(source); super(source);
this.host = source.host(); this.host = source.host();
this.port = source.ports().get(OTLP_PORT); this.grpcPort = source.ports().get(OTLP_GRPC_PORT);
this.httPort = source.ports().get(OTLP_HTTP_PORT);
} }
@Override @Override
public String getUrl() { public String getUrl() {
return "http://%s:%d/v1/traces".formatted(this.host, this.port); return "http://%s:%d/v1/traces".formatted(this.host, this.httPort);
}
@Override
public String getGrpcEndpoint() {
return "http://%s:%d/v1/traces".formatted(this.host, this.grpcPort);
} }
} }

View File

@ -43,13 +43,16 @@ class OpenTelemetryTracingContainerConnectionDetailsFactoryIntegrationTests {
@Container @Container
@ServiceConnection @ServiceConnection
static final GenericContainer<?> container = TestImage.OPENTELEMETRY.genericContainer().withExposedPorts(4318); static final GenericContainer<?> container = TestImage.OPENTELEMETRY.genericContainer()
.withExposedPorts(4317, 4318);
@Autowired @Autowired
private OtlpTracingConnectionDetails connectionDetails; private OtlpTracingConnectionDetails connectionDetails;
@Test @Test
void connectionCanBeMadeToOpenTelemetryContainer() { void connectionCanBeMadeToOpenTelemetryContainer() {
assertThat(this.connectionDetails.getGrpcEndpoint())
.isEqualTo("http://" + container.getHost() + ":" + container.getMappedPort(4317) + "/v1/traces");
assertThat(this.connectionDetails.getUrl()) assertThat(this.connectionDetails.getUrl())
.isEqualTo("http://" + container.getHost() + ":" + container.getMappedPort(4318) + "/v1/traces"); .isEqualTo("http://" + container.getHost() + ":" + container.getMappedPort(4318) + "/v1/traces");
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,6 +35,10 @@ import org.springframework.boot.testcontainers.service.connection.ServiceConnect
class OpenTelemetryTracingContainerConnectionDetailsFactory class OpenTelemetryTracingContainerConnectionDetailsFactory
extends ContainerConnectionDetailsFactory<Container<?>, OtlpTracingConnectionDetails> { extends ContainerConnectionDetailsFactory<Container<?>, OtlpTracingConnectionDetails> {
private static final int OTLP_GRPC_PORT = 4317;
private static final int OTLP_HTTP_PORT = 4318;
OpenTelemetryTracingContainerConnectionDetailsFactory() { OpenTelemetryTracingContainerConnectionDetailsFactory() {
super("otel/opentelemetry-collector-contrib", super("otel/opentelemetry-collector-contrib",
"org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpAutoConfiguration"); "org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpAutoConfiguration");
@ -55,7 +59,14 @@ class OpenTelemetryTracingContainerConnectionDetailsFactory
@Override @Override
public String getUrl() { public String getUrl() {
return "http://%s:%d/v1/traces".formatted(getContainer().getHost(), getContainer().getMappedPort(4318)); return "http://%s:%d/v1/traces".formatted(getContainer().getHost(),
getContainer().getMappedPort(OTLP_HTTP_PORT));
}
@Override
public String getGrpcEndpoint() {
return "http://%s:%d/v1/traces".formatted(getContainer().getHost(),
getContainer().getMappedPort(OTLP_GRPC_PORT));
} }
} }