-
Notifications
You must be signed in to change notification settings - Fork 254
feat: add client logging with slf4j #1586
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
Changes from all commits
c38282b
3f30267
35d9a75
a63d6fe
83329e7
6a5d3d3
930d0aa
44f3de8
598d5b9
445fe08
a7f5a5e
8bc1ae7
bde6ede
7c89c3f
6da450d
9e20be9
db99e70
68307fc
4202902
cfbe873
858b725
fb8889a
15d3016
c2a8d76
6485526
3c65d45
5666430
7f882d8
9e9af89
11cbc54
692080d
fb5142a
7069230
fa7d4a0
314123c
5d6eeb0
084fa17
71fd705
ee3643d
5bcd4ee
7c95364
23712d0
d979f60
a3bb3e4
23844c9
821826d
0fd818d
3b8205d
e1d9a78
b8caf5a
eaca20b
420e0ec
f708d91
ae7e2b7
5f5fb09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -72,6 +72,7 @@ class IamUtils { | |
| "https://iamcredentials.%s/v1/projects/-/serviceAccounts/%s:signBlob"; | ||
| private static final String PARSE_ERROR_MESSAGE = "Error parsing error message response. "; | ||
| private static final String PARSE_ERROR_SIGNATURE = "Error parsing signature response. "; | ||
| private static final LoggerProvider LOGGER_PROVIDER = LoggerProvider.forClazz(IamUtils.class); | ||
|
|
||
| // Following guidance for IAM retries: | ||
| // https://cloud.google.com/iam/docs/retry-strategy#errors-to-retry | ||
|
|
@@ -154,7 +155,11 @@ private static String getSignature( | |
| IamUtils.IAM_RETRYABLE_STATUS_CODES.contains(response.getStatusCode()))); | ||
| request.setIOExceptionHandler(new HttpBackOffIOExceptionHandler(backoff)); | ||
|
|
||
| LoggingUtils.logRequest( | ||
| request, LOGGER_PROVIDER, "Sending request to get signature to sign the blob"); | ||
| HttpResponse response = request.execute(); | ||
| LoggingUtils.logResponse( | ||
| response, LOGGER_PROVIDER, "Received response for signature to sign the blob"); | ||
|
Comment on lines
+158
to
+162
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think logging here makes sense, I am just wondering if it would make sense to have the Credential pass the logger in here. I don't know what the standard would be and I'll defer to you. I think this would currently show up as something like: The concern that pops up is that IamUtils is an internal class and doesn't tell the user which Credentials is actually access the Do you think it would be better as: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, usually the convention is to logging in the class where it occurs. Although to your point, we can probably add another log entry before entering the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok gotcha I see. In the case I think it's fine. Maybe if anything it could be something like |
||
| int statusCode = response.getStatusCode(); | ||
| if (statusCode >= 400 && statusCode < HttpStatusCodes.STATUS_CODE_SERVER_ERROR) { | ||
| GenericData responseError = response.parseAs(GenericData.class); | ||
|
|
@@ -181,6 +186,8 @@ private static String getSignature( | |
| } | ||
|
|
||
| GenericData responseData = response.parseAs(GenericData.class); | ||
| LoggingUtils.logResponsePayload( | ||
| responseData, LOGGER_PROVIDER, "Response payload for sign blob"); | ||
| return OAuth2Utils.validateString(responseData, "signedBlob", PARSE_ERROR_SIGNATURE); | ||
| } | ||
|
|
||
|
|
@@ -234,7 +241,10 @@ static IdToken getIdToken( | |
| MetricsUtils.getGoogleCredentialsMetricsHeader( | ||
| RequestType.ID_TOKEN_REQUEST, credentialTypeForMetrics)); | ||
|
|
||
| LoggingUtils.logRequest(request, LOGGER_PROVIDER, "Sending request to get ID token"); | ||
| HttpResponse response = request.execute(); | ||
|
|
||
| LoggingUtils.logResponse(response, LOGGER_PROVIDER, "Received response for ID token request"); | ||
| int statusCode = response.getStatusCode(); | ||
| if (statusCode >= 400 && statusCode < HttpStatusCodes.STATUS_CODE_SERVER_ERROR) { | ||
| GenericData responseError = response.parseAs(GenericData.class); | ||
|
|
@@ -259,6 +269,8 @@ static IdToken getIdToken( | |
| } | ||
|
|
||
| GenericJson responseData = response.parseAs(GenericJson.class); | ||
| LoggingUtils.logResponsePayload( | ||
| responseData, LOGGER_PROVIDER, "Response payload for ID token request"); | ||
| String rawToken = OAuth2Utils.validateString(responseData, "token", PARSE_ERROR_MESSAGE); | ||
| return IdToken.create(rawToken); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* | ||
| * Copyright 2025 Google LLC | ||
| * | ||
| * Redistribution and use in source and binary forms, with or without | ||
| * modification, are permitted provided that the following conditions are | ||
| * met: | ||
| * | ||
| * * Redistributions of source code must retain the above copyright | ||
| * notice, this list of conditions and the following disclaimer. | ||
| * * Redistributions in binary form must reproduce the above | ||
| * copyright notice, this list of conditions and the following disclaimer | ||
| * in the documentation and/or other materials provided with the | ||
| * distribution. | ||
| * | ||
| * * Neither the name of Google LLC nor the names of its | ||
| * contributors may be used to endorse or promote products derived from | ||
| * this software without specific prior written permission. | ||
| * | ||
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| */ | ||
|
|
||
| package com.google.auth.oauth2; | ||
|
|
||
| import org.slf4j.Logger; | ||
|
|
||
| class LoggerProvider { | ||
|
|
||
| private Logger logger; | ||
| private final Class<?> clazz; | ||
|
|
||
| private LoggerProvider(Class<?> clazz) { | ||
| this.clazz = clazz; | ||
| } | ||
|
|
||
| static LoggerProvider forClazz(Class<?> clazz) { | ||
| return new LoggerProvider(clazz); | ||
| } | ||
|
|
||
| Logger getLogger() { | ||
| if (logger == null) { | ||
| this.logger = Slf4jUtils.getLogger(clazz); | ||
| } | ||
| return logger; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| /* | ||
| * Copyright 2025 Google LLC | ||
| * | ||
| * Redistribution and use in source and binary forms, with or without | ||
| * modification, are permitted provided that the following conditions are | ||
| * met: | ||
| * | ||
| * * Redistributions of source code must retain the above copyright | ||
| * notice, this list of conditions and the following disclaimer. | ||
| * * Redistributions in binary form must reproduce the above | ||
| * copyright notice, this list of conditions and the following disclaimer | ||
| * in the documentation and/or other materials provided with the | ||
| * distribution. | ||
| * | ||
| * * Neither the name of Google LLC nor the names of its | ||
| * contributors may be used to endorse or promote products derived from | ||
| * this software without specific prior written permission. | ||
| * | ||
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| */ | ||
|
|
||
| package com.google.auth.oauth2; | ||
|
|
||
| import com.google.api.client.http.HttpRequest; | ||
| import com.google.api.client.http.HttpResponse; | ||
| import com.google.api.client.util.GenericData; | ||
| import java.util.Map; | ||
| import java.util.logging.Level; | ||
|
|
||
| class LoggingUtils { | ||
|
|
||
| static final String GOOGLE_SDK_JAVA_LOGGING = "GOOGLE_SDK_JAVA_LOGGING"; | ||
| private static EnvironmentProvider environmentProvider = | ||
| SystemEnvironmentProvider.getInstance(); // this may be reset for testing purpose | ||
|
|
||
| private static boolean loggingEnabled = isLoggingEnabled(); | ||
|
|
||
| // expose this setter only for testing purposes | ||
| static void setEnvironmentProvider(EnvironmentProvider provider) { | ||
| environmentProvider = provider; | ||
| // Recalculate LOGGING_ENABLED after setting the new provider | ||
| loggingEnabled = isLoggingEnabled(); | ||
| } | ||
|
|
||
| static boolean isLoggingEnabled() { | ||
| String enableLogging = environmentProvider.getEnv(GOOGLE_SDK_JAVA_LOGGING); | ||
| return "true".equalsIgnoreCase(enableLogging); | ||
| } | ||
|
|
||
| static void logRequest(HttpRequest request, LoggerProvider loggerProvider, String message) { | ||
| if (loggingEnabled) { | ||
| Slf4jLoggingHelpers.logRequest(request, loggerProvider, message); | ||
| } | ||
| } | ||
|
|
||
| static void logResponse(HttpResponse response, LoggerProvider loggerProvider, String message) { | ||
| if (loggingEnabled) { | ||
| Slf4jLoggingHelpers.logResponse(response, loggerProvider, message); | ||
| } | ||
| } | ||
|
|
||
| static void logResponsePayload( | ||
| GenericData genericData, LoggerProvider loggerProvider, String message) { | ||
| if (loggingEnabled) { | ||
| Slf4jLoggingHelpers.logResponsePayload(genericData, loggerProvider, message); | ||
| } | ||
| } | ||
|
|
||
| // generic log method to use when not logging standard request, response and payload | ||
| static void log( | ||
| LoggerProvider loggerProvider, Level level, Map<String, Object> contextMap, String message) { | ||
| if (loggingEnabled) { | ||
| Slf4jLoggingHelpers.log(loggerProvider, level, contextMap, message); | ||
| } | ||
| } | ||
|
|
||
| private LoggingUtils() {} | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.