Repository: incubator-sentry Updated Branches: refs/heads/master 7e3f287ca -> 3be10df92
SENTRY-346: Create new FileAppender used in log4j to keep all the logs ( Colin Ma via Sravya Tirukkovalur) Project: http://git-wip-us.apache.org/repos/asf/incubator-sentry/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-sentry/commit/3be10df9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-sentry/tree/3be10df9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-sentry/diff/3be10df9 Branch: refs/heads/master Commit: 3be10df92c92e39e4d91ff2114f3f72783926e82 Parents: 7e3f287 Author: Sravya Tirukkovalur <[email protected]> Authored: Wed Aug 6 18:19:18 2014 -0700 Committer: Sravya Tirukkovalur <[email protected]> Committed: Wed Aug 6 18:19:18 2014 -0700 ---------------------------------------------------------------------- .../RollingFileWithoutDeleteAppender.java | 195 +++++++++++++++++++ .../TestRollingFileWithoutDeleteAppender.java | 83 ++++++++ 2 files changed, 278 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/3be10df9/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java new file mode 100644 index 0000000..edbd160 --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/log/appender/RollingFileWithoutDeleteAppender.java @@ -0,0 +1,195 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.sentry.provider.db.log.appender; + +import java.io.File; +import java.io.IOException; +import java.io.InterruptedIOException; +import java.io.Writer; + +import org.apache.log4j.FileAppender; +import org.apache.log4j.Layout; +import org.apache.log4j.helpers.CountingQuietWriter; +import org.apache.log4j.helpers.LogLog; +import org.apache.log4j.helpers.OptionConverter; +import org.apache.log4j.spi.LoggingEvent; + +public class RollingFileWithoutDeleteAppender extends FileAppender { + /** + * The default maximum file size is 10MB. + */ + protected long maxFileSize = 10 * 1024 * 1024; + + private long nextRollover = 0; + + /** + * The default constructor simply calls its {@link FileAppender#FileAppender + * parents constructor}. + */ + public RollingFileWithoutDeleteAppender() { + super(); + } + + /** + * Instantiate a RollingFileAppender and open the file designated by + * <code>filename</code>. The opened filename will become the ouput + * destination for this appender. + * <p> + * If the <code>append</code> parameter is true, the file will be appended to. + * Otherwise, the file desginated by <code>filename</code> will be truncated + * before being opened. + */ + public RollingFileWithoutDeleteAppender(Layout layout, String filename, + boolean append) throws IOException { + super(layout, filename, append); + } + + /** + * Instantiate a FileAppender and open the file designated by + * <code>filename</code>. The opened filename will become the output + * destination for this appender. + * <p> + * The file will be appended to. + */ + public RollingFileWithoutDeleteAppender(Layout layout, String filename) + throws IOException { + super(layout, filename); + } + + /** + * Get the maximum size that the output file is allowed to reach before being + * rolled over to backup files. + */ + public long getMaximumFileSize() { + return maxFileSize; + } + + /** + * Implements the usual roll over behaviour. + * <p> + * <code>File</code> is renamed <code>File.yyyyMMddHHmmss</code> and closed. A + * new <code>File</code> is created to receive further log output. + */ + // synchronization not necessary since doAppend is alreasy synched + public void rollOver() { + File target; + File file; + String suffix = Long.toString(System.currentTimeMillis()); + + if (qw != null) { + long size = ((CountingQuietWriter) qw).getCount(); + LogLog.debug("rolling over count=" + size); + // if operation fails, do not roll again until + // maxFileSize more bytes are written + nextRollover = size + maxFileSize; + } + + boolean renameSucceeded = true; + + // Rename fileName to fileName.yyyyMMddHHmmss + target = new File(fileName + "." + suffix); + + this.closeFile(); // keep windows happy. + + file = new File(fileName); + LogLog.debug("Renaming file " + file + " to " + target); + renameSucceeded = file.renameTo(target); + // + // if file rename failed, reopen file with append = true + // + if (!renameSucceeded) { + try { + this.setFile(fileName, true, bufferedIO, bufferSize); + } catch (IOException e) { + if (e instanceof InterruptedIOException) { + Thread.currentThread().interrupt(); + } + LogLog.error("setFile(" + fileName + ", true) call failed.", e); + } + } else { + try { + // This will also close the file. This is OK since multiple + // close operations are safe. + this.setFile(fileName, false, bufferedIO, bufferSize); + nextRollover = 0; + } catch (IOException e) { + if (e instanceof InterruptedIOException) { + Thread.currentThread().interrupt(); + } + LogLog.error("setFile(" + fileName + ", false) call failed.", e); + } + } + } + + public synchronized void setFile(String fileName, boolean append, + boolean bufferedIO, int bufferSize) throws IOException { + super.setFile(fileName, append, this.bufferedIO, this.bufferSize); + if (append) { + File f = new File(fileName); + ((CountingQuietWriter) qw).setCount(f.length()); + } + } + + /** + * Set the maximum size that the output file is allowed to reach before being + * rolled over to backup files. + * <p> + * This method is equivalent to {@link #setMaxFileSize} except that it is + * required for differentiating the setter taking a <code>long</code> argument + * from the setter taking a <code>String</code> argument by the JavaBeans + * {@link java.beans.Introspector Introspector}. + * + * @see #setMaxFileSize(String) + */ + public void setMaximumFileSize(long maxFileSize) { + this.maxFileSize = maxFileSize; + } + + /** + * Set the maximum size that the output file is allowed to reach before being + * rolled over to backup files. + * <p> + * In configuration files, the <b>MaxFileSize</b> option takes an long integer + * in the range 0 - 2^63. You can specify the value with the suffixes "KB", + * "MB" or "GB" so that the integer is interpreted being expressed + * respectively in kilobytes, megabytes or gigabytes. For example, the value + * "10KB" will be interpreted as 10240. + */ + public void setMaxFileSize(String value) { + maxFileSize = OptionConverter.toFileSize(value, maxFileSize + 1); + } + + protected void setQWForFiles(Writer writer) { + this.qw = new CountingQuietWriter(writer, errorHandler); + } + + /** + * This method differentiates RollingFileAppender from its super class. + */ + protected void subAppend(LoggingEvent event) { + super.subAppend(event); + + if (fileName != null && qw != null) { + long size = ((CountingQuietWriter) qw).getCount(); + if (size >= maxFileSize && size >= nextRollover) { + rollOver(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/3be10df9/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java ---------------------------------------------------------------------- diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java new file mode 100644 index 0000000..15393da --- /dev/null +++ b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/log/appender/TestRollingFileWithoutDeleteAppender.java @@ -0,0 +1,83 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.sentry.provider.db.log.appender; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.fail; + +import java.io.File; + +import junit.framework.ComparisonFailure; + +import org.apache.commons.io.FileUtils; +import org.apache.log4j.Logger; +import org.apache.log4j.PatternLayout; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.io.Files; + +public class TestRollingFileWithoutDeleteAppender { + private Logger sentryLogger = Logger.getRootLogger(); + private File dataDir; + + @Before + public void init() { + dataDir = Files.createTempDir(); + } + + @Test + public void testRollOver() throws Throwable { + if (dataDir == null) { + fail("Excepted temp folder for audit log is created."); + } + RollingFileWithoutDeleteAppender appender = new RollingFileWithoutDeleteAppender( + new PatternLayout("%m%n"), dataDir.getPath() + "/auditLog.log"); + appender.setMaximumFileSize(100); + sentryLogger.addAppender(appender); + // Write exactly 10 bytes with each log + for (int i = 0; i < 99; i++) { + if (i < 10) { + sentryLogger.debug("Hello---" + i); + } else if (i < 100) { + sentryLogger.debug("Hello--" + i); + } + } + + if (dataDir != null) { + File[] files = dataDir.listFiles(); + if (files != null) { + assertEquals(files.length, 10); + } else { + fail("Excepted 10 log files."); + } + } else { + fail("Excepted 10 log files."); + } + + } + + @After + public void destroy() { + if (dataDir != null) { + FileUtils.deleteQuietly(dataDir); + } + } +}
