WinまたはLinuxマシンのいずれかにデプロイする必要のあるJavaWebアプリケーションがあります。ロギング用にlog4jを追加したいのですが、展開ごとにファイルパスを変更したくないので、ログファイルの相対パスを使用したいと思います。コンテナはTomcatである可能性が高いですが、必ずしもそうとは限りません。
これを行うための最良の方法は何ですか?
WinまたはLinuxマシンのいずれかにデプロイする必要のあるJavaWebアプリケーションがあります。ロギング用にlog4jを追加したいのですが、展開ごとにファイルパスを変更したくないので、ログファイルの相対パスを使用したいと思います。コンテナはTomcatである可能性が高いですが、必ずしもそうとは限りません。
これを行うための最良の方法は何ですか?
回答:
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
私はついにこのようにそれをしました。
次のことを行う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
このようにすることで、Log4jは、「rootPath」システムプロパティが設定される前に使用しない限り、適切なフォルダーに書き込みます。つまり、ServletContextListener自体からは使用できませんが、アプリ内の他の場所からは使用できるはずです。
コンテナ固有のシステムプロパティに依存せず、OS固有のパスの問題の影響を受けないため、すべてのWebコンテナとOSで機能するはずです。TomcatとOrionのWebコンテナ、およびWindowsとLinuxでテストされ、これまでのところ正常に動作しています。
どう思いますか?
Springを使用する場合、次のことができます。
1)「/ WEB-INF / classes / log4j-myapp.properties」などのlog4j構成ファイルを作成します。「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
「myWebapp-instance-root」は後でポイント(3)で定義します。
2)web.xmlで構成の場所を指定します。
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/classes/log4j-myapp.properties</param-value>
</context-param>
3)Webアプリケーションのルートに一意の変数名を指定します(例: "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
更新(2009/08/01) 記事を英語に翻訳しました:http: //www.megadix.it/node/136
FileAppenderのpathプロパティでルートディレクトリを指定しない場合、log4jはアプリケーションのルートディレクトリを使用するだけではありませんか?したがって、次のものを使用できるはずです。
log4j.appender.file.File = logs / MyLog.log
Java Web開発を行ってからしばらく経ちますが、これは最も直感的であるように思われ、$ {catalina.home} / logsディレクトリに書き込む他の残念な名前のログとも衝突しません。
https://stackoverflow.com/a/218037/2279200に関する追加のコメントとして、Webアプリが他のServletContextListenerを暗黙的に開始すると、これが破損する可能性があります。他のServletContextListenerは以前に呼び出され、すでにlog4jを使用しようとしています。 log4j構成は、ログルートディレクトリを決定するプロパティが設定される前にすでに読み取られて解析されます=>ログファイルは現在のディレクトリ(tomcatを起動したときの現在のディレクトリ)の下のどこかに表示されます。
この問題に対する次の解決策しか考えられませんでした。-log4j.properties(またはlogj4.xml)ファイルの名前をlog4jが自動的に読み取らない名前に変更します。-コンテキストフィルターで、プロパティを設定した後、DOM / PropertyConfiguratorヘルパークラスを呼び出して、log4j-。{xml、properties}が読み取られるようにします-log4j構成をリセットします(IIRCにはそれを行うメソッドがあります)
これは少し野蛮な力ですが、それを水密にする唯一の方法であると考えています。
Mavenを使用している場合、私はあなたのための素晴らしい解決策を持っています:
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>
ここではlogDirectory
、OSファミリ専用のプロパティを定義します。
ファイルで定義済みのlogDirectory
プロパティを使用しlog4j.properties
ます。
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
PS:これはAntを使用して達成できると確信していますが、残念ながら、十分な経験がありません。
私の提案では、ログファイルは常にwebAppのルートコンテキストの上に記録する必要があるため、webAppを再デプロイする場合に備えて、既存のログファイルを上書きしたくありません。
私のソリューションはIkerJimenezのソリューションに似ていますが、使用System.setProperty(...)
する代わりにを使用しますorg.apache.log4j.PropertyConfigurator.configure(Properties)
。そのためには、log4jがそれ自体で構成を見つけることができないようにする必要があり、手動でロードします(両方のポイントはWolfgangLiebichの回答に記載されています))。
IDEから桟橋とTomcat、スタンドアロンまたは実行のためのこの作品は、どんなに多くのアプリケーション(あるコンテナ内、自分のフォルダ内の各アプリケーションのログを配置することができます、ゼロ設定が必要になり、問題とSystem
ベースのソリューション)。このようにして、log4j構成ファイルをWebアプリ内の任意の場所に配置することもできます(たとえば、1つのプロジェクトにすべての構成ファイルが含まれていましたWEB-INF/
)。
詳細:
log4j-no-autoload.properties
クラスパスのファイルにプロパティがあります(たとえば、Mavenプロジェクトではsrc/main/resources
、元々含まれていて、にパッケージ化されています)WEB-INF/classes
)、次のように構成されたファイルアペンダーがあります。
log4j.appender.MyAppFileAppender = org.apache.log4j.FileAppender
log4j.appender.MyAppFileAppender.file = ${webAppRoot}/WEB-INF/logs/my-app.log
...
そして、私はこのようなコンテキストリスナーを持っています(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(...)
}
...
}