Skip to content

Commit 8bd8a4e

Browse files
committed
Fix a bug where the default HeadersSanitizer in logging decorators
Motivation: `HeadersSanitizer` was added in line#5188. If no `HeadersSanitizer` is set, the default santizer masks `Authorization`, `Cookie` `Set-Cookie` and `Proxy-Authorization` with `****`. In addition to `HeadersSantizer`, other new features are added to `LoggingDecoratorBuilder` and the code became messy to maintain backward compatibility. `LoggingDecoratorBuilder`, `LogWriterBuilder`, and `LogFormatterBuilder` each have their own properties, so it was not easy to make the overall operation consistent. As a result, while `LoggingClient.newDecorator()` santizes sensitive headers, LoggingClient.builder().requestLogLevel(...).newDecorator()` did not work. Neither code set a sanitizer, so a default sanitizer should have been set, but it didn't. Modifications: - Refactor `LoggingDecoratorBuilder` to delegate all builder properties to either `LogWriterBuilder` or `LogFormatterBuilder`. - Add missing `@Deprecated` annotation to `LoggingClientBuilder` and `LoggingRpcClientBuilder` and `LoggingServiceBuilder`. - `@Deprecated` in the super method aren't inspected by IntelliJ line#5395 - Breaking) Change the signature of `LogWriterBuilder.responseCauseFilter()` to have `RequestContext` as the first parameter. - It may be a bug or a mistake when adding the API. Our APIs usually provide `RequestContext` for predicates or handlers. Result: `LoggingClient` and `LoggingService` now correctly mask sensitive headers by default.
1 parent c960d23 commit 8bd8a4e

File tree

10 files changed

+400
-248
lines changed

10 files changed

+400
-248
lines changed

core/src/main/java/com/linecorp/armeria/client/logging/LoggingClientBuilder.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ public Function<? super HttpClient, LoggingClient> newDecorator() {
6161
// Override the return type of the chaining methods in the superclass.
6262

6363
@Override
64-
protected LoggingClientBuilder defaultLogger(Logger logger) {
65-
return (LoggingClientBuilder) super.defaultLogger(logger);
64+
protected LoggingClientBuilder defaultLogger(Logger defaultLogger) {
65+
return (LoggingClientBuilder) super.defaultLogger(defaultLogger);
6666
}
6767

6868
@Override
@@ -95,23 +95,33 @@ public LoggingClientBuilder failureSamplingRate(float samplingRate) {
9595
return (LoggingClientBuilder) super.failureSamplingRate(samplingRate);
9696
}
9797

98+
@Override
99+
public LoggingClientBuilder logWriter(LogWriter logWriter) {
100+
return (LoggingClientBuilder) super.logWriter(logWriter);
101+
}
102+
98103
// Override the return type of the chaining methods in the super-superclass.
104+
// All methods below are deprecated.
99105

106+
@Deprecated
100107
@Override
101108
public LoggingClientBuilder logger(Logger logger) {
102109
return (LoggingClientBuilder) super.logger(logger);
103110
}
104111

112+
@Deprecated
105113
@Override
106114
public LoggingClientBuilder logger(String loggerName) {
107115
return (LoggingClientBuilder) super.logger(loggerName);
108116
}
109117

118+
@Deprecated
110119
@Override
111120
public LoggingClientBuilder requestLogLevel(LogLevel requestLogLevel) {
112121
return (LoggingClientBuilder) super.requestLogLevel(requestLogLevel);
113122
}
114123

124+
@Deprecated
115125
@Override
116126
public LoggingClientBuilder requestLogLevel(Class<? extends Throwable> clazz, LogLevel requestLogLevel) {
117127
return (LoggingClientBuilder) super.requestLogLevel(clazz, requestLogLevel);
@@ -124,31 +134,37 @@ public LoggingClientBuilder requestLogLevelMapper(
124134
return (LoggingClientBuilder) super.requestLogLevelMapper(requestLogLevelMapper);
125135
}
126136

137+
@Deprecated
127138
@Override
128139
public LoggingClientBuilder requestLogLevelMapper(RequestLogLevelMapper requestLogLevelMapper) {
129140
return (LoggingClientBuilder) super.requestLogLevelMapper(requestLogLevelMapper);
130141
}
131142

143+
@Deprecated
132144
@Override
133145
public LoggingClientBuilder responseLogLevel(HttpStatus status, LogLevel logLevel) {
134146
return (LoggingClientBuilder) super.responseLogLevel(status, logLevel);
135147
}
136148

149+
@Deprecated
137150
@Override
138151
public LoggingClientBuilder responseLogLevel(HttpStatusClass statusClass, LogLevel logLevel) {
139152
return (LoggingClientBuilder) super.responseLogLevel(statusClass, logLevel);
140153
}
141154

155+
@Deprecated
142156
@Override
143157
public LoggingClientBuilder responseLogLevel(Class<? extends Throwable> clazz, LogLevel logLevel) {
144158
return (LoggingClientBuilder) super.responseLogLevel(clazz, logLevel);
145159
}
146160

161+
@Deprecated
147162
@Override
148163
public LoggingClientBuilder successfulResponseLogLevel(LogLevel successfulResponseLogLevel) {
149164
return (LoggingClientBuilder) super.successfulResponseLogLevel(successfulResponseLogLevel);
150165
}
151166

167+
@Deprecated
152168
@Override
153169
public LoggingClientBuilder failureResponseLogLevel(LogLevel failureResponseLogLevel) {
154170
return (LoggingClientBuilder) super.failureResponseLogLevel(failureResponseLogLevel);
@@ -161,6 +177,7 @@ public LoggingClientBuilder responseLogLevelMapper(
161177
return (LoggingClientBuilder) super.responseLogLevelMapper(responseLogLevelMapper);
162178
}
163179

180+
@Deprecated
164181
@Override
165182
public LoggingClientBuilder responseLogLevelMapper(ResponseLogLevelMapper responseLogLevelMapper) {
166183
return (LoggingClientBuilder) super.responseLogLevelMapper(responseLogLevelMapper);
@@ -238,13 +255,9 @@ public LoggingClientBuilder responseCauseSanitizer(
238255
return (LoggingClientBuilder) super.responseCauseSanitizer(responseCauseSanitizer);
239256
}
240257

258+
@Deprecated
241259
@Override
242260
public LoggingClientBuilder responseCauseFilter(Predicate<Throwable> responseCauseFilter) {
243261
return (LoggingClientBuilder) super.responseCauseFilter(responseCauseFilter);
244262
}
245-
246-
@Override
247-
public LoggingClientBuilder logWriter(LogWriter logWriter) {
248-
return (LoggingClientBuilder) super.logWriter(logWriter);
249-
}
250263
}

core/src/main/java/com/linecorp/armeria/client/logging/LoggingRpcClientBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ public Function<? super RpcClient, LoggingRpcClient> newDecorator() {
6464
// Override the return type of the chaining methods in the superclass.
6565

6666
@Override
67-
protected LoggingRpcClientBuilder defaultLogger(Logger logger) {
68-
return (LoggingRpcClientBuilder) super.defaultLogger(logger);
67+
protected LoggingRpcClientBuilder defaultLogger(Logger defaultLogger) {
68+
return (LoggingRpcClientBuilder) super.defaultLogger(defaultLogger);
6969
}
7070

7171
@Override

core/src/main/java/com/linecorp/armeria/common/logging/AbstractLogFormatterBuilder.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ abstract class AbstractLogFormatterBuilder<T> {
6666
* .requestHeadersSanitizer(headersSanitizer)
6767
* ...
6868
* }</pre>
69+
*
70+
* @see HeadersSanitizer
6971
*/
7072
public AbstractLogFormatterBuilder<T> requestHeadersSanitizer(
7173
BiFunction<? super RequestContext, ? super HttpHeaders, ? extends T> requestHeadersSanitizer) {
@@ -101,6 +103,8 @@ final HeadersSanitizer<T> requestHeadersSanitizer() {
101103
* .responseHeadersSanitizer(headersSanitizer)
102104
* ...
103105
* }</pre>
106+
*
107+
* @see HeadersSanitizer
104108
*/
105109
public AbstractLogFormatterBuilder<T> responseHeadersSanitizer(
106110
BiFunction<? super RequestContext, ? super HttpHeaders, ? extends T> responseHeadersSanitizer) {
@@ -135,6 +139,8 @@ final HeadersSanitizer<T> responseHeadersSanitizer() {
135139
* .requestTrailersSanitizer(headersSanitizer)
136140
* ...
137141
* }</pre>
142+
*
143+
* @see HeadersSanitizer
138144
*/
139145
public AbstractLogFormatterBuilder<T> requestTrailersSanitizer(
140146
BiFunction<? super RequestContext, ? super HttpHeaders, ? extends T> requestTrailersSanitizer) {
@@ -169,6 +175,8 @@ final HeadersSanitizer<T> requestTrailersSanitizer() {
169175
* .responseTrailersSanitizer(headersSanitizer)
170176
* ...
171177
* }</pre>
178+
*
179+
* @see HeadersSanitizer
172180
*/
173181
public AbstractLogFormatterBuilder<T> responseTrailersSanitizer(
174182
BiFunction<? super RequestContext, ? super HttpHeaders, ? extends T> responseTrailersSanitizer) {
@@ -204,6 +212,7 @@ final HeadersSanitizer<T> responseTrailersSanitizer() {
204212
* builder.responseTrailersSanitizer(headersSanitizer);
205213
* }</pre>
206214
*
215+
* @see HeadersSanitizer
207216
* @see #requestHeadersSanitizer(BiFunction)
208217
* @see #requestTrailersSanitizer(BiFunction)
209218
* @see #responseHeadersSanitizer(BiFunction)

core/src/main/java/com/linecorp/armeria/common/logging/DefaultLogWriter.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@
2121
import static com.linecorp.armeria.common.logging.LogWriterBuilder.DEFAULT_RESPONSE_LOG_LEVEL_MAPPER;
2222
import static java.util.Objects.requireNonNull;
2323

24-
import java.util.function.Predicate;
24+
import java.util.function.BiPredicate;
2525

2626
import org.slf4j.Logger;
2727
import org.slf4j.LoggerFactory;
2828

2929
import com.google.common.base.MoreObjects;
3030

31+
import com.linecorp.armeria.common.RequestContext;
3132
import com.linecorp.armeria.common.util.SafeCloseable;
3233

3334
final class DefaultLogWriter implements LogWriter {
@@ -37,20 +38,21 @@ final class DefaultLogWriter implements LogWriter {
3738
static final DefaultLogWriter DEFAULT =
3839
new DefaultLogWriter(defaultLogger, DEFAULT_REQUEST_LOG_LEVEL_MAPPER,
3940
DEFAULT_RESPONSE_LOG_LEVEL_MAPPER,
40-
throwable -> false, LogFormatter.ofText());
41+
(ctx, throwable) -> false, LogFormatter.ofText());
4142

4243
private static boolean warnedNullRequestLogLevelMapper;
4344
private static boolean warnedNullResponseLogLevelMapper;
4445

4546
private final Logger logger;
4647
private final RequestLogLevelMapper requestLogLevelMapper;
4748
private final ResponseLogLevelMapper responseLogLevelMapper;
48-
private final Predicate<? super Throwable> responseCauseFilter;
49+
private final BiPredicate<? super RequestContext, ? super Throwable> responseCauseFilter;
4950
private final LogFormatter logFormatter;
5051

5152
DefaultLogWriter(Logger logger, RequestLogLevelMapper requestLogLevelMapper,
5253
ResponseLogLevelMapper responseLogLevelMapper,
53-
Predicate<? super Throwable> responseCauseFilter, LogFormatter logFormatter) {
54+
BiPredicate<? super RequestContext, ? super Throwable> responseCauseFilter,
55+
LogFormatter logFormatter) {
5456
this.logger = logger;
5557
this.requestLogLevelMapper = requestLogLevelMapper;
5658
this.responseLogLevelMapper = responseLogLevelMapper;
@@ -94,7 +96,8 @@ public void logResponse(RequestLog log) {
9496

9597
if (responseLogLevel.isEnabled(logger)) {
9698
final String responseStr = logFormatter.formatResponse(log);
97-
try (SafeCloseable ignored = log.context().push()) {
99+
final RequestContext ctx = log.context();
100+
try (SafeCloseable ignored = ctx.push()) {
98101
if (responseCause == null) {
99102
responseLogLevel.log(logger, responseStr);
100103
return;
@@ -108,7 +111,7 @@ public void logResponse(RequestLog log) {
108111
responseLogLevel.log(logger, logFormatter.formatRequest(log));
109112
}
110113

111-
if (responseCauseFilter.test(responseCause)) {
114+
if (responseCauseFilter.test(ctx, responseCause)) {
112115
responseLogLevel.log(logger, responseStr);
113116
} else {
114117
responseLogLevel.log(logger, responseStr, responseCause);

core/src/main/java/com/linecorp/armeria/common/logging/LogWriterBuilder.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,18 @@
1616

1717
package com.linecorp.armeria.common.logging;
1818

19+
import static com.google.common.base.MoreObjects.firstNonNull;
1920
import static java.util.Objects.requireNonNull;
2021

22+
import java.util.function.BiPredicate;
2123
import java.util.function.Predicate;
2224

2325
import org.slf4j.Logger;
2426
import org.slf4j.LoggerFactory;
2527

2628
import com.linecorp.armeria.common.HttpStatus;
2729
import com.linecorp.armeria.common.HttpStatusClass;
30+
import com.linecorp.armeria.common.RequestContext;
2831
import com.linecorp.armeria.common.annotation.Nullable;
2932
import com.linecorp.armeria.common.annotation.UnstableApi;
3033

@@ -42,12 +45,14 @@ public final class LogWriterBuilder {
4245
static final ResponseLogLevelMapper DEFAULT_RESPONSE_LOG_LEVEL_MAPPER =
4346
ResponseLogLevelMapper.of(LogLevel.DEBUG, LogLevel.WARN);
4447

45-
private Logger logger = DefaultLogWriter.defaultLogger;
48+
@Nullable
49+
private Logger logger;
4650
@Nullable
4751
private RequestLogLevelMapper requestLogLevelMapper;
4852
@Nullable
4953
private ResponseLogLevelMapper responseLogLevelMapper;
50-
private Predicate<? super Throwable> responseCauseFilter = throwable -> false;
54+
private BiPredicate<? super RequestContext, ? super Throwable> responseCauseFilter =
55+
(ctx, cause) -> false;
5156
private LogFormatter logFormatter = LogFormatter.ofText();
5257

5358
LogWriterBuilder() {}
@@ -71,6 +76,11 @@ public LogWriterBuilder logger(String loggerName) {
7176
return this;
7277
}
7378

79+
@Nullable
80+
Logger logger() {
81+
return logger;
82+
}
83+
7484
/**
7585
* Sets the {@link LogLevel} to use when logging requests. If unset, will use {@link LogLevel#DEBUG}.
7686
*/
@@ -101,7 +111,7 @@ public LogWriterBuilder requestLogLevelMapper(RequestLogLevelMapper requestLogLe
101111
return this;
102112
}
103113

104-
private RequestLogLevelMapper requestLogLevelMapper() {
114+
RequestLogLevelMapper requestLogLevelMapper() {
105115
if (requestLogLevelMapper == null) {
106116
return DEFAULT_REQUEST_LOG_LEVEL_MAPPER;
107117
}
@@ -164,7 +174,7 @@ public LogWriterBuilder responseLogLevelMapper(ResponseLogLevelMapper responseLo
164174
return this;
165175
}
166176

167-
private ResponseLogLevelMapper responseLogLevelMapper() {
177+
ResponseLogLevelMapper responseLogLevelMapper() {
168178
if (responseLogLevelMapper == null) {
169179
return DEFAULT_RESPONSE_LOG_LEVEL_MAPPER;
170180
}
@@ -176,7 +186,8 @@ private ResponseLogLevelMapper responseLogLevelMapper() {
176186
* You can prevent logging the response cause by returning {@code true}
177187
* in the {@link Predicate}. By default, the response cause will always be logged.
178188
*/
179-
public LogWriterBuilder responseCauseFilter(Predicate<? super Throwable> responseCauseFilter) {
189+
public LogWriterBuilder responseCauseFilter(
190+
BiPredicate<? super RequestContext, ? super Throwable> responseCauseFilter) {
180191
this.responseCauseFilter = requireNonNull(responseCauseFilter, "responseCauseFilter");
181192
return this;
182193
}
@@ -196,7 +207,8 @@ public LogWriterBuilder logFormatter(LogFormatter logFormatter) {
196207
* Returns a newly-created {@link LogWriter} based on the properties of this builder.
197208
*/
198209
public LogWriter build() {
199-
return new DefaultLogWriter(logger, requestLogLevelMapper(), responseLogLevelMapper(),
210+
return new DefaultLogWriter(firstNonNull(logger, DefaultLogWriter.defaultLogger),
211+
requestLogLevelMapper(), responseLogLevelMapper(),
200212
responseCauseFilter, logFormatter);
201213
}
202214
}

0 commit comments

Comments
 (0)