diff --git a/doc/changes/changes_18.0.2.md b/doc/changes/changes_18.0.2.md index fdf5625..26b5dd6 100644 --- a/doc/changes/changes_18.0.2.md +++ b/doc/changes/changes_18.0.2.md @@ -26,6 +26,7 @@ Code name: Improve code quality * #307: Fixed `PushdownSqlRenderer` so `HASHTYPE` data types include `bytesize` in rendered pushdown SQL JSON. * #313: Fixed mutable DTO and SQL AST collection handling by adding defensive copies, unmodifiable getters, null-to-empty normalization, and constructor-time `SqlOrderBy` validation. * #312: Fixed logging utility resource and handler lifecycle issues by closing version metadata streams, falling back when the thread context class loader is missing, defaulting absent version properties to `UNKNOWN`, closing replaced root log handlers, and resetting closed remote socket handlers before reuse. +* #316: Fixed `LoggingConfiguration` so invalid `LOG_LEVEL` values now fail with a structured error message that names the invalid value and lists the available log levels. * #318: Fixed several small naming, Javadoc, message, and parsing robustness issues, including locale-independent SQL parser uppercasing and trimmed telemetry property parsing. * Fixed `ColumnMetadata.toString()` so `defaultValue` quotes stay balanced even when no comment is set. * #314: Fixed `SqlFunctionAggregateListagg.Behavior` so LISTAGG overflow behavior is null-safe, value-based, and constructed immutably by the parser. diff --git a/error_code_config.yml b/error_code_config.yml index d3fe2f4..9018a22 100644 --- a/error_code_config.yml +++ b/error_code_config.yml @@ -2,4 +2,4 @@ error-tags: VSCOMJAVA: packages: - com.exasol - highest-index: 46 + highest-index: 47 diff --git a/src/main/java/com/exasol/adapter/request/LoggingConfiguration.java b/src/main/java/com/exasol/adapter/request/LoggingConfiguration.java index bf33a30..4b2aacb 100644 --- a/src/main/java/com/exasol/adapter/request/LoggingConfiguration.java +++ b/src/main/java/com/exasol/adapter/request/LoggingConfiguration.java @@ -4,9 +4,12 @@ import static com.exasol.adapter.AdapterProperties.LOG_LEVEL_PROPERTY; import java.io.Serializable; +import java.util.List; import java.util.Map; import java.util.logging.Level; +import com.exasol.errorreporting.ExaError; + /** * This class represents the logging configuration set in the request properties */ @@ -14,6 +17,8 @@ public final class LoggingConfiguration implements Serializable { private static final long serialVersionUID = 1930189191497837644L; private static final int DEFAULT_REMOTE_LOGGING_PORT = 3000; private static final Level DEFAULT_LOG_LEVEL = Level.INFO; + private static final List AVAILABLE_LOG_LEVELS = List.of(Level.OFF, Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG, Level.FINE, Level.FINER, + Level.FINEST, Level.ALL); /** {@code true} if the adapter should send its log messages to a remote log receiver */ private final boolean logRemotely; /** Name host name where the log receiver listens */ @@ -105,13 +110,20 @@ public static LoggingConfiguration parseFromPropertiesWithDebugAddressGiven(fina } private static Level parseLogLevel(final Map properties) { - final Level level; - if (properties.containsKey(LOG_LEVEL_PROPERTY)) { - level = Level.parse(properties.get(LOG_LEVEL_PROPERTY)); - } else { - level = DEFAULT_LOG_LEVEL; + if (!properties.containsKey(LOG_LEVEL_PROPERTY)) { + return DEFAULT_LOG_LEVEL; + } + final String configuredLogLevel = properties.get(LOG_LEVEL_PROPERTY); + try { + return Level.parse(configuredLogLevel); + } catch (final IllegalArgumentException exception) { + throw new IllegalArgumentException(ExaError.messageBuilder("E-VSCOMJAVA-47") + .message("Invalid value {{log_level_value}} for property {{log_level_property}}.") + .mitigation("Available log levels are: {{available_log_levels}}.") + .parameter("log_level_value", configuredLogLevel) + .parameter("log_level_property", LOG_LEVEL_PROPERTY) + .parameter("available_log_levels", AVAILABLE_LOG_LEVELS).toString(), exception); } - return level; } /** diff --git a/src/test/java/com/exasol/adapter/request/LoggingConfigurationTest.java b/src/test/java/com/exasol/adapter/request/LoggingConfigurationTest.java index b4165f3..b1daf9d 100644 --- a/src/test/java/com/exasol/adapter/request/LoggingConfigurationTest.java +++ b/src/test/java/com/exasol/adapter/request/LoggingConfigurationTest.java @@ -5,6 +5,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertAll; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; import java.util.HashMap; @@ -62,6 +63,16 @@ void testGetLogLevel() { assertThat(createLoggingConfiguration(this.properties).getLogLevel(), equalTo(Level.FINEST)); } + @Test + void testInvalidLogLevelThrowsHelpfulException() { + this.properties.put(LOG_LEVEL_PROPERTY, "invalid"); + final IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> createLoggingConfiguration(this.properties)); + assertThat(exception.getMessage(), equalTo( + "E-VSCOMJAVA-47: Invalid value 'invalid' for property 'LOG_LEVEL'. " + + "Available log levels are: [OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL].")); + } + @Test void testFallBackToLocalLoggingInCaseOfIllegalLoggingPort() { this.properties.put(DEBUG_ADDRESS_PROPERTY, "www.example.org:illegal_non_numeric_port");