Mam aplikację internetową java, którą należy wdrożyć na komputerach z systemem Win lub Linux. Chcę teraz dodać log4j do rejestrowania i chciałbym użyć względnej ścieżki do pliku dziennika, ponieważ nie chcę zmieniać ścieżki pliku przy każdym wdrożeniu. Kontener najprawdopodobniej będzie Tomcat, ale niekoniecznie.
Jaki jest najlepszy sposób na zrobienie tego?
java
web-applications
log4j
Iker Jimenez
źródło
źródło
Odpowiedzi:
Tomcat ustawia właściwość systemową catalina.home. Możesz tego użyć w swoim pliku właściwości log4j. Coś takiego:
Na Debianie (w tym Ubuntu),
${catalina.home}
nie będzie działać, ponieważ wskazuje na / usr / share / tomcat6, który nie ma linku do / var / log / tomcat6. Tutaj po prostu użyj${catalina.base}
.Jeśli używasz innego kontenera, spróbuj znaleźć podobną właściwość systemową lub zdefiniuj własną. Ustawienie właściwości systemu będzie się różnić w zależności od platformy i kontenera. Ale dla Tomcata na Linux / Unix utworzyłbym plik setenv.sh w katalogu CATALINA_HOME / bin. Zawierałby:
export JAVA_OPTS="-Dcustom.logging.root=/var/log/webapps"
Wtedy twój log4j.properties byłby taki:
źródło
W końcu zrobiłem to w ten sposób.
Dodano ServletContextListener, który wykonuje następujące czynności:
public void contextInitialized(ServletContextEvent event) { ServletContext context = event.getServletContext(); System.setProperty("rootPath", context.getRealPath("/")); }
Następnie w pliku log4j.properties:
Robiąc to w ten sposób, Log4j zapisze się we właściwym folderze, o ile nie użyjesz go przed ustawieniem właściwości systemowej "rootPath". Oznacza to, że nie możesz go używać z samego ServletContextListener, ale powinieneś móc go używać z dowolnego innego miejsca w aplikacji.
Powinien działać na każdym kontenerze internetowym i systemie operacyjnym, ponieważ nie jest zależny od właściwości systemu specyficznej dla kontenera i nie ma na niego wpływu problemy ze ścieżką specyficzne dla systemu operacyjnego. Testowane z kontenerami internetowymi Tomcat i Orion oraz w systemach Windows i Linux. Jak dotąd działa dobrze.
Co myślisz?
źródło
Jeśli używasz Springa, możesz:
1) utwórz plik konfiguracyjny log4j, np. „/WEB-INF/classes/log4j-myapp.properties” NIE nazywaj go „log4j.properties”
Przykład:
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
W dalszej części (3) zdefiniujemy „myWebapp-instance-root”
2) Określ lokalizację konfiguracji w web.xml:
3) Określ unikalną nazwę zmiennej dla katalogu głównego swojej aplikacji internetowej, np. „MyWebapp-instance-root”
4) Dodaj Log4jConfigListener:
<listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener>
Jeśli wybierzesz inną nazwę, pamiętaj, aby zmienić ją również w log4j-myapp.properties.
Zobacz mój artykuł (tylko włoski ... ale powinien być zrozumiały): http://www.megadix.it/content/configurare-path-relativi-log4j-utilizzando-spring
UPDATE (2009/08/01) Przetłumaczyłem mój artykuł na język angielski: http://www.megadix.it/node/136
źródło
Tylko komentarz do rozwiązania Ikera .
ServletContext
to dobre rozwiązanie Twojego problemu. Ale nie sądzę, żeby to było dobre na utrzymanie. W większości przypadków pliki dziennika muszą być przechowywane przez długi czas.Ponieważ
ServletContext
tworzy plik pod wdrożonym plikiem, zostanie on usunięty po ponownym wdrożeniu serwera. Sugeruję, aby przejść do folderu nadrzędnego rootPath zamiast folderu podrzędnego.źródło
Czy log4j nie używa tylko katalogu głównego aplikacji, jeśli nie określisz katalogu głównego we właściwości path FileAppender? Więc powinieneś być w stanie użyć:
log4j.appender.file.File = logs / MyLog.log
Minęło trochę czasu, odkąd zajmowałem się tworzeniem stron internetowych w Javie, ale wydaje się, że jest to najbardziej intuicyjne, a także nie koliduje z innymi niestety nazwanymi dziennikami zapisującymi się do katalogu $ {catalina.home} / logs.
źródło
Jako kolejny komentarz na https://stackoverflow.com/a/218037/2279200 - może się to zepsuć, jeśli aplikacja internetowa niejawnie uruchomi inne ServletContextListener, które mogą zostać wywołane wcześniej i które już próbują używać log4j - w tym przypadku Konfiguracja log4j zostanie odczytana i przeanalizowana już przed ustawieniem właściwości określającej katalog główny logów => pliki dziennika pojawią się gdzieś pod bieżącym katalogiem (bieżącym katalogiem podczas uruchamiania tomcat).
Mogłem tylko wymyślić następujące rozwiązanie tego problemu: - zmień nazwę pliku log4j.properties (lub logj4.xml) na coś, czego log4j nie odczyta automatycznie. - W filtrze kontekstu, po ustawieniu właściwości, wywołaj klasę pomocniczą DOM / PropertyConfigurator, aby upewnić się, że Twój log4j -. {Xml, properties} zostanie odczytany - Zresetuj konfigurację log4j (IIRC jest do tego metoda)
To trochę brutalna siła, ale wydaje mi się, że to jedyny sposób, aby uczynić go wodoszczelnym.
źródło
Jeśli korzystasz z Mavena, mam dla Ciebie świetne rozwiązanie:
Edytuj plik pom.xml, aby zawierał następujące wiersze:
<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>
Tutaj definiujesz
logDirectory
właściwość specjalnie dla rodziny systemów operacyjnych.Użyj już zdefiniowanej
logDirectory
właściwości wlog4j.properties
pliku: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: Jestem pewien, że można to osiągnąć za pomocą Ant, ale niestety nie mam z tym wystarczającego doświadczenia.
źródło
Moja sugestia jest taka, że plik dziennika powinien być zawsze rejestrowany powyżej kontekstu głównego aplikacji internetowej, więc w przypadku ponownego wdrożenia aplikacji internetowej nie chcemy nadpisywać istniejących plików dziennika.
źródło
Moje rozwiązanie jest podobne do Iker Jiménez rozwiązania , ale zamiast korzystania z
System.setProperty(...)
pomocy Iorg.apache.log4j.PropertyConfigurator.configure(Properties)
. Do tego trzeba również log4j być w stanie znaleźć swoją konfigurację na własną rękę i załadować go ręcznie (oba punkty opisane w Wolfganga Liebich za odpowiedź ).Działa to w przypadku Jetty i Tomcat, samodzielne lub uruchamiane z IDE, wymaga zerowej konfiguracji, pozwala na umieszczenie dzienników każdej aplikacji w ich własnym folderze, bez względu na to, ile aplikacji znajduje się w kontenerze (co jest problemem z
System
rozwiązaniem opartym na bazie ). W ten sposób można również umieścić plik konfiguracyjny log4j w dowolnym miejscu aplikacji internetowej (np. W jednym projekcie mieliśmy w środku wszystkie pliki konfiguracyjneWEB-INF/
).Detale:
log4j-no-autoload.properties
pliku w ścieżce klas (np. W moim projekcie Mavena, w którym jest oryginalniesrc/main/resources
, jest pakowanyWEB-INF/classes
),Posiada program appender skonfigurowany jako np .:
Mam program nasłuchujący kontekstów, taki jak ten (znacznie krótszy dzięki składni „try-with-resource” w Javie 7):
@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(...) } ... }
źródło
Możesz określić względną ścieżkę do pliku dziennika, używając katalogu roboczego :
Jest to niezależne od kontenera serwletów i nie wymaga przekazywania niestandardowych zmiennych do środowiska systemowego.
źródło