web-dev-qa-db-ja.com

Log4j、相対パスを使用するようにWebアプリを構成する

Java WinまたはLinuxマシンにデプロイする必要があるwebappがあります。今度はロギング用にlog4jを追加したいので、ログファイルの相対パスを使用したいのですがコンテナーはすべてTomcatである可能性が高いですが、必ずしもそうである必要はありません。

これを行う最良の方法は何ですか?

80
Iker Jimenez

私は最終的にこの方法でそれをやった。

以下を行うServletContextListenerを追加しました。

public void contextInitialized(ServletContextEvent event) {
    ServletContext context = event.getServletContext();
    System.setProperty("rootPath", context.getRealPath("/"));
}

次に、log4j.propertiesファイルで:

log4j.appender.file.File=${rootPath}WEB-INF/logs/MyLog.log

このようにして、「rootPath」システムプロパティが設定される前にLog4jを使用しない限り、Log4jは適切なフォルダーに書き込みます。つまり、ServletContextListener自体からは使用できませんが、アプリ内の他のどこからでも使用できるはずです。

コンテナ固有のシステムプロパティに依存せず、OS固有のパスの問題の影響を受けないため、すべてのWebコンテナとOSで動作するはずです。 TomcatとOrionのWebコンテナ、およびWindowsとLinuxでテストされ、これまでのところ正常に動作します。

どう思いますか?

53
Iker Jimenez

Tomcatはcatalina.homeシステムプロパティを設定します。これをlog4jプロパティファイルで使用できます。このようなもの:

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${catalina.home}/logs/LogFilename.log

Debian(Ubuntuを含む)では、${catalina.home}は機能しません。これは、/ var/log/Tomcat6へのリンクがない/ usr/share/Tomcat6を指しているためです。ここでは${catalina.base}を使用します。

別のコンテナを使用している場合は、同様のシステムプロパティを見つけるか、独自のコンテナプロパティを定義してください。システムプロパティの設定は、プラットフォームとコンテナによって異なります。しかし、Linux/Unix上のTomcatの場合、CATALINA_HOME/binディレクトリにsetenv.shを作成します。次のものが含まれます。

export Java_OPTS="-Dcustom.logging.root=/var/log/webapps"

その場合、log4j.propertiesは次のようになります。

log4j.rootCategory=DEBUG,errorfile

log4j.appender.errorfile.File=${custom.logging.root}/LogFilename.log
99
Steve K

Springを使用する場合、次のことができます。

1)log4j構成ファイルを作成します。 「/WEB-INF/classes/log4j-myapp.properties」「log4j.properties」という名前を付けないでください

例:

log4j.rootLogger=ERROR, stdout, rollingFile

log4j.appender.stdout=org.Apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.Apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n

log4j.appender.rollingFile=org.Apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=${myWebapp-instance-root}/WEB-INF/logs/application.log
log4j.appender.rollingFile.MaxFileSize=512KB
log4j.appender.rollingFile.MaxBackupIndex=10
log4j.appender.rollingFile.layout=org.Apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.rollingFile.Encoding=UTF-8

ポイント(3)で「myWebapp-instance-root」を後で定義します

2)web.xmlで設定場所を指定します。

<context-param>
  <param-name>log4jConfigLocation</param-name>
  <param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>

3)Webアプリのルートにunique変数名を指定します。 「myWebapp-instance-root」

<context-param>
  <param-name>webAppRootKey</param-name>
  <param-value>myWebapp-instance-root</param-value>
</context-param>

4)Log4jConfigListenerを追加します。

<listener>
  <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>

別の名前を選択する場合は、log4j-myapp.propertiesで変更することも忘れないでください。

私の記事を参照してください(イタリア語のみ...しかし、理解できるはずです): http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring

UPDATE(2009/08/01)記事を英語に翻訳しました: http://www.megadix.it/node/136

14
Megadix

Iker's ソリューションに関するコメント。

ServletContextはあなたの問題の良い解決策です。しかし、私はそれが維持に良いとは思わない。ほとんどの時間ログファイルは、長時間保存する必要があります。

ServletContextはデプロイされたファイルの下にファイルを作成するため、サーバーが再デプロイされると削除されます。私の提案は、子の代わりにrootPathの親フォルダーを使用することです。

6
lizi

FileAppenderのパスプロパティでルートディレクトリを指定しない場合、log4jはアプリケーションのルートディレクトリのみを使用しませんか?だからあなたはただ使用できるはずです:

log4j.appender.file.File = logs/MyLog.log

Java Web開発を行ってからしばらく経ちましたが、これは最も直感的であるように思われます。また、$ {catalina.home}に書き込む他の残念な名前のログと衝突しません。/logsディレクトリ。

5
Spencer Kormos

https://stackoverflow.com/a/218037/22792 のさらなるコメントとして-これは、Webアプリが暗黙的に他のServletContextListenerを起動した場合、壊れる可能性があります。 log4j-この場合、log4j構成は、ログルートディレクトリを決定するプロパティが設定される前にすでに読み取られ、解析されます=>ログファイルは、現在のディレクトリ(Tomcatの起動時の現在のディレクトリ)の下に表示されます。

私はこの問題に対する次の解決策しか考えられませんでした。 -コンテキストフィルターで、プロパティを設定した後、DOM/PropertyConfiguratorヘルパークラスを呼び出して、log4j-。{xml、properties}が読み取られることを確認します-log4j構成をリセットします(IIRCにはそれを行う方法があります)

これは少し強引ですが、それが水密にする唯一の方法であると思います。

2

私のソリューションはIker Jimenezの solution に似ていますが、System.setProperty(...)を使用する代わりにorg.Apache.log4j.PropertyConfigurator.configure(Properties)を使用します。そのためには、log4jが独自に構成を見つけられないようにし、手動でロードします(両方のポイントはWolfgang Liebichの answer で説明されています)。

これは、JettyおよびTomcatで動作します。スタンドアロンまたはIDEから実行します。設定が不要で、コンテナ内のアプリの数に関係なく、各アプリのログを独自のフォルダーに配置できます(これは 問題Systemベースのソリューション)。この方法では、log4j構成ファイルをWebアプリ内の任意の場所に配置することもできます(たとえば、1つのプロジェクトでは、WEB-INF/内にすべての構成ファイルがありました)。

詳細:

  1. クラスパスのlog4j-no-autoload.propertiesファイルにプロパティがあります(たとえば、Mavenプロジェクトでは元はsrc/main/resourcesにあり、WEB-INF/classesにパッケージ化されます)、
  2. ファイルアペンダーは次のように構成されています:

    log4j.appender.MyAppFileAppender = org.Apache.log4j.FileAppender
    log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log
    ...
    
  3. そして、私はこのようなコンテキストリスナーを持っています(Java 7の "try-with-resource"構文でもっと短くなります):

    @WebListener
    public class ContextListener implements ServletContextListener {
        @Override
        public void contextInitialized(final ServletContextEvent event) {
            Properties props = new Properties();
            InputStream strm =
                ContextListener.class.getClassLoader()
                    .getResourceAsStream("log4j-no-autoload.properties");
            try {
                props.load(strm);
            } catch (IOException propsLoadIOE) {
                throw new Error("can't load logging config file", propsLoadIOE);
            } finally {
                try {
                    strm.close();
                } catch (IOException configCloseIOE) {
                    throw new Error("error closing logging config file", configCloseIOE);
                }
            }
            props.put("webAppRoot", event.getServletContext().getRealPath("/"));
            PropertyConfigurator.configure(props);
            // from now on, I can use LoggerFactory.getLogger(...)
        }
        ...
    }
    
1
starikoff

私の提案では、ログファイルは常にwebAppのルートコンテキストの上に記録する必要があるため、webAppを再デプロイする場合、既存のログファイルを上書きしたくないと考えています。

1
user553633

あなたがMavenを使用している場合、私はあなたのための素晴らしいソリューションを持っています:

  1. Pom.xmlファイルを編集して、次の行を含めます。

    <profiles>
        <profile>
            <id>linux</id>
            <activation>
                <os>
                    <family>unix</family>
                </os>
            </activation>
            <properties>
                <logDirectory>/var/log/Tomcat6</logDirectory>
            </properties>
        </profile>
        <profile>
            <id>windows</id>
            <activation>
                <os>
                    <family>windows</family>
                </os>
            </activation>
            <properties>
                <logDirectory>${catalina.home}/logs</logDirectory>
            </properties>
        </profile>
    </profiles>
    

    ここでは、OSファミリ専用のlogDirectoryプロパティを定義します。

  2. log4j.propertiesファイルで既に定義されているlogDirectoryプロパティを使用します。

    log4j.appender.FILE=org.Apache.log4j.RollingFileAppender
    log4j.appender.FILE.File=${logDirectory}/mylog.log
    log4j.appender.FILE.MaxFileSize=30MB
    log4j.appender.FILE.MaxBackupIndex=10
    log4j.appender.FILE.layout=org.Apache.log4j.PatternLayout
    log4j.appender.FILE.layout.ConversionPattern=%d{ISO8601} [%x] %-5p [%t] [%c{1}] %m%n
    
  3. それでおしまい!

P.S.:これはAntを使用して達成できると確信していますが、残念ながら、十分な経験がありません。

1
alex.antaniuk

work directoryを使用して、ログファイルへの相対パスを指定できます。

appender.file.fileName = ${sys:user.dir}/log/application.log

これはサーブレットコンテナから独立しており、システム環境にカスタム変数を渡す必要はありません。

1
Dimitar II