[SCB-1525]print codec error stack (#1349)

* [SCB-1525]print codec error stack
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java
index afdc96b..454ac62 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java
@@ -72,4 +72,6 @@
   public static final String UPLOAD_FILE_SIZE_THRESHOLD = "servicecomb.uploads.fileSizeThreshold";
 
   public static final String PROVIDER_SCAN_REST_CONTROLLER = "servicecomb.provider.rest.scanRestController";
+
+  public static final String PRINT_CODEC_ERROR_MESSGAGE = "servicecomb.codec.printErrorMessage";
 }
diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java
index a1bf32d..24101cc 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java
@@ -22,12 +22,15 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.ws.rs.core.Response.Status;
 
+import org.apache.servicecomb.common.rest.RestConst;
 import org.apache.servicecomb.common.rest.definition.RestOperationMeta;
 import org.apache.servicecomb.common.rest.definition.RestParam;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.netflix.config.DynamicPropertyFactory;
+
 public final class RestCodec {
   private static final Logger LOG = LoggerFactory.getLogger(RestCodec.class);
 
@@ -61,12 +64,19 @@
       try {
         paramValues[idx] = param.getParamProcessor().getValue(request);
       } catch (Exception e) {
-        // Avoid information leak of user input.
-        throw new InvocationException(Status.BAD_REQUEST,
-            String.format("Parameter is not valid for operation [%s]. Parameter is [%s]. Processor is [%s].",
-                restOperation.getOperationMeta().getMicroserviceQualifiedName(),
-                param.getParamName(),
-                param.getParamProcessor().getProcessorType()));
+        // Avoid information leak of user input, and add option for debug use.
+        String message = String.format("Parameter is not valid for operation [%s]. Parameter is [%s]. Processor is [%s].",
+            restOperation.getOperationMeta().getMicroserviceQualifiedName(),
+            param.getParamName(),
+            param.getParamProcessor().getProcessorType());
+        if (DynamicPropertyFactory.getInstance().getBooleanProperty(
+            RestConst.PRINT_CODEC_ERROR_MESSGAGE, false).get()) {
+          LOG.error(message, e);
+          throw new InvocationException(Status.BAD_REQUEST.getStatusCode(), "", message, e);
+        } else {
+          LOG.error("{} Add {}=true to print the details.", message, RestConst.PRINT_CODEC_ERROR_MESSGAGE);
+          throw new InvocationException(Status.BAD_REQUEST, message);
+        }
       }
     }
 
diff --git a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
index 5be9562..5619c15 100644
--- a/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
+++ b/swagger/swagger-invocation/invocation-core/src/main/java/org/apache/servicecomb/swagger/engine/SwaggerProducerOperation.java
@@ -152,15 +152,16 @@
         asyncResp.handle(processException(invocation, ex));
       });
     } catch (IllegalArgumentException ae) {
+      LOGGER.error("Parameters not valid or types not match {},",
+          invocation.getInvocationQualifiedName(), ae);
       invocation.onBusinessMethodFinish();
       invocation.onBusinessFinish();
       asyncResp.handle(processException(invocation,
           new InvocationException(Status.BAD_REQUEST.getStatusCode(), "",
               new CommonExceptionData("Parameters not valid or types not match."), ae)));
-      LOGGER.error("Parameters not valid or types not match {}, "
-              + "debug this line to find the actual decode errors.",
-          invocation.getInvocationQualifiedName());
     } catch (Throwable e) {
+      LOGGER.error("unexpected error {},",
+          invocation.getInvocationQualifiedName(), e);
       invocation.onBusinessMethodFinish();
       invocation.onBusinessFinish();
       asyncResp.handle(processException(invocation, e));
@@ -190,16 +191,17 @@
       invocation.onBusinessMethodFinish();
       invocation.onBusinessFinish();
     } catch (IllegalArgumentException ae) {
+      LOGGER.error("Parameters not valid or types not match {},",
+          invocation.getInvocationQualifiedName(), ae);
       invocation.onBusinessMethodFinish();
       invocation.onBusinessFinish();
       // ae.getMessage() is always null. Give a custom error message.
       response = processException(invocation,
           new InvocationException(Status.BAD_REQUEST.getStatusCode(), "",
               new CommonExceptionData("Parameters not valid or types not match."), ae));
-      LOGGER.error("Parameters not valid or types not match {}, "
-              + "debug this line to find the actual decode errors.",
-          invocation.getInvocationQualifiedName());
     } catch (Throwable e) {
+      LOGGER.error("unexpected error {},",
+          invocation.getInvocationQualifiedName(), e);
       invocation.onBusinessMethodFinish();
       invocation.onBusinessFinish();
       response = processException(invocation, e);