聞こえないJavaエンジニアが適当に書き連ねていく

つらつらとメモしたり日頃の溜まっている想いを吐き出す場所です。

Spring Boot + Doma2のWebアプリでSQLをログファイルに出力したい

これは何

Spring Boot + Doma2のWebアプリをwarファイルにしてTomcatに配備する時、 SQLを独自のログファイルに出力したいのに出なかったので色々格闘したときのメモ。

各種バージョン等

Spring Bootのバージョン以外はあまり関係ないと思うが、一応。

  • Spring Boot 2.1.8
  • Doma2 2.26.0
  • Slf4j 1.7.28
  • Tomcat 9.0.17
  • Java 11

現象

Tomatのログとは別に、アプリケーションのログファイルに色々ログを出したいが、Doma2が出力するSQLが出力されない。

対応

どこかのプログラムに以下の2行を書く。 なんとなくだが、@Configuration アノテーションを付与したプログラムに書くのがいいかもしれない。

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();

細かい考察等

org.springframework.boot.logging.Slf4JLoggingSystem.javaの中に以下の記述がある。

private void configureJdkLoggingBridgeHandler() {
    try {
        if (isBridgeJulIntoSlf4j()) {
            removeJdkLoggingBridgeHandler();
            SLF4JBridgeHandler.install();
        }
    }
    catch (Throwable ex) {
        // Ignore. No java.util.logging bridge is installed.
    }
}

/**
 * Return whether bridging JUL into SLF4J or not.
 * @return whether bridging JUL into SLF4J or not
 * @since 2.0.4
 */
protected final boolean isBridgeJulIntoSlf4j() {
    return isBridgeHandlerAvailable() && isJulUsingASingleConsoleHandlerAtMost();
}

protected final boolean isBridgeHandlerAvailable() {
    return ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader());
}

private boolean isJulUsingASingleConsoleHandlerAtMost() {
    Logger rootLogger = LogManager.getLogManager().getLogger("");
    Handler[] handlers = rootLogger.getHandlers();
    return handlers.length == 0 || (handlers.length == 1 && handlers[0] instanceof ConsoleHandler);
}

isBridgeHandlerAvailable() メソッドはslf4jライブラリが依存関係に含まれていれば常にtrueになりそう。

warファイルからの起動だと、isJulUsingASingleConsoleHandlerAtMost()falseになってしまうのではと推測はしたが…。

参考文献

上記、2行以外はほぼ以下の記述を参考にした&Spring Bootの基本的な記述通りにしている、つもりではいる。