Ich habe eine Java-Webanwendung, die entweder auf Win- oder Linux-Computern bereitgestellt werden muss. Ich möchte jetzt log4j für die Protokollierung hinzufügen und möchte einen relativen Pfad für die Protokolldatei verwenden, da ich den Dateipfad nicht bei jeder Bereitstellung ändern möchte. Der Container wird höchstwahrscheinlich Tomcat sein, aber nicht unbedingt.
Was ist der beste Weg, dies zu tun?
java
web-applications
log4j
Iker Jimenez
quelle
quelle
Antworten:
Tomcat legt eine Systemeigenschaft Catalina.home fest. Sie können dies in Ihrer log4j-Eigenschaftendatei verwenden. Etwas wie das:
Unter Debian (einschließlich Ubuntu)
${catalina.home}
funktioniert dies nicht, da dies auf / usr / share / tomcat6 verweist, das keinen Link zu / var / log / tomcat6 hat. Hier einfach benutzen${catalina.base}
.Wenn Sie einen anderen Container verwenden, versuchen Sie, eine ähnliche Systemeigenschaft zu finden, oder definieren Sie Ihre eigene. Das Festlegen der Systemeigenschaft variiert je nach Plattform und Container. Aber für Tomcat unter Linux / Unix würde ich eine setenv.sh im Verzeichnis CATALINA_HOME / bin erstellen. Es würde enthalten:
export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"
Dann wären Ihre log4j.properties:
quelle
Ich habe es endlich so gemacht.
Es wurde ein ServletContextListener hinzugefügt, der Folgendes ausführt:
public void contextInitialized(ServletContextEvent event) { ServletContext context = event.getServletContext(); System.setProperty("rootPath", context.getRealPath("/")); }
Dann in der Datei log4j.properties:
Auf diese Weise schreibt Log4j in den richtigen Ordner, solange Sie ihn nicht verwenden, bevor die Systemeigenschaft "rootPath" festgelegt wurde. Dies bedeutet, dass Sie es nicht über den ServletContextListener selbst verwenden können, sondern dass Sie es von einer anderen Stelle in der App aus verwenden können sollten.
Es sollte auf jedem Webcontainer und Betriebssystem funktionieren, da es nicht von einer container-spezifischen Systemeigenschaft abhängig ist und nicht von betriebssystemspezifischen Pfadproblemen betroffen ist. Getestet mit Tomcat- und Orion-Webcontainern sowie unter Windows und Linux und funktioniert bisher einwandfrei.
Was denken Sie?
quelle
Wenn Sie Spring verwenden, können Sie:
1) Erstellen Sie eine log4j-Konfigurationsdatei, z. B. "/WEB-INF/classes/log4j-myapp.properties". Nennen Sie sie NICHT "log4j.properties".
Beispiel:
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
Wir werden "myWebapp-instance-root" später in Punkt (3) definieren.
2) Geben Sie den Konfigurationsspeicherort in web.xml an:
3) Geben Sie einen eindeutigen Variablennamen für das Stammverzeichnis Ihrer Webanwendung an, z. B. "myWebapp-instance-root".
4) Fügen Sie einen Log4jConfigListener hinzu:
<listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener>
Wenn Sie einen anderen Namen wählen, denken Sie daran, ihn auch in log4j-myapp.properties zu ändern.
Siehe meinen Artikel (nur Italienisch ... aber es sollte verständlich sein): http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring
UPDATE (01.08.2009) Ich habe meinen Artikel ins Englische übersetzt: http://www.megadix.it/node/136
quelle
Nur ein Kommentar zu Ikers Lösung.
ServletContext
ist eine gute Lösung für Ihr Problem. Aber ich denke nicht, dass es gut für Unterhalt ist. Die meisten Zeitprotokolldateien müssen für lange Zeit gespeichert werden.Da sich
ServletContext
die Datei unter der bereitgestellten Datei befindet, wird sie entfernt, wenn der Server erneut bereitgestellt wird. Ich empfehle, den übergeordneten Ordner von rootPath anstelle des untergeordneten Ordners zu verwenden.quelle
Verwendet log4j nicht nur das Anwendungsstammverzeichnis, wenn Sie in der Pfadeigenschaft Ihres FileAppender kein Stammverzeichnis angeben? Sie sollten also nur Folgendes verwenden können:
log4j.appender.file.File = logs / MyLog.log
Es ist schon eine Weile her, dass ich Java-Webentwicklung durchgeführt habe, aber dies scheint die intuitivste zu sein und kollidiert auch nicht mit anderen leider benannten Protokollen, die in das Verzeichnis $ {catalogina.home} / logs schreiben.
quelle
Als weiterer Kommentar zu https://stackoverflow.com/a/218037/2279200 - dies kann zu Problemen führen, wenn die Web-App implizit andere ServletContextListener startet, die möglicherweise früher aufgerufen werden und bereits versuchen, log4j zu verwenden - in diesem Fall die Die log4j-Konfiguration wird bereits gelesen und analysiert, bevor die Eigenschaft festgelegt wird, die das Protokollstammverzeichnis bestimmt => Die Protokolldateien werden irgendwo unterhalb des aktuellen Verzeichnisses angezeigt (das aktuelle Verzeichnis beim Starten von Tomcat).
Ich konnte mir nur eine folgende Lösung für dieses Problem vorstellen: - Benennen Sie Ihre Datei log4j.properties (oder logj4.xml) in etwas um, das log4j nicht automatisch liest. - Rufen Sie in Ihrem Kontextfilter nach dem Festlegen der Eigenschaft die Hilfsklasse DOM / PropertyConfigurator auf, um sicherzustellen, dass Ihr log4j -. {Xml, properties} gelesen wird. - Setzen Sie die log4j-Konfiguration zurück (IIRC gibt es eine Methode, um dies zu tun).
Dies ist ein bisschen rohe Gewalt, aber ich denke, es ist der einzige Weg, es wasserdicht zu machen.
quelle
Für den Fall, dass Sie Maven verwenden, habe ich eine großartige Lösung für Sie:
Bearbeiten Sie Ihre Datei pom.xml so, dass sie folgende Zeilen enthält:
<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>
Hier definieren Sie die
logDirectory
Eigenschaft speziell für die Betriebssystemfamilie.Verwenden Sie die bereits definierte
logDirectory
Eigenschaft in derlog4j.properties
Datei: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: Ich bin sicher, dass dies mit Ant erreicht werden kann, aber leider habe ich nicht genug Erfahrung damit.
quelle
Mein Vorschlag ist, dass die Protokolldatei immer über dem Stammkontext der Webanwendung protokolliert werden sollte. Wenn wir die Webanwendung erneut bereitstellen, möchten wir die vorhandenen Protokolldateien nicht überschreiben.
quelle
Meine Lösung ist ähnlich wie Iker Jimenez Lösung , aber anstelle von
System.setProperty(...)
I Verwendungorg.apache.log4j.PropertyConfigurator.configure(Properties)
. Dazu brauche ich auch log4j, um seine Konfiguration nicht selbst finden zu können, und lade es manuell (beide Punkte in Wolfgang Liebichs Antwort beschrieben ).Dies funktioniert für Jetty und Tomcat, eigenständig oder von IDE ausgeführt, erfordert keine Konfiguration und ermöglicht es, die Protokolle jeder App in einem eigenen Ordner abzulegen, unabhängig davon, wie viele Apps sich im Container befinden (was das Problem bei der
System
basierten Lösung ist). Auf diese Weise kann man die log4j-Konfigurationsdatei auch an einer beliebigen Stelle in der Web-App ablegen (z. B. in einem Projekt hatten wir alle KonfigurationsdateienWEB-INF/
).Einzelheiten:
log4j-no-autoload.properties
Datei im Klassenpfad (z. B. in meinem Maven-Projekt, in dem es ursprünglich enthalten ist und insrc/main/resources
das es gepackt wirdWEB-INF/classes
).Der Datei-Appender ist wie folgt konfiguriert:
Und ich habe einen Kontext-Listener wie diesen (wird mit der "Try-with-Resource" -Syntax von Java 7 viel kürzer):
@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(...) } ... }
quelle
Sie können den relativen Pfad zur Protokolldatei über das Arbeitsverzeichnis angeben :
Dies ist unabhängig vom Servlet-Container und erfordert keine Übergabe einer benutzerdefinierten Variablen an die Systemumgebung.
quelle