Spring、SLF4J 和 Logback - 自定义数据库附加程序

Spring, SLF4J, & Logback - Custom DB appender

我刚开始使用 Spring、SLF4J 和 Logback。我正在尝试实现一个自定义数据库附加程序,它只会在 Spring 批处理期间将特定类型的异常记录到数据库中。

到目前为止,我已经开始设置一个扩展 AppenderBase class 的 Logback Database Appender,然后设置一个扩展 spring 中的 InitializingBean 的初始化程序,因此它将附加程序添加到根记录器一次Spring 已初始化(因此我可以使用来自 spring.xml 的数据库信息)。

如何设置此 appender/logger 以便我只能将某些异常记录到我的自定义表中?

编辑:在做了更多研究之后,让我再问一个问题来验证。如果我要创建一个像 "SpecialExceptionLogger" 这样的自定义记录器,我可以只将 DB Appender 添加到那个特定的记录器,然后在我遇到特殊异常时使用那个记录器吗?

在 logback config.xml 中,您应该指定 Appender class 名称,如下所示。

<appender name="CUSTOM_DB_APPENDER" class="my.custom.DBAppender" />

检查 http://logback.qos.ch/manual/configuration.html 以获得更多配置选项

你对"appender using Spring's DB info"的要求有点奇怪。在 Spring 启动期间日志记录已经可用,如果启动期间的日志需要通过该附加程序,它将无法工作,因为您的附加程序尚未正确配置。我建议您单独配置您的 appender(尽管实现您的目标并非不可能)

关于您的其他问题:

If I were to create a custom logger like "SpecialExceptionLogger", can I just add the DB Appender to that specific logger and then use that logger when I get the special exceptions?

当然可以。它应该是使用 Logback 的基础知识。请务必先阅读文档以了解基础知识。

XML 看起来像(不是真实的,只是给你一个想法)

<appender name="dbAppender" ...> ... </appender>
<logger name="SpecialExceptionLogger">
    <appender-ref ref="dbAppender"/>
</logger>

How can I set this appender/logger up so I can only log certain exceptions to my custom tables

相信Logback中的filter可以实现你所需要的。您可以在 Whosebug

existing answer 中找到它

我讨厌坏死,但这可以通过 DelegatingLogbackAppender 实现。该 appender 只保留任何事件,直到您稍后可以在 Spring(和您的数据源)初始化后配置适当的 DBAppender

在我的示例中,我在 Grails 中创建了一个名为 logging 的数据源,我在 bean 配置中引用了它。如果您想要并且能够在根数据源中创建必要的表,您可以只传递 ref(dataSource)(注意大写 S)。

如果您像我们一样创建了自己的自定义数据库附加程序,DelegatingLogbackAppender 也很有用,因为固定的 DBAppender 太死板了。

有很多理由希望将日志事件放入数据库中。对我们来说,一个要求是我们的应用程序是跨数十个实例扩展的,这使得搜索数十个日志文件变得繁重。

logback.groovy(导入省略)

appender('STDOUT', ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
       pattern = "%level %logger - %msg%n"
    }
}

appender('DB', DelegatingLogbackAppender)

root(ERROR, ['STDOUT', 'DB'])

resources.groovy(导入省略)

beans = {
    applicationContextHolder(ApplicationContextHolder)

    loggerContext(LoggerFactory) { bean ->
        bean.factoryMethod = "getILoggerFactory"
    }

    patternLayoutEncoder(PatternLayoutEncoder) { bean ->
        bean.initMethod = 'start'
        bean.destroyMethod = 'stop'

        context = ref(loggerContext)
        pattern = "%level %logger - %msg%n"
    }

    // Configure a console appender JIC    
    STDOUT(ConsoleAppender) { bean ->
        bean.initMethod = 'start'
        bean.destroyMethod = 'stop'
        context = ref(loggerContext)
        encoder = ref(patternLayoutEncoder)
    }

    connectionSource(DataSourceConnectionSource) { bean ->
        bean.initMethod = 'start'
        bean.destroyMethod = 'stop'
        context = ref(loggerContext)
        dataSource = ref(dataSource_logging)
    }

    DB(DBAppender) { bean ->
        bean.initMethod = 'start'
        bean.destroyMethod = 'stop'
        context = ref(loggerContext)
        connectionSource = ref(connectionSource)
    }
}