Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log4j's rollingPolicy.FileNamePattern is also changing name of files that are zipped in

Tags:

I have used log4j's rolling policy for compressing files that reach to certain amount in size. Below log4j properties are working properly.

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

But problem here is after it generates a compressed file, it also renames the file which is present in the compressed gz file with the name of gz file.

For my scenario, I don't want log4j to rename file that is present in the compressed gz archive. Is there any way by which we can restrict log4j to not to change file names which it is compressing.

like image 327
Umar Tahir Avatar asked Sep 04 '20 12:09

Umar Tahir


People also ask

What is the use of RollingFileAppender?

RollingFileAppender extends FileAppender to backup the log files when they reach a certain size. The log4j extras companion includes alternatives which should be considered for new deployments and which are discussed in the documentation for org.

What is rolling file in log4j?

Log4j2 RollingFileAppender is an OutputStreamAppender that writes log messages to files, following a configured triggering policy about when a rollover (backup) should occur. It also has a configured rollover strategy about how to rollover the file.

What is TimeBasedRollingPolicy?

Class TimeBasedRollingPolicy It basically specifies the name of the rolled log files. The value FileNamePattern should consist of the name of the file, plus a suitably placed %d conversion specifier. The %d conversion specifier may contain a date and time pattern as specified by the SimpleDateFormat class.

What is SizeBasedTriggeringPolicy?

SizeBasedTriggeringPolicy looks at the size of the currently active file. If it grows larger than the specified size, it will signal the owning RollingFileAppender to trigger the rollover of the existing active file.


1 Answers

You cannot with the code provided by log4j @UmarTahir.

As you can see in the source code of the FixedWindowRollingPolicyclass, in the method that actually handles the rollover, they first instruct RollingFileAppender to rename, synchronously, the file, and then compress it, asynchronously, if necessary:

  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;
}

The returned RolloverDescription will be used in the RollingFileAppender rollover method to handle the actual rollover process:

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;
}

If you need this special behavior, maybe you can create your own rolling policy, and try to implement something similar to what is done in FixedWindowRollingPolicy, in a way best fits your requirements, and configure log4j to use this new rolling policy.

That been said, be aware that gzip means just compressing your data, there is no actual filename or file entry, just data compressed. If you use the gzip tool, it takes the name of the archive to compress, compress the data, and store the result in a new file with a suffix, typically .gz. This is the behavior log4j is trying to mimic in their code.

like image 99
jccampanero Avatar answered Sep 21 '22 23:09

jccampanero