Log4j, настройка веб-приложения на использование относительного пути

StackOverflow https://stackoverflow.com/questions/216781

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть веб-приложение Java, которое должно быть развернуто либо на компьютерах с Win, либо на Linux.Теперь я хочу добавить log4j для ведения журнала, и я хотел бы использовать относительный путь к файлу журнала, поскольку я не хочу изменять путь к файлу при каждом развертывании.Контейнером, скорее всего, будет Tomcat, но не обязательно.

Каков наилучший способ сделать это?

Это было полезно?

Решение 2

Я наконец сделал это таким образом.

Добавлен 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, но вы должны иметь возможность использовать его из любого другого места в приложении.

Он должен работать в каждом веб-контейнере и ОС, так как он не зависит от конкретного системного свойства контейнера и не подвержен специфическим проблемам ОС. Протестировано с веб-контейнерами Tomcat и Orion, а также в Windows и Linux, и пока работает нормально.

Что ты думаешь?

Другие советы

Tomcat устанавливает системное свойство catalina.home. Вы можете использовать это в вашем файле свойств log4j. Примерно так:

log4j.rootCategory=DEBUG,errorfile

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

В Debian (включая Ubuntu) $ {catalina.home} не будет работать, поскольку он указывает на / usr / share / tomcat6, которая не имеет ссылки на / var / log / tomcat6. Здесь просто используйте $ {catalina.base} .

Если вы используете другой контейнер, попробуйте найти похожее системное свойство или определить свое собственное. Установка системного свойства зависит от платформы и контейнера. Но для Tomcat в Linux / Unix я бы создал setenv.sh в каталоге CATALINA_HOME / bin. Он будет содержать:

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

Тогда ваши log4j.properties будут такими:

log4j.rootCategory=DEBUG,errorfile

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

Если вы используете 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

Мы определим "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) Укажите уникальный имя переменной для корневого каталога вашего веб-приложения, например"MyWebApp-экземпляр-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

Просто комментарий о решении Iker .

ServletContext - хорошее решение вашей проблемы. Но я не думаю, что это хорошо для поддержания. Большую часть времени файлы журнала необходимо сохранять в течение длительного времени.

Поскольку ServletContext создает файл в развернутом файле, он будет удален при повторном развертывании сервера. Я предлагаю использовать родительскую папку rootPath вместо дочерней.

Разве log4j не использует просто корневой каталог приложения, если вы не указываете корневой каталог в свойстве path вашего FileAppender?Так что вы должны просто уметь использовать:

log4j.приложение.файл.Файл=журналы/MyLog.log

Прошло некоторое время с тех пор, как я занимался веб-разработкой на Java, но это кажется наиболее интуитивно понятным, а также не сталкивается с другими, к сожалению, названными журналами, записываемыми в каталог $ {catalina.home} /logs.

В качестве дополнительного комментария к https://stackoverflow.com/a/218037/2279200 - это может сломаться, если веб-приложение неявно запускает другой 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 специально для семейства ОС.

  • Используйте уже определенное свойство 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
    
  • Вот и все!
  • P.S.: Я уверен, что этого можно добиться с помощью Ant, но, к сожалению, у меня недостаточно опыта.

    Мое предложение заключается в том, что файл журнала всегда должен регистрироваться выше корневого контекста webApp, поэтому в случае повторного развертывания webApp мы не хотим переопределять существующие файлы журналов.

    Мое решение похоже на решение Икера Хименеса решение, но вместо того , чтобы использовать System.setProperty(...) Я использую org.apache.log4j.PropertyConfigurator.configure(Properties).Для этого мне также нужно, чтобы log4j не смог самостоятельно найти свою конфигурацию, и я загружаю ее вручную (оба пункта описаны в книге Вольфганга Либиха ответ).

    Это работает для Jetty и Tomcat, автономно или запускается из IDE, требует нулевой настройки, позволяет помещать журналы каждого приложения в их собственную папку, независимо от того, сколько приложений внутри контейнера (который в чем проблема с помощью System-основанное на решении).Таким образом, можно также поместить конфигурационный файл log4j в любое место внутри веб-приложения (напримерв одном проекте у нас были все конфигурационные файлы внутри 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(...)
          }
          ...
      }
      

    Вы можете указать относительный путь к файлу журнала, используя рабочий каталог :

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

    Это не зависит от контейнера сервлета и не требует передачи пользовательской переменной в системную среду.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top