From b7d61b5196cdf01ab27be87c2cae39eefe8a2235 Mon Sep 17 00:00:00 2001 From: hades Date: Fri, 10 Dec 2021 15:13:28 +0800 Subject: [PATCH] =?UTF-8?q?KERNEL-9687=20log4j=E7=89=88=E6=9C=AC=E5=8D=87?= =?UTF-8?q?=E7=BA=A7-=E8=AE=BE=E8=AE=A1=E5=99=A8=E9=85=8D=E5=90=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/fr/design/DesignerEnvManager.java | 15 +++--- .../design/actions/file/PreferencePane.java | 5 +- .../loghandler/DesignerLogAppender.java | 42 ++++++++--------- .../loghandler/DesignerLogHandler.java | 22 ++++----- .../mainframe/loghandler/DesignerLogger.java | 41 ++++++++-------- .../loghandler/LogEventConverter.java | 27 +++++++++++ .../errorinfo/ErrorInfoLogAppender.java | 47 ++++++++++--------- .../errorinfo/ErrorInfoUploader.java | 27 ++++++----- .../mainframe/socketio/DesignerSocketIO.java | 11 ++++- .../fr/start/module/DesignerActivator.java | 4 +- 10 files changed, 141 insertions(+), 100 deletions(-) create mode 100644 designer-base/src/main/java/com/fr/design/mainframe/loghandler/LogEventConverter.java diff --git a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java index 9d84e25bae..1f39f024d2 100644 --- a/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java +++ b/designer-base/src/main/java/com/fr/design/DesignerEnvManager.java @@ -53,7 +53,8 @@ import com.fr.stable.xml.XMLReadable; import com.fr.stable.xml.XMLTools; import com.fr.stable.xml.XMLWriter; import com.fr.stable.xml.XMLableReader; -import com.fr.third.apache.log4j.FileAppender; +import com.fr.third.apache.logging.log4j.core.appender.FileAppender; +import com.fr.third.apache.logging.log4j.core.layout.PatternLayout; import com.fr.third.org.apache.commons.io.FilenameUtils; import com.fr.workspace.WorkContext; import com.fr.workspace.WorkContextCallback; @@ -324,18 +325,18 @@ public class DesignerEnvManager implements XMLReadable, XMLWriter { if (!new File(fileName).exists()) { StableUtils.makesureFileExist(new File(fileName)); } - LogHandler handler = new LogHandler() { - final FileAppender appender = new FileAppender( - new com.fr.third.apache.log4j.PatternLayout("%d{HH:mm:ss} %t %p [%c] %m%n"), - fileName - ); + LogHandler handler = new LogHandler() { + final FileAppender appender = FileAppender.newBuilder(). + setName(FileAppender.class.getSimpleName()). + setLayout(PatternLayout.newBuilder().withPattern("%d{HH:mm:ss} %t %p [%c] %m%n").build()). + withFileName(fileName).build(); @Override public FileAppender getHandler() { return appender; } }; - + handler.getHandler().start(); FineLoggerFactory.getLogger().addLogAppender(handler); } catch (SecurityException e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); diff --git a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java index 303d9fd816..c0797e9462 100644 --- a/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java +++ b/designer-base/src/main/java/com/fr/design/actions/file/PreferencePane.java @@ -29,7 +29,6 @@ import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.layout.TableLayout; import com.fr.design.layout.TableLayoutHelper; import com.fr.design.layout.VerticalFlowLayout; -import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.vcs.VcsConfigManager; import com.fr.design.mainframe.vcs.common.VcsHelper; import com.fr.design.os.impl.SupportOSImpl; @@ -45,14 +44,12 @@ import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import com.fr.stable.Constants; import com.fr.stable.os.OperatingSystem; -import com.fr.third.apache.log4j.Level; +import com.fr.third.apache.logging.log4j.Level; import com.fr.transaction.Configurations; import com.fr.transaction.Worker; import com.fr.workspace.WorkContext; import com.fr.workspace.server.vcs.VcsOperator; import com.fr.workspace.server.vcs.git.config.GcConfig; -import com.sun.javafx.tk.FileChooserType; -import javafx.stage.FileChooser; import javax.swing.BorderFactory; import javax.swing.BoxLayout; diff --git a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java index 118ea2e321..f965c21725 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogAppender.java @@ -1,41 +1,41 @@ package com.fr.design.mainframe.loghandler; - -import com.fr.third.apache.log4j.AppenderSkeleton; -import com.fr.third.apache.log4j.Level; -import com.fr.third.apache.log4j.spi.LoggingEvent; - +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.Filter; +import com.fr.third.apache.logging.log4j.core.Layout; +import com.fr.third.apache.logging.log4j.core.LogEvent; +import com.fr.third.apache.logging.log4j.core.appender.AbstractAppender; +import com.fr.third.apache.logging.log4j.core.config.Property; +import com.fr.third.apache.logging.log4j.core.layout.PatternLayout; +import java.io.Serializable; import java.util.Date; /** * Created by Administrator on 2017/7/18 0018. */ -public class DesignerLogAppender extends AppenderSkeleton { +public class DesignerLogAppender extends AbstractAppender { - public DesignerLogAppender() { - this.layout = new com.fr.third.apache.log4j.PatternLayout("%d{HH:mm:ss} %t %p [%c] %m%n"); + protected DesignerLogAppender(String name, Filter filter, + Layout layout, + boolean ignoreExceptions, + Property[] properties) { + super(name, filter, layout, ignoreExceptions, properties); } - protected void append(LoggingEvent event) { - this.subAppend(event); + public static DesignerLogAppender createDesignerLogAppender() { + return new DesignerLogAppender(DesignerLogAppender.class.getSimpleName(), null, PatternLayout.newBuilder().withPattern("%d{HH:mm:ss} %t %p [%c] %m%n %throwable{0}").build(), false, Property.EMPTY_ARRAY); } - public boolean requiresLayout() { - return true; + @Override + public void append(LogEvent event) { + this.subAppend(event); } - public synchronized void close() { - if (this.closed) { - return; - } - this.closed = true; - - } - public void subAppend(LoggingEvent event) { + public void subAppend(LogEvent event) { synchronized (DesignerLogHandler.getInstance()) { Level level = event.getLevel(); - String msg = this.layout.format(event); + String msg = (String) this.toSerializable(event); DesignerLogHandler.getInstance().printRemoteLog(msg, level, new Date()); } } diff --git a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java index 1d67c47df1..1cb8e5d1aa 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogHandler.java @@ -9,10 +9,9 @@ import com.fr.general.ComparatorUtils; import com.fr.general.log.Log4jConfig; import com.fr.log.FineLoggerFactory; import com.fr.stable.StringUtils; -import com.fr.third.apache.log4j.Level; -import com.fr.third.apache.log4j.spi.LoggingEvent; -import com.fr.third.apache.log4j.spi.ThrowableInformation; +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.LogEvent; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; @@ -128,7 +127,7 @@ public class DesignerLogHandler { JPopupMenu jPopupMenu = new JPopupMenu(); - int logLevelInt = Log4jConfig.getInstance().getRootLevel().toInt(); + int logLevelInt = Log4jConfig.getInstance().getRootLevel().intLevel(); if (logLevelInt <= DesignerLogger.INFO_INT) { jPopupMenu.add(showInfo); jPopupMenu.add(showError); @@ -240,23 +239,22 @@ public class DesignerLogHandler { return resultPane; } - public void printStackTrace(LoggingEvent event) { + public void printStackTrace(LogEvent event) { - int intLevel = event.getLevel().toInt(); - Date date = new Date(event.getTimeStamp()); - ThrowableInformation information = event.getThrowableInformation(); + int intLevel = event.getLevel().intLevel(); + Date date = new Date(event.getTimeMillis()); if (intLevel == DesignerLogger.INFO_INT && showInfo.isSelected()) { - printMessage(event.getRenderedMessage(), intLevel, date, information == null ? null : information.getThrowable()); + printMessage(event.getMessage().getFormattedMessage(), intLevel, date, event.getThrown()); } else if (intLevel == DesignerLogger.ERROR_INT && showError.isSelected()) { - printMessage(event.getRenderedMessage(), intLevel, date, information == null ? null : information.getThrowable()); + printMessage(event.getMessage().getFormattedMessage(), intLevel, date, event.getThrown()); } else if (intLevel == DesignerLogger.WARN_INT && showServer.isSelected()) { - printMessage(event.getRenderedMessage(), intLevel, date, information == null ? null : information.getThrowable()); + printMessage(event.getMessage().getFormattedMessage(), intLevel, date, event.getThrown()); } } public void printStackTrace(String message, Level level, Date date) { - int intLevel = level.toInt(); + int intLevel = level.intLevel(); if (intLevel == DesignerLogger.INFO_INT && showInfo.isSelected()) { printMessage(message, intLevel, date); } else if (intLevel == DesignerLogger.ERROR_INT && showError.isSelected()) { diff --git a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java index b2b35da1cd..3b6d4bf7a6 100644 --- a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java +++ b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/DesignerLogger.java @@ -1,26 +1,25 @@ package com.fr.design.mainframe.loghandler; import com.fr.log.FineLoggerFactory; -import com.fr.third.apache.log4j.Level; -import com.fr.third.apache.log4j.spi.LoggingEvent; -import com.fr.third.apache.log4j.spi.ThrowableInformation; +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.LogEvent; /** * 设计器日志记录 */ public class DesignerLogger { - public static final int INFO_INT = Level.INFO.toInt(); + public static final int INFO_INT = Level.INFO.intLevel(); - public static final int ERROR_INT = Level.ERROR.toInt(); + public static final int ERROR_INT = Level.ERROR.intLevel(); - public static final int WARN_INT = Level.WARN.toInt(); + public static final int WARN_INT = Level.WARN.intLevel(); /** * 记录LoggingEvent对象 * * @param event */ - public static void log(LoggingEvent event) { + public static void log(LogEvent event) { if (event == null) { return; } @@ -30,29 +29,27 @@ public class DesignerLogger { public enum LogParser { DEFAULT(-1) { @Override - public void log(LoggingEvent event) { + public void log(LogEvent event) { } }, - INFO(Level.INFO.toInt()) { + INFO(Level.INFO.intLevel()) { @Override - public void log(LoggingEvent event) { - FineLoggerFactory.getLogger().info(event.getRenderedMessage()); + public void log(LogEvent event) { + FineLoggerFactory.getLogger().info(event.getMessage().getFormattedMessage()); } }, - WARN(Level.WARN.toInt()) { + WARN(Level.WARN.intLevel()) { @Override - public void log(LoggingEvent event) { - ThrowableInformation information = event.getThrowableInformation(); - FineLoggerFactory.getLogger().warn(event.getRenderedMessage(), information == null ? null : information.getThrowable()); + public void log(LogEvent event) { + FineLoggerFactory.getLogger().warn(event.getMessage().getFormattedMessage(), event.getThrown()); } }, - ERROR(Level.ERROR.toInt()) { + ERROR(Level.ERROR.intLevel()) { @Override - public void log(LoggingEvent event) { - ThrowableInformation information = event.getThrowableInformation(); - FineLoggerFactory.getLogger().error(event.getRenderedMessage(), information == null ? null : information.getThrowable()); + public void log(LogEvent event) { + FineLoggerFactory.getLogger().error(event.getMessage().getFormattedMessage(), event.getThrown()); } }; private int level; @@ -65,8 +62,8 @@ public class DesignerLogger { return level; } - public static LogParser parse(LoggingEvent event) { - int intLevel = event.getLevel().toInt(); + public static LogParser parse(LogEvent event) { + int intLevel = event.getLevel().intLevel(); for (LogParser logParser : values()) { if (logParser.getLevel() == intLevel) { return logParser; @@ -76,7 +73,7 @@ public class DesignerLogger { } - public void log(LoggingEvent event) { + public void log(LogEvent event) { } } } \ No newline at end of file diff --git a/designer-base/src/main/java/com/fr/design/mainframe/loghandler/LogEventConverter.java b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/LogEventConverter.java new file mode 100644 index 0000000000..92995add54 --- /dev/null +++ b/designer-base/src/main/java/com/fr/design/mainframe/loghandler/LogEventConverter.java @@ -0,0 +1,27 @@ +package com.fr.design.mainframe.loghandler; + +import com.fr.third.apache.log4j.spi.LoggingEvent; +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.LogEvent; +import com.fr.third.apache.logging.log4j.core.impl.Log4jLogEvent; +import com.fr.third.apache.logging.log4j.message.SimpleMessage; + +/** + * 兼容log4j1和2之间logEvent之间的转换 + * + * @author hades + * @version 11.0 + * Created by hades on 2021/12/9 + */ +public class LogEventConverter { + + public static LogEvent convert(LoggingEvent loggingEvent) { + SimpleMessage message = new SimpleMessage(loggingEvent.getRenderedMessage()); + return Log4jLogEvent.newBuilder(). + setMessage(message). + setLevel(Level.getLevel(loggingEvent.getLevel().toString())). + build(); + } + + +} diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java index 2626193a4c..7157316c2f 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoLogAppender.java @@ -4,6 +4,13 @@ import com.fr.base.io.IOFile; import com.fr.base.io.XMLReadHelper; import com.fr.design.DesignerEnvManager; import com.fr.design.i18n.Toolkit; +import com.fr.third.apache.logging.log4j.Level; +import com.fr.third.apache.logging.log4j.core.Filter; +import com.fr.third.apache.logging.log4j.core.Layout; +import com.fr.third.apache.logging.log4j.core.LogEvent; +import com.fr.third.apache.logging.log4j.core.appender.AbstractAppender; +import com.fr.third.apache.logging.log4j.core.config.Property; +import com.fr.third.apache.logging.log4j.core.layout.PatternLayout; import com.fr.web.session.SessionLocalManager; import com.fr.stable.StableUtils; @@ -12,22 +19,20 @@ import com.fr.stable.project.ProjectConstants; import com.fr.stable.web.SessionProvider; import com.fr.stable.xml.XMLPrintWriter; import com.fr.stable.xml.XMLableReader; -import com.fr.third.apache.log4j.AppenderSkeleton; -import com.fr.third.apache.log4j.Level; -import com.fr.third.apache.log4j.spi.LoggingEvent; import com.fr.web.core.SessionPoolManager; import com.fr.web.core.TemplateSessionIDInfo; import com.fr.workspace.WorkContext; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.io.Serializable; /** * 收集设计器报错信息的appender. *

* Created by Administrator on 2017/7/24 0024. */ -public class ErrorInfoLogAppender extends AppenderSkeleton { +public class ErrorInfoLogAppender extends AbstractAppender { private static final int ERROR_LEN = 8; private static final int ERROR_STACK_TRACE = 15; @@ -38,16 +43,23 @@ public class ErrorInfoLogAppender extends AppenderSkeleton { private String uuid; private String activekey; - public ErrorInfoLogAppender() { - this.layout = new com.fr.third.apache.log4j.PatternLayout("%d{HH:mm:ss} %t %p [%c] %m%n"); - + protected ErrorInfoLogAppender(String name, Filter filter, + Layout layout, + boolean ignoreExceptions, + Property[] properties) { + super(name, filter, layout, ignoreExceptions, properties); DesignerEnvManager envManager = DesignerEnvManager.getEnvManager(); this.username = envManager.getDesignerLoginUsername(); this.uuid = envManager.getUUID(); this.activekey = envManager.getActivationKey(); } - protected void append(LoggingEvent event) { + public static ErrorInfoLogAppender createErrorLogAppender() { + return new ErrorInfoLogAppender(ErrorInfoLogAppender.class.getSimpleName(), null, PatternLayout.newBuilder().withPattern("%d{HH:mm:ss} %t %p [%c] %m%n %throwable{0}").build(), false, Property.EMPTY_ARRAY); + } + + @Override + public void append(LogEvent event) { this.subAppend(event); } @@ -55,19 +67,12 @@ public class ErrorInfoLogAppender extends AppenderSkeleton { return true; } - public synchronized void close() { - if (this.closed) { - return; - } - this.closed = true; - - } - public void subAppend(LoggingEvent event) { + public void subAppend(LogEvent event) { Level level = event.getLevel(); // 只分析上传记录error以上的. - if (level.isGreaterOrEqual(Level.ERROR)) { - String msg = this.layout.format(event); + if (level.isMoreSpecificThan(Level.ERROR)) { + String msg = (String) this.toSerializable(event); // 这个id并不是一定会有的, 有就记录下, 说明是预览模板出的错. String templateid = readTemplateID(); String logid = readLogID(msg); @@ -80,13 +85,13 @@ public class ErrorInfoLogAppender extends AppenderSkeleton { } } - private String readStackTrace(LoggingEvent event) { - String[] s = event.getThrowableStrRep(); + private String readStackTrace(LogEvent event) { + StackTraceElement[] s = event.getThrown() == null ? null : event.getThrown().getStackTrace(); StringBuilder sb = new StringBuilder(); if (s != null) { int len = Math.min(s.length, ERROR_STACK_TRACE); for (int i = 0; i < len; i++) { - sb.append(s[i]).append("\n"); + sb.append(s[i].toString()).append("\n"); } } return sb.toString(); diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoUploader.java b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoUploader.java index 81da862123..73ecf610d1 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoUploader.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/errorinfo/ErrorInfoUploader.java @@ -44,30 +44,35 @@ public class ErrorInfoUploader { //单次发送的错误信息最大条数 private static final int MAX_ITEMS = 200; + private static LogHandler logHandler; + static { GeneralContext.addEnvChangedListener(new EnvChangedListener() { @Override public void envChanged() { - FineLoggerFactory.getLogger().addLogAppender(new LogHandler() { - private ErrorInfoLogAppender errorInfoLogAppender = new ErrorInfoLogAppender(); - - @Override - public ErrorInfoLogAppender getHandler() { - return errorInfoLogAppender; - } - }); + if (logHandler != null) { + logHandler.getHandler().stop(); + FineLoggerFactory.getLogger().removeLogAppender(logHandler); + logHandler.getHandler().start(); + FineLoggerFactory.getLogger().addLogAppender(logHandler); + } } }); } private ErrorInfoUploader() { - FineLoggerFactory.getLogger().addLogAppender(new LogHandler() { + logHandler = new LogHandler() { + + private final ErrorInfoLogAppender errorInfoLogAppender = ErrorInfoLogAppender.createErrorLogAppender(); + @Override public ErrorInfoLogAppender getHandler() { - return new ErrorInfoLogAppender(); + return errorInfoLogAppender; } - }); + }; + logHandler.getHandler().start(); + FineLoggerFactory.getLogger().addLogAppender(logHandler); } public static ErrorInfoUploader getInstance() { diff --git a/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java b/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java index 6b65a7bd3d..1742e3c3dc 100644 --- a/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java +++ b/designer-realize/src/main/java/com/fr/design/mainframe/socketio/DesignerSocketIO.java @@ -11,6 +11,7 @@ import com.fr.design.i18n.Toolkit; import com.fr.design.layout.FRGUIPaneFactory; import com.fr.design.mainframe.DesignerContext; import com.fr.design.mainframe.loghandler.DesignerLogger; +import com.fr.design.mainframe.loghandler.LogEventConverter; import com.fr.design.mainframe.share.ui.base.MouseClickListener; import com.fr.design.mainframe.toast.DesignerToastMsgUtil; import com.fr.design.mainframe.toast.ToastMsgDialog; @@ -23,6 +24,7 @@ import com.fr.serialization.SerializerHelper; import com.fr.stable.ArrayUtils; import com.fr.stable.StableUtils; import com.fr.third.apache.log4j.spi.LoggingEvent; +import com.fr.third.apache.logging.log4j.core.LogEvent; import com.fr.third.org.apache.http.client.config.RequestConfig; import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; import com.fr.third.org.apache.http.client.methods.HttpGet; @@ -148,7 +150,14 @@ public class DesignerSocketIO { public void call(Object... objects) { if (ArrayUtils.isNotEmpty(objects)) { try { - LoggingEvent event = SerializerHelper.deserialize((byte[]) objects[0]); + Object obj = SerializerHelper.deserialize((byte[]) objects[0]); + // 兼容下老版本服务器 + LogEvent event; + if (obj instanceof LoggingEvent) { + event = LogEventConverter.convert((LoggingEvent) obj); + } else { + event = (LogEvent) obj; + } DesignerLogger.log(event); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); diff --git a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java index 477ac8ae38..56b5785784 100644 --- a/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java +++ b/designer-realize/src/main/java/com/fr/start/module/DesignerActivator.java @@ -191,18 +191,20 @@ public class DesignerActivator extends Activator implements Prepare { private void loadLogAppender() { logHandler = new LogHandler() { - final DesignerLogAppender logAppender = new DesignerLogAppender(); + final DesignerLogAppender logAppender = DesignerLogAppender.createDesignerLogAppender(); @Override public DesignerLogAppender getHandler() { return logAppender; } }; + logHandler.getHandler().start(); FineLoggerFactory.getLogger().addLogAppender(logHandler); } private void unloadLogAppender() { if (logHandler != null) { + logHandler.getHandler().stop(); FineLoggerFactory.getLogger().removeLogAppender(logHandler); } }