running Docker-Compose

This commit is contained in:
Tom Hombergs
2021-11-22 11:08:44 +11:00
parent 26a4ef6eb9
commit 149ceab800
41 changed files with 191 additions and 278 deletions

View File

@@ -0,0 +1,11 @@
# Log Tracing with Spring Cloud Sleuth
This project shows how to implement tracing in a network of Spring Boot applications.
## Companion Blog Article
The companion blog article to this repository can be found [here](https://reflectoring.io/tracing-with-spring-cloud-sleuth/).
## Getting Started
* build the sources with `./gradlew clean build` (don't forge to also do this after every change to the code, otherwise Docker will start the old image)
* run the applications in Docker with `docker-compose up --build`

View File

@@ -5,7 +5,7 @@ buildscript {
}
plugins {
id 'org.springframework.boot' version '2.5.6'
id 'org.springframework.boot' version '2.5.6' apply(false) // we don't want the root project to be a Spring Boot project
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
@@ -14,14 +14,6 @@ repositories {
mavenCentral()
}
bootJar {
enabled = false
}
jar {
enabled = true
}
subprojects {
apply plugin: 'java'

View File

@@ -0,0 +1,15 @@
version: "3.5"
services:
downstream:
build: ./downstream-service/
image: downstream:latest
ports:
- "8080:8080"
upstream:
build: ./upstream-service/
image: upstream:latest
ports:
- "8081:8081"

View File

@@ -0,0 +1,5 @@
FROM adoptopenjdk/openjdk11:alpine-jre
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} application.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/application.jar"]

View File

@@ -1,6 +1,14 @@
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
bootJar {
enabled = true
mainClass.set('com.example.demo.DemoApplication')
}
jar {
enabled = false
}

View File

@@ -0,0 +1,24 @@
package com.example.demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class AddressClient {
private final RestTemplate restTemplate;
private final String baseUrl;
public AddressClient(
RestTemplate restTemplate,
@Value("${addressClient.baseUrl}") String baseUrl) {
this.restTemplate = restTemplate;
this.baseUrl = baseUrl;
}
Address getAddressForCustomerId(long id) {
return restTemplate.getForObject(String.format("%s/addresses/%d", baseUrl, id), Address.class);
}
}

View File

@@ -0,0 +1,29 @@
package com.example.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.client.RestTemplate;
@Component
public class CustomerClient {
private static final Logger logger = LoggerFactory.getLogger(CustomerClient.class);
private RestTemplate restTemplate;
private String baseUrl;
public CustomerClient(
RestTemplate restTemplate,
@Value("${customerClient.baseUrl}") String baseUrl) {
this.restTemplate = restTemplate;
this.baseUrl = baseUrl;
}
Customer getCustomer(@PathVariable("id") long id){
String url = String.format("%s/customers/%d", baseUrl, id);
return restTemplate.getForObject(url, Customer.class);
}
}

View File

@@ -0,0 +1,15 @@
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestConfiguration {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

View File

@@ -0,0 +1,14 @@
server.port: 8080
addressClient:
baseUrl: http://upstream:8081
customerClient:
baseUrl: http://upstream:8081
spring:
output:
ansi:
enabled: always
application:
name: downstream-service

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<!-- You can override this to have a custom pattern -->
<property name="CONSOLE_LOG_PATTERN"
value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
<!-- Appender to log to console -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- Minimum logging level to be presented in the console logs-->
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="console"/>
</root>
</configuration>

View File

@@ -6,5 +6,5 @@ pluginManagement {
}
}
include "sleuth-downstream-service"
include "sleuth-upstream-service"
include "downstream-service"
include "upstream-service"

View File

@@ -1,14 +0,0 @@
package com.example.demo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(value = "addresses", path = "/addresses")
public interface AddressClient {
@RequestMapping(method = RequestMethod.GET, path = "/{id}")
Address getAddressForCustomerId(@PathVariable("id") long id);
}

View File

@@ -1,14 +0,0 @@
package com.example.demo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(value = "customers", path = "/customers")
public interface CustomerClient {
@RequestMapping(method = RequestMethod.GET, value = "/{id}")
Customer getCustomer(@PathVariable("id") long id);
}

View File

@@ -1,15 +0,0 @@
package com.example.demo;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfiguration {
@Bean
public Logger.Level logLevel(){
return Logger.Level.FULL;
}
}

View File

@@ -1,20 +0,0 @@
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
@Configuration
public class RequestLoggingFilterConfig {
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter
= new CommonsRequestLoggingFilter();
filter.setIncludeHeaders(true);
filter.setIncludeQueryString(true);
filter.setIncludePayload(true);
filter.setMaxPayloadLength(10000);
return filter;
}
}

View File

@@ -1,18 +0,0 @@
server.port: 8080
customers:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8081
addresses:
ribbon:
eureka:
enabled: false
listOfServers: localhost:8081
spring:
output:
ansi:
enabled: always

View File

@@ -1,2 +0,0 @@
# this file is loaded by Spring Cloud before application.properties
spring.application.name=sleuth-downstream-service

View File

@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<!-- Example for logging into the build folder of your project -->
<property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>
<!-- You can override this to have a custom pattern -->
<property name="CONSOLE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [${springAppName},%X{X-B3-TraceId:-}] %m%n"/>
<!-- Appender to log to console -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- Minimum logging level to be presented in the console logs-->
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- Appender to log to file -->
<appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- Appender to log to file in a JSON format -->
<!--<appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--<file>${LOG_FILE}.json</file>-->
<!--<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
<!--<fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>-->
<!--<maxHistory>7</maxHistory>-->
<!--</rollingPolicy>-->
<!--<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">-->
<!--<providers>-->
<!--<timestamp>-->
<!--<timeZone>UTC</timeZone>-->
<!--</timestamp>-->
<!--<pattern>-->
<!--<pattern>-->
<!--{-->
<!--"severity": "%level",-->
<!--"service": "${springAppName:-}",-->
<!--"trace": "%X{X-B3-TraceId:-}",-->
<!--"span": "%X{X-B3-SpanId:-}",-->
<!--"parent": "%X{X-B3-ParentSpanId:-}",-->
<!--"exportable": "%X{X-Span-Export:-}",-->
<!--"pid": "${PID:-}",-->
<!--"thread": "%thread",-->
<!--"class": "%logger{40}",-->
<!--"rest": "%message"-->
<!--}-->
<!--</pattern>-->
<!--</pattern>-->
<!--</providers>-->
<!--</encoder>-->
<!--</appender>-->
<root level="INFO">
<appender-ref ref="console"/>
<!-- uncomment this to have also JSON logs -->
<!--<appender-ref ref="logstash"/>-->
<appender-ref ref="flatfile"/>
</root>
</configuration>

View File

@@ -1,20 +0,0 @@
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
@Configuration
public class RequestLoggingFilterConfig {
@Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter
= new CommonsRequestLoggingFilter();
filter.setIncludeHeaders(true);
filter.setIncludeQueryString(true);
filter.setIncludePayload(true);
filter.setMaxPayloadLength(10000);
return filter;
}
}

View File

@@ -1,7 +0,0 @@
logging.level.org.springframework.web.filter.CommonsRequestLoggingFilter: DEBUG
server.port: 8081
spring:
output:
ansi:
enabled: always

View File

@@ -1,2 +0,0 @@
# this file is loaded by Spring Cloud before application.properties
spring.application.name=sleuth-upstream-service

View File

@@ -1,76 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<!-- Example for logging into the build folder of your project -->
<property name="LOG_FILE" value="${BUILD_FOLDER:-build}/${springAppName}"/>
<!-- You can override this to have a custom pattern -->
<property name="CONSOLE_LOG_PATTERN"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [${springAppName},%X{X-B3-TraceId:-}] %m%n"/>
<!-- Appender to log to console -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<!-- Minimum logging level to be presented in the console logs-->
<level>DEBUG</level>
</filter>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- Appender to log to file -->
<appender name="flatfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_FILE}</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.gz</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<!-- Appender to log to file in a JSON format -->
<!--<appender name="logstash" class="ch.qos.logback.core.rolling.RollingFileAppender">-->
<!--<file>${LOG_FILE}.json</file>-->
<!--<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
<!--<fileNamePattern>${LOG_FILE}.json.%d{yyyy-MM-dd}.gz</fileNamePattern>-->
<!--<maxHistory>7</maxHistory>-->
<!--</rollingPolicy>-->
<!--<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">-->
<!--<providers>-->
<!--<timestamp>-->
<!--<timeZone>UTC</timeZone>-->
<!--</timestamp>-->
<!--<pattern>-->
<!--<pattern>-->
<!--{-->
<!--"severity": "%level",-->
<!--"service": "${springAppName:-}",-->
<!--"trace": "%X{X-B3-TraceId:-}",-->
<!--"span": "%X{X-B3-SpanId:-}",-->
<!--"parent": "%X{X-B3-ParentSpanId:-}",-->
<!--"exportable": "%X{X-Span-Export:-}",-->
<!--"pid": "${PID:-}",-->
<!--"thread": "%thread",-->
<!--"class": "%logger{40}",-->
<!--"rest": "%message"-->
<!--}-->
<!--</pattern>-->
<!--</pattern>-->
<!--</providers>-->
<!--</encoder>-->
<!--</appender>-->
<root level="INFO">
<appender-ref ref="console"/>
<!-- uncomment this to have also JSON logs -->
<!--<appender-ref ref="logstash"/>-->
<appender-ref ref="flatfile"/>
</root>
</configuration>

View File

@@ -0,0 +1,5 @@
FROM adoptopenjdk/openjdk11:alpine-jre
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} application.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/application.jar"]

View File

@@ -2,4 +2,13 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
bootJar {
enabled = true
mainClass.set('com.example.demo.DemoApplication')
}
jar {
enabled = false
}

View File

@@ -2,10 +2,8 @@ package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class DemoApplication {
public static void main(String[] args) {

View File

@@ -0,0 +1,8 @@
server.port: 8081
spring:
output:
ansi:
enabled: always
application:
name: upstream-service

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="springAppName" source="spring.application.name"/>
<!-- Appender to log to console -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}</pattern>
<charset>utf8</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="console"/>
</root>
</configuration>