This is an automated email from the ASF dual-hosted git repository. wujimin pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push: new 4546c6d [SCB-2170] add configuration to control log invocation exception stack trace 4546c6d is described below commit 4546c6d6ef7a06e138cd38eb7922537599917977 Author: wujimin <wuji...@huawei.com> AuthorDate: Thu Dec 24 01:40:38 2020 +0800 [SCB-2170] add configuration to control log invocation exception stack trace --- .../servicecomb/core/exception/Exceptions.java | 23 ++++++++++++++-- .../core/invocation/ProducerInvocationFlow.java | 32 ++++++++++++++++++++-- .../core/provider/consumer/InvokerUtils.java | 30 ++++++++++++++++---- core/src/main/resources/microservice.yaml | 3 ++ .../highway/HighwayProducerInvocationFlow.java | 14 +++++++++- 5 files changed, 90 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java b/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java index 51b6e8a..7166d6b 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java @@ -32,6 +32,7 @@ import javax.ws.rs.core.Response.StatusType; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; @@ -39,6 +40,8 @@ import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.netflix.config.DynamicPropertyFactory; + public final class Exceptions { private static final Logger LOGGER = LoggerFactory.getLogger(Exceptions.class); @@ -113,13 +116,24 @@ public final class Exceptions { StatusType genericStatus) { InvocationException invocationException = Exceptions.convert(invocation, exception, genericStatus); if (invocation != null) { - LOGGER.error("failed to process {} invocation, operation={}.", - invocation.getInvocationType(), invocation.getMicroserviceQualifiedName(), invocationException); + logException(invocation, invocationException); } return Response.status(invocationException.getStatus()) .entity(invocationException.getErrorData()); } + private static void logException(@Nonnull Invocation invocation, InvocationException invocationException) { + if (isPrintInvocationStackTrace()) { + LOGGER.error("failed to process {} invocation, operation={}.", + invocation.getInvocationType(), invocation.getMicroserviceQualifiedName(), invocationException); + return; + } + + LOGGER.error("failed to process {} invocation, operation={}, message={}.", + invocation.getInvocationType(), invocation.getMicroserviceQualifiedName(), + ExceptionUtils.getExceptionMessageWithoutTrace(invocationException)); + } + public static InvocationException convert(@Nonnull Invocation invocation, Throwable throwable) { StatusType genericStatus = getGenericStatus(invocation); return convert(invocation, throwable, genericStatus); @@ -141,4 +155,9 @@ public final class Exceptions { throw new IllegalStateException("never happened: can not find converter for " + throwable.getClass().getName()); } + + public static boolean isPrintInvocationStackTrace() { + return DynamicPropertyFactory.getInstance() + .getBooleanProperty("servicecomb.exception.invocation.print-stack-trace", false).get(); + } } diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java b/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java index 847936d..93af06c 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java @@ -19,6 +19,7 @@ package org.apache.servicecomb.core.invocation; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.Exceptions; import org.apache.servicecomb.foundation.common.utils.AsyncUtils; +import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.Response; @@ -68,18 +69,43 @@ public abstract class ProducerInvocationFlow { private void finishInvocation(Invocation invocation, Response response, Throwable throwable) { invocation.onFinish(response); + tryLogException(invocation, throwable); + } + + private void tryLogException(Invocation invocation, Throwable throwable) { if (throwable == null) { return; } throwable = Exceptions.unwrap(throwable); if (requestEx == null) { - LOGGER.error("Failed to finish invocation, operation:{}", invocation.getMicroserviceQualifiedName(), throwable); + logException(invocation, throwable); + return; + } + + logException(invocation, requestEx, throwable); + } + + private void logException(Invocation invocation, Throwable throwable) { + if (Exceptions.isPrintInvocationStackTrace()) { + LOGGER.error("Failed to finish invocation, operation:{}.", invocation.getMicroserviceQualifiedName(), throwable); + return; + } + + LOGGER.error("Failed to finish invocation, operation:{}, message={}.", invocation.getMicroserviceQualifiedName(), + ExceptionUtils.getExceptionMessageWithoutTrace(throwable)); + } + + private void logException(Invocation invocation, HttpServletRequestEx requestEx, Throwable throwable) { + if (Exceptions.isPrintInvocationStackTrace()) { + LOGGER.error("Failed to finish invocation, operation:{}, request uri:{}.", + invocation.getMicroserviceQualifiedName(), requestEx.getRequestURI(), throwable); return; } - LOGGER.error("Failed to finish invocation, operation:{}, request uri:{}", - invocation.getMicroserviceQualifiedName(), requestEx.getRequestURI(), throwable); + LOGGER.error("Failed to finish invocation, operation:{}, request uri:{}, message={}.", + invocation.getMicroserviceQualifiedName(), requestEx.getRequestURI(), + ExceptionUtils.getExceptionMessageWithoutTrace(throwable)); } protected abstract Invocation sendCreateInvocationException(Throwable throwable); diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java index b804f36..c14cc24 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java @@ -33,6 +33,7 @@ import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.core.exception.Exceptions; import org.apache.servicecomb.core.invocation.InvocationFactory; +import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; import org.apache.servicecomb.swagger.invocation.AsyncResponse; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; @@ -229,18 +230,35 @@ public final class InvokerUtils { return invocation.getMicroserviceMeta().getFilterChain() .onFilter(invocation) .exceptionally(throwable -> convertException(invocation, throwable)) - .whenComplete((response, throwable) -> processMetrics(invocation, response)); + .whenComplete((response, throwable) -> finishInvocation(invocation, response, throwable)); } private static Response convertException(Invocation invocation, Throwable throwable) { - InvocationException invocationException = Exceptions.convert(invocation, throwable); + throw Exceptions.convert(invocation, throwable); + } + + private static void finishInvocation(Invocation invocation, Response response, Throwable throwable) { + processMetrics(invocation, response); + tryLogException(invocation, throwable); + } + + private static void tryLogException(Invocation invocation, Throwable throwable) { + if (throwable == null) { + return; + } + + if (Exceptions.isPrintInvocationStackTrace()) { + LOGGER.error("failed to invoke {}, endpoint={}.", + invocation.getMicroserviceQualifiedName(), + invocation.getEndpoint(), + throwable); + return; + } - LOGGER.error("failed to invoke {}, endpoint={}.", + LOGGER.error("failed to invoke {}, endpoint={}, message={}.", invocation.getMicroserviceQualifiedName(), invocation.getEndpoint(), - invocationException); - - throw invocationException; + ExceptionUtils.getExceptionMessageWithoutTrace(throwable)); } private static void processMetrics(Invocation invocation, Response response) { diff --git a/core/src/main/resources/microservice.yaml b/core/src/main/resources/microservice.yaml index 8b505cd..969e8ab 100644 --- a/core/src/main/resources/microservice.yaml +++ b/core/src/main/resources/microservice.yaml @@ -18,6 +18,9 @@ servicecomb-config-order: -500 servicecomb: + exception: + invocation: + print-stack-trace: false filter-chains: enabled: false transport: diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayProducerInvocationFlow.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayProducerInvocationFlow.java index 13f8204..36e0af5 100644 --- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayProducerInvocationFlow.java +++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayProducerInvocationFlow.java @@ -17,8 +17,10 @@ package org.apache.servicecomb.transport.highway; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.exception.Exceptions; import org.apache.servicecomb.core.invocation.InvocationCreator; import org.apache.servicecomb.core.invocation.ProducerInvocationFlow; +import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; import org.apache.servicecomb.foundation.vertx.tcp.TcpConnection; import org.apache.servicecomb.swagger.invocation.Response; import org.slf4j.Logger; @@ -39,10 +41,20 @@ public class HighwayProducerInvocationFlow extends ProducerInvocationFlow { @Override protected Invocation sendCreateInvocationException(Throwable throwable) { - LOGGER.error("Failed to prepare invocation, msgId={}", msgId, throwable); + logException(throwable); return null; } + private void logException(Throwable throwable) { + if (Exceptions.isPrintInvocationStackTrace()) { + LOGGER.error("Failed to prepare invocation, msgId={}.", msgId, throwable); + return; + } + + LOGGER.error("Failed to prepare invocation, msgId={}, message={}.", msgId, + ExceptionUtils.getExceptionMessageWithoutTrace(throwable)); + } + @Override protected void sendResponse(Invocation invocation, Response response) { HighwayTransportContext transportContext = invocation.getTransportContext();