Skip to content
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

Merged
merged 55 commits into from
Feb 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
c38282b
add slf4j and other test dep. add logging utils. add logging to req/r…
zhumin8 Dec 5, 2024
3f30267
remove JUL wrapper as fallback condition. Other test setups.
zhumin8 Dec 5, 2024
35d9a75
remove unused LoggingInterceptor.
zhumin8 Dec 5, 2024
a63d6fe
revert unintential change to test. add comments.
zhumin8 Dec 5, 2024
83329e7
remove public from LoggingUtils.
zhumin8 Dec 5, 2024
6a5d3d3
downgrade logback and remove unused.
zhumin8 Dec 5, 2024
930d0aa
put logging inside try-catch block to avoid crashing for logging errors.
zhumin8 Dec 5, 2024
44f3de8
simplify logic for getLogger. remove unused argLine for maven-surefir…
zhumin8 Dec 5, 2024
598d5b9
logging util class refactor.
zhumin8 Dec 5, 2024
445fe08
fix test setup timing issue.
zhumin8 Dec 5, 2024
a7f5a5e
add tests. feedback. minor cleanups.
zhumin8 Dec 7, 2024
8bc1ae7
TestAppender change to per test. add LoggingTest.
zhumin8 Dec 7, 2024
bde6ede
update messages.
zhumin8 Dec 9, 2024
7c89c3f
test setup - try use env for all test in ci.
zhumin8 Dec 10, 2024
6da450d
add env set to sonar test.
zhumin8 Dec 10, 2024
9e20be9
duplicate fields to log in message. add tests.
zhumin8 Dec 10, 2024
db99e70
add tests.
zhumin8 Dec 10, 2024
68307fc
minor cleanup and comment.
zhumin8 Dec 10, 2024
4202902
fix add env to sonar ci.
zhumin8 Dec 10, 2024
cfbe873
add log env to integration in build.sh
zhumin8 Dec 10, 2024
858b725
deps: add gson explicitly. move gson and slf4j-api version to parent …
zhumin8 Dec 10, 2024
fb8889a
deps: explicitly declare org.hamcrest:hamcrest-core:test
zhumin8 Dec 10, 2024
15d3016
update logging messages to rm 'auth'.
zhumin8 Dec 10, 2024
c2a8d76
make sensitive key comparison case insensitive.
zhumin8 Dec 11, 2024
6485526
extract env var name.
zhumin8 Dec 11, 2024
3c65d45
Merge branch 'main' into client-logging
zhumin8 Feb 12, 2025
5666430
progress - porting changes, wip tests.
zhumin8 Feb 13, 2025
7f882d8
test
zhumin8 Feb 13, 2025
9e9af89
cleanups and test setups. test ci groups not complete yet
zhumin8 Feb 13, 2025
11cbc54
add tests, cleanup not used classed, lint.
zhumin8 Feb 13, 2025
692080d
cleanup profiles. add to ci.
zhumin8 Feb 13, 2025
fb5142a
adjust pom profiles so no extra deps brought in for other modules.
zhumin8 Feb 14, 2025
7069230
fixing ci. disable jacoco for dependency and integration tests.
zhumin8 Feb 14, 2025
fa7d4a0
rename method logResponsePayload
zhumin8 Feb 14, 2025
314123c
address feedback: test name
zhumin8 Feb 14, 2025
5d6eeb0
lint
zhumin8 Feb 14, 2025
084fa17
rm logging env for integration test, to avoid failing with no slf4j/b…
zhumin8 Feb 14, 2025
71fd705
add -Pslf4j2x to native ci, so it gets slf4j dep for compiling.
zhumin8 Feb 14, 2025
ee3643d
skip jacoco for sonar ci.
zhumin8 Feb 14, 2025
5bcd4ee
add comment.
zhumin8 Feb 18, 2025
7c95364
pom slf4j2x-test profile cleanup.
zhumin8 Feb 18, 2025
23712d0
remove logging env for sonar run.
zhumin8 Feb 18, 2025
d979f60
fix typo
zhumin8 Feb 18, 2025
a3bb3e4
cleanups.
zhumin8 Feb 18, 2025
23844c9
refactor: separate Slf4jUtils and Slf4jLoggingHelpers.
zhumin8 Feb 18, 2025
821826d
sonar: try to setup separate step for logging tests
zhumin8 Feb 18, 2025
0fd818d
revert sonar changes.
zhumin8 Feb 18, 2025
3b8205d
add private constructor for Slf4jLoggingHelpers.
zhumin8 Feb 18, 2025
e1d9a78
comments.:
zhumin8 Feb 18, 2025
b8caf5a
comment
zhumin8 Feb 20, 2025
eaca20b
surface log() in LoggingUtils for more flexible logs. add log for CPE…
zhumin8 Feb 20, 2025
420e0ec
Merge branch 'main' into client-logging
zhumin8 Feb 20, 2025
f708d91
rm pingComputeEngineMetadata request/response log.
zhumin8 Feb 21, 2025
ae7e2b7
feedback: log message change and field name update.
zhumin8 Feb 24, 2025
5f5fb09
lint
zhumin8 Feb 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@ jobs:
- run: .kokoro/build.sh
env:
JOB_TYPE: test
units-logging:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
java: [11, 17, 21]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: ${{matrix.java}}
- run: java -version
- run: .kokoro/build.sh
env:
JOB_TYPE: test-logging
units-java8:
# Building using Java 17 and run the tests with Java 8 runtime
name: "units (8)"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/sonar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ jobs:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
mvn -B verify -Dcheckstyle.skip \
-Djacoco.skip=true \
-DenableFullTestCoverage \
-Dsonar.coverage.jacoco.xmlReportPaths=oauth2_http/target/site/jacoco/jacoco.xml \
org.sonarsource.scanner.maven:sonar-maven-plugin:sonar \
-Dsonar.projectKey=googleapis_google-auth-library-java \
-Dsonar.organization=googleapis \
-Dsonar.host.url=https://sonarcloud.io

10 changes: 8 additions & 2 deletions .kokoro/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ test)
mvn test -B -ntp -Dclirr.skip=true -Denforcer.skip=true ${SUREFIRE_JVM_OPT}
RETURN_CODE=$?
;;
test-logging)
echo "SUREFIRE_JVM_OPT: ${SUREFIRE_JVM_OPT}"
mvn clean test -P '!slf4j2x,slf4j2x-test' -B -ntp -Dclirr.skip=true -Denforcer.skip=true ${SUREFIRE_JVM_OPT}
RETURN_CODE=$?
;;
lint)
mvn com.coveo:fmt-maven-plugin:check -B -ntp
RETURN_CODE=$?
Expand All @@ -66,6 +71,7 @@ integration)
-DtrimStackTrace=false \
-Dclirr.skip=true \
-Denforcer.skip=true \
-Djacoco.skip=true \
-fae \
verify
RETURN_CODE=$?
Expand All @@ -74,14 +80,14 @@ graalvmA)
# Run Unit and Integration Tests with Native Image
bash .kokoro/populate-secrets.sh
export GOOGLE_APPLICATION_CREDENTIALS="${KOKORO_GFILE_DIR}/secret_manager/java-it-service-account"
mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Pnative-test test -pl 'oauth2_http'
mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Pnative-test -Pslf4j2x test -pl 'oauth2_http'
RETURN_CODE=$?
;;
graalvmB)
# Run Unit and Integration Tests with Native Image
bash .kokoro/populate-secrets.sh
export GOOGLE_APPLICATION_CREDENTIALS="${KOKORO_GFILE_DIR}/secret_manager/java-it-service-account"
mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Pnative-test test -pl 'oauth2_http'
mvn -B ${INTEGRATION_TEST_ARGS} -ntp -Pnative -Pnative-test -Pslf4j2x test -pl 'oauth2_http'
RETURN_CODE=$?
;;
samples)
Expand Down
1 change: 1 addition & 0 deletions .kokoro/dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ retry_with_backoff 3 10 \
mvn install -B -V -ntp \
-DskipTests=true \
-Dmaven.javadoc.skip=true \
-Djacoco.skip=true \
-Dclirr.skip=true

mvn -B dependency:analyze -DfailOnWarning=true
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.BufferedReader;
Expand Down Expand Up @@ -94,6 +95,8 @@ public class ComputeEngineCredentials extends GoogleCredentials
static final Duration COMPUTE_REFRESH_MARGIN = Duration.ofMinutes(3).plusSeconds(45);

private static final Logger LOGGER = Logger.getLogger(ComputeEngineCredentials.class.getName());
private static final LoggerProvider LOGGER_PROVIDER =
LoggerProvider.forClazz(ComputeEngineCredentials.class);

static final String DEFAULT_METADATA_SERVER_URL = "http://metadata.google.internal";

Expand Down Expand Up @@ -371,11 +374,14 @@ public AccessToken refreshAccessToken() throws IOException {
throw new IOException(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE);
}
GenericData responseData = response.parseAs(GenericData.class);
LoggingUtils.logResponsePayload(
responseData, LOGGER_PROVIDER, "Response payload for access token");
String accessToken =
OAuth2Utils.validateString(responseData, "access_token", PARSE_ERROR_PREFIX);
int expiresInSeconds =
OAuth2Utils.validateInt32(responseData, "expires_in", PARSE_ERROR_PREFIX);
long expiresAtMilliseconds = clock.currentTimeMillis() + expiresInSeconds * 1000;

return new AccessToken(accessToken, new Date(expiresAtMilliseconds));
}

Expand Down Expand Up @@ -430,6 +436,12 @@ public IdToken idTokenWithAudience(String targetAudience, List<IdTokenProvider.O
throw new IOException(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE);
}
String rawToken = response.parseAsString();

LoggingUtils.log(
LOGGER_PROVIDER,
Level.FINE,
ImmutableMap.of("idToken", rawToken),
"Response Payload for ID token");
return IdToken.create(rawToken);
}

Expand All @@ -451,7 +463,23 @@ private HttpResponse getMetadataResponse(
request.setThrowExceptionOnExecuteError(false);
HttpResponse response;
try {
String requestMessage;
String responseMessage;
if (requestType.equals(RequestType.ID_TOKEN_REQUEST)) {
requestMessage = "Sending request to get ID token";
responseMessage = "Received response for ID token request";
} else if (requestType.equals(RequestType.ACCESS_TOKEN_REQUEST)) {
requestMessage = "Sending request to refresh access token";
responseMessage = "Received response for refresh access token";
} else {
// TODO: this includes get universe domain and get default sa.
// refactor for more clear logging message.
requestMessage = "Sending request for universe domain/default service account";
responseMessage = "Received response for universe domain/default service account";
}
LoggingUtils.logRequest(request, LOGGER_PROVIDER, requestMessage);
response = request.execute();
LoggingUtils.logResponse(response, LOGGER_PROVIDER, responseMessage);
} catch (UnknownHostException exception) {
throw new IOException(
"ComputeEngineCredentials cannot find the metadata server. This is"
Expand Down Expand Up @@ -730,6 +758,8 @@ private String getDefaultServiceAccount() throws IOException {
throw new IOException(METADATA_RESPONSE_EMPTY_CONTENT_ERROR_MESSAGE);
}
GenericData responseData = response.parseAs(GenericData.class);
LoggingUtils.logResponsePayload(
responseData, LOGGER_PROVIDER, "Received default service account payload");
Map<String, Object> defaultAccount =
OAuth2Utils.validateMap(responseData, "default", PARSE_ERROR_ACCOUNT);
return OAuth2Utils.validateString(defaultAccount, "email", PARSE_ERROR_ACCOUNT);
Expand Down
12 changes: 12 additions & 0 deletions oauth2_http/java/com/google/auth/oauth2/IamUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The 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:
IamUtils.class - Sending request to get signature to sign the blob

The concern that pops up is that IamUtils is an internal class and doesn't tell the user which Credentials is actually access the sign call.

Do you think it would be better as:
ComputeEngineCredentials - Sending request to get signature to sign the blob

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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 IamUtils methods, but I am not sure if that's too much details?

Copy link
Contributor

Choose a reason for hiding this comment

The 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 Sending request to get signature to sign the blob for %s, Credentials.getClass()). That also might be overkill. I think we can keep as is and improve it from user feedback.

int statusCode = response.getStatusCode();
if (statusCode >= 400 && statusCode < HttpStatusCodes.STATUS_CODE_SERVER_ERROR) {
GenericData responseError = response.parseAs(GenericData.class);
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ public class ImpersonatedCredentials extends GoogleCredentials
private int lifetime;
private String iamEndpointOverride;
private final String transportFactoryClassName;
private static final LoggerProvider LOGGER_PROVIDER =
LoggerProvider.forClazz(ImpersonatedCredentials.class);

private transient HttpTransportFactory transportFactory;

Expand Down Expand Up @@ -553,12 +555,17 @@ public AccessToken refreshAccessToken() throws IOException {

HttpResponse response = null;
try {
LoggingUtils.logRequest(request, LOGGER_PROVIDER, "Sending request to refresh access token");
response = request.execute();
LoggingUtils.logResponse(
response, LOGGER_PROVIDER, "Received response for refresh access token");
} catch (IOException e) {
throw new IOException("Error requesting access token", e);
}

GenericData responseData = response.parseAs(GenericData.class);
LoggingUtils.logResponsePayload(
responseData, LOGGER_PROVIDER, "Response payload for access token");
response.disconnect();

String accessToken =
Expand Down
55 changes: 55 additions & 0 deletions oauth2_http/java/com/google/auth/oauth2/LoggerProvider.java
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;
}
}
88 changes: 88 additions & 0 deletions oauth2_http/java/com/google/auth/oauth2/LoggingUtils.java
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() {}
}
Loading
Loading