You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by my...@apache.org on 2018/01/22 15:10:34 UTC

[fineract-cn-command] 04/08: Added optional logging for command handlers. Default is off.

This is an automated email from the ASF dual-hosted git repository.

myrle pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-command.git

commit dfe6e1fe49756fd444b8c8b1981fccfe0bd3cc4f
Author: myrle-krantz <mk...@mifos.org>
AuthorDate: Wed May 31 13:18:14 2017 +0200

    Added optional logging for command handlers.  Default is off.
---
 .../core/command/annotation/CommandHandler.java    |  9 ++---
 .../{CommandHandler.java => CommandLogLevel.java}  | 22 +++++++-----
 .../core/command/domain/CommandHandlerHolder.java  | 20 ++++++++++-
 .../io/mifos/core/command/internal/CommandBus.java | 40 ++++++++++++++++++++--
 4 files changed, 73 insertions(+), 18 deletions(-)

diff --git a/src/main/java/io/mifos/core/command/annotation/CommandHandler.java b/src/main/java/io/mifos/core/command/annotation/CommandHandler.java
index 8b57ae3..e1db3e3 100644
--- a/src/main/java/io/mifos/core/command/annotation/CommandHandler.java
+++ b/src/main/java/io/mifos/core/command/annotation/CommandHandler.java
@@ -15,15 +15,12 @@
  */
 package io.mifos.core.command.annotation;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+import java.lang.annotation.*;
 
 @Retention(RetentionPolicy.RUNTIME)
 @Target(ElementType.METHOD)
 @Documented
 public @interface CommandHandler {
-
+  CommandLogLevel logStart() default CommandLogLevel.NONE;
+  CommandLogLevel logFinish() default CommandLogLevel.NONE;
 }
diff --git a/src/main/java/io/mifos/core/command/annotation/CommandHandler.java b/src/main/java/io/mifos/core/command/annotation/CommandLogLevel.java
similarity index 67%
copy from src/main/java/io/mifos/core/command/annotation/CommandHandler.java
copy to src/main/java/io/mifos/core/command/annotation/CommandLogLevel.java
index 8b57ae3..c042c86 100644
--- a/src/main/java/io/mifos/core/command/annotation/CommandHandler.java
+++ b/src/main/java/io/mifos/core/command/annotation/CommandLogLevel.java
@@ -15,15 +15,19 @@
  */
 package io.mifos.core.command.annotation;
 
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+/**
+ * @author Myrle Krantz
+ */
+public enum CommandLogLevel {
+
+  INFO("INFO"), DEBUG("DEBUG"), TRACE("TRACE"), NONE("TRACE");
 
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-@Documented
-public @interface CommandHandler {
+  private final String strVal;
 
+  CommandLogLevel(final String strVal) {
+    this.strVal = strVal;
+  }
+  public String toString() {
+    return strVal;
+  }
 }
diff --git a/src/main/java/io/mifos/core/command/domain/CommandHandlerHolder.java b/src/main/java/io/mifos/core/command/domain/CommandHandlerHolder.java
index a0d4efa..33a08b5 100644
--- a/src/main/java/io/mifos/core/command/domain/CommandHandlerHolder.java
+++ b/src/main/java/io/mifos/core/command/domain/CommandHandlerHolder.java
@@ -16,8 +16,10 @@
 package io.mifos.core.command.domain;
 
 import io.mifos.core.command.annotation.EventEmitter;
+import io.mifos.core.lang.TenantContextHolder;
 
 import java.lang.reflect.Method;
+import java.util.function.Consumer;
 
 public final class CommandHandlerHolder {
 
@@ -25,14 +27,20 @@ public final class CommandHandlerHolder {
   private final Method method;
   private final EventEmitter eventEmitter;
   private final Class<?>[] exceptionTypes;
+  private final Consumer<Object> logStart;
+  private final Consumer<Object> logFinish;
 
   public CommandHandlerHolder(final Object aggregate, final Method method, final EventEmitter eventEmitter,
-                              final Class<?>[] exceptionTypes) {
+                              final Class<?>[] exceptionTypes,
+                              final Consumer<Object> logStart,
+                              final Consumer<Object> logFinish) {
     super();
     this.aggregate = aggregate;
     this.method = method;
     this.eventEmitter = eventEmitter;
     this.exceptionTypes = exceptionTypes;
+    this.logStart = logStart;
+    this.logFinish = logFinish;
   }
 
   public Object aggregate() {
@@ -50,4 +58,14 @@ public final class CommandHandlerHolder {
   public Class<?>[] exceptionTypes() {
     return exceptionTypes;
   }
+
+  @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
+  public void logStart(final Object command) {
+    logStart.accept(command);
+  }
+
+  @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
+  public void logFinish(final Object command) {
+    logFinish.accept(command);
+  }
 }
diff --git a/src/main/java/io/mifos/core/command/internal/CommandBus.java b/src/main/java/io/mifos/core/command/internal/CommandBus.java
index 73466f7..a460be8 100644
--- a/src/main/java/io/mifos/core/command/internal/CommandBus.java
+++ b/src/main/java/io/mifos/core/command/internal/CommandBus.java
@@ -19,6 +19,7 @@ import com.google.gson.Gson;
 import io.mifos.core.cassandra.core.TenantAwareEntityTemplate;
 import io.mifos.core.command.annotation.Aggregate;
 import io.mifos.core.command.annotation.CommandHandler;
+import io.mifos.core.command.annotation.CommandLogLevel;
 import io.mifos.core.command.annotation.EventEmitter;
 import io.mifos.core.command.domain.CommandHandlerHolder;
 import io.mifos.core.command.domain.CommandProcessingException;
@@ -49,6 +50,7 @@ import java.util.Date;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Future;
+import java.util.function.Consumer;
 
 @Component
 public class CommandBus implements ApplicationContextAware {
@@ -83,8 +85,13 @@ public class CommandBus implements ApplicationContextAware {
     CommandHandlerHolder commandHandlerHolder = null;
     try {
       commandHandlerHolder = this.findCommandHandler(command);
+      commandHandlerHolder.logStart(command);
+
       final Object result = commandHandlerHolder.method().invoke(commandHandlerHolder.aggregate(), command);
       this.updateCommandSource(commandSource, null);
+
+      commandHandlerHolder.logFinish(result);
+
       if (commandHandlerHolder.eventEmitter() != null) {
         this.fireEvent(result, commandHandlerHolder.eventEmitter());
       }
@@ -103,9 +110,13 @@ public class CommandBus implements ApplicationContextAware {
     try {
       // find command handling method
       commandHandlerHolder = this.findCommandHandler(command);
+      commandHandlerHolder.logStart(command);
+
       final Object result = commandHandlerHolder.method().invoke(commandHandlerHolder.aggregate(), command);
       this.updateCommandSource(commandSource, null);
 
+      commandHandlerHolder.logFinish(result);
+
       if (commandHandlerHolder.eventEmitter() != null) {
         this.fireEvent(result, commandHandlerHolder.eventEmitter());
       }
@@ -136,17 +147,42 @@ public class CommandBus implements ApplicationContextAware {
   CommandHandlerHolder getCommandHandlerMethodFromClass(final Class<?> commandClass, final Object aggregate) {
     final Method[] methods = aggregate.getClass().getDeclaredMethods();
     for (final Method method : methods) {
-      if (AnnotationUtils.findAnnotation(method, CommandHandler.class) != null
+      final CommandHandler commandHandlerAnnotation = AnnotationUtils.findAnnotation(method, CommandHandler.class);
+      if (commandHandlerAnnotation != null
           && method.getParameterCount() == 1
           && method.getParameterTypes()[0].isAssignableFrom(commandClass)) {
         this.logger.debug("CommandBus::findCommandHandler added method for {}.", commandClass.getSimpleName());
+
+        //Note that as much of the logic of determining how to log as possible is moved into the creation of the
+        //handler holder rather than performing it in the process of handling the command.  Creation of the command
+        //handler holder is not performance critical, but execution of the command is.
+        final Consumer<Object> logStart = getLogHandler(commandHandlerAnnotation.logStart(),
+                "Handling command of type " + commandClass.getCanonicalName() + " for tenant {}, -> command {}");
+
+        final Consumer<Object> logFinish = getLogHandler(commandHandlerAnnotation.logFinish(),
+                "Handled command of type " + commandClass.getCanonicalName() + " for tenant {}, -> result {}");
+
         return new CommandHandlerHolder(aggregate, method, AnnotationUtils.findAnnotation(method, EventEmitter.class),
-            method.getExceptionTypes());
+            method.getExceptionTypes(), logStart, logFinish);
       }
     }
     return null;
   }
 
+  private Consumer<Object> getLogHandler(final CommandLogLevel level, final String formatString) {
+    switch (level) {
+      case INFO:
+        return (x) -> logger.info(formatString, TenantContextHolder.identifier().orElse("none"), x);
+      case DEBUG:
+        return (x) -> logger.debug(formatString, TenantContextHolder.identifier().orElse("none"), x);
+      case TRACE:
+        return (x) -> logger.trace(formatString, TenantContextHolder.identifier().orElse("none"), x);
+      default:
+      case NONE:
+        return (x) -> { };
+    }
+  }
+
   private <C> CommandSource storeCommand(final C command) {
     this.logger.debug("CommandBus::storeCommand called.");
     final LocalDateTime now = LocalDateTime.now();

-- 
To stop receiving notification emails like this one, please contact
myrle@apache.org.