-
Notifications
You must be signed in to change notification settings - Fork 927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix a bug where the default HeadersSanitizer
does not work in logging decorators
#5519
Conversation
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.
HeadersSanitizer
in logging decoratorsHeadersSanitizer
does not work in logging decorators
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5519 +/- ##
===========================================
+ Coverage 0 74.07% +74.07%
- Complexity 0 20807 +20807
===========================================
Files 0 1801 +1801
Lines 0 76558 +76558
Branches 0 9749 +9749
===========================================
+ Hits 0 56708 +56708
- Misses 0 15233 +15233
- Partials 0 4617 +4617 ☔ View full report in Codecov by Sentry. |
} | ||
|
||
@Override | ||
public String toString() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this since we reached a consensus that toString()
is not a mandatory implementation for builder classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some nits, but the fix looks solid 👍 Thanks @ikhoon ! 🙇 👍 🙇
@@ -176,7 +186,8 @@ private ResponseLogLevelMapper responseLogLevelMapper() { | |||
* You can prevent logging the response cause by returning {@code true} | |||
* in the {@link Predicate}. By default, the response cause will always be logged. | |||
*/ | |||
public LogWriterBuilder responseCauseFilter(Predicate<? super Throwable> responseCauseFilter) { | |||
public LogWriterBuilder responseCauseFilter( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional) I think we can avoid breaking changes by maintaining both methods ((ctx, t) -> bool
, (t) -> (bool)
).
Having said this, I've searched for usages and I think there aren't any usages so far
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought changing was okay since the API is unstable and was added recently.
@@ -42,12 +45,14 @@ public final class LogWriterBuilder { | |||
static final ResponseLogLevelMapper DEFAULT_RESPONSE_LOG_LEVEL_MAPPER = | |||
ResponseLogLevelMapper.of(LogLevel.DEBUG, LogLevel.WARN); | |||
|
|||
private Logger logger = DefaultLogWriter.defaultLogger; | |||
@Nullable | |||
private Logger logger; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understood this change is just a change of code style and there is no difference in functionality
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it nullable to know if a custom logger is set when building LogWriter
.
https://github.com/line/armeria/pull/5519/files#diff-f09a8bbc22f127a6a25e54937af747ca128e8cbb3df28cc19aa326db0e1cedf6R609
@@ -235,8 +214,9 @@ public LoggingDecoratorBuilder responseLogLevel(Class<? extends Throwable> clazz | |||
*/ | |||
@Deprecated | |||
public LoggingDecoratorBuilder successfulResponseLogLevel(LogLevel successfulResponseLogLevel) { | |||
requireNonNull(successfulResponseLogLevel, "successfulResponseLogLevel"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you check the missing rnn in this class overall?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was delegated to logWriterBuilder
. Do you think we also need to add null-checking here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, I guess I missed it. Thanks for the explanation 👍
protected final BiFunction<? super RequestContext, ? super Throwable, ? extends @Nullable Object> | ||
responseCauseSanitizer() { | ||
return responseCauseSanitizer; | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question) Why do we handle this method differently from the other methods?
return null; | |
if (logFormatterBuilder != null) { | |
return logFormatterBuilder.responseContentSanitizer(); | |
} | |
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured out that responseCauseSanitizer
was not used to sanitize an exception.
responseCauseFilter
was actually used and responseCauseSanitizer
was only referenced by toString()
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clean up! 👍 👍 👍
Motivation:
HeadersSanitizer
was added in #5188. If noHeadersSanitizer
is set, the default sanitizer masksAuthorization
,Cookie
Set-Cookie
, andProxy-Authorization
with****
.In addition to
HeadersSantizer
, other new features were added toLoggingDecoratorBuilder
and the code became messy to maintain backward compatibility.LoggingDecoratorBuilder
,LogWriterBuilder
, andLogFormatterBuilder
each have their own properties, so making the overall operation consistent was not easy.As a result, while
LoggingClient.newDecorator()
sanitizes 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:
LoggingDecoratorBuilder
to delegate all builder properties to eitherLogWriterBuilder
orLogFormatterBuilder
.@Deprecated
annotation toLoggingClientBuilder
andLoggingRpcClientBuilder
andLoggingServiceBuilder
.@Deprecated
in the super method isn't inspected by IntelliJ Mark@Deprecated
annotation in overridden methods #5395LogWriterBuilder.responseCauseFilter()
to haveRequestContext
as the first parameter.RequestContext
for predicates or handlers.Result:
LoggingClient
andLoggingService
now correctly mask sensitive headers by default.