diff --git a/spring-cloud/spring-cloud-bootstrap/README.MD b/spring-cloud/spring-cloud-bootstrap/README.MD
index d6f8faf31e..251c861830 100644
--- a/spring-cloud/spring-cloud-bootstrap/README.MD
+++ b/spring-cloud/spring-cloud-bootstrap/README.MD
@@ -1,3 +1,12 @@
### Relevant Articles:
- [Spring Cloud – Bootstrapping](http://www.baeldung.com/spring-cloud-bootstrapping)
- [Spring Cloud – Securing Services](http://www.baeldung.com/spring-cloud-securing-services)
+
+- To run the project:
+ - copy the appliction-config folder to c:\Users\{username}\ on Windows or /Users/{username}/ on *nix. Then open a git bash terminal in application-config and run:
+ - git init
+ - git add .
+ - git commit -m "First commit"
+ - start the config server
+ - start the discover server
+ - start all the other servers in any order (gateway, svc-book, svc-rating, zipkin)
diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties
index e1244a0cf0..49f7d1ed91 100644
--- a/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties
+++ b/spring-cloud/spring-cloud-bootstrap/application-config/book-service.properties
@@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug
spring.redis.host=localhost
spring.redis.port=6379
+
+spring.sleuth.sampler.percentage=1.0
+spring.sleuth.web.skipPattern=(^cleanup.*)
diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties
index 09f7f3bf4a..e9e593284c 100644
--- a/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties
+++ b/spring-cloud/spring-cloud-bootstrap/application-config/gateway.properties
@@ -24,4 +24,7 @@ logging.level.org.springframework.security=debug
logging.level.org.springframework.cloud.netflix.zuul=debug
spring.redis.host=localhost
-spring.redis.port=6379
\ No newline at end of file
+spring.redis.port=6379
+
+spring.sleuth.sampler.percentage=1.0
+spring.sleuth.web.skipPattern=(^cleanup.*|.+favicon.*)
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties
index 4817d12c83..b7cbb6fbd6 100644
--- a/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties
+++ b/spring-cloud/spring-cloud-bootstrap/application-config/rating-service.properties
@@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug
spring.redis.host=localhost
spring.redis.port=6379
+
+spring.sleuth.sampler.percentage=1.0
+spring.sleuth.web.skipPattern=(^cleanup.*)
diff --git a/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties b/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties
new file mode 100644
index 0000000000..ca3aed2263
--- /dev/null
+++ b/spring-cloud/spring-cloud-bootstrap/application-config/zipkin.properties
@@ -0,0 +1,7 @@
+spring.application.name=zipkin
+server.port=9411
+
+eureka.client.region = default
+eureka.client.registryFetchIntervalSeconds = 5
+
+logging.level.org.springframework.web=debug
diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml
index 044730ba22..97c440c249 100644
--- a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml
+++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml
@@ -41,6 +41,11 @@
spring-boot-starter-data-redis
+
+ org.springframework.cloud
+ spring-cloud-starter-zipkin
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java
index b5ae1e4e7b..16aae66cab 100644
--- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java
+++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java
@@ -1,6 +1,9 @@
package com.baeldung.spring.cloud.bootstrap.gateway;
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.discovery.EurekaClient;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
@@ -8,8 +11,13 @@ import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
+import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
+import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter;
+import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
+import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
+import zipkin.Span;
import java.util.ArrayList;
import java.util.List;
@@ -18,23 +26,50 @@ import java.util.List;
@EnableZuulProxy
@EnableEurekaClient
public class GatewayApplication {
- public static void main(String[] args) {
- SpringApplication.run(GatewayApplication.class, args);
- }
+ public static void main(String[] args) {
+ SpringApplication.run(GatewayApplication.class, args);
+ }
- @Autowired(required = false)
- private List configurations = new ArrayList<>();
+ @Autowired(required = false)
+ private List configurations = new ArrayList<>();
+ @Autowired
+ private EurekaClient eurekaClient;
+ @Autowired
+ private SpanMetricReporter spanMetricReporter;
+ @Autowired
+ private ZipkinProperties zipkinProperties;
+ @Value("${spring.sleuth.web.skipPattern}")
+ private String skipPattern;
- @Bean
- @LoadBalanced
- RestTemplate restTemplate() {
- return new RestTemplate();
- }
+ @Bean
+ @LoadBalanced
+ RestTemplate restTemplate() {
+ return new RestTemplate();
+ }
- @Bean
- public SpringClientFactory springClientFactory() {
- SpringClientFactory factory = new SpringClientFactory();
- factory.setConfigurations(this.configurations);
- return factory;
- }
+ @Bean
+ public SpringClientFactory springClientFactory() {
+ SpringClientFactory factory = new SpringClientFactory();
+ factory.setConfigurations(this.configurations);
+ return factory;
+ }
+
+ @Bean
+ public ZipkinSpanReporter makeZipkinSpanReporter() {
+ return new ZipkinSpanReporter() {
+ private HttpZipkinSpanReporter delegate;
+ private String baseUrl;
+
+ @Override
+ public void report(Span span) {
+ InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false);
+ if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) {
+ baseUrl = instance.getHomePageUrl();
+ delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter);
+ if (!span.name.matches(skipPattern)) delegate.report(span);
+ }
+ if (!span.name.matches(skipPattern)) delegate.report(span);
+ }
+ };
+ }
}
diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java
index 9e5c424403..935e50ec72 100644
--- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java
+++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/SecurityConfig.java
@@ -23,6 +23,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/book-service/books").permitAll()
+ .antMatchers("/zipkin/**").permitAll()
.antMatchers("/eureka/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
diff --git a/spring-cloud/spring-cloud-bootstrap/pom.xml b/spring-cloud/spring-cloud-bootstrap/pom.xml
index ccfbdb9735..83879cf7d4 100644
--- a/spring-cloud/spring-cloud-bootstrap/pom.xml
+++ b/spring-cloud/spring-cloud-bootstrap/pom.xml
@@ -16,6 +16,7 @@
gateway
svc-book
svc-rating
+ zipkin
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml
index c351c444f6..cbf7083b83 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml
+++ b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml
@@ -53,6 +53,11 @@
runtime
+
+ org.springframework.cloud
+ spring-cloud-starter-zipkin
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java
index c5499cd924..63ff0fb134 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java
+++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java
@@ -1,13 +1,52 @@
package com.baeldung.spring.cloud.bootstrap.svcbook;
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.discovery.EurekaClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
+import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter;
+import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
+import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
+import org.springframework.context.annotation.Bean;
+import zipkin.Span;
@SpringBootApplication
@EnableEurekaClient
public class BookServiceApplication {
+
+ @Autowired
+ private EurekaClient eurekaClient;
+ @Autowired
+ private SpanMetricReporter spanMetricReporter;
+ @Autowired
+ private ZipkinProperties zipkinProperties;
+ @Value("${spring.sleuth.web.skipPattern}")
+ private String skipPattern;
+
public static void main(String[] args) {
SpringApplication.run(BookServiceApplication.class, args);
}
+
+ @Bean
+ public ZipkinSpanReporter makeZipkinSpanReporter() {
+ return new ZipkinSpanReporter() {
+ private HttpZipkinSpanReporter delegate;
+ private String baseUrl;
+
+ @Override
+ public void report(Span span) {
+ InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false);
+ if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) {
+ baseUrl = instance.getHomePageUrl();
+ delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter);
+ if (!span.name.matches(skipPattern)) delegate.report(span);
+ }
+ if (!span.name.matches(skipPattern)) delegate.report(span);
+ }
+ };
+ }
}
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties
index 8f3a3261ac..481cdc182c 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties
+++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/resources/bootstrap.properties
@@ -4,4 +4,4 @@ spring.cloud.config.discovery.enabled=true
spring.cloud.config.username=configUser
spring.cloud.config.password=configPassword
-eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
+eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml
index 2285286812..f02ba88f04 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml
+++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml
@@ -53,6 +53,11 @@
runtime
+
+ org.springframework.cloud
+ spring-cloud-starter-zipkin
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java
index 61074e0bcc..0d85c5c825 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java
+++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java
@@ -1,13 +1,51 @@
package com.baeldung.spring.cloud.bootstrap.svcrating;
+import com.netflix.appinfo.InstanceInfo;
+import com.netflix.discovery.EurekaClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
+import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter;
+import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
+import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
+import org.springframework.context.annotation.Bean;
+import zipkin.Span;
@SpringBootApplication
@EnableEurekaClient
public class RatingServiceApplication {
+ @Autowired
+ private EurekaClient eurekaClient;
+ @Autowired
+ private SpanMetricReporter spanMetricReporter;
+ @Autowired
+ private ZipkinProperties zipkinProperties;
+ @Value("${spring.sleuth.web.skipPattern}")
+ private String skipPattern;
+
public static void main(String[] args) {
SpringApplication.run(RatingServiceApplication.class, args);
}
+
+ @Bean
+ public ZipkinSpanReporter makeZipkinSpanReporter() {
+ return new ZipkinSpanReporter() {
+ private HttpZipkinSpanReporter delegate;
+ private String baseUrl;
+
+ @Override
+ public void report(Span span) {
+ InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false);
+ if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) {
+ baseUrl = instance.getHomePageUrl();
+ delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter);
+ if (!span.name.matches(skipPattern)) delegate.report(span);
+ }
+ if (!span.name.matches(skipPattern)) delegate.report(span);
+ }
+ };
+ }
}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml
new file mode 100644
index 0000000000..c2fd7cd2dc
--- /dev/null
+++ b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml
@@ -0,0 +1,88 @@
+
+
+ 4.0.0
+
+ zipkin
+ 1.0.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.4.4.RELEASE
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-eureka
+
+
+
+ io.zipkin.java
+ zipkin-server
+
+
+
+ io.zipkin.java
+ zipkin-autoconfigure-ui
+ runtime
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud-dependencies.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ 1.8
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ **/*LiveTest.java
+
+
+
+
+
+
+
+ Brixton.SR7
+ 3.6.0
+
+
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java
new file mode 100644
index 0000000000..bb1355e258
--- /dev/null
+++ b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/java/com/baeldung/spring/cloud/bootstrap/zipkin/ZipkinApplication.java
@@ -0,0 +1,15 @@
+package com.baeldung.spring.cloud.bootstrap.zipkin;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
+import zipkin.server.EnableZipkinServer;
+
+@SpringBootApplication
+@EnableEurekaClient
+@EnableZipkinServer
+public class ZipkinApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(ZipkinApplication.class, args);
+ }
+}
diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties
new file mode 100644
index 0000000000..9569179a4f
--- /dev/null
+++ b/spring-cloud/spring-cloud-bootstrap/zipkin/src/main/resources/bootstrap.properties
@@ -0,0 +1,7 @@
+spring.cloud.config.name=zipkin
+spring.cloud.config.discovery.service-id=config
+spring.cloud.config.discovery.enabled=true
+spring.cloud.config.username=configUser
+spring.cloud.config.password=configPassword
+
+eureka.client.serviceUrl.defaultZone=http://discUser:discPassword@localhost:8082/eureka/
\ No newline at end of file