-
Notifications
You must be signed in to change notification settings - Fork 231
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
feat: add client logging with slf4j #1586
base: main
Are you sure you want to change the base?
Conversation
@lqiu96 I still have some trouble with the test env, but wanted to put it out there so you can get a preview of the changes. Can you take a quick look and let me know if you have any concerns. |
oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java
Outdated
Show resolved
Hide resolved
LoggingUtils.logRequest(request, LOGGER, "auth sending request to get signature."); | ||
HttpResponse response = request.execute(); | ||
LoggingUtils.logResponse(response, LOGGER, "auth received response for signature."); |
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.
nit: Could the message to be more descriptive? i.e. Signature to sign the blob or something that better describes this
logger.info(message); | ||
// Default to INFO level | ||
} | ||
MDC.clear(); |
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.
why does this need to be cleared?
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.
MDC carries contextual information in log messages. It is tied to thread, and is safer to clear it to avoid it be carried over to other log entries.
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. Can you add that as a comment? Or a link to a guide that tells us clear it so future readers?
private GenericData parseResponseAs(HttpResponse response) throws IOException { | ||
GenericData genericData = response.parseAs(GenericData.class); | ||
LoggingUtils.logGenericData(genericData, LOGGER, "Auth response payload."); | ||
return genericData; | ||
} |
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 we move this to LoggingUtils since this seems to be used in the other credentials?
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.
They are slightly different, but I will try to extract any useful shared logics into LoggingUtils.
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 highlight the difference? From what I see, the other Credentials also end up calling GenericData responseData = response.parseAs(GenericData.class);
but this is moved to a function.
Might be missing something, but I don't see what is preventing this from going into LoggingUtils.
@@ -36,6 +36,7 @@ jobs: | |||
- run: .kokoro/build.sh | |||
env: | |||
JOB_TYPE: test | |||
GOOGLE_SDK_JAVA_LOGGING: true |
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.
for next release: this env var is probably only needed for LoggingTest.java class.
sonar has been failing since Dec 2. Filed |
try { | ||
if (logger.isInfoEnabled()) { | ||
Map<String, String> loggingDataMap = new HashMap<>(); | ||
loggingDataMap.put("request.method", request.getRequestMethod()); |
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 think it would be good to duplicate information like request.method
and request.url
in message instead of always relying on MDC, as we discussed yesterday. It would be great if we can make this change in this release. However, if not, it should not be a blocker either, as adding these info later is not a breaking change.
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.
oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java
Outdated
Show resolved
Hide resolved
oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java
Outdated
Show resolved
Hide resolved
// are payload always GenericData? If so, can parse and store in json | ||
if (request.getContent() instanceof UrlEncodedContent) { | ||
|
||
GenericData data = (GenericData) ((UrlEncodedContent) request.getContent()).getData(); |
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 add a quick comment about why UrlEncodedContent is casted to GenericData? But JsonHttpContent (below) doesn't need to be?
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.
added
} | ||
} | ||
|
||
static void logGenericData(GenericData genericData, Logger logger, String message) { |
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.
nit: Can we change this to be something like logResponsePayload
and parseResponsePayload
so it's clearer as to what it's doing?
private GenericData parseResponseAs(HttpResponse response) throws IOException { | ||
GenericData genericData = response.parseAs(GenericData.class); | ||
LoggingUtils.logGenericData(genericData, LOGGER, "Auth response payload"); | ||
return genericData; | ||
} |
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.
qq, isn't this the same thing as LoggingUtils.logGenericData()
? I'm missing why this method needs to exist
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.
This response.parseAs(GenericData.class);
can only be parsed once. So this is a wrapper to parse the data, log and continue with whatever is to do with the genericData.
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.
Apologies, I might be missing something obvious but I'm not see where it's parsed more than once and might as be missing why it's different for ServiceAccountCredentials.
What I see is that it's changed to be:
GenericData responseData = parseResponseAs(response);
but I think it could just be
GenericData responseData = response.parseAs(GenericData.class);
LoggingUtils.logGenericData(responseData, LOGGER, "Auth response payload");
...
which is the same as it is for the other Credential types (i.e.
google-auth-library-java/oauth2_http/java/com/google/auth/oauth2/ComputeEngineCredentials.java
Lines 300 to 302 in 6485526
GenericData responseData = response.parseAs(GenericData.class); | |
LoggingUtils.logGenericData( | |
responseData, SLF4JLOGGER, "Response from refresh access token payload"); |
Quality Gate passedIssues Measures |
} | ||
} | ||
|
||
static void logResponse(HttpResponse response, Logger logger, String message) { |
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.
In general, I think we should not try to call these methods if logging is not enabled due to performance concerns, similar to the comment in sdk-platform-java.
responseLogDataMap.put("response.headers", headers.toString()); | ||
logWithMDC(logger, org.slf4j.event.Level.INFO, responseLogDataMap, message); | ||
} | ||
} catch (Exception e) { |
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.
Similar to the comment in sdk-platform-java, I think we should try to avoid doing these try catches or fail more gracefully.
This is a draft pr for preview changes for adding client logging capability to auth.
see go/java-client-logging-design
Very limited testing added at this point.
changes includes:
LoggingConfigs
to enable logging only when GOOGLE_SDK_JAVA_LOGGING=trueLoggingUtils
for helper method for logging. Add log for request and response made to auth endpoints for UserCredentials, ServiceAccountCredentials, ComputeEngineCredentials, ImpersonatedCredentials. For token values included, added hash in log.Here is an example logging output for access token request from UserCredentials when DEBUG level is allowed.
Update Dec 9: I added basic test coverage, not showcasing all the logging messages details. Will add that as followup task.