From b06a407ebdf5b93d3cb30adec6b174a4e311e47d Mon Sep 17 00:00:00 2001 From: Jens Schulze Date: Fri, 12 Jan 2024 10:08:18 +0100 Subject: [PATCH] add option to customise log formats --- .../api/defaultconfig/ApiRootBuilder.java | 9 +++++ .../defaultconfig/HistoryApiRootBuilder.java | 9 +++++ .../defaultconfig/ImportApiRootBuilder.java | 9 +++++ .../com/commercetools/docs/meta/Logging.java | 4 ++- .../vrap/rmf/base/client/ClientBuilder.java | 18 ++++++++++ .../base/client/http/ErrorLogFormatter.java | 9 +++++ .../client/http/InternalLoggerMiddleware.java | 8 +++++ .../http/InternalLoggerMiddlewareImpl.java | 33 ++++++++++--------- .../rmf/base/client/http/LogFormatter.java | 23 +++++++++++++ .../client/http/ResponseLogFormatter.java | 10 ++++++ 10 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ErrorLogFormatter.java create mode 100644 rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/LogFormatter.java create mode 100644 rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ResponseLogFormatter.java diff --git a/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/defaultconfig/ApiRootBuilder.java b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/defaultconfig/ApiRootBuilder.java index 872b24f0971..c1896008d7f 100644 --- a/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/defaultconfig/ApiRootBuilder.java +++ b/commercetools/commercetools-sdk-java-api/src/main/java/com/commercetools/api/defaultconfig/ApiRootBuilder.java @@ -655,6 +655,15 @@ public ApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactory inte deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents)); } + public ApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactory internalLoggerFactory, + final Level responseLogEvent, final Level deprecationLogEvent, final Level defaultExceptionLogEvent, + final Map, Level> exceptionLogEvents, + final ResponseLogFormatter responseLogFormatter, final ErrorLogFormatter errorLogFormatter) { + return with(clientBuilder -> clientBuilder.withInternalLoggerFactory(internalLoggerFactory, responseLogEvent, + deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents, responseLogFormatter, + errorLogFormatter)); + } + public ApiRootBuilder withApiBaseUrl(String apiBaseUrl) { return with(clientBuilder -> clientBuilder.withApiBaseUrl(apiBaseUrl)); } diff --git a/commercetools/commercetools-sdk-java-history/src/main/java/com/commercetools/history/defaultconfig/HistoryApiRootBuilder.java b/commercetools/commercetools-sdk-java-history/src/main/java/com/commercetools/history/defaultconfig/HistoryApiRootBuilder.java index 63932e05745..1576529702d 100644 --- a/commercetools/commercetools-sdk-java-history/src/main/java/com/commercetools/history/defaultconfig/HistoryApiRootBuilder.java +++ b/commercetools/commercetools-sdk-java-history/src/main/java/com/commercetools/history/defaultconfig/HistoryApiRootBuilder.java @@ -389,6 +389,15 @@ public HistoryApiRootBuilder withInternalLoggerFactory(final InternalLoggerFacto return this; } + public HistoryApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactory internalLoggerFactory, + final Level responseLogEvent, final Level deprecationLogEvent, final Level defaultExceptionLogEvent, + final Map, Level> exceptionLogEvents, + final ResponseLogFormatter responseLogFormatter, final ErrorLogFormatter errorLogFormatter) { + return with(clientBuilder -> clientBuilder.withInternalLoggerFactory(internalLoggerFactory, responseLogEvent, + deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents, responseLogFormatter, + errorLogFormatter)); + } + public HistoryApiRootBuilder withApiBaseUrl(String apiBaseUrl) { builder.withApiBaseUrl(apiBaseUrl); diff --git a/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/defaultconfig/ImportApiRootBuilder.java b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/defaultconfig/ImportApiRootBuilder.java index b109aee9ab7..4fb6226deb9 100644 --- a/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/defaultconfig/ImportApiRootBuilder.java +++ b/commercetools/commercetools-sdk-java-importapi/src/main/java/com/commercetools/importapi/defaultconfig/ImportApiRootBuilder.java @@ -389,6 +389,15 @@ public ImportApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactor return this; } + public ImportApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactory internalLoggerFactory, + final Level responseLogEvent, final Level deprecationLogEvent, final Level defaultExceptionLogEvent, + final Map, Level> exceptionLogEvents, + final ResponseLogFormatter responseLogFormatter, final ErrorLogFormatter errorLogFormatter) { + return with(clientBuilder -> clientBuilder.withInternalLoggerFactory(internalLoggerFactory, responseLogEvent, + deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents, responseLogFormatter, + errorLogFormatter)); + } + public ImportApiRootBuilder withApiBaseUrl(String apiBaseUrl) { builder.withApiBaseUrl(apiBaseUrl); diff --git a/commercetools/internal-docs/src/main/java/com/commercetools/docs/meta/Logging.java b/commercetools/internal-docs/src/main/java/com/commercetools/docs/meta/Logging.java index 7fc53774d06..359f57361c1 100644 --- a/commercetools/internal-docs/src/main/java/com/commercetools/docs/meta/Logging.java +++ b/commercetools/internal-docs/src/main/java/com/commercetools/docs/meta/Logging.java @@ -3,7 +3,9 @@ import java.util.Map; +import io.vrap.rmf.base.client.http.ErrorLogFormatter; import io.vrap.rmf.base.client.http.InternalLoggerFactory; +import io.vrap.rmf.base.client.http.ResponseLogFormatter; import org.slf4j.event.Level; @@ -17,7 +19,7 @@ * *

The {@link io.vrap.rmf.base.client.ClientBuilder} allows the customization of the log levels used for different events. By default responses * will be logged with {@link org.slf4j.event.Level#INFO} and errors with {@link org.slf4j.event.Level#ERROR}. The - * {@link io.vrap.rmf.base.client.ClientBuilder#withInternalLoggerFactory(InternalLoggerFactory, Level, Level, Level, Map)} method can be used + * {@link io.vrap.rmf.base.client.ClientBuilder#withInternalLoggerFactory(InternalLoggerFactory, Level, Level, Level, Map, ResponseLogFormatter, ErrorLogFormatter)} method can be used * to change these defaults. Please see also {@link io.vrap.rmf.base.client.http.InternalLoggerMiddleware} for further details

* * {@include.example example.ExamplesTest#loggingConfiguration} diff --git a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/ClientBuilder.java b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/ClientBuilder.java index b24025bcabd..e03eaf7a942 100644 --- a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/ClientBuilder.java +++ b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/ClientBuilder.java @@ -1381,6 +1381,24 @@ public ClientBuilder withInternalLoggerFactory(final InternalLoggerFactory inter deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents)); } + /** + * @param internalLoggerFactory {@link InternalLoggerFactory} creates the logger for request & responses + * @param responseLogEvent {@link Level} for logging responses. + * @param deprecationLogEvent {@link Level} for logging {@link ApiHttpHeaders#X_DEPRECATION_NOTICE} + * @param defaultExceptionLogEvent {@link Level} for logging errors + * @param exceptionLogEvents {@link Level} for logging by exception class + * @param responseLogFormatter {@link ResponseLogFormatter} response log formatter + * @return ClientBuilder instance + */ + public ClientBuilder withInternalLoggerFactory(final InternalLoggerFactory internalLoggerFactory, + final Level responseLogEvent, final Level deprecationLogEvent, final Level defaultExceptionLogEvent, + final Map, Level> exceptionLogEvents, + final ResponseLogFormatter responseLogFormatter, final ErrorLogFormatter errorLogFormatter) { + return withInternalLoggerMiddleware( + InternalLoggerMiddleware.of(internalLoggerFactory, responseLogEvent, deprecationLogEvent, + defaultExceptionLogEvent, exceptionLogEvents, responseLogFormatter, errorLogFormatter)); + } + /** * @param apiBaseUrl base URI for calling the API * @return ClientBuilder instance diff --git a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ErrorLogFormatter.java b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ErrorLogFormatter.java new file mode 100644 index 00000000000..2667c678dc7 --- /dev/null +++ b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ErrorLogFormatter.java @@ -0,0 +1,9 @@ + +package io.vrap.rmf.base.client.http; + +import io.vrap.rmf.base.client.ApiHttpRequest; + +@FunctionalInterface +public interface ErrorLogFormatter { + public String format(ApiHttpRequest request, Throwable throwable, long executionTime); +} diff --git a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddleware.java b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddleware.java index 67d50bb388b..b3cc9a93dea 100644 --- a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddleware.java +++ b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddleware.java @@ -39,4 +39,12 @@ static InternalLoggerMiddleware of(final InternalLoggerFactory internalLoggerFac return new InternalLoggerMiddlewareImpl(internalLoggerFactory, responseLogEvent, deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents); } + + static InternalLoggerMiddleware of(final InternalLoggerFactory internalLoggerFactory, final Level responseLogEvent, + final Level deprecationLogEvent, final Level defaultExceptionLogEvent, + final Map, Level> exceptionLogEvents, + final ResponseLogFormatter responseLogFormatter, final ErrorLogFormatter errorLogFormatter) { + return new InternalLoggerMiddlewareImpl(internalLoggerFactory, responseLogEvent, deprecationLogEvent, + defaultExceptionLogEvent, exceptionLogEvents, responseLogFormatter, errorLogFormatter); + } } diff --git a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddlewareImpl.java b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddlewareImpl.java index 81d90e11b93..a3114537709 100644 --- a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddlewareImpl.java +++ b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/InternalLoggerMiddlewareImpl.java @@ -26,6 +26,8 @@ class InternalLoggerMiddlewareImpl implements InternalLoggerMiddleware { private final Level responseLogEvent; private final Level defaultExceptionLogEvent; private final Map, Level> exceptionLogEvents; + private final ResponseLogFormatter responseLogFormatter; + private final ErrorLogFormatter errorLogFormatter; public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory) { this(factory, Level.INFO, Level.INFO); @@ -34,17 +36,28 @@ public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory) { public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory, final Level responseLogEvent, Level deprecationLogEvent) { this(factory, responseLogEvent, deprecationLogEvent, Level.ERROR, - Collections.singletonMap(ConcurrentModificationException.class, Level.INFO)); + Collections.singletonMap(ConcurrentModificationException.class, Level.INFO), LogFormatter::formatResponse, + LogFormatter::formatError); } public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory, final Level responseLogEvent, final Level deprecationLogEvent, final Level defaultExceptionLogEvent, final Map, Level> exceptionLogEvents) { + this(factory, responseLogEvent, deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents, + LogFormatter::formatResponse, LogFormatter::formatError); + } + + public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory, final Level responseLogEvent, + final Level deprecationLogEvent, final Level defaultExceptionLogEvent, + final Map, Level> exceptionLogEvents, + final ResponseLogFormatter responseLogFormatter, final ErrorLogFormatter errorLogFormatter) { this.factory = factory; this.responseLogEvent = responseLogEvent; this.deprecationLogEvent = deprecationLogEvent; this.defaultExceptionLogEvent = defaultExceptionLogEvent; this.exceptionLogEvents = exceptionLogEvents; + this.responseLogFormatter = responseLogFormatter; + this.errorLogFormatter = errorLogFormatter; } @Override @@ -105,14 +118,7 @@ public CompletableFuture> invoke(final ApiHttpRequest re .findFirst() .map(Map.Entry::getValue) .orElse(defaultExceptionLogEvent); - responseLogger.log(level, () -> String - .format("%s %s %s %s %s %s", request.getMethod().name(), request.getUrl(), - errorResponse.getStatusCode(), executionTime, - Optional.ofNullable(errorResponse.getHeaders().getFirst(ApiHttpHeaders.SERVER_TIMING)) - .orElse("-"), - Optional.ofNullable( - errorResponse.getHeaders().getFirst(ApiHttpHeaders.X_CORRELATION_ID)).orElse("-")) - .trim()); + responseLogger.log(level, () -> responseLogFormatter.format(request, errorResponse, executionTime)); final List> notices = errorResponse.getHeaders() .getHeaders(ApiHttpHeaders.X_DEPRECATION_NOTICE); if (notices != null) { @@ -133,7 +139,7 @@ public CompletableFuture> invoke(final ApiHttpRequest re .findFirst() .map(Map.Entry::getValue) .orElse(defaultExceptionLogEvent); - responseLogger.log(level, throwable::getCause, throwable); + responseLogger.log(level, () -> errorLogFormatter.format(request, cause, executionTime), cause); } requestContext.ifPresent(c -> MDC.clear()); } @@ -141,11 +147,8 @@ public CompletableFuture> invoke(final ApiHttpRequest re final Optional responseContext = Optional.ofNullable(response.getContext(MDCContext.class)); responseContext.ifPresent(c -> MDC.setContextMap(c.getValue())); - responseLogger.log(responseLogEvent, () -> String.format("%s %s %s %s %s %s", - request.getMethod().name(), request.getUrl(), response.getStatusCode(), executionTime, - Optional.ofNullable(response.getHeaders().getFirst(ApiHttpHeaders.SERVER_TIMING)).orElse("-"), - Optional.ofNullable(response.getHeaders().getFirst(ApiHttpHeaders.X_CORRELATION_ID)).orElse("-")) - .trim()); + responseLogger.log(responseLogEvent, + () -> responseLogFormatter.format(request, response, executionTime)); final List> notices = response.getHeaders() .getHeaders(ApiHttpHeaders.X_DEPRECATION_NOTICE); if (notices != null) { diff --git a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/LogFormatter.java b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/LogFormatter.java new file mode 100644 index 00000000000..f644d444d14 --- /dev/null +++ b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/LogFormatter.java @@ -0,0 +1,23 @@ + +package io.vrap.rmf.base.client.http; + +import java.util.Optional; + +import io.vrap.rmf.base.client.ApiHttpHeaders; +import io.vrap.rmf.base.client.ApiHttpRequest; +import io.vrap.rmf.base.client.ApiHttpResponse; + +public class LogFormatter { + public static String formatResponse(ApiHttpRequest request, ApiHttpResponse response, long executionTime) { + return String + .format("%s %s %s %s %s %s", request.getMethod().name(), request.getUrl(), response.getStatusCode(), + executionTime, + Optional.ofNullable(response.getHeaders().getFirst(ApiHttpHeaders.SERVER_TIMING)).orElse("-"), + Optional.ofNullable(response.getHeaders().getFirst(ApiHttpHeaders.X_CORRELATION_ID)).orElse("-")) + .trim(); + } + + public static String formatError(ApiHttpRequest request, Throwable throwable, long executionTime) { + return throwable.toString(); + } +} diff --git a/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ResponseLogFormatter.java b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ResponseLogFormatter.java new file mode 100644 index 00000000000..555e8897431 --- /dev/null +++ b/rmf/rmf-java-base/src/main/java/io/vrap/rmf/base/client/http/ResponseLogFormatter.java @@ -0,0 +1,10 @@ + +package io.vrap.rmf.base.client.http; + +import io.vrap.rmf.base.client.ApiHttpRequest; +import io.vrap.rmf.base.client.ApiHttpResponse; + +@FunctionalInterface +public interface ResponseLogFormatter { + public String format(ApiHttpRequest request, ApiHttpResponse response, long executionTime); +}