diff --git a/README.md b/README.md index 40b6972..7f99395 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,13 @@ TODO The framework is organized into several key modules: - Module | Purpose -----------------------------------|----------------------------------------------------------------------------------------------------- - microsphere-logging-core | Provides the core utilities across various domains like annotations, collections, concurrency, etc. - microsphere-logging-test | Provides the models and components for logging testing. - microsphere-logging-dependencies | Manages dependency versions across the project. - microsphere-logging-parent | Parent POM with shared configurations. + Module | Purpose +----------------------------------|------------------------------------------------------------------------- + microsphere-logging-parent | Parent POM with shared configurations. + microsphere-logging-dependencies | Manages dependency versions across the project. + microsphere-logging-core | Provides the core features for logging. + microsphere-logging-logback | Provides the extensions features for logback. + microsphere-logging-test | Provides the extensions of JUnit4 or JUnit Jupiter for logging testing. ## Getting Started diff --git a/microsphere-logging-core/src/test/java/io/microsphere/logging/ThrowableLogging.java b/microsphere-logging-core/src/test/java/io/microsphere/logging/ThrowableLogging.java index 859b149..2a74e6d 100644 --- a/microsphere-logging-core/src/test/java/io/microsphere/logging/ThrowableLogging.java +++ b/microsphere-logging-core/src/test/java/io/microsphere/logging/ThrowableLogging.java @@ -20,6 +20,9 @@ import java.util.List; import java.util.Set; +import static java.util.Collections.emptyList; +import static java.util.Collections.emptySet; + /** * Throwable {@link Logging} * @@ -31,12 +34,12 @@ public class ThrowableLogging implements Logging { @Override public List getLoggerNames() { - return List.of(); + return emptyList(); } @Override public Set getSupportedLoggingLevels() { - return Set.of(); + return emptySet(); } @Override @@ -46,7 +49,6 @@ public String getLoggerLevel(String loggerName) { @Override public void setLoggerLevel(String loggerName, String levelName) { - } @Override @@ -58,4 +60,4 @@ public String getParentLoggerName(String loggerName) { public String getName() { throw new RuntimeException("For testing..."); } -} +} \ No newline at end of file diff --git a/microsphere-logging-dependencies/pom.xml b/microsphere-logging-dependencies/pom.xml index ddecac2..2adec52 100644 --- a/microsphere-logging-dependencies/pom.xml +++ b/microsphere-logging-dependencies/pom.xml @@ -33,6 +33,12 @@ ${revision} + + io.github.microsphere-projects + microsphere-logging-log4j2 + ${revision} + + io.github.microsphere-projects microsphere-logging-test diff --git a/microsphere-logging-log4j2/pom.xml b/microsphere-logging-log4j2/pom.xml new file mode 100644 index 0000000..0f4ac5a --- /dev/null +++ b/microsphere-logging-log4j2/pom.xml @@ -0,0 +1,71 @@ + + + + io.github.microsphere-projects + microsphere-logging-parent + ${revision} + ../microsphere-logging-parent/pom.xml + + 4.0.0 + + io.github.microsphere-projects + microsphere-logging-log4j2 + ${revision} + jar + + Microsphere :: Logging :: Logj4 + Microsphere Logging Log4j2 + + + + + + io.github.microsphere-projects + microsphere-logging-core + ${revision} + + + + + io.github.microsphere-projects + microsphere-java-annotations + true + + + + io.github.microsphere-projects + microsphere-java-core + true + + + + + org.apache.logging.log4j + log4j-api + true + + + + org.apache.logging.log4j + log4j-core + true + + + + + org.junit.jupiter + junit-jupiter + test + + + + org.junit.jupiter + junit-jupiter-engine + test + + + + + \ No newline at end of file diff --git a/microsphere-logging-log4j2/src/main/java/io/microsphere/logging/log4j2/Log4j2Logging.java b/microsphere-logging-log4j2/src/main/java/io/microsphere/logging/log4j2/Log4j2Logging.java new file mode 100644 index 0000000..cb0b138 --- /dev/null +++ b/microsphere-logging-log4j2/src/main/java/io/microsphere/logging/log4j2/Log4j2Logging.java @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.microsphere.logging.log4j2; + +import io.microsphere.logging.Logging; +import io.microsphere.logging.log4j2.util.LoggerUtils; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; + +import java.util.List; +import java.util.Set; + +import static io.microsphere.constants.SymbolConstants.DOT; +import static io.microsphere.logging.DefaultLoggingLevelsResolver.INSTANCE; +import static io.microsphere.logging.log4j2.util.LoggerUtils.getLevelString; +import static io.microsphere.logging.log4j2.util.LoggerUtils.getLoggerContext; +import static java.util.stream.Collectors.toList; +import static org.apache.logging.log4j.LogManager.ROOT_LOGGER_NAME; + +/** + * {@link Logging} class based on the log4j2 framework. + * + * @author Mercy + * @see Logging + * @since 1.0.0 + */ +public class Log4j2Logging implements Logging { + + @Override + public List getLoggerNames() { + return getLoggerContext() + .getLoggers() + .stream().map(Logger::getName) + .collect(toList()); + } + + @Override + public Set getSupportedLoggingLevels() { + return INSTANCE.resolve(Level.class); + } + + @Override + public String getLoggerLevel(String loggerName) { + return getLevelString(loggerName); + } + + @Override + public void setLoggerLevel(String loggerName, String levelName) { + LoggerUtils.setLoggerLevel(loggerName, levelName); + } + + @Override + public String getParentLoggerName(String loggerName) { + if (ROOT_LOGGER_NAME.equals(loggerName)) { + return null; + } + int lastDotIndex = loggerName.lastIndexOf(DOT); + if (lastDotIndex == -1) { + return ROOT_LOGGER_NAME; + } + String parentLoggerName = loggerName.substring(0, lastDotIndex); + return parentLoggerName; + } + + @Override + public String getName() { + return "Log4j2"; + } +} \ No newline at end of file diff --git a/microsphere-logging-log4j2/src/main/java/io/microsphere/logging/log4j2/util/LoggerUtils.java b/microsphere-logging-log4j2/src/main/java/io/microsphere/logging/log4j2/util/LoggerUtils.java new file mode 100644 index 0000000..3dbc166 --- /dev/null +++ b/microsphere-logging-log4j2/src/main/java/io/microsphere/logging/log4j2/util/LoggerUtils.java @@ -0,0 +1,159 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.microsphere.logging.log4j2.util; + + +import io.microsphere.annotation.Nonnull; +import io.microsphere.annotation.Nullable; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.LoggerContext; + +import static org.apache.logging.log4j.Level.toLevel; +import static org.apache.logging.log4j.core.LoggerContext.getContext; + +/** + * The Utilities class of Log4j2 Logger + * + * @author Mercy + * @see Logger + * @since 1.0.0 + */ +public abstract class LoggerUtils { + + static final LoggerContext loggerContext = getContext(); + + /** + * Get the LoggerContext + * + * @return LoggerContext , never be null + */ + @Nonnull + public static LoggerContext getLoggerContext() { + return loggerContext; + } + + /** + * Get the Logger by specified name + * + * @param loggerName Logger name + * @return Logger , maby be null + */ + @Nullable + public static Logger getLogger(@Nonnull String loggerName) { + return loggerContext.getLogger(loggerName); + } + + /** + * Get the Logger by the request class + * + * @param requestClass request class + * @return Logger , maby be null + */ + @Nullable + public static Logger getLogger(@Nonnull Class requestClass) { + return getLogger(requestClass.getName()); + } + + /** + * Get the Level of Logger by the specified logger name + * + * @param loggerName Logger name + * @return the Level of Logger , may be null + */ + @Nullable + public static Level getLevel(@Nonnull String loggerName) { + Logger logger = getLogger(loggerName); + return getLevel(logger); + } + + /** + * Get the Level of Logger + * + * @param logger Logger + * @return the Level of Logger , may be null + */ + @Nullable + public static Level getLevel(@Nullable Logger logger) { + Level level = null; + if (logger != null) { + level = logger.getLevel(); + } + return level; + } + + /** + * Set the Level of Logger by the specified logger name + * + * @param loggerName Logger name + * @param levelName level string, if it's null, then {@link Level#DEBUG} will be taken. + */ + public static void setLoggerLevel(String loggerName, String levelName) { + Logger logger = getLogger(loggerName); + setLoggerLevel(logger, levelName); + } + + /** + * Set the Level of Logger + * + * @param logger Logger + * @param levelString level string, if it's null, then {@link Level#DEBUG} will be taken. + */ + public static void setLoggerLevel(@Nullable Logger logger, @Nullable String levelString) { + setLoggerLevel(logger, toLevel(levelString)); + } + + /** + * Set the Level of Logger + * + * @param logger Logger + * @param level level + */ + public static void setLoggerLevel(@Nullable Logger logger, @Nonnull Level level) { + if (logger != null) { + logger.setLevel(level); + } + } + + /** + * Get the Level String of Logger by the specified logger name + * + * @param loggerName Logger name + * @return the Level String of Logger , may be null + */ + @Nullable + public static String getLevelString(@Nonnull String loggerName) { + Logger logger = getLogger(loggerName); + Level level = getLevel(logger); + return getLevelString(level); + } + + /** + * Get the Level String of Logger + * + * @param level Level + * @return the Level String of Logger , may be null + */ + @Nullable + public static String getLevelString(@Nullable Level level) { + return level == null ? null : level.toString(); + } + + private LoggerUtils() { + } +} \ No newline at end of file diff --git a/microsphere-logging-log4j2/src/main/resources/META-INF/services/io.microsphere.logging.Logging b/microsphere-logging-log4j2/src/main/resources/META-INF/services/io.microsphere.logging.Logging new file mode 100644 index 0000000..6c1c655 --- /dev/null +++ b/microsphere-logging-log4j2/src/main/resources/META-INF/services/io.microsphere.logging.Logging @@ -0,0 +1 @@ +io.microsphere.logging.log4j2.Log4j2Logging \ No newline at end of file diff --git a/microsphere-logging-log4j2/src/test/java/io/microsphere/logging/log4j2/Log4j2LoggingTest.java b/microsphere-logging-log4j2/src/test/java/io/microsphere/logging/log4j2/Log4j2LoggingTest.java new file mode 100644 index 0000000..730992b --- /dev/null +++ b/microsphere-logging-log4j2/src/test/java/io/microsphere/logging/log4j2/Log4j2LoggingTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.microsphere.logging.log4j2; + + +import io.microsphere.logging.Logger; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.Set; + +import static io.microsphere.collection.Sets.ofSet; +import static io.microsphere.logging.LoggerFactory.getLogger; +import static org.apache.logging.log4j.LogManager.ROOT_LOGGER_NAME; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; + +/** + * {@link Log4j2Logging} Test + * + * @author Mercy + * @see Log4j2Logging + * @since 1.0.0 + */ +class Log4j2LoggingTest { + + private static final Logger logger = getLogger(Log4j2LoggingTest.class); + + private Log4j2Logging logging; + + /** + * @see org.apache.logging.log4j.Level + */ + public static final Set LOG4J2_LEVELS = ofSet("OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "ALL"); + + @BeforeEach + void setUp() { + this.logging = new Log4j2Logging(); + } + + @Test + void testGetLoggerNames() { + assertFalse(this.logging.getLoggerNames().isEmpty()); + } + + @Test + void testGetSupportedLoggingLevels() { + assertEquals(LOG4J2_LEVELS, this.logging.getSupportedLoggingLevels()); + } + + @Test + void testGetLoggerLevel() { + assertEquals("TRACE", this.logging.getLoggerLevel(ROOT_LOGGER_NAME)); + assertEquals("TRACE", this.logging.getLoggerLevel("io")); + assertEquals("TRACE", this.logging.getLoggerLevel("io.microsphere")); + assertEquals("INFO", this.logging.getLoggerLevel("io.microsphere.logging")); + assertEquals("INFO", this.logging.getLoggerLevel(logger.getName())); + } + + @Test + void testSetLoggerLevel() { + String loggerName = "io.microsphere.logging.log4j2.Log4j2Logging"; + String level = "DEBUG"; + this.logging.setLoggerLevel(loggerName, level); + assertEquals(level, this.logging.getLoggerLevel(loggerName)); + } + + @Test + void testGetParentLoggerName() { + String loggerName = "io.microsphere.logging.log4j2.Log4j2Logging"; + assertEquals("io.microsphere.logging.log4j2", this.logging.getParentLoggerName(loggerName)); + assertEquals("io.microsphere.logging", this.logging.getParentLoggerName("io.microsphere.logging.log4j2")); + assertEquals("io.microsphere", this.logging.getParentLoggerName("io.microsphere.logging")); + assertEquals("io", this.logging.getParentLoggerName("io.microsphere")); + assertEquals(ROOT_LOGGER_NAME, this.logging.getParentLoggerName("io")); + assertNull(this.logging.getParentLoggerName(ROOT_LOGGER_NAME)); + } + + @Test + void testGetName() { + assertEquals("Log4j2", this.logging.getName()); + } +} \ No newline at end of file diff --git a/microsphere-logging-log4j2/src/test/java/io/microsphere/logging/log4j2/util/LoggerUtilsTest.java b/microsphere-logging-log4j2/src/test/java/io/microsphere/logging/log4j2/util/LoggerUtilsTest.java new file mode 100644 index 0000000..9b3ff17 --- /dev/null +++ b/microsphere-logging-log4j2/src/test/java/io/microsphere/logging/log4j2/util/LoggerUtilsTest.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.microsphere.logging.log4j2.util; + + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.Logger; +import org.junit.jupiter.api.Test; + +import static io.microsphere.logging.log4j2.util.LoggerUtils.getLevel; +import static io.microsphere.logging.log4j2.util.LoggerUtils.getLevelString; +import static io.microsphere.logging.log4j2.util.LoggerUtils.getLogger; +import static io.microsphere.logging.log4j2.util.LoggerUtils.getLoggerContext; +import static io.microsphere.logging.log4j2.util.LoggerUtils.setLoggerLevel; +import static org.apache.logging.log4j.Level.INFO; +import static org.apache.logging.log4j.Level.TRACE; +import static org.apache.logging.log4j.core.LoggerContext.getContext; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * {@link LoggerUtils} Test + * + * @author Mercy + * @see LoggerUtils + * @since 1.0.0 + */ +class LoggerUtilsTest { + + @Test + void testGetLoggerContext() { + assertSame(getContext(), getLoggerContext()); + } + + @Test + void testGetLogger() { + assertNotNull(getLogger("test")); + assertNotNull(getLogger(LoggerUtilsTest.class)); + assertThrows(NullPointerException.class, () -> getLogger((Class) null)); + assertThrows(NullPointerException.class, () -> getLogger((String) null)); + } + + @Test + void testGetLevel() { + assertNull(getLevel((Logger) null)); + assertEquals(INFO, getLevel("io.microsphere.logging.log4j2.util.LoggerUtils")); + assertEquals(INFO, getLevel("io.microsphere.logging.log4j2.util")); + assertEquals(INFO, getLevel("io.microsphere.logging.log4j2")); + assertEquals(INFO, getLevel("io.microsphere.logging")); + assertEquals(TRACE, getLevel("io.microsphere")); + assertEquals(TRACE, getLevel("io")); + } + + @Test + void testGetLevelString() { + assertNull(getLevelString((Level) null)); + assertEquals("INFO", getLevelString(INFO)); + assertEquals("TRACE", getLevelString(TRACE)); + } + + @Test + void testSetLoggerLevel() { + setLoggerLevel((Logger) null, "DEBUG"); + assertLoggerLevel("io.microsphere.logging.log4j2.util.LoggerUtils", "DEBUG"); + } + + void assertLoggerLevel(String loggerName, String levelString) { + String oldLevel = getLevelString(loggerName); + setLoggerLevel(loggerName, levelString); + assertEquals(levelString, getLevelString(loggerName)); + setLoggerLevel(loggerName, oldLevel); + } +} \ No newline at end of file diff --git a/microsphere-logging-logback/src/test/resources/META-INF/services/io.microsphere.logging.Logging b/microsphere-logging-log4j2/src/test/resources/META-INF/services/io.microsphere.logging.Logging similarity index 100% rename from microsphere-logging-logback/src/test/resources/META-INF/services/io.microsphere.logging.Logging rename to microsphere-logging-log4j2/src/test/resources/META-INF/services/io.microsphere.logging.Logging diff --git a/microsphere-logging-log4j2/src/test/resources/log4j2.xml b/microsphere-logging-log4j2/src/test/resources/log4j2.xml new file mode 100644 index 0000000..a5f97a5 --- /dev/null +++ b/microsphere-logging-log4j2/src/test/resources/log4j2.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/microsphere-logging-parent/pom.xml b/microsphere-logging-parent/pom.xml index 3ae2919..7b50773 100644 --- a/microsphere-logging-parent/pom.xml +++ b/microsphere-logging-parent/pom.xml @@ -33,6 +33,22 @@ + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + + + junit + junit + ${junit.version} + + io.github.microsphere-projects @@ -90,22 +106,6 @@ ${logback.version} - - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - - - junit - junit - ${junit.version} - - diff --git a/pom.xml b/pom.xml index 09b734b..ed313f6 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,7 @@ microsphere-logging-dependencies microsphere-logging-core microsphere-logging-logback + microsphere-logging-log4j2 microsphere-logging-test