diff --git a/catalog-service/src/main/java/com/example/catalogservice/config/logging/LoggingAspect.java b/catalog-service/src/main/java/com/example/catalogservice/config/logging/LoggingAspect.java index 66837d24..f0d30103 100644 --- a/catalog-service/src/main/java/com/example/catalogservice/config/logging/LoggingAspect.java +++ b/catalog-service/src/main/java/com/example/catalogservice/config/logging/LoggingAspect.java @@ -47,8 +47,8 @@ public void springBeanPointcut() { @Pointcut( """ - @within(com.example.inventoryservice.config.logging.Loggable) - || @annotation(com.example.inventoryservice.config.logging.Loggable) + @within(com.example.catalogservice.config.logging.Loggable) + || @annotation(com.example.catalogservice.config.logging.Loggable) """) public void applicationPackagePointcut() { // pointcut definition diff --git a/order-service/pom.xml b/order-service/pom.xml index 1134da62..8b5efe10 100644 --- a/order-service/pom.xml +++ b/order-service/pom.xml @@ -491,7 +491,7 @@ - 1.18.1 + 1.19.2 diff --git a/order-service/src/main/java/com/example/orderservice/config/logging/LogWriter.java b/order-service/src/main/java/com/example/orderservice/config/logging/LogWriter.java new file mode 100644 index 00000000..d2e7d046 --- /dev/null +++ b/order-service/src/main/java/com/example/orderservice/config/logging/LogWriter.java @@ -0,0 +1,26 @@ +/*** +

+ Licensed under MIT License Copyright (c) 2024 Raja Kolli. +

+***/ + +package com.example.inventoryservice.config.logging; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.logging.LogLevel; + +public class LogWriter { + + public static void write(Class originClass, LogLevel logLevel, String message) { + Logger logger = LoggerFactory.getLogger(originClass); + switch (logLevel) { + case TRACE -> logger.trace(message); + case DEBUG -> logger.debug(message); + case INFO -> logger.info(message); + case WARN -> logger.warn(message); + case ERROR, FATAL -> logger.error(message); + default -> logger.warn("No suitable logLevel found"); + } + } +} diff --git a/order-service/src/main/java/com/example/orderservice/config/logging/Loggable.java b/order-service/src/main/java/com/example/orderservice/config/logging/Loggable.java index b9dbb875..c22ddc84 100644 --- a/order-service/src/main/java/com/example/orderservice/config/logging/Loggable.java +++ b/order-service/src/main/java/com/example/orderservice/config/logging/Loggable.java @@ -1,6 +1,6 @@ /***

- Licensed under MIT License Copyright (c) 2021-2022 Raja Kolli. + Licensed under MIT License Copyright (c) 2021-2024 Raja Kolli.

***/ @@ -13,8 +13,16 @@ Licensed under MIT License Copyright (c) 2021-2022 Raja Kolli. import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.Target; +import org.springframework.boot.logging.LogLevel; @Target({TYPE, METHOD}) @Retention(RUNTIME) @Inherited -public @interface Loggable {} +public @interface Loggable { + + boolean params() default true; + + boolean result() default true; + + LogLevel value() default LogLevel.DEBUG; +} diff --git a/order-service/src/main/java/com/example/orderservice/config/logging/LoggingAspect.java b/order-service/src/main/java/com/example/orderservice/config/logging/LoggingAspect.java index 7ffb8952..9c11d284 100644 --- a/order-service/src/main/java/com/example/orderservice/config/logging/LoggingAspect.java +++ b/order-service/src/main/java/com/example/orderservice/config/logging/LoggingAspect.java @@ -1,29 +1,35 @@ /***

- Licensed under MIT License Copyright (c) 2021-2023 Raja Kolli. + Licensed under MIT License Copyright (c) 2021-2024 Raja Kolli.

***/ package com.example.orderservice.config.logging; import com.example.orderservice.utils.AppConstants; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.boot.logging.LogLevel; import org.springframework.core.env.Environment; import org.springframework.core.env.Profiles; import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; @Aspect @Component public class LoggingAspect { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(LoggingAspect.class); private final Environment env; @@ -40,8 +46,10 @@ public void springBeanPointcut() { } @Pointcut( - "@within(com.example.orderservice.config.logging.Loggable) || " - + "@annotation(com.example.orderservice.config.logging.Loggable)") + """ + @within(com.example.orderservice.config.logging.Loggable) + || @annotation(com.example.orderservice.config.logging.Loggable) + """) public void applicationPackagePointcut() { // pointcut definition } @@ -68,22 +76,76 @@ public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { @Around("applicationPackagePointcut()") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { - if (log.isDebugEnabled()) { - log.debug( - "Enter: {}.{}()", - joinPoint.getSignature().getDeclaringTypeName(), - joinPoint.getSignature().getName()); - } + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + Loggable methodAnnotation = method.getAnnotation(Loggable.class); + + Class originClass = joinPoint.getTarget().getClass(); + Loggable classAnnotation = originClass.getAnnotation(Loggable.class); + + // get current log level + + LogLevel logLevel = + methodAnnotation != null ? methodAnnotation.value() : classAnnotation.value(); + + // before + String methodName = method.getName(); + LogWriter.write(originClass, LogLevel.INFO, methodName + "() start execution"); + + printParamsIfEnabled( + joinPoint, + methodSignature.getParameterNames(), + methodAnnotation, + originClass, + classAnnotation, + logLevel, + methodName); + long start = System.currentTimeMillis(); + // Start method execution Object result = joinPoint.proceed(); long end = System.currentTimeMillis(); - if (log.isDebugEnabled()) { - log.debug( - "Exit: {}.{}(). Time taken: {} millis", - joinPoint.getSignature().getDeclaringTypeName(), - joinPoint.getSignature().getName(), - end - start); + + // show results + if (result != null) { + boolean printResponse = + methodAnnotation != null ? methodAnnotation.result() : classAnnotation.result(); + if (printResponse) { + LogWriter.write(originClass, logLevel, methodName + "() Returned : " + result); + } } + + // print results + LogWriter.write( + originClass, + LogLevel.INFO, + methodName + + "() finished execution and took (" + + (end - start) + + ") mills to execute"); return result; } + + private void printParamsIfEnabled( + ProceedingJoinPoint joinPoint, + String[] parameterNames, + Loggable methodAnnotation, + Class originClass, + Loggable classAnnotation, + LogLevel logLevel, + String methodName) { + boolean printParams = + methodAnnotation != null ? methodAnnotation.params() : classAnnotation.params(); + + if (printParams && !ObjectUtils.isEmpty(joinPoint.getArgs())) { + List stringArrayList = new ArrayList<>(); + Object[] args = joinPoint.getArgs(); + + for (int i = 0; i < args.length; i++) { + stringArrayList.add(parameterNames[i] + " : " + args[i]); + } + String argsString = String.join(", ", stringArrayList); + LogWriter.write(originClass, logLevel, methodName + "() args :: -> " + argsString); + } + } } diff --git a/order-service/src/main/java/com/example/orderservice/services/CatalogService.java b/order-service/src/main/java/com/example/orderservice/services/CatalogService.java index ad9ed2b2..22fdf67f 100644 --- a/order-service/src/main/java/com/example/orderservice/services/CatalogService.java +++ b/order-service/src/main/java/com/example/orderservice/services/CatalogService.java @@ -7,6 +7,7 @@ Licensed under MIT License Copyright (c) 2023 Raja Kolli. package com.example.orderservice.services; import com.example.orderservice.config.ApplicationProperties; +import com.example.orderservice.config.logging.Loggable; import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker; import java.util.List; import org.slf4j.Logger; @@ -14,6 +15,7 @@ Licensed under MIT License Copyright (c) 2023 Raja Kolli. import org.springframework.stereotype.Service; @Service +@Loggable public class CatalogService { private final Logger log = LoggerFactory.getLogger(this.getClass()); diff --git a/order-service/src/main/java/com/example/orderservice/services/CatalogServiceProxy.java b/order-service/src/main/java/com/example/orderservice/services/CatalogServiceProxy.java index 5c18f5eb..13ba14c2 100644 --- a/order-service/src/main/java/com/example/orderservice/services/CatalogServiceProxy.java +++ b/order-service/src/main/java/com/example/orderservice/services/CatalogServiceProxy.java @@ -6,6 +6,7 @@ Licensed under MIT License Copyright (c) 2022-2023 Raja Kolli. package com.example.orderservice.services; +import com.example.orderservice.config.logging.Loggable; import java.util.List; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.service.annotation.GetExchange; @@ -13,6 +14,7 @@ Licensed under MIT License Copyright (c) 2022-2023 Raja Kolli. // @HttpExchange("lb://catalog-service/") // @HttpExchange("http://localhost:18080/catalog-service") // @HttpExchange(url = "${application.catalog-service-url}") +@Loggable public interface CatalogServiceProxy { @GetExchange("/api/catalog/exists") diff --git a/order-service/src/main/java/com/example/orderservice/services/KafkaOrderProducer.java b/order-service/src/main/java/com/example/orderservice/services/KafkaOrderProducer.java index 43893606..5c3a5e75 100644 --- a/order-service/src/main/java/com/example/orderservice/services/KafkaOrderProducer.java +++ b/order-service/src/main/java/com/example/orderservice/services/KafkaOrderProducer.java @@ -7,6 +7,7 @@ Licensed under MIT License Copyright (c) 2023 Raja Kolli. package com.example.orderservice.services; import com.example.common.dtos.OrderDto; +import com.example.orderservice.config.logging.Loggable; import com.example.orderservice.utils.AppConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,6 +16,7 @@ Licensed under MIT License Copyright (c) 2023 Raja Kolli. import org.springframework.stereotype.Service; @Service +@Loggable public class KafkaOrderProducer { private final Logger log = LoggerFactory.getLogger(this.getClass()); diff --git a/order-service/src/main/java/com/example/orderservice/services/OrderGeneratorService.java b/order-service/src/main/java/com/example/orderservice/services/OrderGeneratorService.java index 50a2759b..278ad41d 100644 --- a/order-service/src/main/java/com/example/orderservice/services/OrderGeneratorService.java +++ b/order-service/src/main/java/com/example/orderservice/services/OrderGeneratorService.java @@ -6,6 +6,7 @@ Licensed under MIT License Copyright (c) 2022-2024 Raja Kolli. package com.example.orderservice.services; +import com.example.orderservice.config.logging.Loggable; import com.example.orderservice.model.request.OrderItemRequest; import com.example.orderservice.model.request.OrderRequest; import java.math.BigDecimal; @@ -16,6 +17,7 @@ Licensed under MIT License Copyright (c) 2022-2024 Raja Kolli. import org.springframework.stereotype.Service; @Service +@Loggable public class OrderGeneratorService { private static final int NUM_ORDERS = 10_000; diff --git a/order-service/src/main/java/com/example/orderservice/services/OrderKafkaStreamService.java b/order-service/src/main/java/com/example/orderservice/services/OrderKafkaStreamService.java index 34eb8e6f..e8b65802 100644 --- a/order-service/src/main/java/com/example/orderservice/services/OrderKafkaStreamService.java +++ b/order-service/src/main/java/com/example/orderservice/services/OrderKafkaStreamService.java @@ -7,6 +7,7 @@ Licensed under MIT License Copyright (c) 2022-2023 Raja Kolli. package com.example.orderservice.services; import com.example.common.dtos.OrderDto; +import com.example.orderservice.config.logging.Loggable; import com.example.orderservice.utils.AppConstants; import java.util.ArrayList; import java.util.List; @@ -21,6 +22,7 @@ Licensed under MIT License Copyright (c) 2022-2023 Raja Kolli. import org.springframework.stereotype.Service; @Service +@Loggable public class OrderKafkaStreamService { private final Logger log = LoggerFactory.getLogger(this.getClass()); diff --git a/order-service/src/main/java/com/example/orderservice/services/OrderManageService.java b/order-service/src/main/java/com/example/orderservice/services/OrderManageService.java index 37aff19d..193d1260 100644 --- a/order-service/src/main/java/com/example/orderservice/services/OrderManageService.java +++ b/order-service/src/main/java/com/example/orderservice/services/OrderManageService.java @@ -7,6 +7,7 @@ Licensed under MIT License Copyright (c) 2022-2023 Raja Kolli. package com.example.orderservice.services; import com.example.common.dtos.OrderDto; +import com.example.orderservice.config.logging.Loggable; import com.example.orderservice.entities.OrderStatus; import com.example.orderservice.repositories.OrderRepository; import com.example.orderservice.utils.AppConstants; @@ -15,6 +16,7 @@ Licensed under MIT License Copyright (c) 2022-2023 Raja Kolli. import org.springframework.stereotype.Service; @Service +@Loggable public class OrderManageService { private static final String ACCEPT = "ACCEPT"; diff --git a/order-service/src/main/java/com/example/orderservice/web/controllers/OrderController.java b/order-service/src/main/java/com/example/orderservice/web/controllers/OrderController.java index c43f0373..cbb3c58c 100644 --- a/order-service/src/main/java/com/example/orderservice/web/controllers/OrderController.java +++ b/order-service/src/main/java/com/example/orderservice/web/controllers/OrderController.java @@ -7,6 +7,7 @@ Licensed under MIT License Copyright (c) 2021-2024 Raja Kolli. package com.example.orderservice.web.controllers; import com.example.common.dtos.OrderDto; +import com.example.orderservice.config.logging.Loggable; import com.example.orderservice.exception.ProductNotFoundException; import com.example.orderservice.model.request.OrderRequest; import com.example.orderservice.model.response.OrderResponse; @@ -40,6 +41,7 @@ Licensed under MIT License Copyright (c) 2021-2024 Raja Kolli. @RestController @RequestMapping("/api/orders") @Validated +@Loggable public class OrderController implements OrderApi { private static final Logger log = LoggerFactory.getLogger(OrderController.class);