uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

XML形式のlog4j設定(log4j.xml)をGrailsで使用する

Grailsではロギングの設定がConfig.groovyで設定できますが、なんらかの理由でXML形式の設定(log4j.xml)で行ないたいことがあるかもしれません。しかし、その場合log4j.xmlをどこに置くか、という問題があり得ます。

この問題を説明します。まずGrailslog4jXML設定を使用するには、springの設定ファイルresouces.groovyで、以下のようにlog4jConfigurerを設定します。

GRAILS_PROJ/grails-app/conf/spring/resources.groovy

beans = {
    log4jConfigurer(org.springframework.beans.factory.config.MethodInvokingFactoryBean){
        targetClass = "org.springframework.util.Log4jConfigurer"
        targetMethod = "initLogging"
        // arguments = "grails-app/conf/log4j.xml"  // ★1
        arguments = "classpath:log4j.xml"  // ★2
    }
}

問題は、★1のようにカレントディレクトリ相対で指定すると、warにしてtomcatなどにデプロイした状態では、tomcatが走行しているときのカレントディレクトリ($CATARINA_BASE)からの相対になり、読み取ることができないということです。だからといって、絶対指定も一般にはできないでしょう。

この解決策ですが、まずlog4j.xmlgrails-app/conf配下に置いた上で、(★2)のようにxmlclasspath配下にあると指定します。run-appの際には、grails-app/confはクラスパスに入っていますのでこれで動作します。

ただし、warにしたときには、conf配下は特にはクラスパスにはいっているわけではないので(Config.groovyなどはコンパイルされてclasses配下に移動している)、warの作成時にgrails-app/conf/log4j.xmlを適切なclasspathの通っているところ、たとえば以下ではWAR中の$WEB-INF/classes/配下にコピーするように、BuildConfigに以下の設定を追加します。

GRAILS_PROJ/grails-app/conf/BuildConfig.groovyに追加。

grails.war.resources = { stagingDir, args ->
    println "$stagingDir, $args"
    copy(file: "grails-app/conf/log4j.xml",
         todir: "${stagingDir}/WEB-INF/classes/")
}

なおログファイルをそもそもどこに置くか、という設定はlog4j.xmlに記入しておく必要があります。XML設定の場合、grailsのConfig.groovyで設定するように、developmentのときとprod/testのときに場所を切り替えたりということはたぶんできないので、適当に絶対パスで指定することになるでしょう。

ちなみに、Wiki - Log4j XML Pluginというプラグインもあり、XMLでの設定に対応する、markupbuilderっぽい記法で設定することができるようです。これを使えば、もっとうまくいくのかもしれませんが試してません。