From ee839b0d70715c1f84f638a03b9a7083c23cff70 Mon Sep 17 00:00:00 2001 From: javasabr Date: Sun, 21 Jun 2026 12:55:21 +0200 Subject: [PATCH 1/2] implement json logger config --- gradle/libs.versions.toml | 4 + .../rlib/logger/api/LoggerFactory.java | 8 +- .../rlib/logger/api/LoggerManager.java | 2 +- .../logger/api/impl/NoOpsLoggerFactory.java | 2 +- rlib-logger-impl-json/build.gradle | 10 + .../loader/json/JsonLoggerConfigLoader.java | 176 ++++++++++++++++++ .../json/JsonLoggerConfigLoadersProvider.java | 15 ++ .../loader/json/dto/JsonLoggerConfigDto.java | 70 +++++++ .../config/loader/json/dto/package-info.java | 4 + .../impl/config/loader/json/package-info.java | 4 + ...fig.loader.spi.LoggerConfigLoadersProvider | 1 + .../json/JsonLoggerConfigLoaderTest.java | 150 +++++++++++++++ .../src/test/resources/rlib.logger-test.json | 75 ++++++++ .../logger/impl/DefaultLoggerFactory.java | 4 +- .../logger/impl/DefaultLoggerService.java | 14 +- .../impl/CustomLogMessageConsumer.java | 10 + .../impl/config/impl/DefaultLoggerConfig.java | 15 +- .../config/loader/LoggerConfigResolver.java | 1 + .../impl/DefaultLoggerConfigLoader.java | 4 +- .../impl/PropertyLoggerConfigLoader.java | 4 +- .../LoggerConfigLoadersProvider.java | 3 +- .../impl/config/loader/spi/package-info.java | 4 + .../render/impl/CustomLogMessageRender.java | 10 + .../impl/pattern/PatternLogMessageRender.java | 29 ++- .../rlib/logger/impl/DefaultLoggerTest.java | 9 +- .../rlib/logger/slf4j/Slf4jLoggerFactory.java | 2 +- settings.gradle | 3 +- 27 files changed, 599 insertions(+), 34 deletions(-) create mode 100644 rlib-logger-impl-json/build.gradle create mode 100644 rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java create mode 100644 rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoadersProvider.java create mode 100644 rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/JsonLoggerConfigDto.java create mode 100644 rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/package-info.java create mode 100644 rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/package-info.java create mode 100644 rlib-logger-impl-json/src/main/resources/META-INF/services/javasabr.rlib.logger.impl.config.loader.spi.LoggerConfigLoadersProvider create mode 100644 rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java create mode 100644 rlib-logger-impl-json/src/test/resources/rlib.logger-test.json create mode 100644 rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java rename rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/{ => spi}/LoggerConfigLoadersProvider.java (75%) create mode 100644 rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/spi/package-info.java create mode 100644 rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/CustomLogMessageRender.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2a4b7f90..f58e0873 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,6 +21,8 @@ mockito = "5.20.0" assertj-core = "4.0.0-M1" # https://mvnrepository.com/artifact/org.awaitility/awaitility awaitility = "4.3.0" +# https://mvnrepository.com/artifact/tools.jackson.core/jackson-core/3.2.0 +jackson = "3.2.0" [libraries] project-reactor-core = { module = "io.projectreactor:reactor-core", version.ref = "project-reactor" } @@ -40,6 +42,8 @@ mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockito" } mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" } assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj-core" } awaitility = { module = "org.awaitility:awaitility", version.ref = "awaitility" } +jackson-core = { module = "tools.jackson.core:jackson-core", version.ref = "jackson" } +jackson-databind = { module = "tools.jackson.core:jackson-databind", version.ref = "jackson" } [bundles] mail = ["jakarta-mail-api", "angus-mail"] diff --git a/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerFactory.java b/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerFactory.java index c865f165..7acb02df 100644 --- a/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerFactory.java +++ b/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerFactory.java @@ -7,6 +7,8 @@ */ public interface LoggerFactory { + String ROOT_LOGGER_NAME = "ROOT"; + /** * Creates or gets a logger with the specified name. * @@ -26,12 +28,12 @@ public interface LoggerFactory { Logger getLogger(Class type); /** - * Returns the default logger. + * Returns the root logger. * - * @return the default logger + * @return the root logger * @since 10.0.0 */ - Logger getDefault(); + Logger getRootLogger(); /** * Returns the logger service. diff --git a/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerManager.java b/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerManager.java index aa8cf36c..412433fc 100644 --- a/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerManager.java +++ b/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/LoggerManager.java @@ -59,7 +59,7 @@ public class LoggerManager { * @since 10.0.0 */ public static Logger getDefaultLogger() { - return LOGGER_FACTORY.getDefault(); + return LOGGER_FACTORY.getRootLogger(); } /** diff --git a/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/impl/NoOpsLoggerFactory.java b/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/impl/NoOpsLoggerFactory.java index ce94ea12..f8950ca3 100644 --- a/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/impl/NoOpsLoggerFactory.java +++ b/rlib-logger-api/src/main/java/javasabr/rlib/logger/api/impl/NoOpsLoggerFactory.java @@ -20,7 +20,7 @@ public Logger getLogger(Class type) { } @Override - public Logger getDefault() { + public Logger getRootLogger() { return NO_OPS_LOGGER; } diff --git a/rlib-logger-impl-json/build.gradle b/rlib-logger-impl-json/build.gradle new file mode 100644 index 00000000..3b9dc0a6 --- /dev/null +++ b/rlib-logger-impl-json/build.gradle @@ -0,0 +1,10 @@ +plugins { + id("configure-java") + id("configure-publishing") +} + +dependencies { + api projects.rlibLoggerImpl + api libs.jackson.core + api libs.jackson.databind +} diff --git a/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java new file mode 100644 index 00000000..5f6f9e36 --- /dev/null +++ b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java @@ -0,0 +1,176 @@ +package javasabr.rlib.logger.impl.config.loader.json; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import javasabr.rlib.common.util.StringUtils; +import javasabr.rlib.logger.api.LoggerLevel; +import javasabr.rlib.logger.impl.config.LoggerConfig; +import javasabr.rlib.logger.impl.config.consumer.LogMessageConsumer; +import javasabr.rlib.logger.impl.config.consumer.impl.ConsoleMessageConsumer; +import javasabr.rlib.logger.impl.config.consumer.impl.CustomLogMessageConsumer; +import javasabr.rlib.logger.impl.config.impl.LoggerConfigBuilder; +import javasabr.rlib.logger.impl.config.loader.LoggerConfigLoader; +import javasabr.rlib.logger.impl.config.loader.json.dto.JsonLoggerConfigDto; +import javasabr.rlib.logger.impl.config.loader.json.dto.JsonLoggerConfigDto.ConsumerDto; +import javasabr.rlib.logger.impl.config.loader.json.dto.JsonLoggerConfigDto.LoggerDto; +import javasabr.rlib.logger.impl.config.loader.json.dto.JsonLoggerConfigDto.RenderDto; +import javasabr.rlib.logger.impl.config.render.LogMessageRender; +import javasabr.rlib.logger.impl.config.render.impl.CustomLogMessageRender; +import javasabr.rlib.logger.impl.config.render.impl.SimpleLogMessageRender; +import javasabr.rlib.logger.impl.config.render.impl.pattern.PatternLogMessageRender; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; +import tools.jackson.databind.ObjectMapper; + +@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) +public class JsonLoggerConfigLoader implements LoggerConfigLoader { + + public static final String FILE_MAIN = "rlib.logger.json"; + public static final String FILE_TEST = "rlib.logger-test.json"; + + ObjectMapper objectMapper = new ObjectMapper(); + + @Override + public Optional tryToLoad() { + ClassLoader classLoader = Thread + .currentThread() + .getContextClassLoader(); + InputStream configStream = classLoader.getResourceAsStream(FILE_TEST); + if (configStream == null) { + configStream = classLoader.getResourceAsStream(FILE_MAIN); + } + if (configStream == null) { + return Optional.empty(); + } else { + return Optional.of(load(configStream)); + } + } + + @Override + public int order() { + return LoggerConfigLoader.ORDER_NORMAL; + } + + private LoggerConfig load(InputStream inputStream) { + try (var in = inputStream) { + JsonLoggerConfigDto configDto = objectMapper.readValue(in, JsonLoggerConfigDto.class); + return load(configDto); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private LoggerConfig load(JsonLoggerConfigDto configDto) { + + var builder = new LoggerConfigBuilder(); + + List createdRenders = configDto + .renders() + .stream() + .map(this::createRender) + .toList(); + + Map renderMap = createdRenders + .stream() + .collect(Collectors.toMap(CreatedRender::name, CreatedRender::render)); + + List createdConsumers = configDto + .consumers() + .stream() + .map(consumerDto -> createConsumer(renderMap, consumerDto)) + .toList(); + + Map consumerMap = createdConsumers + .stream() + .collect(Collectors.toMap(CreatedConsumer::name, CreatedConsumer::consumer)); + + for (LoggerDto loggerDto : configDto.loggers()) { + if (loggerDto.level() != null) { + builder.registerLoggerLevel(loggerDto.name(), loggerDto.level()); + } + Set consumerNames = loggerDto.consumerNames(); + if (!consumerNames.isEmpty()) { + for (String consumerName : consumerNames) { + LogMessageConsumer consumer = consumerMap.get(consumerName); + if (consumer == null) { + throw new RuntimeException("Consumer " + consumerName + " not found"); + } + LoggerLevel level = loggerDto.level(); + if (level == null) { + level = LoggerLevel.TRACE; + } + builder.registerLoggerConsumer(loggerDto.name(), level, consumer); + } + } + } + + return builder.build(); + } + + CreatedRender createRender(RenderDto renderDto) { + LogMessageRender render = switch (renderDto.type()) { + case SIMPLE -> new SimpleLogMessageRender(); + case PATTERN -> new PatternLogMessageRender(renderDto.args()); + case CUSTOM -> createCustomRender(renderDto); + }; + return new CreatedRender(renderDto.name(), render); + } + + LogMessageRender createCustomRender(RenderDto renderDto) { + String className = renderDto.className(); + if (StringUtils.isBlank(className)) { + throw new IllegalArgumentException("'class'' is required for custom render"); + } + ClassLoader classLoader = Thread + .currentThread() + .getContextClassLoader(); + try { + var targetClass = (Class) classLoader.loadClass(className); + Constructor constructor = targetClass.getDeclaredConstructor(Map.class); + return constructor.newInstance(renderDto.args()); + } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | + IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + CreatedConsumer createConsumer(Map renderMap, ConsumerDto consumerDto) { + LogMessageRender render = renderMap.get(consumerDto.renderName()); + if (render == null) { + throw new IllegalArgumentException("Unknown render with name: " + consumerDto.renderName()); + } + LogMessageConsumer consumer = switch (consumerDto.type()) { + case CONSOLE -> new ConsoleMessageConsumer(render); + case CUSTOM -> createCustomConsumer(render, consumerDto); + }; + return new CreatedConsumer(consumerDto.name(), consumer); + } + + LogMessageConsumer createCustomConsumer(LogMessageRender render, ConsumerDto consumerDto) { + String className = consumerDto.className(); + if (StringUtils.isBlank(className)) { + throw new IllegalArgumentException("'class'' is required for custom consumer"); + } + ClassLoader classLoader = Thread + .currentThread() + .getContextClassLoader(); + try { + var targetClass = (Class) classLoader.loadClass(className); + Constructor constructor = targetClass.getDeclaredConstructor(Map.class); + return constructor.newInstance(consumerDto.args()); + } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | + IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + private record CreatedRender(String name, LogMessageRender render) {} + private record CreatedConsumer(String name, LogMessageConsumer consumer) {} +} diff --git a/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoadersProvider.java b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoadersProvider.java new file mode 100644 index 00000000..a3a1291a --- /dev/null +++ b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoadersProvider.java @@ -0,0 +1,15 @@ +package javasabr.rlib.logger.impl.config.loader.json; + +import javasabr.rlib.collections.array.Array; +import javasabr.rlib.logger.impl.config.loader.LoggerConfigLoader; +import javasabr.rlib.logger.impl.config.loader.spi.LoggerConfigLoadersProvider; + +public class JsonLoggerConfigLoadersProvider implements LoggerConfigLoadersProvider { + + private static final Array LOADERS = Array.of(new JsonLoggerConfigLoader()); + + @Override + public Array getLoggerConfigLoaders() { + return LOADERS; + } +} diff --git a/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/JsonLoggerConfigDto.java b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/JsonLoggerConfigDto.java new file mode 100644 index 00000000..18e43bd3 --- /dev/null +++ b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/JsonLoggerConfigDto.java @@ -0,0 +1,70 @@ +package javasabr.rlib.logger.impl.config.loader.json.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javasabr.rlib.common.util.StringUtils; +import javasabr.rlib.logger.api.LoggerLevel; +import org.jspecify.annotations.Nullable; + +public record JsonLoggerConfigDto( + List loggers, + List renders, + List consumers) { + + public JsonLoggerConfigDto { + loggers = loggers == null ? List.of() : List.copyOf(loggers); + renders = renders == null ? List.of() : List.copyOf(renders); + consumers = consumers == null ? List.of() : List.copyOf(consumers); + } + + public record LoggerDto( + String name, + @Nullable LoggerLevel level, + @JsonProperty("consumers") Set consumerNames) { + + public LoggerDto { + consumerNames = consumerNames == null ? Set.of() : Set.copyOf(consumerNames); + } + } + + public record RenderDto( + String name, + RenderType type, + @JsonProperty("class") @Nullable String className, + Map args) { + + public RenderDto { + if (StringUtils.isBlank(name)) { + throw new IllegalArgumentException("name is blank"); + } else if (type == null) { + throw new IllegalArgumentException("type is null"); + } + args = args == null ? Map.of() : Map.copyOf(args); + } + } + + public enum RenderType { + SIMPLE, + PATTERN, + CUSTOM + } + + public record ConsumerDto( + String name, + ConsumerType type, + @JsonProperty("render") String renderName, + @JsonProperty("class") @Nullable String className, + Map args) { + + public ConsumerDto { + args = args == null ? Map.of() : Map.copyOf(args); + } + } + + public enum ConsumerType { + CONSOLE, + CUSTOM + } +} diff --git a/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/package-info.java b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/package-info.java new file mode 100644 index 00000000..cfbf911a --- /dev/null +++ b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/dto/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package javasabr.rlib.logger.impl.config.loader.json.dto; + +import org.jspecify.annotations.NullMarked; diff --git a/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/package-info.java b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/package-info.java new file mode 100644 index 00000000..535dd972 --- /dev/null +++ b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package javasabr.rlib.logger.impl.config.loader.json; + +import org.jspecify.annotations.NullMarked; diff --git a/rlib-logger-impl-json/src/main/resources/META-INF/services/javasabr.rlib.logger.impl.config.loader.spi.LoggerConfigLoadersProvider b/rlib-logger-impl-json/src/main/resources/META-INF/services/javasabr.rlib.logger.impl.config.loader.spi.LoggerConfigLoadersProvider new file mode 100644 index 00000000..8c93c34a --- /dev/null +++ b/rlib-logger-impl-json/src/main/resources/META-INF/services/javasabr.rlib.logger.impl.config.loader.spi.LoggerConfigLoadersProvider @@ -0,0 +1 @@ +javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoadersProvider \ No newline at end of file diff --git a/rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java b/rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java new file mode 100644 index 00000000..dfc1cd26 --- /dev/null +++ b/rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java @@ -0,0 +1,150 @@ +package javasabr.rlib.logger.impl.config.loader.json; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; +import java.util.Optional; +import javasabr.rlib.collections.array.ArrayFactory; +import javasabr.rlib.collections.array.MutableArray; +import javasabr.rlib.logger.api.Logger; +import javasabr.rlib.logger.api.LoggerLevel; +import javasabr.rlib.logger.impl.DefaultLoggerService; +import javasabr.rlib.logger.impl.config.LoggerConfig; +import javasabr.rlib.logger.impl.config.consumer.impl.CustomLogMessageConsumer; +import javasabr.rlib.logger.impl.config.render.impl.CustomLogMessageRender; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +class JsonLoggerConfigLoaderTest { + + private static final ThreadLocal> CONSUMED_MESSAGES = ThreadLocal + .withInitial(() -> ArrayFactory.mutableArray(String.class)); + + @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) + public static class TestCustomLogMessageConsumer extends CustomLogMessageConsumer { + + int consumerArg1; + String consumerArg2; + + public TestCustomLogMessageConsumer(Map args) { + super(args); + consumerArg1 = (Integer) args.get("consumerArg1"); + consumerArg2 = (String) args.get("consumerArg2"); + } + + @Override + public void consume(LoggerLevel level, Logger logger, String message) { + CONSUMED_MESSAGES.get().add("[%s][%s]->%s->%s:%s".formatted( + consumerArg1, + consumerArg2, + level, + logger.name(), + message)); + } + } + + @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) + public static class TestCustomLogMessageRender extends CustomLogMessageRender { + + int renderArg1; + String renderArg2; + + public TestCustomLogMessageRender(Map args) { + super(args); + renderArg1 = (Integer) args.get("renderArg1"); + renderArg2 = (String) args.get("renderArg2+"); + } + + @Override + public String render(LoggerLevel level, Logger logger, String message) { + return "[%s][%s]->%s".formatted(renderArg1, renderArg2, message); + } + } + + @AfterEach + void cleanup() { + CONSUMED_MESSAGES.get().clear(); + } + + @Test + void shouldLoadConfigCorrectly() { + // given: + var loader = new JsonLoggerConfigLoader(); + MutableArray receivedMessages = CONSUMED_MESSAGES.get(); + + //when: + Optional loadedLoggerConfig = loader.tryToLoad(); + + // then: + assertThat(loadedLoggerConfig).isPresent(); + + // when: + var service = new DefaultLoggerService(loadedLoggerConfig.get()); + Logger logger1 = service.getLogger( + "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger1"); + logger1.error("test error 1"); + logger1.warn("test warning 1"); + logger1.info("test info 1"); + logger1.debug("test debug 1"); + logger1.trace("test trace 1"); + + // then: + assertThat(receivedMessages) + .hasSize(2) + .containsExactly( + "[66][arg2]->ERROR->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger1:test error 1", + "[66][arg2]->WARN->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger1:test warning 1"); + + // when: + receivedMessages.clear(); + Logger logger2 = service.getLogger( + "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2"); + logger2.error("test error 2"); + logger2.warn("test warning 2"); + logger2.info("test info 2"); + logger2.debug("test debug 2"); + logger2.trace("test trace 2"); + + // then: + assertThat(receivedMessages) + .hasSize(4) + .containsExactly( + "[66][arg2]->ERROR->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test error 2", + "[66][arg2]->WARN->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test warning 2", + "[66][arg2]->INFO->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test info 2", + "[66][arg2]->DEBUG->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test debug 2"); + + // when: + receivedMessages.clear(); + Logger logger3 = service.getLogger( + "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger3"); + logger3.error("test error 3"); + logger3.warn("test warning 3"); + logger3.info("test info 3"); + logger3.debug("test debug 3"); + logger3.trace("test trace 3"); + + // then: + assertThat(receivedMessages) + .hasSize(1) + .containsExactly( + "[66][arg2]->ERROR->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger3:test error 3"); + + // when: + receivedMessages.clear(); + Logger rootLogger = service.getRootLogger(); + rootLogger.error("test error 4"); + rootLogger.warn("test warning 4"); + rootLogger.info("test info 4"); + rootLogger.debug("test debug 4"); + rootLogger.trace("test trace 4"); + + // then: + assertThat(receivedMessages) + .hasSize(1) + .containsExactly( + "[66][arg2]->ERROR->ROOT:test error 4"); + } +} diff --git a/rlib-logger-impl-json/src/test/resources/rlib.logger-test.json b/rlib-logger-impl-json/src/test/resources/rlib.logger-test.json new file mode 100644 index 00000000..08d1b5de --- /dev/null +++ b/rlib-logger-impl-json/src/test/resources/rlib.logger-test.json @@ -0,0 +1,75 @@ +{ + "renders": [ + { + "name": "Render1", + "type": "PATTERN", + "args": { + "pattern": "%dateTime{d.MM.yyyy HH:mm:ss:SSS} %level : %msg" + } + }, + { + "name": "Render2", + "type": "CUSTOM", + "class": "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest$TestCustomLogMessageRender", + "args": { + "renderArg1": 55, + "renderArg2": "arg2" + } + } + ], + "consumers": [ + { + "name": "Consumer1", + "type": "CONSOLE", + "render": "Render1" + }, + { + "name": "Consumer2", + "type": "CUSTOM", + "class": "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest$TestCustomLogMessageConsumer", + "render": "Render2", + "args": { + "consumerArg1": 66, + "consumerArg2": "arg2" + } + } + ], + "loggers": [ + { + "name": "ROOT", + "level": "ERROR", + "consumers": [ + "Consumer2" + ] + }, + { + "name": "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger1", + "level": "DEBUG", + "consumers": [ + "Consumer1", + "Consumer2" + ] + }, + { + "name": "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger1", + "level": "WARN", + "consumers": [ + "Consumer2" + ] + }, + { + "name": "javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2", + "level": "DEBUG", + "consumers": [ + "Consumer2" + ] + }, + { + "name": "javasabr.mqtt.service.session.impl.InMemoryMqttSessionService", + "level": "WARN", + "consumers": [ + "Consumer2" + ] + } + ] +} diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerFactory.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerFactory.java index 263d0e9a..4eec085a 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerFactory.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerFactory.java @@ -27,8 +27,8 @@ public Logger getLogger(Class type) { } @Override - public Logger getDefault() { - return defaultLoggerService.getDefault(); + public Logger getRootLogger() { + return defaultLoggerService.getRootLogger(); } @Override diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerService.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerService.java index 48221594..82a833d9 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerService.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/DefaultLoggerService.java @@ -6,11 +6,13 @@ import javasabr.rlib.collections.dictionary.DictionaryFactory; import javasabr.rlib.collections.dictionary.LockableRefToRefDictionary; import javasabr.rlib.logger.api.Logger; +import javasabr.rlib.logger.api.LoggerFactory; import javasabr.rlib.logger.api.LoggerLevel; import javasabr.rlib.logger.api.LoggerService; import javasabr.rlib.logger.impl.config.LoggerConfig; import javasabr.rlib.logger.impl.config.consumer.LogMessageConsumer; import lombok.AccessLevel; +import lombok.Getter; import lombok.experimental.FieldDefaults; /** @@ -22,12 +24,12 @@ public class DefaultLoggerService implements LoggerService { public static final LoggerLevel[] LOGGER_LEVELS = LoggerLevel.values(); - public static final String ROOT_LOGGER_NAME = "ROOT"; final LockableRefToRefDictionary loggers; final Function loggerFactory = this::createNew; - final Logger logger; + @Getter + final Logger rootLogger; final int[] override; volatile LoggerConfig config; @@ -35,15 +37,11 @@ public class DefaultLoggerService implements LoggerService { public DefaultLoggerService(LoggerConfig config) { this.config = config; this.loggers = DictionaryFactory.stampedLockBasedRefToRefDictionary(); - this.logger = getLogger(ROOT_LOGGER_NAME); + this.rootLogger = getLogger(LoggerFactory.ROOT_LOGGER_NAME); this.override = new int[LOGGER_LEVELS.length]; Arrays.fill(override, NOT_CONFIGURE); } - - public Logger getDefault() { - return logger; - } - + public DefaultLogger getLogger(Class type) { long lock = loggers.writeLock(); try { diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java new file mode 100644 index 00000000..863ea0fc --- /dev/null +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java @@ -0,0 +1,10 @@ +package javasabr.rlib.logger.impl.config.consumer.impl; + +import java.util.Map; +import javasabr.rlib.logger.impl.config.consumer.LogMessageConsumer; + +public abstract class CustomLogMessageConsumer implements LogMessageConsumer { + + protected CustomLogMessageConsumer(Map args) { + } +} diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/impl/DefaultLoggerConfig.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/impl/DefaultLoggerConfig.java index 19074272..ea185adb 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/impl/DefaultLoggerConfig.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/impl/DefaultLoggerConfig.java @@ -5,6 +5,7 @@ import javasabr.rlib.collections.dictionary.DictionaryFactory; import javasabr.rlib.collections.dictionary.RefToRefDictionary; import javasabr.rlib.logger.api.Logger; +import javasabr.rlib.logger.api.LoggerFactory; import javasabr.rlib.logger.api.LoggerLevel; import javasabr.rlib.logger.impl.DefaultLoggerService; import javasabr.rlib.logger.impl.config.LoggerConfig; @@ -49,18 +50,18 @@ public class DefaultLoggerConfig implements LoggerConfig { .asUnsafe(); public static final LoggerConsumersKey ROOT_TRACE_CONSUMERS_KEY = - new LoggerConsumersKey(DefaultLoggerService.ROOT_LOGGER_NAME, LoggerLevel.TRACE); + new LoggerConsumersKey(LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.TRACE); public static final LoggerConsumersKey ROOT_DEBUG_CONSUMERS_KEY = - new LoggerConsumersKey(DefaultLoggerService.ROOT_LOGGER_NAME, LoggerLevel.DEBUG); + new LoggerConsumersKey(LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.DEBUG); public static final LoggerConsumersKey ROOT_INFO_CONSUMERS_KEY = - new LoggerConsumersKey(DefaultLoggerService.ROOT_LOGGER_NAME, LoggerLevel.INFO); + new LoggerConsumersKey(LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.INFO); public static final LoggerConsumersKey ROOT_WARN_CONSUMERS_KEY = - new LoggerConsumersKey(DefaultLoggerService.ROOT_LOGGER_NAME, LoggerLevel.WARNING); + new LoggerConsumersKey(LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.WARNING); public static final LoggerConsumersKey ROOT_ERROR_CONSUMERS_KEY = - new LoggerConsumersKey(DefaultLoggerService.ROOT_LOGGER_NAME, LoggerLevel.ERROR); + new LoggerConsumersKey(LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.ERROR); public static final RefToRefDictionary ENABLE_ALL_LEVELS = RefToRefDictionary.of( - DefaultLoggerService.ROOT_LOGGER_NAME, + LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.TRACE); final RefToRefDictionary loggerLevels; @@ -77,7 +78,7 @@ public DefaultLoggerConfig( public void configureLevels(Logger logger) { LoggerLevel targetLevel = loggerLevels.get(logger.name()); if (targetLevel == null) { - targetLevel = loggerLevels.get(DefaultLoggerService.ROOT_LOGGER_NAME); + targetLevel = loggerLevels.get(LoggerFactory.ROOT_LOGGER_NAME); } if (targetLevel == null) { return; diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/LoggerConfigResolver.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/LoggerConfigResolver.java index 1e363748..7e14a3f4 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/LoggerConfigResolver.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/LoggerConfigResolver.java @@ -9,6 +9,7 @@ import javasabr.rlib.logger.impl.config.LoggerConfig; import javasabr.rlib.logger.impl.config.loader.impl.DefaultLoggerConfigLoader; import javasabr.rlib.logger.impl.config.loader.impl.PropertyLoggerConfigLoader; +import javasabr.rlib.logger.impl.config.loader.spi.LoggerConfigLoadersProvider; /** * Resolver of logger configuration from available loaders. diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/DefaultLoggerConfigLoader.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/DefaultLoggerConfigLoader.java index 725bad75..4b356dd7 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/DefaultLoggerConfigLoader.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/DefaultLoggerConfigLoader.java @@ -3,8 +3,8 @@ import java.util.Optional; import javasabr.rlib.collections.array.Array; import javasabr.rlib.collections.dictionary.RefToRefDictionary; +import javasabr.rlib.logger.api.LoggerFactory; import javasabr.rlib.logger.api.LoggerLevel; -import javasabr.rlib.logger.impl.DefaultLoggerService; import javasabr.rlib.logger.impl.config.LoggerConfig; import javasabr.rlib.logger.impl.config.consumer.LogMessageConsumer; import javasabr.rlib.logger.impl.config.consumer.impl.ConsoleMessageConsumer; @@ -18,7 +18,7 @@ public class DefaultLoggerConfigLoader implements LoggerConfigLoader { @Override public Optional tryToLoad() { RefToRefDictionary loggerLevels = RefToRefDictionary.of( - DefaultLoggerService.ROOT_LOGGER_NAME, + LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.INFO); RefToRefDictionary> loggerConsumers = RefToRefDictionary.of( DefaultLoggerConfig.ROOT_INFO_CONSUMERS_KEY, diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/PropertyLoggerConfigLoader.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/PropertyLoggerConfigLoader.java index 2d1d4d04..076dee24 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/PropertyLoggerConfigLoader.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/impl/PropertyLoggerConfigLoader.java @@ -4,8 +4,8 @@ import java.io.InputStream; import java.util.Optional; import java.util.Properties; +import javasabr.rlib.logger.api.LoggerFactory; import javasabr.rlib.logger.api.LoggerLevel; -import javasabr.rlib.logger.impl.DefaultLoggerService; import javasabr.rlib.logger.impl.config.LoggerConfig; import javasabr.rlib.logger.impl.config.consumer.impl.ConsoleMessageConsumer; import javasabr.rlib.logger.impl.config.impl.LoggerConfigBuilder; @@ -59,7 +59,7 @@ LoggerConfig loadFromProperties(Properties properties) { messageRender = new SimpleLogMessageRender(); } builder.registerLoggerConsumer( - DefaultLoggerService.ROOT_LOGGER_NAME, + LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.TRACE, new ConsoleMessageConsumer(messageRender)); return builder.build(); diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/LoggerConfigLoadersProvider.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/spi/LoggerConfigLoadersProvider.java similarity index 75% rename from rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/LoggerConfigLoadersProvider.java rename to rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/spi/LoggerConfigLoadersProvider.java index 26691d3d..15c66c1c 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/LoggerConfigLoadersProvider.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/spi/LoggerConfigLoadersProvider.java @@ -1,6 +1,7 @@ -package javasabr.rlib.logger.impl.config.loader; +package javasabr.rlib.logger.impl.config.loader.spi; import javasabr.rlib.collections.array.Array; +import javasabr.rlib.logger.impl.config.loader.LoggerConfigLoader; /** * Provider of additional logger configuration loaders. diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/spi/package-info.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/spi/package-info.java new file mode 100644 index 00000000..4c6b894a --- /dev/null +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/loader/spi/package-info.java @@ -0,0 +1,4 @@ +@NullMarked +package javasabr.rlib.logger.impl.config.loader.spi; + +import org.jspecify.annotations.NullMarked; diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/CustomLogMessageRender.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/CustomLogMessageRender.java new file mode 100644 index 00000000..a4c96b97 --- /dev/null +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/CustomLogMessageRender.java @@ -0,0 +1,10 @@ +package javasabr.rlib.logger.impl.config.render.impl; + +import java.util.Map; +import javasabr.rlib.logger.impl.config.render.LogMessageRender; + +public abstract class CustomLogMessageRender implements LogMessageRender { + + protected CustomLogMessageRender(Map args) { + } +} diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/pattern/PatternLogMessageRender.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/pattern/PatternLogMessageRender.java index 5e2e8fe7..f1b8d4ab 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/pattern/PatternLogMessageRender.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/render/impl/pattern/PatternLogMessageRender.java @@ -1,5 +1,6 @@ package javasabr.rlib.logger.impl.config.render.impl.pattern; +import java.util.Map; import javasabr.rlib.collections.array.UnsafeArray; import javasabr.rlib.logger.api.Logger; import javasabr.rlib.logger.api.LoggerLevel; @@ -10,12 +11,18 @@ @FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true) public class PatternLogMessageRender implements LogMessageRender { + + private static final int DEF_INIT_BUFFER_SIZE = 256; UnsafeArray renderNodes; int initBufferSize; + public PatternLogMessageRender(Map args) { + this(extractPattern(args), extractInitBufferSize(args)); + } + public PatternLogMessageRender(String pattern) { - this(pattern, 256); + this(pattern, DEF_INIT_BUFFER_SIZE); } public PatternLogMessageRender(String pattern, int initBufferSize) { @@ -34,4 +41,24 @@ public String render(LoggerLevel level, Logger logger, String message) { } return buffer.toString(); } + + private static String extractPattern(Map args) { + Object pattern = args.get("pattern"); + if (pattern instanceof String stringPattern) { + return stringPattern; + } else { + throw new IllegalArgumentException("'pattern' argument must be a string"); + } + } + + private static int extractInitBufferSize(Map args) { + Object initBufferSize = args.get("initBufferSize"); + if (initBufferSize instanceof Integer integer) { + return integer; + } else if (initBufferSize instanceof String string) { + return Integer.parseInt(string); + } else { + return DEF_INIT_BUFFER_SIZE; + } + } } diff --git a/rlib-logger-impl/src/test/java/javasabr/rlib/logger/impl/DefaultLoggerTest.java b/rlib-logger-impl/src/test/java/javasabr/rlib/logger/impl/DefaultLoggerTest.java index 8a1d5ac9..36a7aa52 100644 --- a/rlib-logger-impl/src/test/java/javasabr/rlib/logger/impl/DefaultLoggerTest.java +++ b/rlib-logger-impl/src/test/java/javasabr/rlib/logger/impl/DefaultLoggerTest.java @@ -7,6 +7,7 @@ import javasabr.rlib.collections.array.Array; import javasabr.rlib.collections.dictionary.RefToRefDictionary; import javasabr.rlib.logger.api.Logger; +import javasabr.rlib.logger.api.LoggerFactory; import javasabr.rlib.logger.api.LoggerLevel; import javasabr.rlib.logger.api.LoggerManager; import javasabr.rlib.logger.impl.config.consumer.LogMessageConsumer; @@ -101,7 +102,7 @@ void shouldSendLogMessagesForAllLevels() { void shouldSendOnlyErrorLogMessages() { // given: var enabledLevels = RefToRefDictionary.of( - DefaultLoggerService.ROOT_LOGGER_NAME, + LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.ERROR); RefToRefDictionary> loggerConsumers = RefToRefDictionary.of( DefaultLoggerConfig.ROOT_TRACE_CONSUMERS_KEY, @@ -130,7 +131,7 @@ void shouldSendOnlyErrorLogMessages() { void shouldSendOnlyWarnAndHigherLogMessages() { // given: var enabledLevels = RefToRefDictionary.of( - DefaultLoggerService.ROOT_LOGGER_NAME, + LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.WARNING); RefToRefDictionary> loggerConsumers = RefToRefDictionary.of( DefaultLoggerConfig.ROOT_TRACE_CONSUMERS_KEY, @@ -165,7 +166,7 @@ void shouldSendOnlyWarnAndHigherLogMessages() { void shouldSendOnlyInfoAndHigherLogMessages() { // given: var enabledLevels = RefToRefDictionary.of( - DefaultLoggerService.ROOT_LOGGER_NAME, + LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.INFO); RefToRefDictionary> loggerConsumers = RefToRefDictionary.of( DefaultLoggerConfig.ROOT_TRACE_CONSUMERS_KEY, @@ -206,7 +207,7 @@ void shouldSendOnlyInfoAndHigherLogMessages() { void shouldSendOnlyDebugAndHigherLogMessages() { // given: var enabledLevels = RefToRefDictionary.of( - DefaultLoggerService.ROOT_LOGGER_NAME, + LoggerFactory.ROOT_LOGGER_NAME, LoggerLevel.DEBUG); RefToRefDictionary> loggerConsumers = RefToRefDictionary.of( DefaultLoggerConfig.ROOT_TRACE_CONSUMERS_KEY, diff --git a/rlib-logger-slf4j/src/main/java/javasabr/rlib/logger/slf4j/Slf4jLoggerFactory.java b/rlib-logger-slf4j/src/main/java/javasabr/rlib/logger/slf4j/Slf4jLoggerFactory.java index 2920dfce..1d3d4e58 100644 --- a/rlib-logger-slf4j/src/main/java/javasabr/rlib/logger/slf4j/Slf4jLoggerFactory.java +++ b/rlib-logger-slf4j/src/main/java/javasabr/rlib/logger/slf4j/Slf4jLoggerFactory.java @@ -37,7 +37,7 @@ public Logger getLogger(Class type) { } @Override - public Logger getDefault() { + public Logger getRootLogger() { return logger; } diff --git a/settings.gradle b/settings.gradle index ed51c8af..08282df7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,7 +9,9 @@ include ':rlib-testcontainers' include ':rlib-mail' include ':rlib-logger-api' include ':rlib-logger-impl' +include ':rlib-logger-impl-json' include ':rlib-logger-slf4j' +include ':rlib-logger-slf4j-impl' include ':rlib-plugin-system' include ':rlib-geometry' include ':rlib-classpath' @@ -21,5 +23,4 @@ include ':rlib-reusable' include ':rlib-reference' include ':rlib-concurrent' include ':rlib-eventbus' -include ':rlib-logger-slf4j-impl' include ':test-coverage' From d1c040e57a49f87da2770e19aa1f36676ddda6c6 Mon Sep 17 00:00:00 2001 From: javasabr Date: Sun, 21 Jun 2026 13:45:12 +0200 Subject: [PATCH 2/2] implement json logger config --- .../loader/json/JsonLoggerConfigLoader.java | 5 ++-- .../json/JsonLoggerConfigLoaderTest.java | 30 +++++++++---------- .../impl/CustomLogMessageConsumer.java | 9 +++++- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java index 5f6f9e36..e677f5ed 100644 --- a/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java +++ b/rlib-logger-impl-json/src/main/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoader.java @@ -163,8 +163,9 @@ LogMessageConsumer createCustomConsumer(LogMessageRender render, ConsumerDto con .getContextClassLoader(); try { var targetClass = (Class) classLoader.loadClass(className); - Constructor constructor = targetClass.getDeclaredConstructor(Map.class); - return constructor.newInstance(consumerDto.args()); + Constructor constructor = targetClass + .getDeclaredConstructor(LogMessageRender.class, Map.class); + return constructor.newInstance(render, consumerDto.args()); } catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { throw new RuntimeException(e); diff --git a/rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java b/rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java index dfc1cd26..e570f67e 100644 --- a/rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java +++ b/rlib-logger-impl-json/src/test/java/javasabr/rlib/logger/impl/config/loader/json/JsonLoggerConfigLoaderTest.java @@ -11,6 +11,7 @@ import javasabr.rlib.logger.impl.DefaultLoggerService; import javasabr.rlib.logger.impl.config.LoggerConfig; import javasabr.rlib.logger.impl.config.consumer.impl.CustomLogMessageConsumer; +import javasabr.rlib.logger.impl.config.render.LogMessageRender; import javasabr.rlib.logger.impl.config.render.impl.CustomLogMessageRender; import lombok.AccessLevel; import lombok.experimental.FieldDefaults; @@ -28,20 +29,19 @@ public static class TestCustomLogMessageConsumer extends CustomLogMessageConsume int consumerArg1; String consumerArg2; - public TestCustomLogMessageConsumer(Map args) { - super(args); + public TestCustomLogMessageConsumer(LogMessageRender render, Map args) { + super(render, args); consumerArg1 = (Integer) args.get("consumerArg1"); consumerArg2 = (String) args.get("consumerArg2"); } @Override public void consume(LoggerLevel level, Logger logger, String message) { - CONSUMED_MESSAGES.get().add("[%s][%s]->%s->%s:%s".formatted( + CONSUMED_MESSAGES.get().add("[%s][%s]->%s->%s".formatted( consumerArg1, consumerArg2, - level, - logger.name(), - message)); + logger.shortName(), + render.render(level, logger, message))); } } @@ -54,7 +54,7 @@ public static class TestCustomLogMessageRender extends CustomLogMessageRender { public TestCustomLogMessageRender(Map args) { super(args); renderArg1 = (Integer) args.get("renderArg1"); - renderArg2 = (String) args.get("renderArg2+"); + renderArg2 = (String) args.get("renderArg2"); } @Override @@ -94,8 +94,8 @@ void shouldLoadConfigCorrectly() { assertThat(receivedMessages) .hasSize(2) .containsExactly( - "[66][arg2]->ERROR->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger1:test error 1", - "[66][arg2]->WARN->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger1:test warning 1"); + "[66][arg2]->logger1->[55][arg2]->test error 1", + "[66][arg2]->logger1->[55][arg2]->test warning 1"); // when: receivedMessages.clear(); @@ -111,10 +111,10 @@ void shouldLoadConfigCorrectly() { assertThat(receivedMessages) .hasSize(4) .containsExactly( - "[66][arg2]->ERROR->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test error 2", - "[66][arg2]->WARN->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test warning 2", - "[66][arg2]->INFO->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test info 2", - "[66][arg2]->DEBUG->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger2:test debug 2"); + "[66][arg2]->logger2->[55][arg2]->test error 2", + "[66][arg2]->logger2->[55][arg2]->test warning 2", + "[66][arg2]->logger2->[55][arg2]->test info 2", + "[66][arg2]->logger2->[55][arg2]->test debug 2"); // when: receivedMessages.clear(); @@ -130,7 +130,7 @@ void shouldLoadConfigCorrectly() { assertThat(receivedMessages) .hasSize(1) .containsExactly( - "[66][arg2]->ERROR->javasabr.rlib.logger.impl.config.loader.json.JsonLoggerConfigLoaderTest.logger3:test error 3"); + "[66][arg2]->logger3->[55][arg2]->test error 3"); // when: receivedMessages.clear(); @@ -145,6 +145,6 @@ void shouldLoadConfigCorrectly() { assertThat(receivedMessages) .hasSize(1) .containsExactly( - "[66][arg2]->ERROR->ROOT:test error 4"); + "[66][arg2]->ROOT->[55][arg2]->test error 4"); } } diff --git a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java index 863ea0fc..8ec58f52 100644 --- a/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java +++ b/rlib-logger-impl/src/main/java/javasabr/rlib/logger/impl/config/consumer/impl/CustomLogMessageConsumer.java @@ -2,9 +2,16 @@ import java.util.Map; import javasabr.rlib.logger.impl.config.consumer.LogMessageConsumer; +import javasabr.rlib.logger.impl.config.render.LogMessageRender; +import lombok.AccessLevel; +import lombok.experimental.FieldDefaults; +@FieldDefaults(level = AccessLevel.PROTECTED, makeFinal = true) public abstract class CustomLogMessageConsumer implements LogMessageConsumer { - protected CustomLogMessageConsumer(Map args) { + LogMessageRender render; + + protected CustomLogMessageConsumer(LogMessageRender render, Map args) { + this.render = render; } }