Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds eureka support to micrometer example #114

Merged
merged 2 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build-bin/test
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ build-bin/docker/docker_build ${docker_image} ${VERSION}
docker_compose_file=build-bin/docker-compose.test.yml

case ${VERSION} in
armeria|*sleuth* )
armeria|*sleuth*|*micrometer* )
docker_compose_file=build-bin/docker-compose-eureka.test.yml
;;
armeria-kafka )
Expand Down
43 changes: 18 additions & 25 deletions webflux6-micrometer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,34 +19,10 @@
<jre.version>21</jre.version>
<maven.compiler.release>17</maven.compiler.release>

<spring-boot.version>3.3.0-RC1</spring-boot.version>
<spring-boot.version>3.3.0</spring-boot.version>
<micrometer.version>1.3.0</micrometer.version>
</properties>

<!-- Temporary until Spring boot 3.3.0 -->
<pluginRepositories>
<pluginRepository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>

<!-- Temporary until Spring boot 3.3.0 -->
<repositories>
<repository>
<id>repository.spring.milestone</id>
<name>Spring Milestone Repository</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

<dependencyManagement>
<dependencies>
<dependency>
Expand All @@ -71,6 +47,23 @@
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>4.1.1</version>
<exclusions>
<!-- dodge spring-jcl conflict error -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- micrometer-tracing-bridge-brave configures instrumentation including what's in Brave and their own. -->
<dependency>
Expand Down
16 changes: 11 additions & 5 deletions webflux6-micrometer/src/main/java/brave/example/Backend.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package brave.example;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
Expand All @@ -12,7 +16,10 @@

@EnableAutoConfiguration
@RestController
@Import(CustomObservationConfiguration.class)
@Import(value = {
CustomObservationConfiguration.class,
ZipkinDiscoveryConfiguration.class
})
public class Backend {

@GetMapping("/api")
Expand All @@ -24,9 +31,8 @@ public Mono<String> printDate(@RequestHeader("user_name") Optional<String> usern
}

public static void main(String[] args) {
SpringApplication.run(Backend.class,
"--spring.application.name=backend",
"--server.port=9000"
);
new SpringApplicationBuilder(Backend.class)
.properties(ZipkinDiscoveryConfiguration.discoveryProperties())
.run("--spring.application.name=backend", "--server.port=9000");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package brave.example;

import brave.http.HttpTracing;
import io.micrometer.observation.ObservationPredicate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -21,7 +20,7 @@ public class CustomObservationConfiguration {
* spring.sleuth.web.additional-skip-pattern=/health
* </pre>
*
* <p>Brave uses {@link HttpTracing#serverRequestSampler()} for server request sampling policy.
* <p>Brave uses {@code HttpTracing#serverRequestSampler()} for server request sampling policy.
* Micrometer tracing bridges to Brave's core API, so it doesn't see or use the HTTP, Messaging or
* RPC policies. Instead, it relies on its own type, {@link ObservationPredicate}, which applies
* both to metrics and tracing.
Expand Down
16 changes: 10 additions & 6 deletions webflux6-micrometer/src/main/java/brave/example/Frontend.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Import;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -12,7 +12,10 @@

@EnableAutoConfiguration
@RestController
@Import(CustomObservationConfiguration.class)
@Import(value = {
CustomObservationConfiguration.class,
ZipkinDiscoveryConfiguration.class
})
public class Frontend {
final WebClient webClient;

Expand All @@ -26,9 +29,10 @@ public class Frontend {
}

public static void main(String[] args) {
SpringApplication.run(Frontend.class,
"--spring.application.name=frontend",
"--server.port=8081"
);
new SpringApplicationBuilder(Frontend.class)
.properties(ZipkinDiscoveryConfiguration.discoveryProperties())
.run("--spring.application.name=frontend",
"--server.port=8081"
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package brave.example;

import java.net.URI;
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import zipkin2.reporter.HttpEndpointSupplier;
import zipkin2.reporter.HttpEndpointSuppliers;

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty("EUREKA_SERVICE_URL")
public class ZipkinDiscoveryConfiguration {

/**
* It is very difficult to stop loadbalancer or discovery from initializing when starters are on
* the classpath. This is a workaround to disable it when EUREKA_SERVICE_URL is not set.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

*/
static Map<String, Object> discoveryProperties() {
Map<String, Object> properties = new LinkedHashMap<>();
String eurekaServiceUrl = System.getenv("EUREKA_SERVICE_URL");
boolean eurekaEnabled = eurekaServiceUrl != null && !eurekaServiceUrl.isEmpty();
if (eurekaEnabled) {
properties.put("eureka.client.serviceUrl.defaultZone", eurekaServiceUrl);
}
properties.put("spring.cloud.loadbalancer.enabled", eurekaEnabled);
properties.put("spring.cloud.discovery.enabled", eurekaEnabled);
return properties;
}

@Bean HttpEndpointSupplier.Factory loadbalancerEndpoints(LoadBalancerClient loadBalancerClient) {
LoadBalancerHttpEndpointSupplier.Factory httpEndpointSupplierFactory =
new LoadBalancerHttpEndpointSupplier.Factory(loadBalancerClient);
// don't ask more than 30 seconds (just to show)
return HttpEndpointSuppliers.newRateLimitedFactory(httpEndpointSupplierFactory, 30);
}

record LoadBalancerHttpEndpointSupplier(LoadBalancerClient loadBalancerClient, URI virtualURL)
implements HttpEndpointSupplier {
record Factory(LoadBalancerClient loadBalancerClient) implements HttpEndpointSupplier.Factory {

@Override public HttpEndpointSupplier create(String endpoint) {
return new LoadBalancerHttpEndpointSupplier(loadBalancerClient, URI.create(endpoint));
}
}

@Override public String get() {
// At least spring-cloud-netflix wants the actual hostname as a lookup value
ServiceInstance instance = loadBalancerClient.choose(virtualURL.getHost());
if (instance != null) {
return instance.getUri() + virtualURL.getPath();
}
throw new IllegalArgumentException(
virtualURL.getHost() + " is not an instance registered in Eureka");
}

@Override public void close() {
}

@Override public String toString() {
return "LoadBalancer{" + virtualURL + "}";
}
}
}
4 changes: 4 additions & 0 deletions webflux6-micrometer/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ management:
tracing:
# Note: There is no property to bind ${brave.localServiceName:${spring.application.name}}
endpoint: ${zipkin.baseUrl:http://127.0.0.1:9411}/api/v2/spans
spring:
cloud:
compatibilityVerifier:
enabled: false

logging:
level:
Expand Down
Loading