Dropwizard不会将自定义记录程序记录到文件中

Dropwizard不会将自定义记录程序记录到文件中,第1张

Dropwizard不会将自定义记录程序记录到文件中

更新 最新版本的dropwizard支持开箱即用地记录配置

我在尝试使用单独的文件设置Dropwizard(0.8.4)时遇到了相同的问题。我遇到了同样的问题。因此,我进行了更深入的研究,为我找到了一个解决方案(不是最干净的解决方案,但是我似乎无法以不同的方式进行工作)。

问题是

LoggingFactory#configure
自动将每个追加程序添加到根目录。这不是很理想,因此需要覆盖。我所做的是:

  1. 覆盖
    LoggingFactory

这有点混乱,因为有些事情需要复制:(这是我的实现:

import java.io.PrintStream;import java.lang.management.ManagementFactory;import java.util.Map;import javax.management.InstanceAlreadyExistsException;import javax.management.MBeanRegistrationException;import javax.management.MBeanServer;import javax.management.MalformedObjectNameException;import javax.management.NotCompliantMBeanException;import javax.management.ObjectName;import org.slf4j.LoggerFactory;import org.slf4j.bridge.SLF4JBridgeHandler;import com.codahale.metrics.MetricRegistry;import com.codahale.metrics.logback.InstrumentedAppender;import com.fasterxml.jackson.annotation.JsonIgnore;import com.fasterxml.jackson.annotation.JsonProperty;import com.google.common.collect.ImmutableMap;import ch.qos.logback.classic.Level;import ch.qos.logback.classic.Logger;import ch.qos.logback.classic.LoggerContext;import ch.qos.logback.classic.PatternLayout;import ch.qos.logback.classic.jmx.JMXConfigurator;import ch.qos.logback.classic.jul.LevelChangePropagator;import ch.qos.logback.classic.spi.ILoggingEvent;import ch.qos.logback.core.Appender;import ch.qos.logback.core.util.StatusPrinter;import io.dropwizard.logging.AppenderFactory;import io.dropwizard.logging.LoggingFactory;public class BetterDropWizardLoggingConfig extends LoggingFactory {    @JsonIgnore    final LoggerContext loggerContext;    @JsonIgnore    final PrintStream configurationErrorsStream;    @JsonProperty("loggerMapping")    private ImmutableMap<String, String> loggerMappings;    private static void hijackJDKLogging() {        SLF4JBridgeHandler.removeHandlersForRootLogger();        SLF4JBridgeHandler.install();    }    public BetterDropWizardLoggingConfig() {        PatternLayout.defaultConverterMap.put("h", HostNameConverter.class.getName());        this.loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();        this.configurationErrorsStream = System.err;    }    private Logger configureLevels() {        final Logger root = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);        loggerContext.reset();        final LevelChangePropagator propagator = new LevelChangePropagator();        propagator.setContext(loggerContext);        propagator.setResetJUL(true);        loggerContext.addListener(propagator);        root.setLevel(getLevel());        for (Map.Entry<String, Level> entry : getLoggers().entrySet()) { loggerContext.getLogger(entry.getKey()).setLevel(entry.getValue());        }        return root;    }    @Override    public void configure(MetricRegistry metricRegistry, String name) {        hijackJDKLogging();        final Logger root = configureLevels();        for (AppenderFactory output : getAppenders()) { Appender<ILoggingEvent> build = output.build(loggerContext, name, null); if(output instanceof MappedLogger && ((MappedLogger) output).getLoggerName() != null) {     String appenderName = ((MappedLogger) output).getLoggerName();     String loggerName = loggerMappings.get(appenderName);     Logger logger = this.loggerContext.getLogger(loggerName);     logger.addAppender(build); } else {     root.addAppender(build); }        }        StatusPrinter.setPrintStream(configurationErrorsStream);        try { StatusPrinter.printIfErrorsOccured(loggerContext);        } finally { StatusPrinter.setPrintStream(System.out);        }        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();        try { final ObjectName objectName = new ObjectName("io.dropwizard:type=Logging"); if (!server.isRegistered(objectName)) {     server.registerMBean(new JMXConfigurator(loggerContext, server, objectName), objectName); }        } catch (MalformedObjectNameException | InstanceAlreadyExistsException | NotCompliantMBeanException     | MBeanRegistrationException e) { throw new RuntimeException(e);        }        configureInstrumentation(root, metricRegistry);    }    private void configureInstrumentation(Logger root, MetricRegistry metricRegistry) {        final InstrumentedAppender appender = new InstrumentedAppender(metricRegistry);        appender.setContext(loggerContext);        appender.start();        root.addAppender(appender);    }}

如您所知,不幸的是,我不得不复制/粘贴一些私有成员和方法以使事情按预期进行。

我添加了一个新字段:

@JsonProperty("loggerMapping")private ImmutableMap<String, String> loggerMappings;

这使我可以为每个记录器配置一个映射。这不是开箱即用的,因为我无法获得名称(dropwizard默认为附加程序名称,非常不便…)

因此,我添加了一个新的Logger,以我为例,由于不同的原因,它也可以替换主机名。为此,我覆盖了旧版本

FileAppenderFactory
并实现了自己的接口
MappedLogger
。此处的实现:

import com.fasterxml.jackson.annotation.JsonProperty;import com.fasterxml.jackson.annotation.JsonTypeName;import ch.qos.logback.classic.LoggerContext;import ch.qos.logback.classic.spi.ILoggingEvent;import ch.qos.logback.core.FileAppender;import ch.qos.logback.core.rolling.RollingFileAppender;import io.dropwizard.logging.AppenderFactory;import io.dropwizard.logging.FileAppenderFactory;@JsonTypeName("hostnameFile")public class HostnameFileAppender extends FileAppenderFactory implements AppenderFactory, MappedLogger {    private static String uuid = UUID.randomUUID().toString();    @JsonProperty    private String name;    public void setCurrentLogFilename(String currentLogFilename) {        super.setCurrentLogFilename(substitute(currentLogFilename));    }    private String substitute(final String pattern) {        String substitute = null;        try { substitute = InetAddress.getLocalHost().getHostName();        } catch (UnknownHostException e) { System.err.println("Failed to get local hostname:"); e.printStackTrace(System.err); substitute = uuid; System.err.println("Using " + substitute + " as fallback.");        }        return pattern.replace("${HOSTNAME}", substitute);    }    @Override    public void setArchivedLogFilenamePattern(String archivedLogFilenamePattern) {        super.setArchivedLogFilenamePattern(substitute(archivedLogFilenamePattern));    }    @Override    public String getLoggerName() {        return name;    }}

请注意,为了添加新的json类型,您将必须遵循JavaDoc

AppenderFactory
(将meta-inf添加到类路径并使新的附加程序可发现)中

到目前为止,到目前为止,我们已经有了一个可以使用记录器映射的配置,我们有一个可以使用可选名称的记录器。

现在,在configure方法中,将这两个绑定在一起:

for (AppenderFactory output : getAppenders()) {        Appender<ILoggingEvent> build = output.build(loggerContext, name, null);        if(output instanceof MappedLogger && ((MappedLogger) output).getLoggerName() != null) { String appenderName = ((MappedLogger) output).getLoggerName(); String loggerName = loggerMappings.get(appenderName); Logger logger = this.loggerContext.getLogger(loggerName); logger.addAppender(build);        } else { root.addAppender(build);        }    }

为了向后兼容,我保留了默认行为。如果未定义名称,则将附加程序添加到根记录器。否则,我将解析键入的记录器,并根据需要向其添加追加器。

最后但并非最不重要的一点是,旧的yaml配置良好:

logging:  # The default level of all loggers. Can be OFF, ERROR, WARN, INFO, DEBUG, TRACE, or ALL.  level: INFO  loggers:    "EVENT" : INFO  loggerMapping:    # for easier search this is defined as: appenderName -> loggerName rather than the other way around    "eventLog" : "EVENT"  appenders:   - type: console        threshold: ALL     logFormat: "myformat"   - type: hostnameFile # NOTE THE NEW TYPE WITH HOSTNAME RESOLVE     currentLogFilename: /Users/artur/tmp/log/my-${HOSTNAME}.log     threshold: ALL     archive: true     archivedLogFilenamePattern: mypattern     archivedFileCount: 31     timeZone: UTC     logFormat: "myFormat"   - type: hostnameFile     name: eventLog # NOTE THE APPENDER NAME     currentLogFilename: something     threshold: ALL     archive: true     archivedLogFilenamePattern: something     archivedFileCount: 31     timeZone: UTC     logFormat: "myFormat"   - type: hostnameFile     currentLogFilename: something     threshold: ERROR     archive: true     archivedLogFilenamePattern: something     archivedFileCount: 31     timeZone: UTC     logFormat: "myFormat"

如您所见,我正在将事件追加器映射到事件记录器。这样,我所有的事件都结束于文件A中,而其他信息结束于其他地方。

我希望这有帮助。可能不是最干净的解决方案,但我不认为Dropwizard当前允许此功能。



欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5002998.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-14
下一篇2022-11-14

发表评论

登录后才能评论

评论列表(0条)

    保存