microservice
send the tracing info to the zipkin tracing server. Zipkin store the information in database and provides UI.Zipkin
locally on http://localhost:9411/zipkin/
.Note: We can also develop spring boot app with zipkin serevr intead of using Zipking docker image.
d1-zipkin-tracing-server
d2-zipkin-currency-exchange-service
d3-zepkin-currency-conversion-service-openfeign
d4-zepkin-api-gateway-routes
Purpose / Feature
Steps
feign
clients. By default requests made using feign clients are not traced.management.tracing.sampling.probability=1.0 # 1.0 -> 100%, #SB3
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}] #SB3
RestTemplate
using RestTemplateBuilder
to enable tracing of requests.
new RestTemplate()
will not be traced.RestTemplate
and autowire in controller.Maven / External dependency
<!-- SB3 : Micrometer
> OpenTelemetry
> Zipkin
-->
<!-- Micrometer - Vendor-neutral application observability facade.
Instrument your JVM-based application code without vendor lock-in.
Observation (Metrics & Logs) + Tracing.
-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation</artifactId>
</dependency>
<!-- Open Telemetry
- Open Telemetry as Bridge (RECOMMENDED)
- Simplified Observability (metrics, logs, and traces) -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-zipkin</artifactId>
</dependency>
<!-- requres where feign client is getting used. -->
<!-- Enables tracing of REST API calls made using Feign - SB-V3 ONLY-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-micrometer</artifactId>
</dependency>
Code / Config changes
import org.springframework.boot.web.client.RestTemplateBuilder;
@Configuration
public class RestTemplateConfiguration {
@Bean
RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
import org.springframework.boot.web.client.RestTemplateBuilder;
// standard controller code
@GetMapping("/currency-conversion/from/{from}/to/{to}/quantity/{quantity}")
public CurrencyConversion calculateCurrencyConversion(@PathVariable String from, @PathVariable String to,
@PathVariable BigDecimal quantity) {
logger.info("Executing CurrencyConversionController.calculateCurrencyConversion(..) API.");
// Standardize
from = from.toUpperCase();
to = to.toUpperCase();
final Map<String, String> uriVariables = new HashMap<>();
uriVariables.put("from", from);
uriVariables.put("to", to);
// Send request to Currency exchange micro-service
final ResponseEntity<CurrencyConversion> response = restTemplate.getForEntity(
"http://localhost:8000/jpa/currency-exchange/from/{from}/to/{to}", CurrencyConversion.class,
uriVariables);
final CurrencyConversion currencyConversionExchange = response.getBody();
logger.debug("Response from currency-exchange : {}", currencyConversionExchange);
final CurrencyConversion currencyConversion = new CurrencyConversion(currencyConversionExchange.getId(), from,
to, quantity, currencyConversionExchange.getConversionMultiples(),
quantity.multiply(currencyConversionExchange.getConversionMultiples()),
currencyConversionExchange.getEnvironment());
logger.debug("Response returned : {}", currencyConversionExchange);
return currencyConversion;
}
// other APIs
# logging
logging.pattern.level=%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]
logging.level.com.srvivek.sboot=debug
# Start: micrometer configuration
# Add sampling configuration to define how much percentage of request will be sampled.
management.tracing.sampling.probability=1.0 # 100%
# End: micrometer configuration
docker-compose.yaml
.
tabs
for formatting/indentation, use only spaces. version: '3.7'
services:
naming-server:
image: srvivek/b6-naming-service:0.0.1-SNAPSHOT
mem_limit: 800m
ports:
- "8761:8761"
networks:
- currency-network
currency-exchange:
image: srvivek/d2-zipkin-currency-exchange-service:0.0.1-SNAPSHOT
mem_limit: 800m
ports:
- "8000:8000"
networks:
- currency-network
depends_on:
- naming-server
environment: # Properties - override defaults in appplication.properties
EUREKA.CLIENT.SERVICE-URL.DEFAULTZONE: http://naming-server:8761/eureka
MANAGEMENT.ZIPKIN.TRACING.ENDPOINT: http://zipkin-server:9411/api/v2/spans
currency-conversion:
image: srvivek/d3-zepkin-currency-conversion-service-openfeign:0.0.1-SNAPSHOT
mem_limit: 800m
ports:
- "8100:8100"
networks:
- currency-network
depends_on:
- naming-server
environment: # Properties - override defaults in appplication.properties
EUREKA.CLIENT.SERVICE-URL.DEFAULTZONE: http://naming-server:8761/eureka
MANAGEMENT.ZIPKIN.TRACING.ENDPOINT: http://zipkin-server:9411/api/v2/spans
api-gateway:
image: srvivek/d4-zepkin-api-gateway-routes:0.0.1-SNAPSHOT
mem_limit: 800m
ports:
- "8765:8765"
networks:
- currency-network
depends_on:
- naming-server
environment: # Properties - override defaults in appplication.properties
EUREKA.CLIENT.SERVICE-URL.DEFAULTZONE: http://naming-server:8761/eureka
MANAGEMENT.ZIPKIN.TRACING.ENDPOINT: http://zipkin-server:9411/api/v2/spans
zipkin-server:
image: openzipkin/zipkin
mem_limit: 800m
ports:
- "9411:9411"
networks:
- currency-network
restart: always #Restart if there is a problem starting up
networks:
currency-network: