Skip to content

Commit

Permalink
SNOW-1229142: Improve commons logging wrapping (#2036)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-dprzybysz authored Jan 21, 2025
1 parent 9aaaa10 commit e517038
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,6 @@ wss*.config
wss-unified-agent.jar
whitesource/
*.swp

#created in some tests
placeholder
93 changes: 93 additions & 0 deletions src/main/java/net/snowflake/client/log/CommonsLoggingWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2025 Snowflake Computing Inc. All rights reserved.
*/
package net.snowflake.client.log;

import net.snowflake.client.core.SnowflakeJdbcInternalApi;
import org.apache.commons.logging.Log;

/**
* This is a wrapper class of apache commons logging which uses SFLogger to use driver configuration
* (via java.util.logging or SLF4J) and mask secrets. Wrapper does not hide trace and debug
* messages.
*/
@SnowflakeJdbcInternalApi
public class CommonsLoggingWrapper implements Log {
private final SFLogger logger;

public CommonsLoggingWrapper(String className) {
this.logger = SFLoggerFactory.getLogger(className);
}

public void debug(Object msg) {
logger.debug(String.valueOf(msg), true);
}

public void debug(Object msg, Throwable t) {
logger.debug(String.valueOf(msg), t);
}

public void error(Object msg) {
logger.error(String.valueOf(msg), true);
}

public void error(Object msg, Throwable t) {
logger.error(String.valueOf(msg), t);
}

public void fatal(Object msg) {
this.error(msg);
}

public void fatal(Object msg, Throwable t) {
this.error(msg, t);
}

public void info(Object msg) {
logger.info(String.valueOf(msg), true);
}

public void info(Object msg, Throwable t) {
logger.info(String.valueOf(msg), t);
}

public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}

public boolean isErrorEnabled() {
return logger.isErrorEnabled();
}

public boolean isFatalEnabled() {
return logger.isErrorEnabled();
}

public boolean isInfoEnabled() {
return logger.isInfoEnabled();
}

public boolean isTraceEnabled() {
return logger.isTraceEnabled();
}

public boolean isWarnEnabled() {
return logger.isWarnEnabled();
}

public void trace(Object msg) {
logger.debug(String.valueOf(msg), true);
}

public void trace(Object msg, Throwable t) {
logger.trace(String.valueOf(msg), t);
}

public void warn(Object msg) {
logger.warn(String.valueOf(msg));
}

public void warn(Object msg, Throwable t) {
logger.warn(String.valueOf(msg), t);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (c) 2025 Snowflake Computing Inc. All rights reserved.
*/
package net.snowflake.client.log;

import static net.snowflake.client.jdbc.SnowflakeUtil.systemGetProperty;

import java.util.stream.Collectors;
import java.util.stream.Stream;

enum CommonsLoggingWrapperMode {
/** All logs from commons logging are passed to SFLogger (check {@link CommonsLoggingWrapper}) */
ALL,
/**
* The default behaviour is forwarding all logs to java.util.logging from commons logging (check
* {@link JDK14JCLWrapper}), no logs are forwarded to SLF4J logger (check {@link SLF4JJCLWrapper})
*/
DEFAULT,
/**
* Logs from commons logging are not forwarded and commons logging is not reconfigured - may be
* the option when if you need to replace commons logging with the SLF4J bridge when thin jar is
* used
*/
OFF;

static final String JAVA_PROPERTY = "net.snowflake.jdbc.commons_logging_wrapper";

static CommonsLoggingWrapperMode detect() {
String value = systemGetProperty(JAVA_PROPERTY);
if (value == null) {
return DEFAULT;
}
try {
return CommonsLoggingWrapperMode.valueOf(value);
} catch (Exception e) {
throw new IllegalArgumentException(
"Unknown commons logging wrapper value '"
+ value
+ "', expected one of: "
+ Stream.of(CommonsLoggingWrapperMode.values())
.map(Enum::name)
.collect(Collectors.joining(", ")));
}
}
}
10 changes: 10 additions & 0 deletions src/main/java/net/snowflake/client/log/SFLoggerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,19 @@ public static void initializeSnowflakeLogger() {
loggerImplementation = SFLoggerFactory.LoggerImpl.JDK14LOGGER;
}

CommonsLoggingWrapperMode commonsLoggingWrapperMode = CommonsLoggingWrapperMode.detect();
if (commonsLoggingWrapperMode == CommonsLoggingWrapperMode.OFF) {
return;
}

System.setProperty(
"org.apache.commons.logging.LogFactory", "org.apache.commons.logging.impl.LogFactoryImpl");
LogFactory logFactory = LogFactory.getFactory();
if (commonsLoggingWrapperMode == CommonsLoggingWrapperMode.ALL) {
logFactory.setAttribute(
"org.apache.commons.logging.Log", CommonsLoggingWrapper.class.getName());
return;
}
switch (loggerImplementation) {
case SLF4JLOGGER:
logFactory.setAttribute(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2025 Snowflake Computing Inc. All rights reserved.
*/
package net.snowflake.client.log;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

public class CommonsLoggingWrapperModeTest {

private String propertyValue;

@BeforeEach
public void setUp() {
propertyValue = System.getProperty(CommonsLoggingWrapperMode.JAVA_PROPERTY);
}

@AfterEach
public void tearDown() {
if (propertyValue != null) {
System.setProperty(CommonsLoggingWrapperMode.JAVA_PROPERTY, propertyValue);
} else {
System.clearProperty(CommonsLoggingWrapperMode.JAVA_PROPERTY);
}
}

@ParameterizedTest
@EnumSource(CommonsLoggingWrapperMode.class)
public void shouldDetectMode(CommonsLoggingWrapperMode value) {
System.setProperty(CommonsLoggingWrapperMode.JAVA_PROPERTY, value.name());
assertEquals(value, CommonsLoggingWrapperMode.detect());
}

@Test
public void shouldPickDefaultMode() {
System.clearProperty(CommonsLoggingWrapperMode.JAVA_PROPERTY);
assertEquals(CommonsLoggingWrapperMode.DEFAULT, CommonsLoggingWrapperMode.detect());
}

@Test
public void shouldThrowOnUnknownMode() {
System.setProperty(CommonsLoggingWrapperMode.JAVA_PROPERTY, "invalid");
IllegalArgumentException illegalArgumentException =
assertThrows(IllegalArgumentException.class, CommonsLoggingWrapperMode::detect);
assertEquals(
"Unknown commons logging wrapper value 'invalid', expected one of: ALL, DEFAULT, OFF",
illegalArgumentException.getMessage());
}
}

0 comments on commit e517038

Please sign in to comment.