Skip to content

Commit

Permalink
Merge pull request #548 from commercetools/log_formatter
Browse files Browse the repository at this point in the history
add option to customise log formats
  • Loading branch information
jenschude authored Jan 12, 2024
2 parents f79f7fd + b06a407 commit 49e14e5
Show file tree
Hide file tree
Showing 10 changed files with 116 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<Class<? extends Throwable>, 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));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Class<? extends Throwable>, 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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Class<? extends Throwable>, 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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -17,7 +19,7 @@
*
* <p>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</p>
*
* {@include.example example.ExamplesTest#loggingConfiguration}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Class<? extends Throwable>, 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
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Class<? extends Throwable>, Level> exceptionLogEvents,
final ResponseLogFormatter responseLogFormatter, final ErrorLogFormatter errorLogFormatter) {
return new InternalLoggerMiddlewareImpl(internalLoggerFactory, responseLogEvent, deprecationLogEvent,
defaultExceptionLogEvent, exceptionLogEvents, responseLogFormatter, errorLogFormatter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class InternalLoggerMiddlewareImpl implements InternalLoggerMiddleware {
private final Level responseLogEvent;
private final Level defaultExceptionLogEvent;
private final Map<Class<? extends Throwable>, Level> exceptionLogEvents;
private final ResponseLogFormatter responseLogFormatter;
private final ErrorLogFormatter errorLogFormatter;

public InternalLoggerMiddlewareImpl(final InternalLoggerFactory factory) {
this(factory, Level.INFO, Level.INFO);
Expand All @@ -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<Class<? extends Throwable>, 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<Class<? extends Throwable>, 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
Expand Down Expand Up @@ -105,14 +118,7 @@ public CompletableFuture<ApiHttpResponse<byte[]>> 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<Map.Entry<String, String>> notices = errorResponse.getHeaders()
.getHeaders(ApiHttpHeaders.X_DEPRECATION_NOTICE);
if (notices != null) {
Expand All @@ -133,19 +139,16 @@ public CompletableFuture<ApiHttpResponse<byte[]>> 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());
}
else {
final Optional<MDCContext> 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<Map.Entry<String, String>> notices = response.getHeaders()
.getHeaders(ApiHttpHeaders.X_DEPRECATION_NOTICE);
if (notices != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<byte[]> 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();
}
}
Original file line number Diff line number Diff line change
@@ -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<byte[]> response, long executionTime);
}

0 comments on commit 49e14e5

Please sign in to comment.