Repository: tomee Updated Branches: refs/heads/tomee-1.7.x 8afa54e86 -> da4df975e
http://git-wip-us.apache.org/repos/asf/tomee/blob/da4df975/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/ArchivingTest.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/ArchivingTest.java b/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/ArchivingTest.java new file mode 100644 index 0000000..c022149 --- /dev/null +++ b/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/ArchivingTest.java @@ -0,0 +1,215 @@ +/* + * 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.tomee.jul.handler.rotating; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.zip.GZIPInputStream; +import java.util.zip.ZipInputStream; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@RunWith(Parameterized.class) +public class ArchivingTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable<Object[]> formats() { + return asList(new Object[] {"zip"}, new Object[] {"gzip"}); + } + + @Parameterized.Parameter(0) + public String format; + + @Test + public void logAndRotate() throws IOException, NoSuchMethodException { + clean("target/ArchivingTest-" + format + "/logs"); + + final AtomicReference<String> today = new AtomicReference<String>(); + final Map<String, String> config = new HashMap<String, String>(); + + // initial config + today.set("2015-09-01"); + config.put("filenamePattern", "target/ArchivingTest-" + format + "/logs/test.%s.%d.log"); + config.put("archiveDirectory", "target/ArchivingTest-" + format + "/logs/archives"); + config.put("archiveFormat", format); + config.put("archiveOlderThan", "1 s"); + config.put("limit", "10 kilobytes"); + config.put("level", "INFO"); + config.put("dateCheckInterval", "1 second"); + + final LocalFileHandler handler = new LocalFileHandler() { + @Override + protected String currentDate() { + return today.get(); + } + + @Override + protected String getProperty(final String name, final String defaultValue) { + final String s = config.get(name.substring(name.lastIndexOf('.') + 1)); + return s != null ? s : defaultValue; + } + }; + + final String string10chars = "abcdefghij"; + final int iterations = 950; + for (int i = 0; i < iterations; i++) { + handler.publish(new LogRecord(Level.INFO, string10chars)); + } + + today.set("2015-09-02"); + try { // ensure we test the date + Thread.sleep(1500); + } catch (final InterruptedException e) { + Thread.interrupted(); + } + handler.publish(new LogRecord(Level.INFO, string10chars)); // will trigger the archiving + handler.close(); + + final File logGzip = new File("target/ArchivingTest-" + format + "/logs/archives/test.2015-09-01.0.log." + format); + assertTrue(logGzip.getAbsolutePath(), logGzip.isFile()); + + if ("gzip".equals(format)) { + final GZIPInputStream gis = new GZIPInputStream(new FileInputStream("target/ArchivingTest-gzip/logs/archives/test.2015-09-01.0.log.gzip")); + final String content = IOUtils.toString(gis); + assertTrue(content.contains("INFO: abcdefghij\n")); + assertTrue(content.length() > 10000); + gis.close(); + } else { + final ZipInputStream zis = new ZipInputStream(new FileInputStream("target/ArchivingTest-zip/logs/archives/test.2015-09-01.0.log.zip")); + assertEquals("test.2015-09-01.0.log", zis.getNextEntry().getName()); + final String content = IOUtils.toString(zis); + assertTrue(content.contains("INFO: abcdefghij\n")); + assertTrue(content.length() > 10000); + assertNull(zis.getNextEntry()); + zis.close(); + } + } + + @Test + public void logAndRotateAndPurge() throws IOException, NoSuchMethodException { + clean("target/ArchivingTestPurge-" + format + "/logs"); + + final AtomicReference<String> today = new AtomicReference<String>(); + final Map<String, String> config = new HashMap<String, String>(); + + // initial config + today.set("2015-09-01"); + config.put("filenamePattern", "target/ArchivingTestPurge-" + format + "/logs/test.%s.%d.log"); + config.put("archiveDirectory", "target/ArchivingTestPurge-" + format + "/logs/archives"); + config.put("archiveFormat", format); + config.put("archiveOlderThan", "1 s"); + config.put("purgeOlderThan", "2 s"); + config.put("limit", "10 kilobytes"); + config.put("level", "INFO"); + config.put("dateCheckInterval", "1 second"); + + final LocalFileHandler handler = new LocalFileHandler() { + @Override + protected String currentDate() { + return today.get(); + } + + @Override + protected String getProperty(final String name, final String defaultValue) { + final String s = config.get(name.substring(name.lastIndexOf('.') + 1)); + return s != null ? s : defaultValue; + } + }; + + final String string10chars = "abcdefghij"; + final int iterations = 950; + for (int i = 0; i < iterations; i++) { + handler.publish(new LogRecord(Level.INFO, string10chars)); + } + + final File logArchive = new File("target/ArchivingTestPurge-" + format + "/logs/archives/test.2015-09-01.0.log." + format); + + today.set("2015-09-02"); + try { + Thread.sleep(1500); + } catch (final InterruptedException e) { + Thread.interrupted(); + } + handler.publish(new LogRecord(Level.INFO, string10chars)); // will trigger the archiving + for (int i = 0; i < 120; i++) { // async so retry + if (logArchive.exists()) { + break; + } + try { + Thread.sleep(250); + } catch (final InterruptedException e) { + Thread.interrupted(); + } + } + assertTrue(logArchive.getAbsolutePath() + " was archived", logArchive.exists()); + + today.set("2015-09-03"); + try { + Thread.sleep(2500); + } catch (final InterruptedException e) { + Thread.interrupted(); + } + handler.publish(new LogRecord(Level.INFO, string10chars)); // will trigger the purging + handler.close(); + + assertFalse(logArchive.getAbsolutePath() + " was purged", logArchive.exists()); + } + + private static void clean(final String base) { + { + final File out = new File(base); + if (out.exists()) { + for (final File file : asList(out.listFiles(new FileFilter() { + @Override + public boolean accept(final File pathname) { + return pathname.getName().startsWith("test"); + } + }))) { + file.delete(); + } + } + } + { + final File out = new File(base + "/archives"); + if (out.exists()) { + for (final File file : asList(out.listFiles(new FileFilter() { + @Override + public boolean accept(final File pathname) { + return pathname.getName().startsWith("test"); + } + }))) { + file.delete(); + } + } + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/da4df975/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/LocalFileHandlerTest.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/LocalFileHandlerTest.java b/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/LocalFileHandlerTest.java new file mode 100644 index 0000000..6279b11 --- /dev/null +++ b/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/LocalFileHandlerTest.java @@ -0,0 +1,128 @@ +/* + * 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.tomee.jul.handler.rotating; + +import org.apache.commons.io.IOUtils; +import org.junit.Test; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +import static java.lang.System.lineSeparator; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class LocalFileHandlerTest { + @Test + public void logAndRotate() throws IOException { + final File out = new File("target/LocalFileHandlerTest/logs/"); + if (out.exists()) { + for (final File file : asList(out.listFiles(new FileFilter() { + @Override + public boolean accept(final File pathname) { + return pathname.getName().startsWith("test"); + } + }))) { + file.delete(); + } + } + + final AtomicReference<String> today = new AtomicReference<String>(); + final Map<String, String> config = new HashMap<String, String>(); + + // initial config + today.set("day1"); + config.put("filenamePattern", "target/LocalFileHandlerTest/logs/test.%s.%d.log"); + config.put("limit", "10 kilobytes"); + config.put("level", "INFO"); + config.put("dateCheckInterval", "1 second"); + config.put("formatter", MessageOnlyFormatter.class.getName()); + + final LocalFileHandler handler = new LocalFileHandler() { + @Override + protected String currentDate() { + return today.get(); + } + + @Override + protected String getProperty(final String name, final String defaultValue) { + final String s = config.get(name.substring(name.lastIndexOf('.') + 1)); + return s != null ? s : defaultValue; + } + }; + + final String string10chars = "abcdefghij"; + final int iterations = 950; + for (int i = 0; i < iterations; i++) { + handler.publish(new LogRecord(Level.INFO, string10chars)); + } + + final File[] logFiles = out.listFiles(new FileFilter() { + @Override + public boolean accept(final File pathname) { + return pathname.getName().startsWith("test"); + } + }); + final Set<String> logFilesNames = new HashSet<String>(); + for (final File f : logFiles) { + logFilesNames.add(f.getName()); + } + assertEquals(2, logFiles.length); + assertEquals(new HashSet<String>(asList("test.day1.0.log", "test.day1.1.log")), logFilesNames); + + final InputStream is = new FileInputStream(new File(out, "test.day1.1.log")); + final List<String> lines = IOUtils.readLines(is); + assertEquals(19, lines.size()); + assertEquals(string10chars, lines.iterator().next()); + is.close(); + + final long firstFileLen = new File(out, "test.day1.0.log").length(); + assertTrue(firstFileLen >= 1024 * 10 && firstFileLen < 1024 * 10 + (1 + string10chars.getBytes().length)); + + // now change of day + today.set("day2"); + try { // ensure we tets the date + Thread.sleep(1500); + } catch (final InterruptedException e) { + Thread.interrupted(); + } + handler.publish(new LogRecord(Level.INFO, string10chars)); + assertTrue(new File(out, "test.day2.0.log").exists()); + + handler.close(); + } + + public static class MessageOnlyFormatter extends Formatter { + @Override + public String format(final LogRecord record) { + return record.getMessage() + lineSeparator(); + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/da4df975/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/PerfRunner.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/PerfRunner.java b/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/PerfRunner.java new file mode 100644 index 0000000..8094e9c --- /dev/null +++ b/tomee/tomee-juli/src/test/java/org/apache/tomee/jul/handler/rotating/PerfRunner.java @@ -0,0 +1,109 @@ +package org.apache.tomee.jul.handler.rotating; + +import org.apache.juli.OneLineFormatter; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Handler; +import java.util.logging.Logger; + +/* +#1 thread +Benchmark Mode Cnt Score Error Units +PerfRunner.bufferizedLogger thrpt 5 70875.992 ± 14974.425 ops/s +PerfRunner.defaultLogger thrpt 5 54832.426 ± 11709.029 ops/s + +#30 threads +Benchmark Mode Cnt Score Error Units +PerfRunner.bufferizedLogger thrpt 5 123684.947 ± 103294.959 ops/s +PerfRunner.defaultLogger thrpt 5 62014.127 ± 36682.710 ops/s + */ +@State(Scope.Benchmark) +public class PerfRunner { + private Logger defaultLogger; + private Logger bufferizedLogger; + + @Setup + public void setup() { + { + defaultLogger = Logger.getLogger("perf.logger.default"); + cleanHandlers(defaultLogger); + + final Map<String, String> config = new HashMap<String, String>(); + + // initial config + config.put("filenamePattern", "target/PerfRunner/logs/performance.default.%s.%02d.log"); + config.put("limit", "10 Mega"); + config.put("formatter", OneLineFormatter.class.getName()); + defaultLogger.addHandler(new LocalFileHandler() { + @Override + protected String getProperty(final String name, final String defaultValue) { + final String key = name.substring(name.lastIndexOf('.') + 1); + return config.containsKey(key) ? config.get(key) : defaultValue; + } + }); + } + { + bufferizedLogger = Logger.getLogger("perf.logger.buffer"); + cleanHandlers(bufferizedLogger); + + final Map<String, String> config = new HashMap<String, String>(); + + // initial config + config.put("filenamePattern", "target/PerfRunner/logs/performance.buffer.%s.%02d.log"); + config.put("limit", "10 Mega"); + config.put("bufferSize", "1 Mega"); + config.put("formatter", OneLineFormatter.class.getName()); + bufferizedLogger.addHandler(new LocalFileHandler() { + @Override + protected String getProperty(final String name, final String defaultValue) { + final String key = name.substring(name.lastIndexOf('.') + 1); + return config.containsKey(key) ? config.get(key) : defaultValue; + } + }); + } + } + + @TearDown + public void tearDown() { + defaultLogger.getHandlers()[0].close(); + bufferizedLogger.getHandlers()[0].close(); + } + + private void cleanHandlers(final Logger logger) { + for (final Handler h : logger.getHandlers()) { + logger.removeHandler(h); + } + logger.setUseParentHandlers(false); + } + + @Benchmark + public void defaultLogger() { + defaultLogger.info("something happens here and nowhere else so i need to write it down"); + } + + + @Benchmark + public void bufferizedLogger() { + bufferizedLogger.info("something happens here and nowhere else so i need to write it down"); + } + + public static void main(final String[] args) throws RunnerException { + new Runner(new OptionsBuilder() + .include(PerfRunner.class.getSimpleName()) + .forks(0) + .warmupIterations(5) + .measurementIterations(5) + .threads(1) + .build()) + .run(); + } +}