Политика свертывания Log4j.fileNamePattern также изменяет имя файлов, которые заархивированы в

#java #log4j

#java #log4j

Вопрос:

Я использовал rolling policy log4j для сжатия файлов, размер которых достигает определенного размера. Приведенные ниже свойства log4j работают должным образом.

 log4j.appender.FILE=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.FILE.rollingPolicy=org.apache.log4j.rolling.FixedWindowRollingPolicy
log4j.appender.FILE.rollingPolicy.maxIndex=13
log4j.appender.FILE.triggeringPolicy=org.apache.log4j.rolling.SizeBasedTriggeringPolicy
log4j.appender.FILE.triggeringPolicy.MaxFileSize=80
log4j.appender.FILE.rollingPolicy.FileNamePattern=log/projectlog_${current.date.time}.%i.log.gz
log4j.appender.FILE.rollingPolicy.ActiveFileName=log/project_log_${current.date.time}.log
log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
log4j.appender.FILE.layout.ConversionPattern=%m%n
  

Но проблема здесь в том, что после создания сжатого файла он также переименовывает файл, который присутствует в сжатом файле gz, с именем файла gz.

В моем сценарии я не хочу, чтобы log4j переименовывал файл, который присутствует в сжатом архиве gz. Есть ли какой-либо способ, с помощью которого мы можем ограничить log4j, чтобы не изменять имена файлов, которые он сжимает.

Ответ №1:

Вы не можете с помощью кода, предоставленного log4j @UmarTahir.

Как вы можете видеть в исходном коде FixedWindowRollingPolicy класса, в методе, который фактически обрабатывает rollover , они сначала инструктируют RollingFileAppender синхронно переименовать файл, а затем при необходимости асинхронно сжать его:

   public RolloverDescription rollover(final String currentFileName) {
  if (maxIndex >= 0) {
    int purgeStart = minIndex;
    if (!explicitActiveFile) {
      purgeStart  ;
    }
    if (!purge(purgeStart, maxIndex)) {
      return null;
    }
    StringBuffer buf = new StringBuffer();
    formatFileName(new Integer(purgeStart), buf);
    String renameTo = buf.toString();
    String compressedName = renameTo;
    Action compressAction = null;
    if (renameTo.endsWith(".gz")) {
      renameTo = renameTo.substring(0, renameTo.length() - 3);
      compressAction =
        new GZCompressAction(
          new File(renameTo), new File(compressedName), true);
    } else if (renameTo.endsWith(".zip")) {
      renameTo = renameTo.substring(0, renameTo.length() - 4);
      compressAction =
        new ZipCompressAction(
          new File(renameTo), new File(compressedName), true);
    }
    FileRenameAction renameAction =
      new FileRenameAction(
        new File(currentFileName), new File(renameTo), false);
    return new RolloverDescriptionImpl(
      currentFileName, false, renameAction, compressAction);
  }
  return null;
}
  

Возвращенное значение RolloverDescription будет использоваться в RollingFileAppender rollover методе для обработки фактического процесса ролловера:

 public boolean rollover() {
  //
  //   can't roll without a policy
  //
  if (rollingPolicy != null) {
    Exception exception = null;
    synchronized (this) {
      //
      //   if a previous async task is still running
      //}
      if (lastRolloverAsyncAction != null) {
        //
        //  block until complete
        //
        lastRolloverAsyncAction.close();
        //
        //    or don't block and return to rollover later
        //
        //if (!lastRolloverAsyncAction.isComplete()) return false;
      }
      try {
        RolloverDescription rollover = rollingPolicy.rollover(getFile());
        if (rollover != null) {
          if (rollover.getActiveFileName().equals(getFile())) {
            closeWriter();
            boolean success = true;
            if (rollover.getSynchronous() != null) {
              success = false;
              try {
                success = rollover.getSynchronous().execute();
              } catch (Exception ex) {
                exception = ex;
              }
            }
            if (success) {
              if (rollover.getAppend()) {
                fileLength = new File(rollover.getActiveFileName()).length();
              } else {
                fileLength = 0;
              }
              if (rollover.getAsynchronous() != null) {
                lastRolloverAsyncAction = rollover.getAsynchronous();
                new Thread(lastRolloverAsyncAction).start();
              }
              setFile(
                rollover.getActiveFileName(), rollover.getAppend(),
                bufferedIO, bufferSize);
            } else {
              setFile(
                rollover.getActiveFileName(), true, bufferedIO, bufferSize);
              if (exception == null) {
                LogLog.warn("Failure in post-close rollover action");
              } else {
                LogLog.warn(
                  "Exception in post-close rollover action", exception);
              }
            }
          } else {
            Writer newWriter =
              createWriter(
                  createFileOutputStream(
                      rollover.getActiveFileName(), rollover.getAppend()));
            closeWriter();
            setFile(rollover.getActiveFileName());
            this.qw = createQuietWriter(newWriter);
            boolean success = true;
            if (rollover.getSynchronous() != null) {
              success = false;
              try {
                success = rollover.getSynchronous().execute();
              } catch (Exception ex) {
                exception = ex;
              }
            }
            if (success) {
              if (rollover.getAppend()) {
                fileLength = new File(rollover.getActiveFileName()).length();
              } else {
                fileLength = 0;
              }
              if (rollover.getAsynchronous() != null) {
                lastRolloverAsyncAction = rollover.getAsynchronous();
                new Thread(lastRolloverAsyncAction).start();
              }
            }
            writeHeader();
          }
          return true;
        }
      } catch (Exception ex) {
        exception = ex;
      }
    }
    if (exception != null) {
      LogLog.warn(
        "Exception during rollover, rollover deferred.", exception);
    }
  }
  return false;
}
  

Если вам нужно это особое поведение, возможно, вы можете создать свою собственную политику перехода и попытаться реализовать что-то похожее на то, что сделано в FixedWindowRollingPolicy , способом, наилучшим образом соответствующим вашим требованиям, и настроить log4j на использование этой новой политики перехода.

Как уже было сказано, имейте в виду, что gzip означает просто сжатие ваших данных, фактическое имя файла или запись файла отсутствуют, просто данные сжаты. Если вы используете gzip инструмент, он использует имя архива для сжатия, сжимает данные и сохраняет результат в новом файле с суффиксом, обычно .gz . Это поведение log4j пытается имитировать в своем коде.

Комментарии:

1. Большое вам спасибо за ваш ответ и за то, что поделились ссылкой на кодовую базу. Я удивлен, что они пытались сделать это таким образом.

2. Добро пожаловать @UmarTahir. Вы правы, хотя, если вы хорошенько подумаете, это имеет смысл: сначала синхронно выполняется операция переименования, которая должна быть быстрой операцией, а затем асинхронно выполняется операция сжатия, которая с точки зрения времени и использования ресурсов может быть более дорогостоящей и с риском блокирования нормальной работы регистраторов.

3. Да, вы правы. Также в моем сценарии, поскольку мой продукт должен возвращать результат за 20 мс, log4j не приносит нам пользы, поскольку у нас много потоков. Вчера я провел несколько тестов на log4j / log4j2, чтобы узнать, сколько времени требуется потоку 30, чтобы вернуться после выполнения log.info . В основном результаты были за 20 мс.

4. Я думаю, было бы здорово, если бы было действительно небольшое количество потоков-потребителей, работающих в базовой функциональности ведения журнала. Таким образом, избегая основных потоков для выполнения чего-то еще.

5. Добро пожаловать @UmarTahir. На самом деле, спасибо, я действительно ценю, когда people заботится о коде на таком глубоком уровне, молодец.