This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch issue/split-log-support in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-mcp-server-contributions.git
commit f22460014bf1c359bf1ea92b7d2a076677be85ef Author: Robert Munteanu <[email protected]> AuthorDate: Tue May 12 17:57:39 2026 +0200 chore: clearer separation of 'api' and 'impl' classes for the log support This is related to SLING-13188 --- .../internal => contribs/log}/LogSnapshot.java | 44 +----------------- .../server/contribs/log/StructuredLogBuffer.java} | 19 ++++---- .../server/impl/contribs/LogToolContribution.java | 21 +++++---- .../mcp/server/impl/contribs/log/LogLevel.java} | 28 ++++++++---- .../StructuredLogBufferAppender.java | 39 +++++----------- .../StructuredLogBufferImpl.java} | 52 ++++++++++++++++++---- .../contribs/log/StructuredLogBufferSink.java} | 14 ++---- .../internal => contribs/log}/LogSnapshotTest.java | 14 +++--- .../StructuredLogBufferAppenderTest.java | 43 ++++++++++++++---- .../StructuredLogBufferImplTest.java} | 36 ++++++++++----- 10 files changed, 169 insertions(+), 141 deletions(-) diff --git a/src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshot.java b/src/main/java/org/apache/sling/mcp/server/contribs/log/LogSnapshot.java similarity index 53% rename from src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshot.java rename to src/main/java/org/apache/sling/mcp/server/contribs/log/LogSnapshot.java index 6dc4cb4..c986ad8 100644 --- a/src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshot.java +++ b/src/main/java/org/apache/sling/mcp/server/contribs/log/LogSnapshot.java @@ -16,11 +16,9 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.contribs.log; -import java.util.Arrays; import java.util.Collections; -import java.util.List; import java.util.Map; /** @@ -29,52 +27,14 @@ import java.util.Map; */ public record LogSnapshot( long timeMillis, - LogLevel level, // avoid binding to logback or a specific version of slf4j + String level, String loggerName, String threadName, String formattedMessage, String throwableText, Map<String, String> mdc) { - public static boolean isValidLogLevel(String logLevelName) { - try { - LogLevel.valueOf(logLevelName); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } - - public static List<String> getValidLogLevelNames() { - return Arrays.stream(LogLevel.values()).map(Enum::toString).toList(); - } - - public static String getHighestLogLevelName() { - return LogLevel.values()[LogLevel.values().length - 1].toString(); - } - public LogSnapshot { mdc = mdc == null ? Collections.emptyMap() : Collections.unmodifiableMap(mdc); } - - enum LogLevel { - TRACE, - DEBUG, - INFO, - WARN, - ERROR; - - boolean isGreaterOrEqual(LogLevel minLevel) { - return ordinal() >= minLevel.ordinal(); - } - - public boolean isValid(String logLevelName) { - try { - LogLevel.valueOf(logLevelName); - return true; - } catch (IllegalArgumentException e) { - return false; - } - } - } } diff --git a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java b/src/main/java/org/apache/sling/mcp/server/contribs/log/StructuredLogBuffer.java similarity index 68% copy from src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java copy to src/main/java/org/apache/sling/mcp/server/contribs/log/StructuredLogBuffer.java index 8c494b5..07e0c8d 100644 --- a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java +++ b/src/main/java/org/apache/sling/mcp/server/contribs/log/StructuredLogBuffer.java @@ -16,17 +16,18 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.contribs.log; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot.LogLevel; -import org.junit.jupiter.api.Test; +import java.util.List; +import java.util.regex.Pattern; -import static org.junit.jupiter.api.Assertions.*; +public interface StructuredLogBuffer { -class LogSnapshotTest { + boolean isValidLogLevel(String logLevelName); - @Test - void logLevelComparison() { - assertTrue(LogSnapshot.LogLevel.INFO.isGreaterOrEqual(LogLevel.TRACE)); - } + List<String> getValidLogLevelNames(); + + String getHighestLogLevelName(); + + List<LogSnapshot> getRecent(Pattern pattern, String minLevel, int maxEntries); } diff --git a/src/main/java/org/apache/sling/mcp/server/impl/contribs/LogToolContribution.java b/src/main/java/org/apache/sling/mcp/server/impl/contribs/LogToolContribution.java index bbd11c9..169ad35 100644 --- a/src/main/java/org/apache/sling/mcp/server/impl/contribs/LogToolContribution.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/contribs/LogToolContribution.java @@ -30,8 +30,8 @@ import io.modelcontextprotocol.json.McpJsonMapperSupplier; import io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncToolSpecification; import io.modelcontextprotocol.spec.McpSchema.CallToolResult; import io.modelcontextprotocol.spec.McpSchema.Tool; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot; -import org.apache.sling.mcp.server.impl.contribs.internal.StructuredLogBufferAppender; +import org.apache.sling.mcp.server.contribs.log.LogSnapshot; +import org.apache.sling.mcp.server.contribs.log.StructuredLogBuffer; import org.apache.sling.mcp.server.spi.McpServerContribution; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -44,7 +44,7 @@ import org.osgi.service.component.annotations.Reference; public class LogToolContribution implements McpServerContribution { @Reference - private StructuredLogBufferAppender structuredLogBufferAppender; + private StructuredLogBuffer structuredLogBuffer; @Reference private McpJsonMapperSupplier jsonMapper; @@ -79,7 +79,7 @@ public class LogToolContribution implements McpServerContribution { } """.formatted( validLogLevelValuesAsCsv(), - LogSnapshot.getHighestLogLevelName(), + structuredLogBuffer.getHighestLogLevelName(), validLogLevelValuesAsJsonSchemaEnum()); return List.of(new SyncToolSpecification( @@ -103,12 +103,12 @@ public class LogToolContribution implements McpServerContribution { maxEntries = Math.min(maxEntries, 1000); // Cap at 1000 } - String minLogLevel = LogSnapshot.getHighestLogLevelName(); + String minLogLevel = structuredLogBuffer.getHighestLogLevelName(); if (logLevelStr != null && !logLevelStr.isEmpty()) { - if (!LogSnapshot.isValidLogLevel(logLevelStr)) { + if (!structuredLogBuffer.isValidLogLevel(logLevelStr)) { return CallToolResult.builder() .addTextContent("Invalid log level: " + logLevelStr + ". Valid options are: " - + String.join(", ", LogSnapshot.getValidLogLevelNames())) + + String.join(", ", structuredLogBuffer.getValidLogLevelNames())) .isError(true) .build(); } @@ -128,8 +128,7 @@ public class LogToolContribution implements McpServerContribution { } } - List<LogSnapshot> filteredLogs = - structuredLogBufferAppender.getBuffer().getRecent(pattern, minLogLevel, maxEntries); + List<LogSnapshot> filteredLogs = structuredLogBuffer.getRecent(pattern, minLogLevel, maxEntries); // Format output String result = formatLogs(filteredLogs, regexPattern, minLogLevel, maxEntries); @@ -216,13 +215,13 @@ public class LogToolContribution implements McpServerContribution { } private String validLogLevelValuesAsCsv() { - return String.join(", ", LogSnapshot.getValidLogLevelNames()); + return String.join(", ", structuredLogBuffer.getValidLogLevelNames()); } private String validLogLevelValuesAsJsonSchemaEnum() { StringBuilder result = new StringBuilder(); result.append("[ "); - result.append(LogSnapshot.getValidLogLevelNames().stream() + result.append(structuredLogBuffer.getValidLogLevelNames().stream() .map(name -> '"' + name + '"') .collect(Collectors.joining(", "))); result.append(" ]"); diff --git a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/LogLevel.java similarity index 60% copy from src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java copy to src/main/java/org/apache/sling/mcp/server/impl/contribs/log/LogLevel.java index 8c494b5..c0cb8fd 100644 --- a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/LogLevel.java @@ -16,17 +16,29 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.impl.contribs.log; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot.LogLevel; -import org.junit.jupiter.api.Test; +enum LogLevel { + TRACE, + DEBUG, + INFO, + WARN, + ERROR; -import static org.junit.jupiter.api.Assertions.*; + static boolean isValid(String logLevelName) { + try { + LogLevel.valueOf(logLevelName); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } -class LogSnapshotTest { + static String getHighestName() { + return values()[values().length - 1].toString(); + } - @Test - void logLevelComparison() { - assertTrue(LogSnapshot.LogLevel.INFO.isGreaterOrEqual(LogLevel.TRACE)); + boolean isGreaterOrEqual(LogLevel minLevel) { + return ordinal() >= minLevel.ordinal(); } } diff --git a/src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferAppender.java b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferAppender.java similarity index 81% rename from src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferAppender.java rename to src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferAppender.java index 244f297..2122531 100644 --- a/src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferAppender.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferAppender.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.impl.contribs.log; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -29,52 +29,37 @@ import ch.qos.logback.classic.spi.IThrowableProxy; import ch.qos.logback.classic.spi.StackTraceElementProxy; import ch.qos.logback.core.Appender; import ch.qos.logback.core.AppenderBase; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot.LogLevel; +import org.apache.sling.mcp.server.contribs.log.LogSnapshot; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; -import org.osgi.service.metatype.annotations.AttributeDefinition; -import org.osgi.service.metatype.annotations.Designate; -import org.osgi.service.metatype.annotations.ObjectClassDefinition; +import org.osgi.service.component.annotations.Reference; @Component( - service = {Appender.class, StructuredLogBufferAppender.class}, - property = { - "loggers=ROOT", - "service.description=Structured in-memory MCP log appender", - "service.vendor=The Apache Software Foundation" - }) -@Designate(ocd = StructuredLogBufferAppender.Configuration.class) + service = Appender.class, + property = {"loggers=ROOT"}) public class StructuredLogBufferAppender extends AppenderBase<ILoggingEvent> { // Forward compatibility with logback 1.5+, where IThrowableProxy may expose getOverridingMessage(). private static final MethodHandle GET_OVERRIDING_MESSAGE = findGetOverridingMessage(); - @ObjectClassDefinition(name = "Apache Sling Structured Log Buffer") - public @interface Configuration { - - @AttributeDefinition(name = "Max entries") - int maxEntries() default 10000; - } - - private final StructuredLogBuffer buffer; + private final StructuredLogBufferSink buffer; @Activate - public StructuredLogBufferAppender(Configuration configuration) { - buffer = new StructuredLogBuffer(configuration.maxEntries()); + public StructuredLogBufferAppender(@Reference StructuredLogBufferSink buffer) { + this.buffer = buffer; setName("structured-log-buffer"); } - public StructuredLogBuffer getBuffer() { - return buffer; - } - @Override protected void append(ILoggingEvent eventObject) { if (eventObject == null) { return; } - LogLevel logLevel = LogLevel.valueOf(eventObject.getLevel().levelStr); + String logLevel = eventObject.getLevel().levelStr; + if (!LogLevel.isValid(logLevel)) { + return; + } buffer.append(new LogSnapshot( eventObject.getTimeStamp(), diff --git a/src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBuffer.java b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferImpl.java similarity index 65% rename from src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBuffer.java rename to src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferImpl.java index 9a9ba53..c3bfe5f 100644 --- a/src/main/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBuffer.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferImpl.java @@ -16,26 +16,48 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.impl.contribs.log; import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Arrays; import java.util.Deque; import java.util.List; import java.util.regex.Pattern; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot.LogLevel; +import org.apache.sling.mcp.server.contribs.log.LogSnapshot; +import org.apache.sling.mcp.server.contribs.log.StructuredLogBuffer; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.Designate; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; -public class StructuredLogBuffer { +@Component(service = {StructuredLogBuffer.class, StructuredLogBufferSink.class}) +@Designate(ocd = StructuredLogBufferImpl.Configuration.class) +public class StructuredLogBufferImpl implements StructuredLogBuffer, StructuredLogBufferSink { + + @ObjectClassDefinition(name = "Apache Sling Structured Log Buffer") + public @interface Configuration { + + @AttributeDefinition(name = "Max entries") + int maxEntries() default 10000; + } private final Object lock = new Object(); private final Deque<LogSnapshot> entries = new ArrayDeque<>(); private int maxEntriesKept; - public StructuredLogBuffer(int maxEntriesKept) { + public StructuredLogBufferImpl(int maxEntriesKept) { this.maxEntriesKept = Math.max(1, maxEntriesKept); } + @Activate + public StructuredLogBufferImpl(Configuration configuration) { + this(configuration.maxEntries()); + } + + @Override public void append(LogSnapshot snapshot) { synchronized (lock) { entries.addLast(snapshot); @@ -43,9 +65,24 @@ public class StructuredLogBuffer { } } + @Override + public boolean isValidLogLevel(String logLevelName) { + return LogLevel.isValid(logLevelName); + } + + @Override + public List<String> getValidLogLevelNames() { + return Arrays.stream(LogLevel.values()).map(Enum::toString).toList(); + } + + @Override + public String getHighestLogLevelName() { + return LogLevel.getHighestName(); + } + public List<LogSnapshot> getRecent(Pattern pattern, String minLevel, int maxEntries) { - if (!LogSnapshot.isValidLogLevel(minLevel)) { + if (!isValidLogLevel(minLevel)) { throw new IllegalArgumentException("Invalid log level: " + minLevel); } @@ -70,12 +107,11 @@ public class StructuredLogBuffer { private boolean matches(LogSnapshot snapshot, Pattern pattern, LogLevel minLevel) { - if (snapshot.level().isGreaterOrEqual(minLevel)) { + if (LogLevel.valueOf(snapshot.level()).isGreaterOrEqual(minLevel)) { if (pattern == null) { return true; } - return matchesField( - pattern, snapshot.level() != null ? snapshot.level().toString() : null) + return matchesField(pattern, snapshot.level()) || matchesField(pattern, snapshot.loggerName()) || matchesField(pattern, snapshot.threadName()) || matchesField(pattern, snapshot.formattedMessage()) diff --git a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferSink.java similarity index 68% copy from src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java copy to src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferSink.java index 8c494b5..1524641 100644 --- a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java +++ b/src/main/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferSink.java @@ -16,17 +16,11 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.impl.contribs.log; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot.LogLevel; -import org.junit.jupiter.api.Test; +import org.apache.sling.mcp.server.contribs.log.LogSnapshot; -import static org.junit.jupiter.api.Assertions.*; +interface StructuredLogBufferSink { -class LogSnapshotTest { - - @Test - void logLevelComparison() { - assertTrue(LogSnapshot.LogLevel.INFO.isGreaterOrEqual(LogLevel.TRACE)); - } + void append(LogSnapshot snapshot); } diff --git a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java b/src/test/java/org/apache/sling/mcp/server/contribs/log/LogSnapshotTest.java similarity index 69% rename from src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java rename to src/test/java/org/apache/sling/mcp/server/contribs/log/LogSnapshotTest.java index 8c494b5..5ea3105 100644 --- a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/LogSnapshotTest.java +++ b/src/test/java/org/apache/sling/mcp/server/contribs/log/LogSnapshotTest.java @@ -16,17 +16,21 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.contribs.log; + +import java.util.Map; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot.LogLevel; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class LogSnapshotTest { @Test - void logLevelComparison() { - assertTrue(LogSnapshot.LogLevel.INFO.isGreaterOrEqual(LogLevel.TRACE)); + void storesMdcAsUnmodifiableMap() { + LogSnapshot snapshot = new LogSnapshot(1L, "INFO", "logger", "thread", "message", null, Map.of("k", "v")); + + assertEquals("INFO", snapshot.level()); + assertEquals(Map.of("k", "v"), snapshot.mdc()); } } diff --git a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferAppenderTest.java b/src/test/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferAppenderTest.java similarity index 58% rename from src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferAppenderTest.java rename to src/test/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferAppenderTest.java index 1d34628..aa81263 100644 --- a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferAppenderTest.java +++ b/src/test/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferAppenderTest.java @@ -16,26 +16,28 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.impl.contribs.log; +import java.lang.reflect.Constructor; import java.util.List; -import java.util.Map; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.spi.LoggingEvent; +import org.apache.sling.mcp.server.contribs.log.LogSnapshot; import org.junit.jupiter.api.Test; -import org.osgi.util.converter.Converters; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.fail; class StructuredLogBufferAppenderTest { @Test void appenderSnapshotsFormattedMessageAndThrowable() { - StructuredLogBufferAppender appender = new StructuredLogBufferAppender(configuration(5)); + StructuredLogBufferImpl buffer = new StructuredLogBufferImpl(5); + StructuredLogBufferAppender appender = new StructuredLogBufferAppender(buffer); LoggerContext context = new LoggerContext(); appender.setContext(context); @@ -47,16 +49,39 @@ class StructuredLogBufferAppenderTest { appender.append(event); - List<LogSnapshot> logs = appender.getBuffer().getRecent(null, "TRACE", 10); + List<LogSnapshot> logs = buffer.getRecent(null, "TRACE", 10); assertEquals(1, logs.size()); assertEquals("message", logs.get(0).formattedMessage()); assertEquals("worker-1", logs.get(0).threadName()); + assertEquals("ERROR", logs.get(0).level()); assertNotNull(logs.get(0).throwableText()); } - private StructuredLogBufferAppender.Configuration configuration(int maxEntries) { - return Converters.standardConverter() - .convert(Map.of("maxEntries", maxEntries)) - .to(StructuredLogBufferAppender.Configuration.class); + @Test + void appenderSkipsInvalidLogLevels() { + StructuredLogBufferImpl buffer = new StructuredLogBufferImpl(5); + StructuredLogBufferAppender appender = new StructuredLogBufferAppender(buffer); + + LoggerContext context = new LoggerContext(); + LoggingEvent event = new LoggingEvent(); + event.setLoggerName("invalid.logger"); + event.setThreadName("invalid-thread"); + event.setMessage("ignored"); + event.setLevel(invalidLevel()); + + appender.append(event); + + assertEquals(List.of(), buffer.getRecent(null, "TRACE", 10)); + } + + private Level invalidLevel() { + try { + Constructor<Level> constructor = Level.class.getDeclaredConstructor(int.class, String.class); + constructor.setAccessible(true); + return constructor.newInstance(Integer.MAX_VALUE, "INVALID"); + } catch (ReflectiveOperationException e) { + fail("Unable to construct invalid log level", e); + return null; + } } } diff --git a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferTest.java b/src/test/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferImplTest.java similarity index 57% rename from src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferTest.java rename to src/test/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferImplTest.java index 8557801..d2e4d7d 100644 --- a/src/test/java/org/apache/sling/mcp/server/impl/contribs/internal/StructuredLogBufferTest.java +++ b/src/test/java/org/apache/sling/mcp/server/impl/contribs/log/StructuredLogBufferImplTest.java @@ -16,26 +16,28 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.sling.mcp.server.impl.contribs.internal; +package org.apache.sling.mcp.server.impl.contribs.log; import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import org.apache.sling.mcp.server.impl.contribs.internal.LogSnapshot.LogLevel; +import org.apache.sling.mcp.server.contribs.log.LogSnapshot; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -class StructuredLogBufferTest { +class StructuredLogBufferImplTest { @Test void keepsOnlyNewestEntriesWithinCapacity() { - StructuredLogBuffer buffer = new StructuredLogBuffer(2); + StructuredLogBufferImpl buffer = new StructuredLogBufferImpl(2); - buffer.append(snapshot(1L, LogLevel.INFO, "first")); - buffer.append(snapshot(2L, LogLevel.INFO, "second")); - buffer.append(snapshot(3L, LogLevel.INFO, "third")); + buffer.append(snapshot(1L, "INFO", "first")); + buffer.append(snapshot(2L, "INFO", "second")); + buffer.append(snapshot(3L, "INFO", "third")); List<LogSnapshot> logs = buffer.getRecent(null, "TRACE", 10); assertEquals( @@ -45,11 +47,11 @@ class StructuredLogBufferTest { @Test void filtersByLevelAndRegex() { - StructuredLogBuffer buffer = new StructuredLogBuffer(10); + StructuredLogBufferImpl buffer = new StructuredLogBufferImpl(10); - buffer.append(snapshot(1L, LogLevel.DEBUG, "debug trace")); - buffer.append(snapshot(2L, LogLevel.INFO, "first user ok")); - buffer.append(snapshot(3L, LogLevel.ERROR, "first user failure")); + buffer.append(snapshot(1L, "DEBUG", "debug trace")); + buffer.append(snapshot(2L, "INFO", "first user ok")); + buffer.append(snapshot(3L, "ERROR", "first user failure")); List<LogSnapshot> logs = buffer.getRecent(Pattern.compile("first", Pattern.CASE_INSENSITIVE), "INFO", 10); @@ -58,7 +60,17 @@ class StructuredLogBufferTest { logs.stream().map(LogSnapshot::formattedMessage).toList()); } - private LogSnapshot snapshot(long timeMillis, LogLevel level, String message) { + @Test + void exposesSupportedLogLevels() { + StructuredLogBufferImpl buffer = new StructuredLogBufferImpl(10); + + assertTrue(buffer.isValidLogLevel("INFO")); + assertFalse(buffer.isValidLogLevel("info")); + assertEquals(List.of("TRACE", "DEBUG", "INFO", "WARN", "ERROR"), buffer.getValidLogLevelNames()); + assertEquals("ERROR", buffer.getHighestLogLevelName()); + } + + private LogSnapshot snapshot(long timeMillis, String level, String message) { return new LogSnapshot(timeMillis, level, "logger", "thread", message, null, Map.of()); } }
