feat: Distributed tracing (#3006)

* added microservices distributed tracing pattern

* feat: Implement Microservice pattern: Distributed tracing #2693
This commit is contained in:
Walyson Moises
2024-07-20 07:42:12 -03:00
committed by GitHub
parent 1d454f7721
commit 9c43d85f36
35 changed files with 1724 additions and 0 deletions
+201
View File
@@ -0,0 +1,201 @@
---
title: "Microservices Distributed Tracing Pattern: Enhancing Visibility in Service Communication"
shortTitle: Distributed Tracing in Microservices
description: "Learn how the Distributed Tracing pattern enhances visibility into service communication across microservices. Discover its benefits, implementation examples, and best practices."
category: Integration
language: en
tag:
- Distributed tracing
- Microservices architecture
- Service communication
- Performance monitoring
- Scalability
- Observability
---
## Intent of Microservices Distributed Tracing Design Pattern
Distributed tracing aims to monitor and track requests as they flow through different services in a microservices architecture, providing insights into performance, dependencies, and failures.
## Also known as
* Distributed Request Tracing
* End-to-End Tracing
## Detailed Explanation of Microservices Distributed Tracing Pattern with Real-World Examples
Real-world example
> In an e-commerce platform, distributed tracing is used to track a customer's request from the moment they add an item to the cart until the order is processed and shipped. This helps in identifying bottlenecks, errors, and latency issues across different services.
In plain words
> Distributed tracing allows you to follow a request's journey through all the services it interacts with, providing insights into system performance and aiding in debugging.
Wikipedia says
> Tracing in software engineering refers to the process of capturing and recording information about the execution of a software program. This information is typically used by programmers for debugging purposes, and additionally, depending on the type and detail of information contained in a trace log, by experienced system administrators or technical-support personnel and by software monitoring tools to diagnose common problems with software.
## Programmatic Example of Microservices Distributed Tracing in Java
This implementation shows how an e-commerce platform's `OrderService` interacts with both `PaymentService` and `ProductService`. When a customer places an order, the `OrderService` calls the `PaymentService` to process the payment and the `ProductService` to check the product inventory. Distributed tracing logs are generated for each of these interactions and can be viewed in the Zipkin interface to monitor the flow and performance of requests across these services.
Here's the `Order microservice` implementation.
```java
@Slf4j
@RestController
public class OrderController {
private final OrderService orderService;
public OrderController(final OrderService orderService) {
this.orderService = orderService;
}
@PostMapping("/order")
public ResponseEntity<String> processOrder(@RequestBody(required = false) String request) {
LOGGER.info("Received order request: {}", request);
var result = orderService.processOrder();
LOGGER.info("Order processed result: {}", result);
return ResponseEntity.ok(result);
}
}
```
```java
@Slf4j
@Service
public class OrderService {
private final RestTemplateBuilder restTemplateBuilder;
public OrderService(final RestTemplateBuilder restTemplateBuilder) {
this.restTemplateBuilder = restTemplateBuilder;
}
public String processOrder() {
if (validateProduct() && processPayment()) {
return "Order processed successfully";
}
return "Order processing failed";
}
Boolean validateProduct() {
try {
ResponseEntity<Boolean> productValidationResult = restTemplateBuilder
.build()
.postForEntity("http://localhost:30302/product/validate", "validating product",
Boolean.class);
LOGGER.info("Product validation result: {}", productValidationResult.getBody());
return productValidationResult.getBody();
} catch (ResourceAccessException | HttpClientErrorException e) {
LOGGER.error("Error communicating with product service: {}", e.getMessage());
return false;
}
}
Boolean processPayment() {
try {
ResponseEntity<Boolean> paymentProcessResult = restTemplateBuilder
.build()
.postForEntity("http://localhost:30301/payment/process", "processing payment",
Boolean.class);
LOGGER.info("Payment processing result: {}", paymentProcessResult.getBody());
return paymentProcessResult.getBody();
} catch (ResourceAccessException | HttpClientErrorException e) {
LOGGER.error("Error communicating with payment service: {}", e.getMessage());
return false;
}
}
}
```
Here's the `Payment microservice` implementation.
```java
@Slf4j
@RestController
public class PaymentController {
@PostMapping("/payment/process")
public ResponseEntity<Boolean> payment(@RequestBody(required = false) String request) {
LOGGER.info("Received payment request: {}", request);
boolean result = true;
LOGGER.info("Payment result: {}", result);
return ResponseEntity.ok(result);
}
}
```
Here's the `Product microservice` implementation.
```java
/**
* Controller for handling product validation requests.
*/
@Slf4j
@RestController
public class ProductController {
/**
* Validates the product based on the request.
*
* @param request the request body containing product information (can be null)
* @return ResponseEntity containing the validation result (true)
*/
@PostMapping("/product/validate")
public ResponseEntity<Boolean> validateProduct(@RequestBody(required = false) String request) {
LOGGER.info("Received product validation request: {}", request);
boolean result = true;
LOGGER.info("Product validation result: {}", result);
return ResponseEntity.ok(result);
}
}
```
## When to Use the Microservices Distributed Tracing Pattern in Java
* When you have a microservices architecture and need to monitor the flow of requests across multiple services.
* When troubleshooting performance issues or errors in a distributed system.
* When you need to gain insights into system bottlenecks and optimize overall performance.
## Microservices Distributed Tracing Pattern Java Tutorials
* [Spring Boot - Tracing (Spring)](https://docs.spring.io/spring-boot/reference/actuator/tracing.html)
* [Reactive Observability (Spring Academy)](https://spring.academy/guides/microservices-observability-reactive-spring-boot-3)
* [Spring Cloud Tracing Services with Zipkin (Baeldung)](https://dzone.com/articles/getting-started-with-spring-cloud-gateway)
## Benefits and Trade-offs of Microservices Distributed Tracing Pattern
Benefits:
* Provides end-to-end visibility into requests.
* Helps in identifying performance bottlenecks.
* Aids in debugging and troubleshooting complex systems.
Trade-offs:
* Adds overhead to each request due to tracing data.
* Requires additional infrastructure (e.g., Zipkin, Jaeger) for collecting and visualizing traces.
* Can become complex to manage in large-scale systems.
## Real-World Applications of Microservices Distributed Tracing Pattern in Java
* Monitoring and troubleshooting e-commerce platforms.
* Performance monitoring in financial transaction systems.
* Observability in large-scale SaaS applications.
## Related Java Design Patterns
* [Log Aggregation Microservice](https://java-design-patterns.com/patterns/microservices-log-aggregation/) - Distributed tracing works well in conjunction with log aggregation to provide comprehensive observability and troubleshooting capabilities.
* [Circuit Breaker](https://java-design-patterns.com/patterns/circuit-breaker/) - Distributed tracing can be used alongside the Circuit Breaker pattern to monitor and handle failures gracefully, preventing cascading failures in microservices.
* [API Gateway Microservice](https://java-design-patterns.com/patterns/microservices-api-gateway/) - The API Gateway pattern can be integrated with distributed tracing to provide a single entry point for tracing requests across multiple microservices.
## References and Credits
* [Building Microservices](https://amzn.to/3UACtrU)
* [OpenTelemetry Documentation](https://opentelemetry.io/docs/)
* [Distributed tracing (microservices.io)](https://microservices.io/patterns/observability/distributed-tracing.html)
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

@@ -0,0 +1,31 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Order Microservice" {
class OrderController {
+processOrder()
}
class OrderService {
+validateProduct()
+processPayment()
}
}
package "Payment Microservice" {
class PaymentController {
+processPayment()
}
}
package "Product Microservice" {
class ProductController {
+validateProduct()
}
}
OrderController --> OrderService
OrderService --> PaymentController : processPayment()
OrderService --> ProductController : validateProduct()
}
@enduml
@@ -0,0 +1,31 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Order Microservice" {
class OrderController {
+processOrder()
}
class OrderService {
+validateProduct()
+processPayment()
}
}
package "Payment Microservice" {
class PaymentController {
+processPayment()
}
}
package "Product Microservice" {
class ProductController {
+validateProduct()
}
}
OrderController --> OrderService
OrderService --> PaymentController : processPayment()
OrderService --> ProductController : validateProduct()
}
@enduml
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,15 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Order Microservice" {
class OrderController {
+processOrder()
}
class OrderService {
+validateProduct()
+processPayment()
}
}
}
@enduml
@@ -0,0 +1,15 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Order Microservice" {
class OrderController {
+processOrder()
}
class OrderService {
+validateProduct()
+processPayment()
}
}
}
@enduml
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
The MIT License
Copyright © 2014-2022 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>microservices-distributed-tracing</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-microservice</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.order.microservice.com.iluwatar.product.microservice.Main</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<name>Maven Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
</project>
@@ -0,0 +1,80 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* With the Microservices pattern, a request often travels through multiple different microservices.
* Tracking the entire request flow across these services can be challenging, especially when trying
* to diagnose performance issues or failures. Distributed tracing addresses this challenge by
* providing end-to-end visibility into the lifecycle of a request as it passes through various
* microservices.
*
* <p>The intent of the Distributed Tracing pattern is to trace a request across different
* microservices, collecting detailed timing data and logs that help in understanding the flow,
* performance bottlenecks, and failure points in a distributed system. Each microservice involved
* in the request contributes to the tracing data, creating a comprehensive view of the request's
* journey.
*
* <p>This implementation demonstrates distributed tracing in a microservices architecture for an
* e-commerce platform. When a customer places an order, the {@link OrderService} interacts with
* both the payment-microservice to process the payment and the product-microservice to check the
* product inventory. Tracing logs are generated for each interaction, and these logs can be
* visualized using Zipkin.
*
* <p>To run Zipkin and view the tracing logs, you can use the following Docker command:
*
* <pre>
* {@code docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin }
* </pre>
*
* <p>Start Zipkin with the command above. Once Zipkin is running, you can
* access the Zipkin UI at `<a href="http://localhost:9411">...</a>`
* to view the tracing logs and analyze the request flows across your microservices.
*
*
* <p>To place an order and generate tracing data, you can use the following curl command:
*
* <pre>
* {@code curl -X POST http://localhost:30300/order -H "Content-Type: application/json" -d '{"orderId": "123"}' }
* </pre>
*
* <p>This command sends a POST request to create an order, which will trigger interactions with the
* payment and product microservices, generating tracing logs that can be viewed in Zipkin.
*
*/
@SpringBootApplication
public class Main {
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
@@ -0,0 +1,64 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* This controller handles order processing by calling necessary microservices.
*/
@Slf4j
@RestController
public class OrderController {
private final OrderService orderService;
/**
* Constructor to inject OrderService.
*
* @param orderService the service to process orders
*/
public OrderController(final OrderService orderService) {
this.orderService = orderService;
}
/**
* Endpoint to process an order.
*
* @param request the order request body (can be null)
* @return ResponseEntity with a status message
*/
@PostMapping("/order")
public ResponseEntity<String> processOrder(@RequestBody(required = false) String request) {
LOGGER.info("Received order request: {}", request);
var result = orderService.processOrder();
LOGGER.info("Order processed result: {}", result);
return ResponseEntity.ok(result);
}
}
@@ -0,0 +1,103 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.ResourceAccessException;
/**
* Service to handle order processing logic.
*/
@Slf4j
@Service
public class OrderService {
private final RestTemplateBuilder restTemplateBuilder;
/**
* Constructor to inject RestTemplateBuilder.
*
* @param restTemplateBuilder the RestTemplateBuilder to build RestTemplate instances
*/
public OrderService(final RestTemplateBuilder restTemplateBuilder) {
this.restTemplateBuilder = restTemplateBuilder;
}
/**
* Processes an order by calling
* {@link OrderService#validateProduct()} and
* {@link OrderService#processPayment()}.
*
* @return A string indicating whether the order was processed successfully or failed.
*/
public String processOrder() {
if (validateProduct() && processPayment()) {
return "Order processed successfully";
}
return "Order processing failed";
}
/**
* Validates the product by calling the respective microservice.
*
* @return true if the product is valid, false otherwise.
*/
Boolean validateProduct() {
try {
ResponseEntity<Boolean> productValidationResult = restTemplateBuilder
.build()
.postForEntity("http://localhost:30302/product/validate", "validating product",
Boolean.class);
LOGGER.info("Product validation result: {}", productValidationResult.getBody());
return productValidationResult.getBody();
} catch (ResourceAccessException | HttpClientErrorException e) {
LOGGER.error("Error communicating with product service: {}", e.getMessage());
return false;
}
}
/**
* Validates the product by calling the respective microservice.
*
* @return true if the product is valid, false otherwise.
*/
Boolean processPayment() {
try {
ResponseEntity<Boolean> paymentProcessResult = restTemplateBuilder
.build()
.postForEntity("http://localhost:30301/payment/process", "processing payment",
Boolean.class);
LOGGER.info("Payment processing result: {}", paymentProcessResult.getBody());
return paymentProcessResult.getBody();
} catch (ResourceAccessException | HttpClientErrorException e) {
LOGGER.error("Error communicating with payment service: {}", e.getMessage());
return false;
}
}
}
@@ -0,0 +1,33 @@
#
# The MIT License
# Copyright © 2014-2021 Ilkka Seppälä
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
spring.application.name=order-microservice
server.port=30300
management.tracing.sampling.probability=1
logging.pattern.level=%5p [${spring.zipkin.service.name:${spring.application.name:}},%X{traceId:-},%X{spanId:-}]
management.tracing.propagation.type=w3c
management.tracing.baggage.enabled=true
management.tracing.enabled=true
management.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans
@@ -0,0 +1,39 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.junit.jupiter.api.Test;
/**
* Application test
*/
class MainTest {
@Test
void shouldExecuteApplicationWithoutException() {
assertDoesNotThrow(() -> Main.main(new String[]{}));
}
}
@@ -0,0 +1,76 @@
package com.iluwatar.order.microservice;/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
/**
* OrderControllerTest class to test the OrderController.
*/
class OrderControllerTest {
@InjectMocks
private OrderController orderController;
@Mock
private OrderService orderService;
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
}
/**
* Test to process the order successfully.
*/
@Test
void processOrderShouldReturnSuccessStatus() {
// Arrange
when(orderService.processOrder()).thenReturn("Order processed successfully");
// Act
ResponseEntity<String> response = orderController.processOrder("test order");
// Assert
assertEquals("Order processed successfully", response.getBody());
}
/**
* Test to process the order with failure.
*/
@Test
void ProcessOrderShouldReturnFailureStatusWhen() {
// Arrange
when(orderService.processOrder()).thenReturn("Order processing failed");
// Act
ResponseEntity<String> response = orderController.processOrder("test order");
// Assert
assertEquals("Order processing failed", response.getBody());
}
}
@@ -0,0 +1,192 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.ResourceAccessException;
/**
* OrderServiceTest class to test the OrderService.
*/
class OrderServiceTest {
@InjectMocks
private OrderService orderService;
@Mock
private RestTemplateBuilder restTemplateBuilder;
@Mock
private RestTemplate restTemplate;
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
when(restTemplateBuilder.build()).thenReturn(restTemplate);
}
/**
* Test to process the order successfully.
*/
@Test
void testProcessOrder_Success() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
// Act
String result = orderService.processOrder();
// Assert
assertEquals("Order processed successfully", result);
}
/**
* Test to process the order with failure caused by product validation failure.
*/
@Test
void testProcessOrder_FailureWithProductValidationFailure() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(false));
// Act
String result = orderService.processOrder();
// Assert
assertEquals("Order processing failed", result);
}
/**
* Test to process the order with failure caused by payment processing failure.
*/
@Test
void testProcessOrder_FailureWithPaymentProcessingFailure() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(false));
// Act
String result = orderService.processOrder();
// Assert
assertEquals("Order processing failed", result);
}
/**
* Test to validate the product.
*/
@Test
void testValidateProduct() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
// Act
Boolean result = orderService.validateProduct();
// Assert
assertEquals(true, result);
}
/**
* Test to process the payment.
*/
@Test
void testProcessPayment() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
// Act
Boolean result = orderService.processPayment();
// Assert
assertEquals(true, result);
}
/**
* Test to validate the product with ResourceAccessException.
*/
@Test
void testValidateProduct_ResourceAccessException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenThrow(new ResourceAccessException("Service unavailable"));
// Act
Boolean result = orderService.validateProduct();
// Assert
assertEquals(false, result);
}
/**
* Test to validate the product with HttpClientErrorException.
*/
@Test
void testValidateProduct_HttpClientErrorException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenThrow(new HttpClientErrorException(org.springframework.http.HttpStatus.BAD_REQUEST, "Bad request"));
// Act
Boolean result = orderService.validateProduct();
// Assert
assertEquals(false, result);
}
/**
* Test to process the payment with ResourceAccessException.
*/
@Test
void testProcessPayment_ResourceAccessException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenThrow(new ResourceAccessException("Service unavailable"));
// Act
Boolean result = orderService.processPayment();
// Assert
assertEquals(false, result);
}
/**
* Test to process the payment with HttpClientErrorException.
*/
@Test
void testProcessPayment_HttpClientErrorException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenThrow(new HttpClientErrorException(org.springframework.http.HttpStatus.BAD_REQUEST, "Bad request"));
// Act
Boolean result = orderService.processPayment();
// Assert
assertEquals(false, result);
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,11 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Payment Microservice" {
class PaymentController {
+processPayment()
}
}
}
@enduml
@@ -0,0 +1,11 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Payment Microservice" {
class PaymentController {
+processPayment()
}
}
}
@enduml
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
The MIT License
Copyright © 2014-2022 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>microservices-distributed-tracing</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>payment-microservice</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.payment.microservice.com.iluwatar.product.microservice.Main</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,79 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.payment.microservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* With the Microservices pattern, a request often travels through multiple different microservices.
* Tracking the entire request flow across these services can be challenging, especially when trying
* to diagnose performance issues or failures. Distributed tracing addresses this challenge by
* providing end-to-end visibility into the lifecycle of a request as it passes through various
* microservices.
*
* <p>The intent of the Distributed Tracing pattern is to trace a request across different
* microservices, collecting detailed timing data and logs that help in understanding the flow,
* performance bottlenecks, and failure points in a distributed system. Each microservice involved
* in the request contributes to the tracing data, creating a comprehensive view of the request's
* journey.
*
* <p>This implementation demonstrates distributed tracing in a microservices architecture for an
* e-commerce platform. When a customer places an order, the OrderService interacts with
* both the PaymentService to process the payment and the ProductService to check the
* product inventory. Tracing logs are generated for each interaction, and these logs can be
* visualized using Zipkin.
*
* <p>To run Zipkin and view the tracing logs, you can use the following Docker command:
*
* <pre>
* {@code docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin }
* </pre>
*
* <p>Start Zipkin with the command above. Once Zipkin is running, you can
* access the Zipkin UI at <a href="http://localhost:9411">http://localhost:9411</a>
* to view the tracing logs and analyze the request flows across your microservices.
*
* <p>To place an order and generate tracing data, you can use the following curl command:
*
* <pre>
* {@code curl -X POST http://localhost:30300/order -H "Content-Type: application/json" -d '{"orderId": "123"}' }
* </pre>
*
* <p>This command sends a POST request to create an order, which will trigger interactions with the
* payment and product microservices, generating tracing logs that can be viewed in Zipkin.
*
*/
@SpringBootApplication
public class Main {
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
@@ -0,0 +1,53 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.payment.microservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller for handling payment processing requests.
*/
@Slf4j
@RestController
public class PaymentController {
/**
* Processes the payment based on the request.
*
* @param request the request body containing payment information (can be null)
* @return ResponseEntity containing the payment processing result (true)
*/
@PostMapping("/payment/process")
public ResponseEntity<Boolean> payment(@RequestBody(required = false) String request) {
LOGGER.info("Received payment request: {}", request);
boolean result = true;
LOGGER.info("Payment result: {}", result);
return ResponseEntity.ok(result);
}
}
@@ -0,0 +1,32 @@
#
# The MIT License
# Copyright © 2014-2021 Ilkka Seppälä
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
spring.application.name=payment-microservice
server.port=30301
management.tracing.sampling.probability=1
logging.pattern.level=%5p [${spring.zipkin.service.name:${spring.application.name:}},%X{traceId:-},%X{spanId:-}]
management.tracing.propagation.type=w3c
management.tracing.baggage.enabled=true
management.tracing.enabled=true
management.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans
@@ -0,0 +1,39 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.payment.microservice;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
/**
* Application Context loads test
*/
class MainTest {
@Test
void shouldExecuteApplicationWithoutException() {
assertDoesNotThrow(() -> Main.main(new String[]{}));
}
}
@@ -0,0 +1,68 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.payment.microservice;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Payment controller test.
*/
class ProductControllerTest {
private PaymentController paymentController;
@BeforeEach
void setUp() {
paymentController = new PaymentController();
}
/**
* Test to process the payment.
*/
@Test
void testValidateProduct() {
// Arrange
String request = "Sample payment process request";
// Act
ResponseEntity<Boolean> response = paymentController.payment(request);
// Assert
assertEquals(ResponseEntity.ok(true), response);
}
/**
* Test to process the payment with null request.
*/
@Test
void testValidateProductWithNullRequest() {
// Arrange
// Act
ResponseEntity<Boolean> response = paymentController.payment(null);
// Assert
assertEquals(ResponseEntity.ok(true), response);
}
}
+82
View File
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
The MIT License
Copyright © 2014-2022 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>java-design-patterns</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>microservices-distributed-tracing</artifactId>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<type>pom</type>
<version>3.3.1</version>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<modules>
<module>order-microservice</module>
<module>payment-microservice</module>
<module>product-microservice</module>
</modules>
</project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

@@ -0,0 +1,10 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Product Microservice" {
class ProductController {
+validateProduct()
}
}
}
@enduml
@@ -0,0 +1,10 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Product Microservice" {
class ProductController {
+validateProduct()
}
}
}
@enduml
@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
The MIT License
Copyright © 2014-2022 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>microservices-distributed-tracing</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>product-microservice</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.product.com.iluwatar.product.microservice.microservice.Main</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,79 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.product.microservice.microservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* With the Microservices pattern, a request often travels through multiple different microservices.
* Tracking the entire request flow across these services can be challenging, especially when trying
* to diagnose performance issues or failures. Distributed tracing addresses this challenge by
* providing end-to-end visibility into the lifecycle of a request as it passes through various
* microservices.
*
* <p>The intent of the Distributed Tracing pattern is to trace a request across different
* microservices, collecting detailed timing data and logs that help in understanding the flow,
* performance bottlenecks, and failure points in a distributed system. Each microservice involved
* in the request contributes to the tracing data, creating a comprehensive view of the request's
* journey.
*
* <p>This implementation demonstrates distributed tracing in a microservices architecture for an
* e-commerce platform. When a customer places an order, the OrderService interacts with
* both the PaymentService to process the payment and the ProductService to check the
* product inventory. Tracing logs are generated for each interaction, and these logs can be
* visualized using Zipkin.
*
* <p>To run Zipkin and view the tracing logs, you can use the following Docker command:
*
* <pre>
* {@code docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin }
* </pre>
*
* <p>Start Zipkin with the command above. Once Zipkin is running, you can
* access the Zipkin UI at <a href="http://localhost:9411">http://localhost:9411</a>
* to view the tracing logs and analyze the request flows across your microservices.
*
* <p>To place an order and generate tracing data, you can use the following curl command:
*
* <pre>
* {@code curl -X POST http://localhost:30300/order -H "Content-Type: application/json" -d '{"orderId": "123"}' }
* </pre>
*
* <p>This command sends a POST request to create an order, which will trigger interactions with the
* payment and product microservices, generating tracing logs that can be viewed in Zipkin.
*
*/
@SpringBootApplication
public class Main {
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
@@ -0,0 +1,53 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.product.microservice.microservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* Controller for handling product validation requests.
*/
@Slf4j
@RestController
public class ProductController {
/**
* Validates the product based on the request.
*
* @param request the request body containing product information (can be null)
* @return ResponseEntity containing the validation result (true)
*/
@PostMapping("/product/validate")
public ResponseEntity<Boolean> validateProduct(@RequestBody(required = false) String request) {
LOGGER.info("Received product validation request: {}", request);
boolean result = true;
LOGGER.info("Product validation result: {}", result);
return ResponseEntity.ok(result);
}
}
@@ -0,0 +1,33 @@
#
# The MIT License
# Copyright © 2014-2021 Ilkka Seppälä
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
spring.application.name=product-microservice
server.port=30302
management.tracing.sampling.probability=1
logging.pattern.level=%5p [${spring.zipkin.service.name:${spring.application.name:}},%X{traceId:-},%X{spanId:-}]
management.tracing.propagation.type=w3c
management.tracing.baggage.enabled=true
management.tracing.enabled=true
management.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans
@@ -0,0 +1,40 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.product.microservice;
import com.iluwatar.product.microservice.microservice.Main;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
/**
* Application test
*/
class MainTest {
@Test
void shouldExecuteApplicationWithoutException() {
assertDoesNotThrow(() -> Main.main(new String[]{}));
}
}
@@ -0,0 +1,68 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.product.microservice;
import com.iluwatar.product.microservice.microservice.ProductController;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ProductControllerTest {
private ProductController productController;
@BeforeEach
public void setUp() {
productController = new ProductController();
}
/**
* Test to validate the product.
*/
@Test
void testValidateProduct() {
// Arrange
String request = "Sample product validation request";
// Act
ResponseEntity<Boolean> response = productController.validateProduct(request);
// Assert
assertEquals(ResponseEntity.ok(true), response);
}
/**
* Test to validate the product with null request.
*/
@Test
void testValidateProductWithNullRequest() {
// Arrange
// Act
ResponseEntity<Boolean> response = productController.validateProduct(null);
// Assert
assertEquals(ResponseEntity.ok(true), response);
}
}
+1
View File
@@ -216,6 +216,7 @@
<module>server-session</module>
<module>virtual-proxy</module>
<module>function-composition</module>
<module>microservices-distributed-tracing</module>
</modules>
<repositories>
<repository>