diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3cf03915..16f2cd0ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@
* 【core 】 ArrayConverter增加可选是否忽略错误(issue#I1VNYQ@Gitee)
* 【db 】 增加ConditionBuilder
* 【setting】 Setting和Props增加create方法
+* 【log 】 增加TinyLog2支持(issue#1094@Github)
### Bug修复
* 【core 】 修复Dict.of错误(issue#I1UUO5@Gitee)
diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml
index e64d82b0c..4561c6920 100644
--- a/hutool-log/pom.xml
+++ b/hutool-log/pom.xml
@@ -71,6 +71,12 @@
${tinylog.version}
true
+
+ org.tinylog
+ tinylog-api
+ 2.1.2
+ true
+
org.jboss.logging
jboss-logging
@@ -83,5 +89,11 @@
${slf4j.version}
test
+
+ org.tinylog
+ tinylog-impl
+ 2.1.2
+ test
+
diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2.java b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2.java
new file mode 100644
index 000000000..758a92e2f
--- /dev/null
+++ b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2.java
@@ -0,0 +1,177 @@
+package cn.hutool.log.dialect.tinylog;
+
+import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.log.AbstractLog;
+import org.tinylog.Level;
+import org.tinylog.configuration.Configuration;
+import org.tinylog.format.AdvancedMessageFormatter;
+import org.tinylog.format.MessageFormatter;
+import org.tinylog.provider.LoggingProvider;
+import org.tinylog.provider.ProviderRegistry;
+
+/**
+ * tinylog log.
+ *
+ * @author Looly
+ *
+ */
+public class TinyLog2 extends AbstractLog {
+ private static final long serialVersionUID = 1L;
+
+ /** 堆栈增加层数,因为封装因此多了两层,此值用于正确获取当前类名 */
+ private static final int DEPTH = 5;
+
+ private final int level;
+ private final String name;
+ private static final LoggingProvider provider = ProviderRegistry.getLoggingProvider();
+ private static final MessageFormatter formatter = new AdvancedMessageFormatter(
+ Configuration.getLocale(),
+ Configuration.isEscapingEnabled()
+ );
+
+ // ------------------------------------------------------------------------- Constructor
+ public TinyLog2(Class> clazz) {
+ this(null == clazz ? StrUtil.NULL : clazz.getName());
+ }
+
+ public TinyLog2(String name) {
+ this.name = name;
+ this.level = provider.getMinimumLevel().ordinal();
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+ // ------------------------------------------------------------------------- Trace
+ @Override
+ public boolean isTraceEnabled() {
+ return this.level <= Level.TRACE.ordinal();
+ }
+
+ @Override
+ public void trace(String fqcn, Throwable t, String format, Object... arguments) {
+ logIfEnabled(fqcn, Level.TRACE, t, format, arguments);
+ }
+
+ // ------------------------------------------------------------------------- Debug
+ @Override
+ public boolean isDebugEnabled() {
+ return this.level <= Level.DEBUG.ordinal();
+ }
+
+ @Override
+ public void debug(String fqcn, Throwable t, String format, Object... arguments) {
+ logIfEnabled(fqcn, Level.DEBUG, t, format, arguments);
+ }
+ // ------------------------------------------------------------------------- Info
+ @Override
+ public boolean isInfoEnabled() {
+ return this.level <= Level.INFO.ordinal();
+ }
+
+ @Override
+ public void info(String fqcn, Throwable t, String format, Object... arguments) {
+ logIfEnabled(fqcn, Level.INFO, t, format, arguments);
+ }
+
+ // ------------------------------------------------------------------------- Warn
+ @Override
+ public boolean isWarnEnabled() {
+ return this.level <= Level.WARN.ordinal();
+ }
+
+ @Override
+ public void warn(String fqcn, Throwable t, String format, Object... arguments) {
+ logIfEnabled(fqcn, Level.WARN, t, format, arguments);
+ }
+
+ // ------------------------------------------------------------------------- Error
+ @Override
+ public boolean isErrorEnabled() {
+ return this.level <= Level.ERROR.ordinal();
+ }
+
+ @Override
+ public void error(String fqcn, Throwable t, String format, Object... arguments) {
+ logIfEnabled(fqcn, Level.ERROR, t, format, arguments);
+ }
+
+ // ------------------------------------------------------------------------- Log
+ @Override
+ public void log(String fqcn, cn.hutool.log.level.Level level, Throwable t, String format, Object... arguments) {
+ logIfEnabled(fqcn, toTinyLevel(level), t, format, arguments);
+ }
+
+ @Override
+ public boolean isEnabled(cn.hutool.log.level.Level level) {
+ return this.level <= toTinyLevel(level).ordinal();
+ }
+
+ /**
+ * 在对应日志级别打开情况下打印日志
+ * @param fqcn 完全限定类名(Fully Qualified Class Name),用于定位日志位置
+ * @param level 日志级别
+ * @param t 异常,null则检查最后一个参数是否为Throwable类型,是则取之,否则不打印堆栈
+ * @param format 日志消息模板
+ * @param arguments 日志消息参数
+ */
+ private void logIfEnabled(String fqcn, Level level, Throwable t, String format, Object... arguments) {
+ // fqcn 无效
+ if(null == t){
+ t = getLastArgumentIfThrowable(arguments);
+ }
+ provider.log(DEPTH, null, level, t, formatter, StrUtil.toString(format), arguments);
+ }
+
+ /**
+ * 将Hutool的Level等级转换为Tinylog的Level等级
+ *
+ * @param level Hutool的Level等级
+ * @return Tinylog的Level
+ * @since 4.0.3
+ */
+ private Level toTinyLevel(cn.hutool.log.level.Level level) {
+ Level tinyLevel;
+ switch (level) {
+ case TRACE:
+ tinyLevel = Level.TRACE;
+ break;
+ case DEBUG:
+ tinyLevel = Level.DEBUG;
+ break;
+ case INFO:
+ tinyLevel = Level.INFO;
+ break;
+ case WARN:
+ tinyLevel = Level.WARN;
+ break;
+ case ERROR:
+ tinyLevel = Level.ERROR;
+ break;
+ case OFF:
+ tinyLevel = Level.OFF;
+ break;
+ default:
+ throw new Error(StrUtil.format("Can not identify level: {}", level));
+ }
+ return tinyLevel;
+ }
+
+ /**
+ * 如果最后一个参数为异常参数,则获取之,否则返回null
+ *
+ * @param arguments 参数
+ * @return 最后一个异常参数
+ * @since 4.0.3
+ */
+ private static Throwable getLastArgumentIfThrowable(Object... arguments) {
+ if (ArrayUtil.isNotEmpty(arguments) && arguments[arguments.length - 1] instanceof Throwable) {
+ return (Throwable) arguments[arguments.length - 1];
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2Factory.java b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2Factory.java
new file mode 100644
index 000000000..ebb0cd96d
--- /dev/null
+++ b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/TinyLog2Factory.java
@@ -0,0 +1,32 @@
+package cn.hutool.log.dialect.tinylog;
+
+import cn.hutool.log.Log;
+import cn.hutool.log.LogFactory;
+
+/**
+ * TinyLog2 log.
+ *
+ * @author Looly
+ *
+ */
+public class TinyLog2Factory extends LogFactory {
+
+ /**
+ * 构造
+ */
+ public TinyLog2Factory() {
+ super("TinyLog");
+ checkLogExist(org.tinylog.Logger.class);
+ }
+
+ @Override
+ public Log createLog(String name) {
+ return new TinyLog2(name);
+ }
+
+ @Override
+ public Log createLog(Class> clazz) {
+ return new TinyLog2(clazz);
+ }
+
+}
diff --git a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/package-info.java b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/package-info.java
index e9ed843c9..f935993e1 100644
--- a/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/package-info.java
+++ b/hutool-log/src/main/java/cn/hutool/log/dialect/tinylog/package-info.java
@@ -1,7 +1,7 @@
/**
- * TinyLog的实现封装
- *
- * @author looly
+ * tinylog的实现封装
+ * 封装包括TinyLog和TinyLog2
*
+ * @author looly
*/
package cn.hutool.log.dialect.tinylog;
\ No newline at end of file
diff --git a/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory b/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory
index e2d708ccf..487035520 100644
--- a/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory
+++ b/hutool-log/src/main/resources/META-INF/services/cn.hutool.log.LogFactory
@@ -3,4 +3,5 @@ cn.hutool.log.dialect.log4j2.Log4j2LogFactory
cn.hutool.log.dialect.log4j.Log4jLogFactory
cn.hutool.log.dialect.commons.ApacheCommonsLogFactory
cn.hutool.log.dialect.tinylog.TinyLogFactory
+cn.hutool.log.dialect.tinylog.TinyLog2Factory
cn.hutool.log.dialect.jboss.JbossLogFactory
\ No newline at end of file
diff --git a/hutool-log/src/test/java/cn/hutool/log/test/CustomLogTest.java b/hutool-log/src/test/java/cn/hutool/log/test/CustomLogTest.java
index f1b46c5d9..b72ffda6b 100644
--- a/hutool-log/src/test/java/cn/hutool/log/test/CustomLogTest.java
+++ b/hutool-log/src/test/java/cn/hutool/log/test/CustomLogTest.java
@@ -1,7 +1,5 @@
package cn.hutool.log.test;
-import org.junit.Test;
-
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.dialect.commons.ApacheCommonsLogFactory;
@@ -11,7 +9,9 @@ import cn.hutool.log.dialect.jdk.JdkLogFactory;
import cn.hutool.log.dialect.log4j.Log4jLogFactory;
import cn.hutool.log.dialect.log4j2.Log4j2LogFactory;
import cn.hutool.log.dialect.slf4j.Slf4jLogFactory;
+import cn.hutool.log.dialect.tinylog.TinyLog2Factory;
import cn.hutool.log.dialect.tinylog.TinyLogFactory;
+import org.junit.Test;
/**
* 日志门面单元测试
@@ -62,6 +62,17 @@ public class CustomLogTest {
log.info((String)null);
log.info("This is custom '{}' log\n{}", factory.getName(), LINE);
}
+
+ @Test
+ public void tinyLog2Test(){
+ LogFactory factory = new TinyLog2Factory();
+ LogFactory.setCurrentLogFactory(factory);
+ Log log = LogFactory.get();
+
+ log.info(null);
+ log.info((String)null);
+ log.info("This is custom '{}' log\n{}", factory.getName(), LINE);
+ }
@Test
public void log4j2LogTest(){
diff --git a/hutool-log/src/test/resources/tinylog.properties b/hutool-log/src/test/resources/tinylog.properties
index 6078a18b4..2d7c470c9 100644
--- a/hutool-log/src/test/resources/tinylog.properties
+++ b/hutool-log/src/test/resources/tinylog.properties
@@ -5,7 +5,9 @@
# \u65e5\u5fd7\u5199\u51fa\u65b9\u5f0f\uff1a[console] [file] [jdbc] [logcat] [rollingfile] [sharedfile] [null]
tinylog.writer = console
+writer = console
# \u65e5\u5fd7\u5199\u51fa\u7ea7\u522b\uff1aTRACE < DEBUG < INFO < WARNING < ERROR < OFF
tinylog.level = debug
# \u65e5\u5fd7\u6253\u5370\u683c\u5f0f
-tinylog.format = [{date:HH:mm:ss}][{level}] {class}:{line} - {message}
\ No newline at end of file
+tinylog.format = [{date:HH:mm:ss}][{level}] {class}:{line} - {message}
+writer.format = [{date:HH:mm:ss}][{level}] {class}:{line} - {message}
\ No newline at end of file