diff --git a/pluto-server/pom.xml b/pluto-server/pom.xml index e1839ad91d257a61a586f8d38b449d45b1573463..8400a8cd69f473d7705a9e7c9159a1b7be47a78f 100644 --- a/pluto-server/pom.xml +++ b/pluto-server/pom.xml @@ -77,6 +77,16 @@ <artifactId>spring-boot-starter-validation</artifactId> </dependency> + <!-- aspectJ --> + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjweaver</artifactId> + </dependency> + <dependency> + <groupId>org.aspectj</groupId> + <artifactId>aspectjrt</artifactId> + </dependency> + <!-- Tools --> <dependency> @@ -158,11 +168,6 @@ <artifactId>junit-jupiter-params</artifactId> <scope>test</scope> </dependency> -<!-- <dependency> --> -<!-- <groupId>de.flapdoodle.embed</groupId> --> -<!-- <artifactId>de.flapdoodle.embed.mongo</artifactId> --> -<!-- <scope>test</scope> --> -<!-- </dependency> --> <dependency> <groupId>org.testcontainers</groupId> @@ -179,9 +184,9 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> - <image> - <builder>paketobuildpacks/builder:0.1.111-base</builder> - </image> + <image> + <builder>paketobuildpacks/builder:0.1.111-base</builder> + </image> </configuration> <executions> <execution> diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java index c84033620f6c9a3b346bc6175a6e97b1cbc3ec04..6f928aad7cabf4a1498882a5c288853f7d7c7aad 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/PlutoServerApplication.java @@ -4,10 +4,12 @@ import java.util.TimeZone; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication(scanBasePackages = "de.itvsh.ozg") @EnableAsync +@EnableAspectJAutoProxy(proxyTargetClass = true) public class PlutoServerApplication { public static void main(String[] args) { diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/AspectLoggingUtils.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/AspectLoggingUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..a8f758d4d7c25020bc88b55daa681f48bdf9ce66 --- /dev/null +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/AspectLoggingUtils.java @@ -0,0 +1,150 @@ +package de.itvsh.ozg.pluto.common.logging; + +import java.util.Collection; +import java.util.StringJoiner; + +import org.apache.commons.lang3.ArrayUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.reflect.MethodSignature; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.itvsh.ozg.pluto.common.datatypes.StringBasedValue; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +public class AspectLoggingUtils { + + private static final String LOGGING_TEMPLATE = "%s: %s"; + + private static final String LOGGING_CALL_TEMPLATE = "%s(%s)"; + private static final String LOGGING_RESULT_TEMPLATE = "%s => %s"; + + private AspectLoggingUtils() { + } + + static void log(final JoinPoint joinPoint) { + try { + MethodSignature sig = (MethodSignature) joinPoint.getSignature(); + var log = getLogger(joinPoint); + if (log.isDebugEnabled()) { + log.debug(String.format(LOGGING_CALL_TEMPLATE, sig.getName(), formatDebuggingParameter(joinPoint))); + } else { + log.info(String.format(LOGGING_CALL_TEMPLATE, sig.getName(), formatInfoParameters(joinPoint))); + } + } catch (RuntimeException e) { + LOG.error("Error on generating log output for " + joinPoint, e); + } + } + + static void logException(JoinPoint joinPoint, Exception exception) { + try { + var log = getLogger(joinPoint); + if (log.isWarnEnabled()) { + log.warn(String.format(LOGGING_TEMPLATE, exception.getClass().getSimpleName(), exception.getMessage())); + } + if (log.isDebugEnabled()) { + log.debug(exception.getMessage(), exception); + } + } catch (RuntimeException e) { + LOG.error("Error on generating log on exception.", e); + LOG.error("Original exception log", exception); + } + } + + static void logReturnValue(JoinPoint joinPoint, Object returnValue) { + try { + + MethodSignature sig = (MethodSignature) joinPoint.getSignature(); + var log = getLogger(joinPoint); + if (log.isInfoEnabled()) { + log.info(String.format(LOGGING_RESULT_TEMPLATE, sig.getName(), + sig.getReturnType() == Void.TYPE ? "<Void>" : formatInfoParameter(returnValue))); + } + } catch (RuntimeException e) { + LOG.error("Error on generating log for returnValue.", e); + } + } + + private static Logger getLogger(final JoinPoint joinPoint) { + return LoggerFactory.getLogger(joinPoint.getSignature().getDeclaringType()); + } + + private static String formatInfoParameters(final JoinPoint joinPoint) { + String[] paramNames = getSignature(joinPoint).getParameterNames(); + Object[] paramValues = joinPoint.getArgs(); + + var stringJoiner = new StringJoiner(", "); + + for (int n = 0; n < paramValues.length; n++) { + if (paramNames != null) { + stringJoiner.add(String.format(LOGGING_TEMPLATE, paramNames[n], formatInfoParameter(paramValues[n]))); + } else { + stringJoiner.add(formatInfoParameter(paramValues[n])); + } + } + + return stringJoiner.toString(); + } + + private static String formatInfoParameter(Object value) { + if (value != null && printValueOnInfoLevel(value.getClass())) { + return formatParameter(value); + } else if (value != null) { + var sb = new StringBuilder(); + sb.append("<").append(value.getClass().getSimpleName()); + if (value.getClass().isArray()) { + sb.deleteCharAt(sb.length() - 1); + try { + sb.append(ArrayUtils.getLength(value)).append("]"); + } catch (ClassCastException e) { + e.printStackTrace(); + System.out.println(value.getClass().getSimpleName()); + } + } + sb.append(">"); + return sb.toString(); + } else { + return "-null-"; + } + } + + private static boolean printValueOnInfoLevel(Class<?> paramClass) { + return paramClass.isPrimitive() || // + StringBasedValue.class.isAssignableFrom(paramClass) || // + String.class.isAssignableFrom(paramClass) || // + Number.class.isAssignableFrom(paramClass); + } + + private static String formatDebuggingParameter(final JoinPoint joinPoint) { + String[] paramNames = getSignature(joinPoint).getParameterNames(); + Object[] paramValues = joinPoint.getArgs(); + + var sb = new StringBuilder(); + for (int n = 0; n < paramValues.length; n++) { + if (n > 0) { + sb.append(", "); + } + if (paramNames != null) { + sb.append(paramNames[n]).append(": "); + } + sb.append(formatParameter(paramValues[n])); + } + return sb.toString(); + } + + private static String formatParameter(final Object param) { + if (param == null) { + return "NULL"; + } + if (Collection.class.isAssignableFrom(param.getClass())) { + return "Collection with size " + ((Collection<?>) param).size(); + } else { + return param.toString(); + } + } + + private static MethodSignature getSignature(final JoinPoint joinPoint) { + return (MethodSignature) joinPoint.getSignature(); + } +} \ No newline at end of file diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/AspectPointcuts.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/AspectPointcuts.java new file mode 100644 index 0000000000000000000000000000000000000000..5d538fc9cd01f770e280677e36a16168d49962d8 --- /dev/null +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/AspectPointcuts.java @@ -0,0 +1,31 @@ +package de.itvsh.ozg.pluto.common.logging; + +import org.aspectj.lang.annotation.Pointcut; + +public class AspectPointcuts { + + @Pointcut("execution(public * *(..))") + void anyPublicMethods() { + // aspect pointcut - no implementation needed + } + + @Pointcut("within(de.itvsh.ozg..*)") + void anythingInBMS() { + // aspect pointcut - no implementation needed + } + + @Pointcut("anyPublicMethods() && anythingInBMS()") + void anyPublicMethodInBMS() { + // aspect pointcut - no implementation needed + } + + @Pointcut("anyPublicMethodInBMS() && @target(org.springframework.stereotype.Service)") + void anyPublicServiceMethod() { + // aspect pointcut - no implementation needed + } + + @Pointcut("execution(public * org.springframework.data.repository.Repository+.*(..))") + void anyPublicRepositoryMethod() { + // aspect pointcut - no implementation needed + } +} diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/KopLoggingAspect.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/KopLoggingAspect.java new file mode 100644 index 0000000000000000000000000000000000000000..7b826323d83e6c4d0b25586bd32a286014e9c142 --- /dev/null +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/common/logging/KopLoggingAspect.java @@ -0,0 +1,33 @@ +package de.itvsh.ozg.pluto.common.logging; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.springframework.stereotype.Component; + +@Aspect +@Component +public class KopLoggingAspect extends AspectPointcuts { + + @Before("anyPublicServiceMethod()") + public void onServiceMethod(JoinPoint joinPoint) { + AspectLoggingUtils.log(joinPoint); + } + + @Before("anyPublicRepositoryMethod()") + public void onRepositoryMethod(JoinPoint joinPoint) { + AspectLoggingUtils.log(joinPoint); + } + + @AfterThrowing(pointcut = "anyPublicServiceMethod()", throwing = "ex") + public void afterExceptionInServiceMethod(JoinPoint joinPoint, Exception ex) { + AspectLoggingUtils.logException(joinPoint, ex); + } + + @AfterReturning(pointcut = "anyPublicServiceMethod()", returning = "returnValue") + public void afterServiceMethod(JoinPoint joinPoint, Object returnValue) { + AspectLoggingUtils.logReturnValue(joinPoint, returnValue); + } +} diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Eingang.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Eingang.java index e1c899a63d345e045a1c4d765c28b4d8473c2062..af91a253b2f52ebaf66044af0279f8ccecd4fd71 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Eingang.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/Eingang.java @@ -8,13 +8,15 @@ import lombok.Getter; import lombok.Singular; import lombok.ToString; -@ToString(exclude = { "formData" }) +@ToString(onlyExplicitlyIncluded = true) @Getter @Builder public class Eingang { + @ToString.Include private String id; + @ToString.Include private EingangHeader header; private Antragsteller antragsteller; diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeader.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeader.java index d278df228bd57108a6b10c0cd863f19952cf4998..171a3472896ff6acf1a828b8251ce42665a30be9 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeader.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/EingangHeader.java @@ -15,6 +15,7 @@ public class EingangHeader { private ZonedDateTime createdAt; private String formId; private String formName; + private String sender; private String customer; private String customerId; diff --git a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangService.java b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangService.java index 9667f2982f0fc769730fe5379143728b9056eeac..1675c321086194be2d8f83add1e17071df8ad728 100644 --- a/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangService.java +++ b/pluto-server/src/main/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangService.java @@ -28,7 +28,6 @@ class GrpcVorgangService extends VorgangServiceGrpc.VorgangServiceImplBase { @Override public void createVorgang(GrpcCreateVorgangRequest request, StreamObserver<GrpcCreateVorgangResponse> responseObserver) { Eingang eingang = eingangMapper.fromGrpc(request.getEingang()); - LOG.info(eingang); vorgangService.createVorgang(eingang); diff --git a/pluto-server/src/main/resources/application.yml b/pluto-server/src/main/resources/application.yml index e704319e106313b34155d57050b4dabd3c8e6526..8f51cae4e6ee81a1465a757e59fa6253c90b1d09 100644 --- a/pluto-server/src/main/resources/application.yml +++ b/pluto-server/src/main/resources/application.yml @@ -26,11 +26,12 @@ pluto: management: server: port: 8081 + health: + livenessState: + enabled: true + readinessState: + enabled: true endpoint: health: probes.enabled: true - livenessState: - enabled: true - readinessState: - enabled: true diff --git a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangServiceITCase.java b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangITCase.java similarity index 98% rename from pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangServiceITCase.java rename to pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangITCase.java index c6f356864928cc9c3e916f6261a92d5bdeab16fa..cdda1f93513ba361d6001997aab25af3095d3d82 100644 --- a/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/GrpcVorgangServiceITCase.java +++ b/pluto-server/src/test/java/de/itvsh/ozg/pluto/vorgang/VorgangITCase.java @@ -14,7 +14,7 @@ import de.itvsh.ozg.pluto.common.grpc.StreamRecorder; import de.itvsh.ozg.pluto.common.test.DataITCase; @DataITCase -class GrpcVorgangServiceITCase { +class VorgangITCase { @Autowired private GrpcVorgangService service; diff --git a/pluto-server/src/test/resources/application-itcase.yml b/pluto-server/src/test/resources/application-itcase.yml index f7f501a6cc3ddeaa7bc8659b95c66852bca59544..d3e6686d9c8a22a245fe9de22ca9f5edb5d2b2a7 100644 --- a/pluto-server/src/test/resources/application-itcase.yml +++ b/pluto-server/src/test/resources/application-itcase.yml @@ -1,6 +1,7 @@ logging: level: - ROOT: ERROR + ROOT: ERROR, + '[de.itvsh]': WARN grpc: server: