From ead4d1018db67aa68fe15e4ac237682f82662a61 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Wed, 17 Jun 2020 21:25:42 +0900 Subject: [PATCH] Provide `RequestContext` to `RequestLog` sanitizers (#2803) Motivation: A user sometimes needs to sanitize a `RequestLog` depending on additional information available in `RequestContext`, e.g. current request path. Modifications: - Use `BiFunction` instead of `Function` for sanitization. - `RegexBasedSanitizer` is now a `BiFunction`. - Deprecate the methods that require `Function`s in: - `Logging{Client,RpcClient,Service}Builder` - `RequestOnlyLog.toRequestOnlyString()` - `RequestLog.toResponseOnlyString()` Result: - A user can implement a sanitizer that behaves differently dependin on the current context. - The methods that require `Function`s in the following methods have been deprecated: - `Logging{Client,RpcClient,Service}Builder` - `RequestOnlyLog.toRequestOnlyString()` - `RequestLog.toResponseOnlyString()` --- .../client/logging/AbstractLoggingClient.java | 62 +++-- .../armeria/client/logging/LoggingClient.java | 28 +- .../client/logging/LoggingClientBuilder.java | 66 ++++- .../client/logging/LoggingRpcClient.java | 28 +- .../logging/LoggingRpcClientBuilder.java | 66 ++++- .../common/logging/DefaultRequestLog.java | 47 ++-- .../logging/LoggingDecoratorBuilder.java | 253 +++++++++++++++--- .../common/logging/RegexBasedSanitizer.java | 8 +- .../armeria/common/logging/RequestLog.java | 77 ++++-- .../common/logging/RequestOnlyLog.java | 83 +++++- .../armeria/common/util/Functions.java | 14 + .../common/logging/LoggingDecorators.java | 24 +- .../server/logging/LoggingService.java | 34 +-- .../server/logging/LoggingServiceBuilder.java | 65 +++++ .../logging/LoggingDecoratorBuilderTest.java | 65 +++-- .../server/logging/LoggingServiceTest.java | 29 +- 16 files changed, 738 insertions(+), 211 deletions(-) diff --git a/core/src/main/java/com/linecorp/armeria/client/logging/AbstractLoggingClient.java b/core/src/main/java/com/linecorp/armeria/client/logging/AbstractLoggingClient.java index 9e78c5cee18..263e01eee51 100644 --- a/core/src/main/java/com/linecorp/armeria/client/logging/AbstractLoggingClient.java +++ b/core/src/main/java/com/linecorp/armeria/client/logging/AbstractLoggingClient.java @@ -20,6 +20,7 @@ import static com.linecorp.armeria.internal.common.logging.LoggingDecorators.logResponse; import static java.util.Objects.requireNonNull; +import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; @@ -33,10 +34,12 @@ import com.linecorp.armeria.client.SimpleDecoratingClient; import com.linecorp.armeria.common.HttpHeaders; import com.linecorp.armeria.common.Request; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.Response; import com.linecorp.armeria.common.logging.LogLevel; import com.linecorp.armeria.common.logging.RequestLog; import com.linecorp.armeria.common.logging.RequestOnlyLog; +import com.linecorp.armeria.common.util.Functions; import com.linecorp.armeria.common.util.Sampler; /** @@ -54,14 +57,16 @@ abstract class AbstractLoggingClient private final Logger logger; private final Function requestLogLevelMapper; private final Function responseLogLevelMapper; - private final Function requestHeadersSanitizer; - private final Function requestContentSanitizer; - private final Function requestTrailersSanitizer; - - private final Function responseHeadersSanitizer; - private final Function responseContentSanitizer; - private final Function responseTrailersSanitizer; - private final Function responseCauseSanitizer; + + private final BiFunction requestHeadersSanitizer; + private final BiFunction requestContentSanitizer; + private final BiFunction requestTrailersSanitizer; + + private final BiFunction responseHeadersSanitizer; + private final BiFunction responseContentSanitizer; + private final BiFunction responseTrailersSanitizer; + private final BiFunction responseCauseSanitizer; + private final Sampler sampler; /** @@ -73,13 +78,13 @@ abstract class AbstractLoggingClient null, log -> level, log -> level, - Function.identity(), - Function.identity(), - Function.identity(), - Function.identity(), - Function.identity(), - Function.identity(), - Function.identity(), + Functions.second(), + Functions.second(), + Functions.second(), + Functions.second(), + Functions.second(), + Functions.second(), + Functions.second(), Sampler.always()); } @@ -87,19 +92,22 @@ abstract class AbstractLoggingClient * Creates a new instance that logs {@link Request}s and {@link Response}s at the specified * {@link LogLevel}s with the specified sanitizers. */ - AbstractLoggingClient(Client delegate, - @Nullable Logger logger, - Function requestLogLevelMapper, - Function responseLogLevelMapper, - Function requestHeadersSanitizer, - Function requestContentSanitizer, - Function requestTrailersSanitizer, - Function responseHeadersSanitizer, - Function responseContentSanitizer, - Function responseTrailersSanitizer, - Function responseCauseSanitizer, - Sampler sampler) { + AbstractLoggingClient( + Client delegate, + @Nullable Logger logger, + Function requestLogLevelMapper, + Function responseLogLevelMapper, + BiFunction requestHeadersSanitizer, + BiFunction requestContentSanitizer, + BiFunction requestTrailersSanitizer, + BiFunction responseHeadersSanitizer, + BiFunction responseContentSanitizer, + BiFunction responseTrailersSanitizer, + BiFunction responseCauseSanitizer, + Sampler sampler) { + super(requireNonNull(delegate, "delegate")); + this.logger = logger != null ? logger : LoggerFactory.getLogger(getClass()); this.requestLogLevelMapper = requireNonNull(requestLogLevelMapper, "requestLogLevelMapper"); this.responseLogLevelMapper = requireNonNull(responseLogLevelMapper, "responseLogLevelMapper"); diff --git a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClient.java b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClient.java index 9f1a7ba0ed3..f54846a1ecc 100644 --- a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClient.java +++ b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClient.java @@ -16,6 +16,7 @@ package com.linecorp.armeria.client.logging; +import java.util.function.BiFunction; import java.util.function.Function; import javax.annotation.Nullable; @@ -28,6 +29,7 @@ import com.linecorp.armeria.common.HttpRequest; import com.linecorp.armeria.common.HttpResponse; import com.linecorp.armeria.common.Request; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.Response; import com.linecorp.armeria.common.logging.LogLevel; import com.linecorp.armeria.common.logging.RequestLog; @@ -65,18 +67,20 @@ public static LoggingClientBuilder builder() { * {@link LogLevel}s with the specified sanitizers. * If the logger is null, it means that the default logger is used. */ - LoggingClient(HttpClient delegate, - @Nullable Logger logger, - Function requestLogLevelMapper, - Function responseLogLevelMapper, - Function requestHeadersSanitizer, - Function requestContentSanitizer, - Function requestTrailersSanitizer, - Function responseHeadersSanitizer, - Function responseContentSanitizer, - Function responseTrailersSanitizer, - Function responseCauseSanitizer, - Sampler sampler) { + LoggingClient( + HttpClient delegate, + @Nullable Logger logger, + Function requestLogLevelMapper, + Function responseLogLevelMapper, + BiFunction requestHeadersSanitizer, + BiFunction requestContentSanitizer, + BiFunction requestTrailersSanitizer, + BiFunction responseHeadersSanitizer, + BiFunction responseContentSanitizer, + BiFunction responseTrailersSanitizer, + BiFunction responseCauseSanitizer, + Sampler sampler) { + super(delegate, logger, requestLogLevelMapper, responseLogLevelMapper, requestHeadersSanitizer, requestContentSanitizer, requestTrailersSanitizer, responseHeadersSanitizer, responseContentSanitizer, responseTrailersSanitizer, diff --git a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClientBuilder.java b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClientBuilder.java index c9449073384..8b6446d16e5 100644 --- a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClientBuilder.java +++ b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingClientBuilder.java @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ - package com.linecorp.armeria.client.logging; +import java.util.function.BiFunction; import java.util.function.Function; import org.slf4j.Logger; @@ -23,6 +23,7 @@ import com.linecorp.armeria.client.ClientRequestContext; import com.linecorp.armeria.client.HttpClient; import com.linecorp.armeria.common.HttpHeaders; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.logging.LogLevel; import com.linecorp.armeria.common.logging.RequestLog; import com.linecorp.armeria.common.logging.RequestOnlyLog; @@ -108,50 +109,113 @@ public LoggingClientBuilder responseLogLevelMapper( } @Override + public LoggingClientBuilder requestHeadersSanitizer( + BiFunction requestHeadersSanitizer) { + return (LoggingClientBuilder) super.requestHeadersSanitizer(requestHeadersSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder requestHeadersSanitizer( Function requestHeadersSanitizer) { return (LoggingClientBuilder) super.requestHeadersSanitizer(requestHeadersSanitizer); } @Override + public LoggingClientBuilder responseHeadersSanitizer( + BiFunction responseHeadersSanitizer) { + return (LoggingClientBuilder) super.responseHeadersSanitizer(responseHeadersSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder responseHeadersSanitizer( Function responseHeadersSanitizer) { return (LoggingClientBuilder) super.responseHeadersSanitizer(responseHeadersSanitizer); } @Override + public LoggingClientBuilder requestTrailersSanitizer( + BiFunction requestTrailersSanitizer) { + return (LoggingClientBuilder) super.requestTrailersSanitizer(requestTrailersSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder requestTrailersSanitizer( Function requestTrailersSanitizer) { return (LoggingClientBuilder) super.requestTrailersSanitizer(requestTrailersSanitizer); } @Override + public LoggingClientBuilder responseTrailersSanitizer( + BiFunction responseTrailersSanitizer) { + return (LoggingClientBuilder) super.responseTrailersSanitizer(responseTrailersSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder responseTrailersSanitizer( Function responseTrailersSanitizer) { return (LoggingClientBuilder) super.responseTrailersSanitizer(responseTrailersSanitizer); } @Override + public LoggingClientBuilder headersSanitizer( + BiFunction headersSanitizer) { + return (LoggingClientBuilder) super.headersSanitizer(headersSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder headersSanitizer(Function headersSanitizer) { return (LoggingClientBuilder) super.headersSanitizer(headersSanitizer); } @Override + public LoggingClientBuilder requestContentSanitizer( + BiFunction requestContentSanitizer) { + return (LoggingClientBuilder) super.requestContentSanitizer(requestContentSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder requestContentSanitizer(Function requestContentSanitizer) { return (LoggingClientBuilder) super.requestContentSanitizer(requestContentSanitizer); } @Override + public LoggingClientBuilder responseContentSanitizer( + BiFunction responseContentSanitizer) { + return (LoggingClientBuilder) super.responseContentSanitizer(responseContentSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder responseContentSanitizer(Function responseContentSanitizer) { return (LoggingClientBuilder) super.responseContentSanitizer(responseContentSanitizer); } @Override + public LoggingClientBuilder contentSanitizer( + BiFunction contentSanitizer) { + return (LoggingClientBuilder) super.contentSanitizer(contentSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder contentSanitizer(Function contentSanitizer) { return (LoggingClientBuilder) super.contentSanitizer(contentSanitizer); } @Override + public LoggingClientBuilder responseCauseSanitizer( + BiFunction responseCauseSanitizer) { + return (LoggingClientBuilder) super.responseCauseSanitizer(responseCauseSanitizer); + } + + @Override + @Deprecated public LoggingClientBuilder responseCauseSanitizer( Function responseCauseSanitizer) { return (LoggingClientBuilder) super.responseCauseSanitizer(responseCauseSanitizer); diff --git a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClient.java b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClient.java index 4a054eb2cd4..5926e499c80 100644 --- a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClient.java +++ b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClient.java @@ -16,6 +16,7 @@ package com.linecorp.armeria.client.logging; +import java.util.function.BiFunction; import java.util.function.Function; import javax.annotation.Nullable; @@ -26,6 +27,7 @@ import com.linecorp.armeria.client.RpcClient; import com.linecorp.armeria.common.HttpHeaders; import com.linecorp.armeria.common.Request; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.Response; import com.linecorp.armeria.common.RpcRequest; import com.linecorp.armeria.common.RpcResponse; @@ -65,18 +67,20 @@ public static LoggingRpcClientBuilder builder() { * {@link LogLevel}s with the specified sanitizers. * If the logger is null, it means that the default logger is used. */ - LoggingRpcClient(RpcClient delegate, - @Nullable Logger logger, - Function requestLogLevelMapper, - Function responseLogLevelMapper, - Function requestHeadersSanitizer, - Function requestContentSanitizer, - Function requestTrailersSanitizer, - Function responseHeadersSanitizer, - Function responseContentSanitizer, - Function responseTrailersSanitizer, - Function responseCauseSanitizer, - Sampler sampler) { + LoggingRpcClient( + RpcClient delegate, + @Nullable Logger logger, + Function requestLogLevelMapper, + Function responseLogLevelMapper, + BiFunction requestHeadersSanitizer, + BiFunction requestContentSanitizer, + BiFunction requestTrailersSanitizer, + BiFunction responseHeadersSanitizer, + BiFunction responseContentSanitizer, + BiFunction responseTrailersSanitizer, + BiFunction responseCauseSanitizer, + Sampler sampler) { + super(delegate, logger, requestLogLevelMapper, responseLogLevelMapper, requestHeadersSanitizer, requestContentSanitizer, requestTrailersSanitizer, responseHeadersSanitizer, responseContentSanitizer, responseTrailersSanitizer, diff --git a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClientBuilder.java b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClientBuilder.java index abddf011766..4b4c0d94c81 100644 --- a/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClientBuilder.java +++ b/core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClientBuilder.java @@ -13,9 +13,9 @@ * License for the specific language governing permissions and limitations * under the License. */ - package com.linecorp.armeria.client.logging; +import java.util.function.BiFunction; import java.util.function.Function; import org.slf4j.Logger; @@ -23,6 +23,7 @@ import com.linecorp.armeria.client.ClientRequestContext; import com.linecorp.armeria.client.RpcClient; import com.linecorp.armeria.common.HttpHeaders; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.logging.LogLevel; import com.linecorp.armeria.common.logging.RequestLog; import com.linecorp.armeria.common.logging.RequestOnlyLog; @@ -111,50 +112,113 @@ public LoggingRpcClientBuilder responseLogLevelMapper( } @Override + public LoggingRpcClientBuilder requestHeadersSanitizer( + BiFunction requestHeadersSanitizer) { + return (LoggingRpcClientBuilder) super.requestHeadersSanitizer(requestHeadersSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder requestHeadersSanitizer( Function requestHeadersSanitizer) { return (LoggingRpcClientBuilder) super.requestHeadersSanitizer(requestHeadersSanitizer); } @Override + public LoggingRpcClientBuilder responseHeadersSanitizer( + BiFunction responseHeadersSanitizer) { + return (LoggingRpcClientBuilder) super.responseHeadersSanitizer(responseHeadersSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder responseHeadersSanitizer( Function responseHeadersSanitizer) { return (LoggingRpcClientBuilder) super.responseHeadersSanitizer(responseHeadersSanitizer); } @Override + public LoggingRpcClientBuilder requestTrailersSanitizer( + BiFunction requestTrailersSanitizer) { + return (LoggingRpcClientBuilder) super.requestTrailersSanitizer(requestTrailersSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder requestTrailersSanitizer( Function requestTrailersSanitizer) { return (LoggingRpcClientBuilder) super.requestTrailersSanitizer(requestTrailersSanitizer); } @Override + public LoggingRpcClientBuilder responseTrailersSanitizer( + BiFunction responseTrailersSanitizer) { + return (LoggingRpcClientBuilder) super.responseTrailersSanitizer(responseTrailersSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder responseTrailersSanitizer( Function responseTrailersSanitizer) { return (LoggingRpcClientBuilder) super.responseTrailersSanitizer(responseTrailersSanitizer); } @Override + public LoggingRpcClientBuilder headersSanitizer( + BiFunction headersSanitizer) { + return (LoggingRpcClientBuilder) super.headersSanitizer(headersSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder headersSanitizer(Function headersSanitizer) { return (LoggingRpcClientBuilder) super.headersSanitizer(headersSanitizer); } @Override + public LoggingRpcClientBuilder requestContentSanitizer( + BiFunction requestContentSanitizer) { + return (LoggingRpcClientBuilder) super.requestContentSanitizer(requestContentSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder requestContentSanitizer(Function requestContentSanitizer) { return (LoggingRpcClientBuilder) super.requestContentSanitizer(requestContentSanitizer); } @Override + public LoggingRpcClientBuilder responseContentSanitizer( + BiFunction responseContentSanitizer) { + return (LoggingRpcClientBuilder) super.responseContentSanitizer(responseContentSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder responseContentSanitizer(Function responseContentSanitizer) { return (LoggingRpcClientBuilder) super.responseContentSanitizer(responseContentSanitizer); } @Override + public LoggingRpcClientBuilder contentSanitizer( + BiFunction contentSanitizer) { + return (LoggingRpcClientBuilder) super.contentSanitizer(contentSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder contentSanitizer(Function contentSanitizer) { return (LoggingRpcClientBuilder) super.contentSanitizer(contentSanitizer); } @Override + public LoggingRpcClientBuilder responseCauseSanitizer( + BiFunction responseCauseSanitizer) { + return (LoggingRpcClientBuilder) super.responseCauseSanitizer(responseCauseSanitizer); + } + + @Override + @Deprecated public LoggingRpcClientBuilder responseCauseSanitizer( Function responseCauseSanitizer) { return (LoggingRpcClientBuilder) super.responseCauseSanitizer(responseCauseSanitizer); diff --git a/core/src/main/java/com/linecorp/armeria/common/logging/DefaultRequestLog.java b/core/src/main/java/com/linecorp/armeria/common/logging/DefaultRequestLog.java index 95292e57248..e97357f8a6c 100644 --- a/core/src/main/java/com/linecorp/armeria/common/logging/DefaultRequestLog.java +++ b/core/src/main/java/com/linecorp/armeria/common/logging/DefaultRequestLog.java @@ -26,7 +26,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import java.util.function.Function; +import java.util.function.BiFunction; import javax.annotation.Nullable; import javax.net.ssl.SSLSession; @@ -1267,9 +1267,11 @@ public String toString() { } @Override - public String toStringRequestOnly(Function headersSanitizer, - Function contentSanitizer, - Function trailersSanitizer) { + public String toStringRequestOnly( + BiFunction headersSanitizer, + BiFunction contentSanitizer, + BiFunction trailersSanitizer) { + requireNonNull(headersSanitizer, "headersSanitizer"); requireNonNull(contentSanitizer, "contentSanitizer"); requireNonNull(trailersSanitizer, "trailersSanitizer"); @@ -1369,9 +1371,10 @@ public String toStringRequestOnly(Function headersSan } @Override - public String toStringResponseOnly(Function headersSanitizer, - Function contentSanitizer, - Function trailersSanitizer) { + public String toStringResponseOnly( + BiFunction headersSanitizer, + BiFunction contentSanitizer, + BiFunction trailersSanitizer) { requireNonNull(headersSanitizer, "headersSanitizer"); requireNonNull(contentSanitizer, "contentSanitizer"); @@ -1467,8 +1470,9 @@ public String toStringResponseOnly(Function headersS return responseStr; } - private static String sanitize(Function headersSanitizer, T requestHeaders) { - final Object sanitized = headersSanitizer.apply(requestHeaders); + private String sanitize(BiFunction headersSanitizer, + T requestHeaders) { + final Object sanitized = headersSanitizer.apply(ctx, requestHeaders); return sanitized != null ? sanitized.toString() : ""; } @@ -1725,9 +1729,11 @@ public HttpHeaders requestTrailers() { } @Override - public String toStringRequestOnly(Function headersSanitizer, - Function contentSanitizer, - Function trailersSanitizer) { + public String toStringRequestOnly( + BiFunction headersSanitizer, + BiFunction contentSanitizer, + BiFunction trailersSanitizer) { + return DefaultRequestLog.this.toStringRequestOnly( headersSanitizer, contentSanitizer, trailersSanitizer); } @@ -1798,20 +1804,11 @@ public HttpHeaders responseTrailers() { } @Override - public String toStringResponseOnly() { - return DefaultRequestLog.this.toStringResponseOnly(); - } + public String toStringResponseOnly( + BiFunction headersSanitizer, + BiFunction contentSanitizer, + BiFunction trailersSanitizer) { - @Override - public String toStringResponseOnly(Function headersSanitizer, - Function contentSanitizer) { - return DefaultRequestLog.this.toStringResponseOnly(headersSanitizer, contentSanitizer); - } - - @Override - public String toStringResponseOnly(Function headersSanitizer, - Function contentSanitizer, - Function trailersSanitizer) { return DefaultRequestLog.this.toStringResponseOnly(headersSanitizer, contentSanitizer, trailersSanitizer); } diff --git a/core/src/main/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilder.java b/core/src/main/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilder.java index bb94e1d8f0c..6173dd01411 100644 --- a/core/src/main/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilder.java +++ b/core/src/main/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilder.java @@ -17,6 +17,7 @@ import static java.util.Objects.requireNonNull; +import java.util.function.BiFunction; import java.util.function.Function; import javax.annotation.Nullable; @@ -28,15 +29,20 @@ import com.google.common.base.MoreObjects.ToStringHelper; import com.linecorp.armeria.common.HttpHeaders; +import com.linecorp.armeria.common.RequestContext; +import com.linecorp.armeria.common.util.Functions; /** * Builds a new logging decorator. */ public abstract class LoggingDecoratorBuilder { - private static final Function DEFAULT_HEADERS_SANITIZER = Function.identity(); - private static final Function DEFAULT_CONTENT_SANITIZER = Function.identity(); - private static final Function DEFAULT_CAUSE_SANITIZER = Function.identity(); + private static final BiFunction DEFAULT_HEADERS_SANITIZER = + Functions.second(); + private static final BiFunction DEFAULT_CONTENT_SANITIZER = + Functions.second(); + private static final BiFunction DEFAULT_CAUSE_SANITIZER = + Functions.second(); @Nullable private Logger logger; @@ -51,14 +57,21 @@ public abstract class LoggingDecoratorBuilder { private boolean isResponseLogLevelSet; private boolean isRequestLogLevelMapperSet; private boolean isResponseLogLevelMapperSet; - private Function requestHeadersSanitizer = DEFAULT_HEADERS_SANITIZER; - private Function requestContentSanitizer = DEFAULT_CONTENT_SANITIZER; - private Function requestTrailersSanitizer = DEFAULT_HEADERS_SANITIZER; - - private Function responseHeadersSanitizer = DEFAULT_HEADERS_SANITIZER; - private Function responseContentSanitizer = DEFAULT_CONTENT_SANITIZER; - private Function responseCauseSanitizer = DEFAULT_CAUSE_SANITIZER; - private Function responseTrailersSanitizer = DEFAULT_HEADERS_SANITIZER; + private BiFunction requestHeadersSanitizer = + DEFAULT_HEADERS_SANITIZER; + private BiFunction requestContentSanitizer = + DEFAULT_CONTENT_SANITIZER; + private BiFunction requestTrailersSanitizer = + DEFAULT_HEADERS_SANITIZER; + + private BiFunction responseHeadersSanitizer = + DEFAULT_HEADERS_SANITIZER; + private BiFunction responseContentSanitizer = + DEFAULT_CONTENT_SANITIZER; + private BiFunction responseCauseSanitizer = + DEFAULT_CAUSE_SANITIZER; + private BiFunction responseTrailersSanitizer = + DEFAULT_HEADERS_SANITIZER; /** * Sets the {@link Logger} to use when logging. @@ -182,76 +195,157 @@ protected Function responseLogLevelMapper() { return responseLogLevelMapper; } + /** + * Sets the {@link BiFunction} to use to sanitize request headers before logging. It is common to have the + * {@link BiFunction} that removes sensitive headers, like {@code Cookie}, before logging. If unset, will + * not sanitize request headers. + */ + public LoggingDecoratorBuilder requestHeadersSanitizer( + BiFunction requestHeadersSanitizer) { + this.requestHeadersSanitizer = requireNonNull(requestHeadersSanitizer, "requestHeadersSanitizer"); + return this; + } + /** * Sets the {@link Function} to use to sanitize request headers before logging. It is common to have the * {@link Function} that removes sensitive headers, like {@code Cookie}, before logging. If unset, will use * {@link Function#identity()}. + * + * @deprecated Use {@link #requestHeadersSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder requestHeadersSanitizer( Function requestHeadersSanitizer) { - this.requestHeadersSanitizer = requireNonNull(requestHeadersSanitizer, "requestHeadersSanitizer"); - return this; + requireNonNull(requestHeadersSanitizer, "requestHeadersSanitizer"); + return requestHeadersSanitizer((ctx, headers) -> requestHeadersSanitizer.apply(headers)); } /** - * Returns the {@link Function} to use to sanitize request headers before logging. + * Returns the {@link BiFunction} to use to sanitize request headers before logging. */ - protected Function requestHeadersSanitizer() { + protected BiFunction requestHeadersSanitizer() { return requestHeadersSanitizer; } + /** + * Sets the {@link BiFunction} to use to sanitize response headers before logging. It is common to have the + * {@link BiFunction} that removes sensitive headers, like {@code Set-Cookie}, before logging. If unset, + * will not sanitize response headers. + */ + public LoggingDecoratorBuilder responseHeadersSanitizer( + BiFunction responseHeadersSanitizer) { + this.responseHeadersSanitizer = requireNonNull(responseHeadersSanitizer, "responseHeadersSanitizer"); + return this; + } + /** * Sets the {@link Function} to use to sanitize response headers before logging. It is common to have the * {@link Function} that removes sensitive headers, like {@code Set-Cookie}, before logging. If unset, * will use {@link Function#identity()}. + * + * @deprecated Use {@link #responseHeadersSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder responseHeadersSanitizer( Function responseHeadersSanitizer) { - this.responseHeadersSanitizer = requireNonNull(responseHeadersSanitizer, "responseHeadersSanitizer"); - return this; + requireNonNull(responseHeadersSanitizer, "responseHeadersSanitizer"); + return responseHeadersSanitizer((ctx, headers) -> responseHeadersSanitizer.apply(headers)); } /** - * Returns the {@link Function} to use to sanitize response headers before logging. + * Returns the {@link BiFunction} to use to sanitize response headers before logging. */ - protected Function responseHeadersSanitizer() { + protected BiFunction responseHeadersSanitizer() { return responseHeadersSanitizer; } + /** + * Sets the {@link BiFunction} to use to sanitize request trailers before logging. If unset, + * will not sanitize request trailers. + */ + public LoggingDecoratorBuilder requestTrailersSanitizer( + BiFunction requestTrailersSanitizer) { + this.requestTrailersSanitizer = requireNonNull(requestTrailersSanitizer, "requestTrailersSanitizer"); + return this; + } + /** * Sets the {@link Function} to use to sanitize request trailers before logging. If unset, * will use {@link Function#identity()}. + * + * @deprecated Use {@link #requestTrailersSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder requestTrailersSanitizer( Function requestTrailersSanitizer) { - this.requestTrailersSanitizer = requireNonNull(requestTrailersSanitizer, "requestTrailersSanitizer"); - return this; + requireNonNull(requestTrailersSanitizer, "requestTrailersSanitizer"); + return requestTrailersSanitizer((ctx, trailers) -> requestTrailersSanitizer.apply(trailers)); } /** - * Returns the {@link Function} to use to sanitize request trailers before logging. + * Returns the {@link BiFunction} to use to sanitize request trailers before logging. */ - protected Function requestTrailersSanitizer() { + protected BiFunction requestTrailersSanitizer() { return requestTrailersSanitizer; } + /** + * Sets the {@link BiFunction} to use to sanitize response trailers before logging. If unset, + * will not sanitize response trailers. + */ + public LoggingDecoratorBuilder responseTrailersSanitizer( + BiFunction responseTrailersSanitizer) { + this.responseTrailersSanitizer = requireNonNull(responseTrailersSanitizer, "responseTrailersSanitizer"); + return this; + } + /** * Sets the {@link Function} to use to sanitize response trailers before logging. If unset, * will use {@link Function#identity()}. + * + * @deprecated Use {@link #responseTrailersSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder responseTrailersSanitizer( Function responseTrailersSanitizer) { - this.responseTrailersSanitizer = requireNonNull(responseTrailersSanitizer, "responseTrailersSanitizer"); - return this; + requireNonNull(responseTrailersSanitizer, "responseTrailersSanitizer"); + return responseTrailersSanitizer((ctx, trailers) -> responseTrailersSanitizer.apply(trailers)); } /** * Returns the {@link Function} to use to sanitize response trailers before logging. */ - protected Function responseTrailersSanitizer() { + protected BiFunction responseTrailersSanitizer() { return responseTrailersSanitizer; } + /** + * Sets the {@link BiFunction} to use to sanitize request, response and trailers before logging. + * It is common to have the {@link BiFunction} that removes sensitive headers, like {@code "Cookie"} and + * {@code "Set-Cookie"}, before logging. This method is a shortcut for: + *
{@code
+     * builder.requestHeadersSanitizer(headersSanitizer);
+     * builder.requestTrailersSanitizer(headersSanitizer);
+     * builder.responseHeadersSanitizer(headersSanitizer);
+     * builder.responseTrailersSanitizer(headersSanitizer);
+     * }
+ * + * @see #requestHeadersSanitizer(BiFunction) + * @see #requestTrailersSanitizer(BiFunction) + * @see #responseHeadersSanitizer(BiFunction) + * @see #responseTrailersSanitizer(BiFunction) + */ + public LoggingDecoratorBuilder headersSanitizer( + BiFunction headersSanitizer) { + + requireNonNull(headersSanitizer, "headersSanitizer"); + requestHeadersSanitizer(headersSanitizer); + requestTrailersSanitizer(headersSanitizer); + responseHeadersSanitizer(headersSanitizer); + responseTrailersSanitizer(headersSanitizer); + return this; + } + /** * Sets the {@link Function} to use to sanitize request, response and trailers before logging. * It is common to have the {@link Function} that removes sensitive headers, like {@code "Cookie"} and @@ -267,7 +361,10 @@ public LoggingDecoratorBuilder responseTrailersSanitizer( * @see #requestTrailersSanitizer(Function) * @see #responseHeadersSanitizer(Function) * @see #responseTrailersSanitizer(Function) + * + * @deprecated Use {@link #headersSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder headersSanitizer(Function headersSanitizer) { requireNonNull(headersSanitizer, "headersSanitizer"); requestHeadersSanitizer(headersSanitizer); @@ -277,40 +374,89 @@ public LoggingDecoratorBuilder headersSanitizer(Function return this; } + /** + * Sets the {@link BiFunction} to use to sanitize request content before logging. It is common to have the + * {@link BiFunction} that removes sensitive content, such as an GPS location query, before logging. + * If unset, will not sanitize request content. + */ + public LoggingDecoratorBuilder requestContentSanitizer( + BiFunction requestContentSanitizer) { + this.requestContentSanitizer = requireNonNull(requestContentSanitizer, "requestContentSanitizer"); + return this; + } + /** * Sets the {@link Function} to use to sanitize request content before logging. It is common to have the * {@link Function} that removes sensitive content, such as an GPS location query, before logging. If unset, * will use {@link Function#identity()}. + * + * @deprecated Use {@link #requestContentSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder requestContentSanitizer(Function requestContentSanitizer) { - this.requestContentSanitizer = requireNonNull(requestContentSanitizer, "requestContentSanitizer"); - return this; + requireNonNull(requestContentSanitizer, "requestContentSanitizer"); + return requestContentSanitizer((ctx, content) -> requestContentSanitizer.apply(content)); } /** - * Returns the {@link Function} to use to sanitize request content before logging. + * Returns the {@link BiFunction} to use to sanitize request content before logging. */ - protected Function requestContentSanitizer() { + protected BiFunction requestContentSanitizer() { return requestContentSanitizer; } + /** + * Sets the {@link BiFunction} to use to sanitize response content before logging. It is common to have the + * {@link BiFunction} that removes sensitive content, such as an address, before logging. If unset, + * will not sanitize response content. + */ + public LoggingDecoratorBuilder responseContentSanitizer( + BiFunction responseContentSanitizer) { + this.responseContentSanitizer = requireNonNull(responseContentSanitizer, "responseContentSanitizer"); + return this; + } + /** * Sets the {@link Function} to use to sanitize response content before logging. It is common to have the * {@link Function} that removes sensitive content, such as an address, before logging. If unset, * will use {@link Function#identity()}. + * + * @deprecated Use {@link #responseContentSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder responseContentSanitizer(Function responseContentSanitizer) { - this.responseContentSanitizer = requireNonNull(responseContentSanitizer, "responseContentSanitizer"); - return this; + requireNonNull(responseContentSanitizer, "responseContentSanitizer"); + return responseContentSanitizer((ctx, content) -> responseContentSanitizer.apply(content)); } /** - * Returns the {@link Function} to use to sanitize response content before logging. + * Returns the {@link BiFunction} to use to sanitize response content before logging. */ - protected Function responseContentSanitizer() { + protected BiFunction responseContentSanitizer() { return responseContentSanitizer; } + /** + * Sets the {@link BiFunction} to use to sanitize request and response content before logging. It is common + * to have the {@link BiFunction} that removes sensitive content, such as an GPS location query and + * an address, before logging. If unset, will not sanitize content. + * This method is a shortcut for: + *
{@code
+     * builder.requestContentSanitizer(contentSanitizer);
+     * builder.responseContentSanitizer(contentSanitizer);
+     * }
+ * + * @see #requestContentSanitizer(BiFunction) + * @see #responseContentSanitizer(BiFunction) + */ + public LoggingDecoratorBuilder contentSanitizer( + BiFunction contentSanitizer) { + requireNonNull(contentSanitizer, "contentSanitizer"); + requestContentSanitizer(contentSanitizer); + responseContentSanitizer(contentSanitizer); + return this; + } + /** * Sets the {@link Function} to use to sanitize request and response content before logging. It is common * to have the {@link Function} that removes sensitive content, such as an GPS location query and @@ -323,7 +469,10 @@ public LoggingDecoratorBuilder responseContentSanitizer(Function resp * * @see #requestContentSanitizer(Function) * @see #responseContentSanitizer(Function) + * + * @deprecated Use {@link #contentSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder contentSanitizer(Function contentSanitizer) { requireNonNull(contentSanitizer, "contentSanitizer"); requestContentSanitizer(contentSanitizer); @@ -331,22 +480,37 @@ public LoggingDecoratorBuilder contentSanitizer(Function contentSanit return this; } + /** + * Sets the {@link BiFunction} to use to sanitize a response cause before logging. You can + * sanitize the stack trace of the exception to remove sensitive information, or prevent from logging + * the stack trace completely by returning {@code null} in the {@link BiFunction}. If unset, will not + * sanitize a response cause. + */ + public LoggingDecoratorBuilder responseCauseSanitizer( + BiFunction responseCauseSanitizer) { + this.responseCauseSanitizer = requireNonNull(responseCauseSanitizer, "responseCauseSanitizer"); + return this; + } + /** * Sets the {@link Function} to use to sanitize a response cause before logging. You can * sanitize the stack trace of the exception to remove sensitive information, or prevent from logging * the stack trace completely by returning {@code null} in the {@link Function}. If unset, will use * {@link Function#identity()}. + * + * @deprecated Use {@link #responseCauseSanitizer(BiFunction)}. */ + @Deprecated public LoggingDecoratorBuilder responseCauseSanitizer( Function responseCauseSanitizer) { - this.responseCauseSanitizer = requireNonNull(responseCauseSanitizer, "responseCauseSanitizer"); - return this; + requireNonNull(responseCauseSanitizer, "responseCauseSanitizer"); + return responseCauseSanitizer((ctx, cause) -> responseCauseSanitizer.apply(cause)); } /** - * Returns the {@link Function} to use to sanitize response cause before logging. + * Returns the {@link BiFunction} to use to sanitize response cause before logging. */ - protected Function responseCauseSanitizer() { + protected BiFunction responseCauseSanitizer() { return responseCauseSanitizer; } @@ -369,12 +533,13 @@ private static String toString( Function responseLogLevelMapper, boolean isRequestLogLevelMapperSet, boolean isResponseLogLevelMapperSet, - Function requestHeadersSanitizer, - Function requestContentSanitizer, - Function requestTrailersSanitizer, - Function responseHeadersSanitizer, - Function responseContentSanitizer, - Function responseTrailersSanitizer) { + BiFunction requestHeadersSanitizer, + BiFunction requestContentSanitizer, + BiFunction requestTrailersSanitizer, + BiFunction responseHeadersSanitizer, + BiFunction responseContentSanitizer, + BiFunction responseTrailersSanitizer) { + final ToStringHelper helper = MoreObjects.toStringHelper(self) .omitNullValues() .add("logger", logger); diff --git a/core/src/main/java/com/linecorp/armeria/common/logging/RegexBasedSanitizer.java b/core/src/main/java/com/linecorp/armeria/common/logging/RegexBasedSanitizer.java index cc1f7921897..b81568a630a 100644 --- a/core/src/main/java/com/linecorp/armeria/common/logging/RegexBasedSanitizer.java +++ b/core/src/main/java/com/linecorp/armeria/common/logging/RegexBasedSanitizer.java @@ -18,7 +18,7 @@ import static java.util.Objects.requireNonNull; import java.util.List; -import java.util.function.Function; +import java.util.function.BiFunction; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,10 +26,12 @@ import com.google.common.collect.ImmutableList; +import com.linecorp.armeria.common.RequestContext; + /** * Regex based sanitizer. */ -public final class RegexBasedSanitizer implements Function { +public final class RegexBasedSanitizer implements BiFunction { /** * Returns a new instance created from the specified {@link Pattern}s. @@ -59,7 +61,7 @@ public static RegexBasedSanitizer of(Iterable patterns) { @Nullable @Override - public String apply(@Nullable Object input) { + public String apply(RequestContext ctx, @Nullable Object input) { if (input == null) { return null; } diff --git a/core/src/main/java/com/linecorp/armeria/common/logging/RequestLog.java b/core/src/main/java/com/linecorp/armeria/common/logging/RequestLog.java index 7dc0e3cf987..60c1ab18681 100644 --- a/core/src/main/java/com/linecorp/armeria/common/logging/RequestLog.java +++ b/core/src/main/java/com/linecorp/armeria/common/logging/RequestLog.java @@ -18,6 +18,7 @@ import static java.util.Objects.requireNonNull; +import java.util.function.BiFunction; import java.util.function.Function; import javax.annotation.Nullable; @@ -31,6 +32,7 @@ import com.linecorp.armeria.common.ResponseHeaders; import com.linecorp.armeria.common.RpcResponse; import com.linecorp.armeria.common.SerializationFormat; +import com.linecorp.armeria.common.util.Functions; import com.linecorp.armeria.server.Service; import com.linecorp.armeria.server.logging.ContentPreviewingService; @@ -198,11 +200,13 @@ default long totalDurationNanos() { * Returns the string representation of the {@link Response}, with no sanitization of headers or content. * This method is a shortcut for: *
{@code
-     * toStringResponseOnly(Function.identity(), Function.identity(), Function.identity());
+     * toStringResponseOnly((ctx, headers) -> headers,
+     *                      (ctx, content) -> content,
+     *                      (ctx, trailers) -> trailers);
      * }
*/ default String toStringResponseOnly() { - return toStringResponseOnly(Function.identity(), Function.identity(), Function.identity()); + return toStringResponseOnly(Functions.second(), Functions.second(), Functions.second()); } /** @@ -211,11 +215,45 @@ default String toStringResponseOnly() { * toStringResponseOnly(headersSanitizer, contentSanitizer, headersSanitizer); * } * - * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of the - * {@link Function} is what is actually logged as headers. - * @param contentSanitizer a {@link Function} for sanitizing response content for logging. The result of the - * {@link Function} is what is actually logged as content. + * @param headersSanitizer a {@link BiFunction} for sanitizing HTTP headers for logging. The result of + * the {@link BiFunction} is what is actually logged as headers. + * @param contentSanitizer a {@link BiFunction} for sanitizing response content for logging. The result of + * the {@link BiFunction} is what is actually logged as content. */ + default String toStringResponseOnly( + BiFunction headersSanitizer, + BiFunction contentSanitizer) { + return toStringResponseOnly(headersSanitizer, contentSanitizer, headersSanitizer); + } + + /** + * Returns the string representation of the {@link Response}. + * + * @param headersSanitizer a {@link BiFunction} for sanitizing HTTP headers for logging. The result of + * the {@link BiFunction} is what is actually logged as headers. + * @param contentSanitizer a {@link BiFunction} for sanitizing response content for logging. The result of + * the {@link BiFunction} is what is actually logged as content. + * @param trailersSanitizer a {@link BiFunction} for sanitizing HTTP trailers for logging. The result of + * the {@link BiFunction} is what is actually logged as trailers. + */ + String toStringResponseOnly(BiFunction headersSanitizer, + BiFunction contentSanitizer, + BiFunction trailersSanitizer); + + /** + * Returns the string representation of the {@link Response}. This method is a shortcut for: + *
{@code
+     * toStringResponseOnly(headersSanitizer, contentSanitizer, headersSanitizer);
+     * }
+ * + * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of + * the {@link Function} is what is actually logged as headers. + * @param contentSanitizer a {@link Function} for sanitizing response content for logging. The result of + * the {@link Function} is what is actually logged as content. + * + * @deprecated Use {@link #toStringResponseOnly(BiFunction, BiFunction)}. + */ + @Deprecated default String toStringResponseOnly(Function headersSanitizer, Function contentSanitizer) { return toStringResponseOnly(headersSanitizer, contentSanitizer, headersSanitizer); @@ -224,14 +262,23 @@ default String toStringResponseOnly(Function headersSani /** * Returns the string representation of the {@link Response}. * - * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of the - * {@link Function} is what is actually logged as headers. - * @param contentSanitizer a {@link Function} for sanitizing response content for logging. The result of the - * {@link Function} is what is actually logged as content. - * @param trailersSanitizer a {@link Function} for sanitizing HTTP trailers for logging. The result of the - * {@link Function} is what is actually logged as trailers. + * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of + * the {@link Function} is what is actually logged as headers. + * @param contentSanitizer a {@link Function} for sanitizing response content for logging. The result of + * the {@link Function} is what is actually logged as content. + * @param trailersSanitizer a {@link Function} for sanitizing HTTP trailers for logging. The result of + * the {@link Function} is what is actually logged as trailers. + * @deprecated Use {@link #toStringResponseOnly(BiFunction, BiFunction, BiFunction)}. */ - String toStringResponseOnly(Function headersSanitizer, - Function contentSanitizer, - Function trailersSanitizer); + @Deprecated + default String toStringResponseOnly(Function headersSanitizer, + Function contentSanitizer, + Function trailersSanitizer) { + requireNonNull(headersSanitizer, "headersSanitizer"); + requireNonNull(contentSanitizer, "contentSanitizer"); + requireNonNull(trailersSanitizer, "trailersSanitizer"); + return toStringResponseOnly((ctx, headers) -> headersSanitizer.apply(headers), + (ctx, content) -> contentSanitizer.apply(content), + (ctx, trailers) -> trailersSanitizer.apply(trailers)); + } } diff --git a/core/src/main/java/com/linecorp/armeria/common/logging/RequestOnlyLog.java b/core/src/main/java/com/linecorp/armeria/common/logging/RequestOnlyLog.java index e6311a3310b..b0156a8743f 100644 --- a/core/src/main/java/com/linecorp/armeria/common/logging/RequestOnlyLog.java +++ b/core/src/main/java/com/linecorp/armeria/common/logging/RequestOnlyLog.java @@ -15,6 +15,9 @@ */ package com.linecorp.armeria.common.logging; +import static java.util.Objects.requireNonNull; + +import java.util.function.BiFunction; import java.util.function.Function; import javax.annotation.Nullable; @@ -24,10 +27,12 @@ import com.linecorp.armeria.client.logging.ContentPreviewingClient; import com.linecorp.armeria.common.HttpHeaders; import com.linecorp.armeria.common.Request; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.RequestHeaders; import com.linecorp.armeria.common.Scheme; import com.linecorp.armeria.common.SerializationFormat; import com.linecorp.armeria.common.SessionProtocol; +import com.linecorp.armeria.common.util.Functions; import com.linecorp.armeria.server.Service; import com.linecorp.armeria.server.logging.ContentPreviewingService; @@ -236,9 +241,15 @@ default long requestDurationNanos() { /** * Returns the string representation of the {@link Request}, with no sanitization of headers or content. + * This method is a shortcut for: + *
{@code
+     * toStringRequestOnly((ctx, headers) -> headers,
+     *                     (ctx, content) -> content,
+     *                     (ctx, trailers) -> trailers);
+     * }
*/ default String toStringRequestOnly() { - return toStringRequestOnly(Function.identity(), Function.identity(), Function.identity()); + return toStringRequestOnly(Functions.second(), Functions.second(), Functions.second()); } /** @@ -247,11 +258,45 @@ default String toStringRequestOnly() { * toStringRequestOnly(headersSanitizer, contentSanitizer, headersSanitizer); * } * - * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of the - * {@link Function} is what is actually logged as headers. - * @param contentSanitizer a {@link Function} for sanitizing request content for logging. The result of the - * {@link Function} is what is actually logged as content. + * @param headersSanitizer a {@link BiFunction} for sanitizing HTTP headers for logging. The result of + * the {@link BiFunction} is what is actually logged as headers. + * @param contentSanitizer a {@link BiFunction} for sanitizing request content for logging. The result of + * the {@link BiFunction} is what is actually logged as content. */ + default String toStringRequestOnly( + BiFunction headersSanitizer, + BiFunction contentSanitizer) { + return toStringRequestOnly(headersSanitizer, contentSanitizer, headersSanitizer); + } + + /** + * Returns the string representation of the {@link Request}. + * + * @param headersSanitizer a {@link BiFunction} for sanitizing HTTP headers for logging. The result of + * the {@link BiFunction} is what is actually logged as headers. + * @param contentSanitizer a {@link Function} for sanitizing request content for logging. The result of + * the {@link BiFunction} is what is actually logged as content. + * @param trailersSanitizer a {@link BiFunction} for sanitizing HTTP trailers for logging. The result of + * the {@link BiFunction} is what is actually logged as trailers. + */ + String toStringRequestOnly(BiFunction headersSanitizer, + BiFunction contentSanitizer, + BiFunction trailersSanitizer); + + /** + * Returns the string representation of the {@link Request}. This method is a shortcut for: + *
{@code
+     * toStringRequestOnly(headersSanitizer, contentSanitizer, headersSanitizer);
+     * }
+ * + * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of + * the {@link Function} is what is actually logged as headers. + * @param contentSanitizer a {@link Function} for sanitizing request content for logging. The result of + * the {@link Function} is what is actually logged as content. + * + * @deprecated Use {@link #toStringRequestOnly(BiFunction, BiFunction)}. + */ + @Deprecated default String toStringRequestOnly(Function headersSanitizer, Function contentSanitizer) { return toStringRequestOnly(headersSanitizer, contentSanitizer, headersSanitizer); @@ -260,14 +305,24 @@ default String toStringRequestOnly(Function headersSanit /** * Returns the string representation of the {@link Request}. * - * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of the - * {@link Function} is what is actually logged as headers. - * @param contentSanitizer a {@link Function} for sanitizing request content for logging. The result of the - * {@link Function} is what is actually logged as content. - * @param trailersSanitizer a {@link Function} for sanitizing HTTP trailers for logging. The result of the - * {@link Function} is what is actually logged as trailers. + * @param headersSanitizer a {@link Function} for sanitizing HTTP headers for logging. The result of + * the {@link Function} is what is actually logged as headers. + * @param contentSanitizer a {@link Function} for sanitizing request content for logging. The result of + * the {@link Function} is what is actually logged as content. + * @param trailersSanitizer a {@link Function} for sanitizing HTTP trailers for logging. The result of + * the {@link Function} is what is actually logged as trailers. + * + * @deprecated Use {@link #toStringRequestOnly(BiFunction, BiFunction, BiFunction)}. */ - String toStringRequestOnly(Function headersSanitizer, - Function contentSanitizer, - Function trailersSanitizer); + @Deprecated + default String toStringRequestOnly(Function headersSanitizer, + Function contentSanitizer, + Function trailersSanitizer) { + requireNonNull(headersSanitizer, "headersSanitizer"); + requireNonNull(contentSanitizer, "contentSanitizer"); + requireNonNull(trailersSanitizer, "trailersSanitizer"); + return toStringRequestOnly((ctx, headers) -> headersSanitizer.apply(headers), + (ctx, content) -> contentSanitizer.apply(content), + (ctx, trailers) -> trailersSanitizer.apply(trailers)); + } } diff --git a/core/src/main/java/com/linecorp/armeria/common/util/Functions.java b/core/src/main/java/com/linecorp/armeria/common/util/Functions.java index 6aceed524ce..7b4aa66233d 100644 --- a/core/src/main/java/com/linecorp/armeria/common/util/Functions.java +++ b/core/src/main/java/com/linecorp/armeria/common/util/Functions.java @@ -194,5 +194,19 @@ public static BiFunction voidFunction(BiConsumer consum }; } + /** + * Returns a {@link BiFunction} that returns the first argument. + */ + public static BiFunction first() { + return (first, second) -> first; + } + + /** + * Returns a {@link BiFunction} that returns the second argument. + */ + public static BiFunction second() { + return (first, second) -> second; + } + private Functions() {} } diff --git a/core/src/main/java/com/linecorp/armeria/internal/common/logging/LoggingDecorators.java b/core/src/main/java/com/linecorp/armeria/internal/common/logging/LoggingDecorators.java index 314b339c4e5..8cd399f9c2e 100644 --- a/core/src/main/java/com/linecorp/armeria/internal/common/logging/LoggingDecorators.java +++ b/core/src/main/java/com/linecorp/armeria/internal/common/logging/LoggingDecorators.java @@ -15,6 +15,7 @@ */ package com.linecorp.armeria.internal.common.logging; +import java.util.function.BiFunction; import java.util.function.Function; import org.slf4j.Logger; @@ -44,9 +45,9 @@ private LoggingDecorators() {} public static void logRequest( Logger logger, RequestOnlyLog log, Function requestLogLevelMapper, - Function requestHeadersSanitizer, - Function requestContentSanitizer, - Function requestTrailersSanitizer) { + BiFunction requestHeadersSanitizer, + BiFunction requestContentSanitizer, + BiFunction requestTrailersSanitizer) { final LogLevel requestLogLevel = requestLogLevelMapper.apply(log); if (requestLogLevel.isEnabled(logger)) { @@ -67,13 +68,14 @@ public static void logResponse( Logger logger, RequestLog log, Function requestLogLevelMapper, Function responseLogLevelMapper, - Function requestHeadersSanitizer, - Function requestContentSanitizer, - Function requestTrailersSanitizer, - Function responseHeadersSanitizer, - Function responseContentSanitizer, - Function responseTrailersSanitizer, - Function responseCauseSanitizer) { + BiFunction requestHeadersSanitizer, + BiFunction requestContentSanitizer, + BiFunction requestTrailersSanitizer, + BiFunction responseHeadersSanitizer, + BiFunction responseContentSanitizer, + BiFunction responseTrailersSanitizer, + BiFunction responseCauseSanitizer) { + final LogLevel responseLogLevel = responseLogLevelMapper.apply(log); final Throwable responseCause = log.responseCause(); @@ -98,7 +100,7 @@ public static void logResponse( requestTrailersSanitizer)); } - final Object sanitizedResponseCause = responseCauseSanitizer.apply(responseCause); + final Object sanitizedResponseCause = responseCauseSanitizer.apply(ctx, responseCause); if (sanitizedResponseCause == null) { responseLogLevel.log(logger, RESPONSE_FORMAT, ctx, responseStr); return; diff --git a/core/src/main/java/com/linecorp/armeria/server/logging/LoggingService.java b/core/src/main/java/com/linecorp/armeria/server/logging/LoggingService.java index 6ea3b4ee5fe..ebfa0725eb1 100644 --- a/core/src/main/java/com/linecorp/armeria/server/logging/LoggingService.java +++ b/core/src/main/java/com/linecorp/armeria/server/logging/LoggingService.java @@ -21,6 +21,7 @@ import static com.linecorp.armeria.internal.common.logging.LoggingDecorators.logResponse; import static java.util.Objects.requireNonNull; +import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; @@ -32,6 +33,7 @@ import com.linecorp.armeria.common.HttpHeaders; import com.linecorp.armeria.common.HttpRequest; import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.RequestHeaders; import com.linecorp.armeria.common.ResponseHeaders; import com.linecorp.armeria.common.logging.LogLevel; @@ -75,14 +77,16 @@ public static LoggingServiceBuilder builder() { private final Logger logger; private final Function requestLogLevelMapper; private final Function responseLogLevelMapper; - private final Function requestHeadersSanitizer; - private final Function requestContentSanitizer; - private final Function requestTrailersSanitizer; - - private final Function responseHeadersSanitizer; - private final Function responseContentSanitizer; - private final Function responseTrailersSanitizer; - private final Function responseCauseSanitizer; + + private final BiFunction requestHeadersSanitizer; + private final BiFunction requestContentSanitizer; + private final BiFunction requestTrailersSanitizer; + + private final BiFunction responseHeadersSanitizer; + private final BiFunction responseContentSanitizer; + private final BiFunction responseTrailersSanitizer; + private final BiFunction responseCauseSanitizer; + private final Sampler sampler; /** @@ -94,13 +98,13 @@ public static LoggingServiceBuilder builder() { @Nullable Logger logger, Function requestLogLevelMapper, Function responseLogLevelMapper, - Function requestHeadersSanitizer, - Function requestContentSanitizer, - Function requestTrailersSanitizer, - Function responseHeadersSanitizer, - Function responseContentSanitizer, - Function responseTrailersSanitizer, - Function responseCauseSanitizer, + BiFunction requestHeadersSanitizer, + BiFunction requestContentSanitizer, + BiFunction requestTrailersSanitizer, + BiFunction responseHeadersSanitizer, + BiFunction responseContentSanitizer, + BiFunction responseTrailersSanitizer, + BiFunction responseCauseSanitizer, Sampler sampler) { super(requireNonNull(delegate, "delegate")); diff --git a/core/src/main/java/com/linecorp/armeria/server/logging/LoggingServiceBuilder.java b/core/src/main/java/com/linecorp/armeria/server/logging/LoggingServiceBuilder.java index 344bf9d4f80..5b72856a2ec 100644 --- a/core/src/main/java/com/linecorp/armeria/server/logging/LoggingServiceBuilder.java +++ b/core/src/main/java/com/linecorp/armeria/server/logging/LoggingServiceBuilder.java @@ -19,11 +19,13 @@ import static com.google.common.base.Preconditions.checkArgument; import static java.util.Objects.requireNonNull; +import java.util.function.BiFunction; import java.util.function.Function; import org.slf4j.Logger; import com.linecorp.armeria.common.HttpHeaders; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.logging.LogLevel; import com.linecorp.armeria.common.logging.LoggingDecoratorBuilder; import com.linecorp.armeria.common.logging.RequestLog; @@ -120,50 +122,113 @@ public LoggingServiceBuilder responseLogLevelMapper( } @Override + public LoggingServiceBuilder requestHeadersSanitizer( + BiFunction requestHeadersSanitizer) { + return (LoggingServiceBuilder) super.requestHeadersSanitizer(requestHeadersSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder requestHeadersSanitizer( Function requestHeadersSanitizer) { return (LoggingServiceBuilder) super.requestHeadersSanitizer(requestHeadersSanitizer); } @Override + public LoggingServiceBuilder responseHeadersSanitizer( + BiFunction responseHeadersSanitizer) { + return (LoggingServiceBuilder) super.responseHeadersSanitizer(responseHeadersSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder responseHeadersSanitizer( Function responseHeadersSanitizer) { return (LoggingServiceBuilder) super.responseHeadersSanitizer(responseHeadersSanitizer); } @Override + public LoggingServiceBuilder requestTrailersSanitizer( + BiFunction requestTrailersSanitizer) { + return (LoggingServiceBuilder) super.requestTrailersSanitizer(requestTrailersSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder requestTrailersSanitizer( Function requestTrailersSanitizer) { return (LoggingServiceBuilder) super.requestTrailersSanitizer(requestTrailersSanitizer); } @Override + public LoggingServiceBuilder responseTrailersSanitizer( + BiFunction responseTrailersSanitizer) { + return (LoggingServiceBuilder) super.responseTrailersSanitizer(responseTrailersSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder responseTrailersSanitizer( Function responseTrailersSanitizer) { return (LoggingServiceBuilder) super.responseTrailersSanitizer(responseTrailersSanitizer); } @Override + public LoggingServiceBuilder headersSanitizer( + BiFunction headersSanitizer) { + return (LoggingServiceBuilder) super.headersSanitizer(headersSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder headersSanitizer(Function headersSanitizer) { return (LoggingServiceBuilder) super.headersSanitizer(headersSanitizer); } @Override + public LoggingServiceBuilder requestContentSanitizer( + BiFunction requestContentSanitizer) { + return (LoggingServiceBuilder) super.requestContentSanitizer(requestContentSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder requestContentSanitizer(Function requestContentSanitizer) { return (LoggingServiceBuilder) super.requestContentSanitizer(requestContentSanitizer); } @Override + public LoggingServiceBuilder responseContentSanitizer( + BiFunction responseContentSanitizer) { + return (LoggingServiceBuilder) super.responseContentSanitizer(responseContentSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder responseContentSanitizer(Function responseContentSanitizer) { return (LoggingServiceBuilder) super.responseContentSanitizer(responseContentSanitizer); } @Override + public LoggingServiceBuilder contentSanitizer( + BiFunction contentSanitizer) { + return (LoggingServiceBuilder) super.contentSanitizer(contentSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder contentSanitizer(Function contentSanitizer) { return (LoggingServiceBuilder) super.contentSanitizer(contentSanitizer); } @Override + public LoggingServiceBuilder responseCauseSanitizer( + BiFunction responseCauseSanitizer) { + return (LoggingServiceBuilder) super.responseCauseSanitizer(responseCauseSanitizer); + } + + @Override + @Deprecated public LoggingServiceBuilder responseCauseSanitizer( Function responseCauseSanitizer) { return (LoggingServiceBuilder) super.responseCauseSanitizer(responseCauseSanitizer); diff --git a/core/src/test/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilderTest.java b/core/src/test/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilderTest.java index d7546255585..f7d8b69feea 100644 --- a/core/src/test/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilderTest.java +++ b/core/src/test/java/com/linecorp/armeria/common/logging/LoggingDecoratorBuilderTest.java @@ -13,26 +13,48 @@ * License for the specific language governing permissions and limitations * under the License. */ - package com.linecorp.armeria.common.logging; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; -import java.util.function.Function; +import java.util.function.BiFunction; + +import javax.annotation.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import com.linecorp.armeria.common.HttpHeaders; +import com.linecorp.armeria.common.RequestContext; +import com.linecorp.armeria.common.util.Functions; class LoggingDecoratorBuilderTest { - private static final Function HEADER_SANITIZER = header -> "dummy header sanitizer"; - private static final Function CONTENT_SANITIZER = object -> "dummy content sanitizer"; - private static final Function CAUSE_SANITIZER = object -> "dummy cause sanitizer"; + @Nullable + @SuppressWarnings("rawtypes") + private static final BiFunction nullBiFunction = null; + + private static final BiFunction HEADER_SANITIZER = + (ctx, headers) -> { + assertThat(ctx).isNotNull(); + assertThat(headers).isNotNull(); + return "dummy header sanitizer"; + }; + private static final BiFunction CONTENT_SANITIZER = + (ctx, content) -> { + assertThat(ctx).isNotNull(); + assertThat(content).isNotNull(); + return "dummy content sanitizer"; + }; + private static final BiFunction CAUSE_SANITIZER = + (ctx, cause) -> { + assertThat(ctx).isNotNull(); + assertThat(cause).isNotNull(); + return "dummy cause sanitizer"; + }; private Builder builder; @@ -84,9 +106,9 @@ void failureResponseLogLevel() { @Test void requestHeadersSanitizer() { - assertThatThrownBy(() -> builder.requestHeadersSanitizer(null)) + assertThatThrownBy(() -> builder.requestHeadersSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); - assertThat(builder.requestHeadersSanitizer()).isEqualTo(Function.identity()); + assertThat(builder.requestHeadersSanitizer()).isEqualTo(Functions.second()); builder.requestHeadersSanitizer(HEADER_SANITIZER); assertThat(builder.requestHeadersSanitizer()).isEqualTo(HEADER_SANITIZER); @@ -94,9 +116,9 @@ void requestHeadersSanitizer() { @Test void responseHeadersSanitizer() { - assertThatThrownBy(() -> builder.responseHeadersSanitizer(null)) + assertThatThrownBy(() -> builder.responseHeadersSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); - assertThat(builder.responseHeadersSanitizer()).isEqualTo(Function.identity()); + assertThat(builder.responseHeadersSanitizer()).isEqualTo(Functions.second()); builder.responseHeadersSanitizer(HEADER_SANITIZER); assertThat(builder.responseHeadersSanitizer()).isEqualTo(HEADER_SANITIZER); @@ -104,9 +126,9 @@ void responseHeadersSanitizer() { @Test void requestTrailersSanitizer() { - assertThatThrownBy(() -> builder.requestTrailersSanitizer(null)) + assertThatThrownBy(() -> builder.requestTrailersSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); - assertThat(builder.requestTrailersSanitizer()).isEqualTo(Function.identity()); + assertThat(builder.requestTrailersSanitizer()).isEqualTo(Functions.second()); builder.requestTrailersSanitizer(HEADER_SANITIZER); assertThat(builder.requestTrailersSanitizer()).isEqualTo(HEADER_SANITIZER); @@ -114,9 +136,9 @@ void requestTrailersSanitizer() { @Test void responseTrailersSanitizer() { - assertThatThrownBy(() -> builder.responseTrailersSanitizer(null)) + assertThatThrownBy(() -> builder.responseTrailersSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); - assertThat(builder.responseTrailersSanitizer()).isEqualTo(Function.identity()); + assertThat(builder.responseTrailersSanitizer()).isEqualTo(Functions.second()); builder.responseTrailersSanitizer(HEADER_SANITIZER); assertThat(builder.responseTrailersSanitizer()).isEqualTo(HEADER_SANITIZER); @@ -124,7 +146,7 @@ void responseTrailersSanitizer() { @Test void headerSanitizer() { - assertThatThrownBy(() -> builder.headersSanitizer(null)) + assertThatThrownBy(() -> builder.headersSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); builder.headersSanitizer(HEADER_SANITIZER); @@ -136,9 +158,9 @@ void headerSanitizer() { @Test void requestContentSanitizer() { - assertThatThrownBy(() -> builder.requestContentSanitizer(null)) + assertThatThrownBy(() -> builder.requestContentSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); - assertThat(builder.requestContentSanitizer()).isEqualTo(Function.identity()); + assertThat(builder.requestContentSanitizer()).isEqualTo(Functions.second()); builder.requestContentSanitizer(CONTENT_SANITIZER); assertThat(builder.requestContentSanitizer()).isEqualTo(CONTENT_SANITIZER); @@ -146,9 +168,9 @@ void requestContentSanitizer() { @Test void responseContentSanitizer() { - assertThatThrownBy(() -> builder.responseContentSanitizer(null)) + assertThatThrownBy(() -> builder.responseContentSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); - assertThat(builder.responseContentSanitizer()).isEqualTo(Function.identity()); + assertThat(builder.responseContentSanitizer()).isEqualTo(Functions.second()); builder.responseContentSanitizer(CONTENT_SANITIZER); assertThat(builder.responseContentSanitizer()).isEqualTo(CONTENT_SANITIZER); @@ -156,7 +178,7 @@ void responseContentSanitizer() { @Test void contentSanitizer() { - assertThatThrownBy(() -> builder.contentSanitizer(null)) + assertThatThrownBy(() -> builder.contentSanitizer(nullBiFunction)) .isInstanceOf(NullPointerException.class); builder.contentSanitizer(CONTENT_SANITIZER); @@ -166,8 +188,9 @@ void contentSanitizer() { @Test void responseCauseSanitizer() { - assertThatThrownBy(() -> builder.responseCauseSanitizer(null)).isInstanceOf(NullPointerException.class); - assertThat(builder.responseCauseSanitizer()).isEqualTo(Function.identity()); + assertThatThrownBy(() -> builder.responseCauseSanitizer(nullBiFunction)) + .isInstanceOf(NullPointerException.class); + assertThat(builder.responseCauseSanitizer()).isEqualTo(Functions.second()); builder.responseCauseSanitizer(CAUSE_SANITIZER); assertThat(builder.responseCauseSanitizer()).isEqualTo(CAUSE_SANITIZER); diff --git a/core/src/test/java/com/linecorp/armeria/server/logging/LoggingServiceTest.java b/core/src/test/java/com/linecorp/armeria/server/logging/LoggingServiceTest.java index 1179878a5af..deeb3dfcd55 100644 --- a/core/src/test/java/com/linecorp/armeria/server/logging/LoggingServiceTest.java +++ b/core/src/test/java/com/linecorp/armeria/server/logging/LoggingServiceTest.java @@ -29,7 +29,7 @@ import static org.mockito.Mockito.when; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; +import java.util.function.BiFunction; import java.util.regex.Pattern; import org.junit.jupiter.api.AfterEach; @@ -41,6 +41,7 @@ import com.linecorp.armeria.common.HttpMethod; import com.linecorp.armeria.common.HttpRequest; import com.linecorp.armeria.common.HttpResponse; +import com.linecorp.armeria.common.RequestContext; import com.linecorp.armeria.common.RequestHeaders; import com.linecorp.armeria.common.ResponseHeaders; import com.linecorp.armeria.common.logging.LogLevel; @@ -255,12 +256,18 @@ void sanitize() throws Exception { final String sanitizedResponseHeaders = "sanitizedResponseHeaders"; final String sanitizedResponseContent = "sanitizedResponseContent"; final String sanitizedResponseTrailers = "sanitizedResponseTrailer"; - final Function requestHeadersSanitizer = headers -> sanitizedRequestHeaders; - final Function requestContentSanitizer = content -> sanitizedRequestContent; - final Function requestTrailersSanitizer = trailers -> sanitizedRequestTrailers; - final Function responseHeadersSanitizer = headers -> sanitizedResponseHeaders; - final Function responseContentSanitizer = content -> sanitizedResponseContent; - final Function responseTrailersSanitizer = trailers -> sanitizedResponseTrailers; + final BiFunction requestHeadersSanitizer = + (ctx, headers) -> sanitizedRequestHeaders; + final BiFunction requestContentSanitizer = + (ctx, content) -> sanitizedRequestContent; + final BiFunction requestTrailersSanitizer = + (ctx, trailers) -> sanitizedRequestTrailers; + final BiFunction responseHeadersSanitizer = + (ctx, headers) -> sanitizedResponseHeaders; + final BiFunction responseContentSanitizer = + (ctx, content) -> sanitizedResponseContent; + final BiFunction responseTrailersSanitizer = + (ctx, trailers) -> sanitizedResponseTrailers; final ServiceRequestContext ctx = ServiceRequestContext.of(HttpRequest.of(HttpMethod.GET, "/")); ctx.logBuilder().requestContent(new Object(), new Object()); @@ -300,7 +307,8 @@ void sanitize() throws Exception { @Test void sanitizeExceptionIntoException() throws Exception { final Exception sanitizedResponseCause = new Exception("sanitized"); - final Function responseCauseSanitizer = cause -> sanitizedResponseCause; + final BiFunction responseCauseSanitizer = + (ctx, cause) -> sanitizedResponseCause; final ServiceRequestContext ctx = ServiceRequestContext.of(HttpRequest.of(HttpMethod.GET, "/")); ctx.logBuilder().endResponse(new Exception("not sanitized")); @@ -328,7 +336,8 @@ void sanitizeExceptionIntoException() throws Exception { @Test void sanitizeExceptionIntoString() throws Exception { final String sanitizedResponseCause = "sanitizedResponseCause"; - final Function responseCauseSanitizer = cause -> sanitizedResponseCause; + final BiFunction responseCauseSanitizer = + (ctx, cause) -> sanitizedResponseCause; final ServiceRequestContext ctx = ServiceRequestContext.of(HttpRequest.of(HttpMethod.GET, "/")); ctx.logBuilder().endResponse(new Exception("not sanitized")); @@ -401,7 +410,7 @@ void sanitizeRequestContent() throws Exception { .requestLogLevel(LogLevel.INFO) .successfulResponseLogLevel(LogLevel.INFO) .requestContentSanitizer(RegexBasedSanitizer.of( - Pattern.compile("\\d{3}[-\\.\\s]\\d{3}[-\\.\\s]\\d{4}"))) + Pattern.compile("\\d{3}[-.\\s]\\d{3}[-.\\s]\\d{4}"))) .newDecorator().apply(delegate); assertThat(ctx.logBuilder().toString()).contains("333-490-4499");