Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LOGMGR-30] Add ability to compress files when rotated if the suffix … #113

Merged
merged 1 commit into from
May 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,17 @@

package org.jboss.logmanager.handlers;

import org.jboss.logmanager.ExtLogRecord;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.io.File;
import java.io.FileNotFoundException;

import java.util.logging.ErrorManager;

import org.jboss.logmanager.ExtLogRecord;

/**
* A file handler which rotates the log at a preset time interval. The interval is determined by the content of the
* suffix string which is passed in to {@link #setSuffix(String)}.
Expand All @@ -46,6 +41,7 @@ public class PeriodicRotatingFileHandler extends FileHandler {
private Period period = Period.NEVER;
private long nextRollover = Long.MAX_VALUE;
private TimeZone timeZone = TimeZone.getDefault();
private SuffixRotator suffixRotator = SuffixRotator.EMPTY;

/**
* Construct a new instance with no formatter and no output file.
Expand Down Expand Up @@ -124,17 +120,22 @@ protected void preWrite(final ExtLogRecord record) {
/**
* Set the suffix string. The string is in a format which can be understood by {@link java.text.SimpleDateFormat}.
* The period of the rotation is automatically calculated based on the suffix.
* <p>
* If the suffix ends with {@code .gz} or {@code .zip} the file will be compressed on rotation.
* </p>
*
* @param suffix the suffix
* @throws IllegalArgumentException if the suffix is not valid
*/
public void setSuffix(String suffix) throws IllegalArgumentException {
final SimpleDateFormat format = new SimpleDateFormat(suffix);
final SuffixRotator suffixRotator = SuffixRotator.parse(suffix);
final String dateSuffix = suffixRotator.getDatePattern();
final SimpleDateFormat format = new SimpleDateFormat(dateSuffix);
format.setTimeZone(timeZone);
final int len = suffix.length();
final int len = dateSuffix.length();
Period period = Period.NEVER;
for (int i = 0; i < len; i ++) {
switch (suffix.charAt(i)) {
switch (dateSuffix.charAt(i)) {
case 'y': period = min(period, Period.YEAR); break;
case 'M': period = min(period, Period.MONTH); break;
case 'w':
Expand All @@ -149,14 +150,15 @@ public void setSuffix(String suffix) throws IllegalArgumentException {
case 'K':
case 'h': period = min(period, Period.HOUR); break;
case 'm': period = min(period, Period.MINUTE); break;
case '\'': while (suffix.charAt(++i) != '\''); break;
case '\'': while (dateSuffix.charAt(++i) != '\''); break;
case 's':
case 'S': throw new IllegalArgumentException("Rotating by second or millisecond is not supported");
}
}
synchronized (outputLock) {
this.format = format;
this.period = period;
this.suffixRotator = suffixRotator;
final long now;
final File file = getFile();
if (file != null && file.lastModified() > 0) {
Expand All @@ -177,14 +179,22 @@ protected final String getNextSuffix() {
return nextSuffix;
}

/**
* Returns the file rotator for this handler.
*
* @return the file rotator
*/
SuffixRotator getSuffixRotator() {
return suffixRotator;
}

private void rollOver() {
try {
final File file = getFile();
// first, close the original file (some OSes won't let you move/rename a file that is open)
setFile(null);
// next, rotate it
final Path target = Paths.get(file.getAbsolutePath() + nextSuffix);
Files.move(file.toPath(), target, StandardCopyOption.REPLACE_EXISTING);
suffixRotator.rotate(file.toPath(), nextSuffix);
// start new file
setFile(file);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.logging.ErrorManager;

import org.jboss.logmanager.ExtLogRecord;
Expand Down Expand Up @@ -156,7 +152,11 @@ public void setFile(final File file) throws FileNotFoundException {
// Check for a rotate
if (rotateOnBoot && maxBackupIndex > 0 && file != null && file.exists() && file.length() > 0L) {
try {
rotate(file);
final String suffix = getNextSuffix();
final SuffixRotator suffixRotator = getSuffixRotator();
if (suffixRotator != SuffixRotator.EMPTY && suffix != null) {
suffixRotator.rotate(file.toPath(), suffix, maxBackupIndex);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -229,25 +229,12 @@ protected void preWrite(final ExtLogRecord record) {
}
// close the old file.
setFile(null);
rotate(file);
getSuffixRotator().rotate(file.toPath(), getNextSuffix(), maxBackupIndex);
// start with new file.
setFile(file);
} catch (IOException e) {
reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE);
}
}
}

private void rotate(final File file) throws IOException {
final Path fileWithSuffix = Paths.get(file.getAbsolutePath() + getNextSuffix());
Files.deleteIfExists(Paths.get(fileWithSuffix + "." + maxBackupIndex));
for (int i = maxBackupIndex - 1; i >= 1; i--) {
final Path src = Paths.get(fileWithSuffix + "." + i);
if (Files.exists(src)) {
final Path target = Paths.get(fileWithSuffix + "." + (i + 1));
Files.move(src, target, StandardCopyOption.REPLACE_EXISTING);
}
}
Files.move(file.toPath(), Paths.get(fileWithSuffix + ".1"), StandardCopyOption.REPLACE_EXISTING);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@
import java.io.FileNotFoundException;
import org.jboss.logmanager.ExtLogRecord;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.ErrorManager;

public class SizeRotatingFileHandler extends FileHandler {
Expand All @@ -39,7 +33,7 @@ public class SizeRotatingFileHandler extends FileHandler {
private int maxBackupIndex = 1;
private CountingOutputStream outputStream;
private boolean rotateOnBoot;
private String suffix;
private SuffixRotator suffixRotator = SuffixRotator.EMPTY;

/**
* Construct a new instance with no formatter and no output file.
Expand Down Expand Up @@ -146,7 +140,7 @@ public void setFile(final File file) throws FileNotFoundException {
// Check for a rotate
if (rotateOnBoot && maxBackupIndex > 0 && file != null && file.exists() && file.length() > 0L) {
try {
rotate(file);
suffixRotator.rotate(file.toPath(), maxBackupIndex);
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -211,15 +205,22 @@ public void setMaxBackupIndex(final int maxBackupIndex) {
* @return the suffix or {@code null} if no suffix should be used
*/
public String getSuffix() {
return suffix;
if (suffixRotator == SuffixRotator.EMPTY) {
return null;
}
return suffixRotator.toString();
}

/**
* Sets the suffix to be appended to the file name during the file rotation. The suffix does not play a role in
* determining when the file should be rotated.
* <p/>
* The suffix must be a string understood by the {@link java.text.SimpleDateFormat}.
* The suffix must be a string understood by the {@link java.text.SimpleDateFormat}. Optionally the suffix can end
* with {@code .gz} or {@code .zip} which will compress the file on rotation.
* <p/>
* <p>
* If the suffix ends with {@code .gz} or {@code .zip} the file will be compressed on rotation.
* </p>
* <b>Note:</b> Any files rotated with the suffix appended will not be deleted. The {@link #setMaxBackupIndex(int)
* maxBackupIndex} is not used for files with a suffix.
*
Expand All @@ -228,7 +229,7 @@ public String getSuffix() {
public void setSuffix(final String suffix) {
checkAccess(this);
synchronized (outputLock) {
this.suffix = suffix;
this.suffixRotator = SuffixRotator.parse(suffix);
}
}

Expand All @@ -245,44 +246,12 @@ protected void preWrite(final ExtLogRecord record) {
}
// close the old file.
setFile(null);
rotate(file);
suffixRotator.rotate(file.toPath(), maxBackupIndex);
// start with new file.
setFile(file);
} catch (IOException e) {
reportError("Unable to rotate log file", e, ErrorManager.OPEN_FAILURE);
}
}
}

private void rotate(final File file) throws IOException {
if (suffix == null) {
// rotate. First, drop the max file (if any), then move each file to the next higher slot.
Files.deleteIfExists(Paths.get(file.getAbsolutePath() + "." + maxBackupIndex));
for (int i = maxBackupIndex - 1; i >= 1; i--) {
final Path src = Paths.get(file.getAbsolutePath() + "." + i);
if (Files.exists(src)) {
final Path target = Paths.get(file.getAbsolutePath() + "." + (i + 1));
Files.move(src, target, StandardCopyOption.REPLACE_EXISTING);
}
}
Files.move(file.toPath(), Paths.get(file.getAbsolutePath() + ".1"), StandardCopyOption.REPLACE_EXISTING);
} else {
// This is not efficient, but performance risks were noted on the setSuffix() method
final String suffix = new SimpleDateFormat(this.suffix).format(new Date());
// Create the file name
final String newBaseFilename = file.getAbsolutePath() + suffix;

// rotate. First, drop the max file (if any), then move each file to the next higher slot.
Files.deleteIfExists(Paths.get(newBaseFilename + "." + maxBackupIndex));
for (int i = maxBackupIndex - 1; i >= 1; i--) {
final Path src = Paths.get(newBaseFilename + "." + i);
if (Files.exists(src)) {
final Path target = Paths.get(newBaseFilename + "." + (i + 1));
Files.move(src, target, StandardCopyOption.REPLACE_EXISTING);
}
}
// Rename the current file
Files.move(file.toPath(), Paths.get(newBaseFilename + ".1"), StandardCopyOption.REPLACE_EXISTING);
}
}
}