如何使用slf4j记录liquibase日志?

36

许多人们不确定如何修复liquibase的日志记录,无论是输出到控制台还是文件。

是否可以使liquibase记录到slf4j?

4个回答

53

有一个方法,但有点晦涩。引用使用SLF4J和Log4J修复Liquibase日志记录

有一个“简单的方法”,只需添加一个依赖项即可:

<!-- your own standard logging dependencies -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.5</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId><!-- or log4j2 or logback or whatever-->
    <version>1.7.5</version>
</dependency>

<!-- special dependency to fix liquibase's logging fetish -->
<dependency>
    <groupId>com.mattbertolini</groupId>
    <artifactId>liquibase-slf4j</artifactId>
    <version>1.2.1</version>
</dependency>

现在,前两个是日常记录框架(slf4j api和log4j实现)。它们除了路由到物理记录框架外,与您的标准log4j依赖项没有区别。没有log4j/logback等本身,它们仍然无法路由任何内容。

然而,最后一个很有趣,因为它提供了一个特定包中的单个类,liquibase将扫描其中的Logger实现。这是由Matt Bertolini开源的,所以您可以在GitHub上找到它

如果您希望自己完成此操作,还有The Hard Way

package liquibase.ext.logging; // this is *very* important

import liquibase.changelog.ChangeSet;
import liquibase.changelog.DatabaseChangeLog;
import liquibase.logging.core.AbstractLogger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Liquibase finds this class by itself by doing a custom component scan (sl4fj wasn't generic enough).
 */
public class LiquibaseLogger extends AbstractLogger {
    private static final Logger LOGGER = LoggerFactory.getLogger(LiquibaseLogger.class);
    private String name = "";

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void severe(String message) {
        LOGGER.error("{} {}", name, message);
    }

    @Override
    public void severe(String message, Throwable e) {
        LOGGER.error("{} {}", name, message, e);
    }

    @Override
    public void warning(String message) {
        LOGGER.warn("{} {}", name, message);
    }

    @Override
    public void warning(String message, Throwable e) {
        LOGGER.warn("{} {}", name, message, e);
    }

    @Override
    public void info(String message) {
        LOGGER.info("{} {}", name, message);
    }

    @Override
    public void info(String message, Throwable e) {
        LOGGER.info("{} {}", name, message, e);
    }

    @Override
    public void debug(String message) {
        LOGGER.debug("{} {}", name, message);
    }

    @Override
    public void debug(String message, Throwable e) {
        LOGGER.debug("{} {}", message, e);
    }

    @Override
    public void setLogLevel(String logLevel, String logFile) {
    }

    @Override
    public void setChangeLog(DatabaseChangeLog databaseChangeLog) {
    }

    @Override
    public void setChangeSet(ChangeSet changeSet) {
    }

    @Override
    public int getPriority() {
        return Integer.MAX_VALUE;
    }
}

这个实现方法可用,但仅作为示例使用。例如,我没有使用Liquibase的名称来要求日志记录,而是直接使用Logger类本身。Matt的版本还进行了一些null检查,因此可能更成熟,而且它是开源的。

请注意,这个额外的 liquibase-slf4j 依赖项似乎只在使用 Liquibase 3.4.1 时对我有效。如果我使用 3.4.03.4.23.5.3,它就会恢复到自己奇怪的日志记录方式。 - Craig Otis
无法在Liquibase 4.x版本中使用该功能。 - Olivier Boissé

7
我是一名有用的助手,可以为您翻译文本。

我对您的要求不是很确定,但我的理解是您想使用SLF4J API记录所有Liquibase日志。如果我没理解错的话,那么您应该能够做到。

首先将以下依赖项添加到您的pom.xml文件中:

<dependency>
    <groupId>com.mattbertolini</groupId>
    <artifactId>liquibase-slf4j</artifactId>
    <version>1.2.1</version>
</dependency>

<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.6.6</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
        <version>1.6.6</version>
    </dependency>

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.0.7</version>
    </dependency>

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.7</version>
    </dependency>

在你的 logback.xml 文件中,添加 liquibase 的记录器,并根据您的要求设置 LEVEL。
  <logger name="liquibase" level="DEBUG" />

2
这在Liquibase中不起作用,因为它会进行自己的类扫描并要求特定接口实现位于特定包中。有关更多信息,请参见其他答案。 - Benny Bottema
我已修改了上面的答案,请检查。我添加了用于记录Liquibase日志的依赖项。<dependency> <groupId>com.mattbertolini</groupId> <artifactId>liquibase-slf4j</artifactId> <version>1.2.1</version> </dependency> - Waheed
1
你没有读取已接受的答案,我猜,因为那已经建议了相同的解决方案。 - Benny Bottema

2
以下是我的配方,可以使liquibase 3.5.3在Windows命令行下记录日志到文件中。它并没有使用完全的“slf4j”,但通过让liquibase使用java.util.logging来解决获取数据库更新日志文件的问题。
1)从这里获取liquibase-javalogger-3.0.jar。
2)将其放置于%LIQUIBASE_HOME%/lib目录下。
3)创建logger.properties文件,包含以下内容:
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
.level=FINEST
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.pattern=liquibase.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.FileHandler.append=true
#2018-04-28 17:29:44 INFO Example logging record
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %5$s%6$s%n

4) 给Liquibase添加Java选项(例如通过设置JAVA_OPTS = ...):

-Djava.util.logging.config.file=logger.properties

我的Liquibase包装批处理文件示例:

set username=%USER%
set password="%PASSWORD%"

set URL="jdbc:db2://mydbserver:50000/MYDB"

set JAVA_OPTS=-Djava.util.logging.config.file=db2/logger.properties

call liquibase.bat ^
    --driver="com.ibm.db2.jcc.DB2Driver" ^
    --defaultSchemaName=MYSCHEMA ^
    --liquibaseSchemaName=MYSCHEMA ^
    --changeLogFile=db2/changelog.xml ^
    --url=%URL% ^
    --username=%USER% ^
    --password="%PASSWORD%" ^
    --logLevel=debug

更新:

我已经切换到新的Liquibase版本,该版本默认使用Logback。对于Liquibase 3.6.2,请使用以下设置从Windows命令行运行:

1)确保Java类路径中可以访问slfj。 将slf4j-api-1.7.25.jar放入liquibase/lib文件夹中。 该jar文件可以在官方slfj发行包中找到: https://www.slf4j.org/download.html

2)设置logback配置文件路径参数:

JAVA_OPTS=-Dlogback.configurationFile=logback.xml

3) 添加logback.xml配置文件。示例在此处:https://www.mkyong.com/logging/logback-xml-example/


1
我应该把logger.properties文件放在哪里?第四步具体是什么样子? - Mad Scientist
1
我正在当前目录下运行liquibase,该目录下有一个名为“db2”的子目录,其中包含changelogs和properties文件。附上示例。 - vrogach

0

我在我的应用程序中尝试了相同的操作,似乎它可以正常工作。我可以看到liquibase日志记录在我的日志文件中。

2014-01-08 11:16:21,452 [main] DEBUG liquibase - Computed checksum for addColumn:[
    columns=[
        column:[
            name="IS_NEW"
            type="BIT"
        ]
    ]
    tableName="TENANT"
] as e2eb1f5cb8dcfca7d064223044d06de9
2014-01-08 11:16:21,452 [main] DEBUG liquibase - Computed checksum for 3:e2eb1f5cb8dcfca7d064223044d06de9: as 549852ffb531de4929ae433ff0be2742
2014-01-08 11:16:21,455 [main] DEBUG liquibase - Release Database Lock
2014-01-08 11:16:21,456 [main] DEBUG liquibase - Executing UPDATE database command: UPDATE `DATABASECHANGELOGLOCK` SET `LOCKED` = 0, `LOCKEDBY` = NULL, `LOCKGRANTED` = NULL WHERE `ID` = 1
2014-01-08 11:16:21,518 [main] INFO  liquibase - Successfully released change log lock

1
你使用的是哪个Liquibase版本? - Benny Bottema

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接