[ASTERIXDB-1564][CONF] Replace Remaining Usage of JUL

- user model changes: no
- storage format changes: no
- interface changes: no

Details:
- Replace remaining usage of java.util.logging
  by Log4j2.

Change-Id: I894348b09a862693ae31de7c2f4768877a5297db
Reviewed-on: https://asterix-gerrit.ics.uci.edu/2254
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Contrib: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Michael Blow <mblow@apache.org>
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/IoUtil.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/IoUtil.java
index 329b24d..396c026 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/IoUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/util/IoUtil.java
@@ -23,13 +23,13 @@
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.hyracks.api.exceptions.ErrorCode;
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.io.FileReference;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * This util class takes care of creation and deletion of files and directories
@@ -38,7 +38,7 @@
 public class IoUtil {
 
     public static final String FILE_NOT_FOUND_MSG = "Deleting non-existing file!";
-    private static final Logger LOGGER = Logger.getLogger(IoUtil.class.getName());
+    private static final Logger LOGGER = LogManager.getLogger();
 
     private IoUtil() {
     }
@@ -71,7 +71,7 @@
                 Files.delete(file.toPath());
             }
         } catch (NoSuchFileException | FileNotFoundException e) {
-            LOGGER.log(Level.WARNING, FILE_NOT_FOUND_MSG + ": " + e.getMessage(), e);
+            LOGGER.warn(() -> FILE_NOT_FOUND_MSG + ": " + e.getMessage(), e);
         } catch (IOException e) {
             throw HyracksDataException.create(ErrorCode.CANNOT_DELETE_FILE, e, file.getAbsolutePath());
         }
diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/pom.xml b/hyracks-fullstack/hyracks/hyracks-test-support/pom.xml
index 6559308..fde7394 100644
--- a/hyracks-fullstack/hyracks/hyracks-test-support/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-test-support/pom.xml
@@ -108,5 +108,9 @@
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
   </dependencies>
 </project>
diff --git a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexLifecycleTest.java b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexLifecycleTest.java
index 8fc4275..ddb5717 100644
--- a/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexLifecycleTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-test-support/src/main/java/org/apache/hyracks/storage/am/common/AbstractIndexLifecycleTest.java
@@ -18,16 +18,13 @@
  */
 package org.apache.hyracks.storage.am.common;
 
-import java.nio.file.NoSuchFileException;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-
 import org.apache.hyracks.api.exceptions.HyracksDataException;
 import org.apache.hyracks.api.util.IoUtil;
 import org.apache.hyracks.storage.common.IIndex;
-import org.apache.hyracks.util.RuntimeLogsMonitor;
+import org.apache.hyracks.util.Log4j2Monitor;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.Configurator;
 import org.junit.After;
-import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -49,12 +46,8 @@
 
     @BeforeClass
     public static void startLogsMonitor() {
-        RuntimeLogsMonitor.monitor("org.apache.hyracks");
-    }
-
-    @AfterClass
-    public static void afterClass() {
-        RuntimeLogsMonitor.stop();
+        Configurator.setLevel("org.apache.hyracks", Level.INFO);
+        Log4j2Monitor.start();
     }
 
     @Before
@@ -65,7 +58,7 @@
 
     @Test
     public void validSequenceTest() throws Exception {
-        RuntimeLogsMonitor.reset();
+        Log4j2Monitor.reset();
         // Double create is invalid
         index.create();
         Assert.assertTrue(persistentStateExists());
@@ -104,8 +97,7 @@
         index.destroy();
         Assert.assertFalse(persistentStateExists());
         index.destroy();
-        final LogRecord fileNotFoundWarnLog = new LogRecord(Level.WARNING, IoUtil.FILE_NOT_FOUND_MSG);
-        Assert.assertTrue(RuntimeLogsMonitor.count(fileNotFoundWarnLog) > 0);
+        Assert.assertTrue(Log4j2Monitor.count(IoUtil.FILE_NOT_FOUND_MSG) > 0);
         Assert.assertFalse(persistentStateExists());
     }
 
diff --git a/hyracks-fullstack/hyracks/hyracks-util/pom.xml b/hyracks-fullstack/hyracks/hyracks-util/pom.xml
index 52ccf2f..c521f08 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-util/pom.xml
@@ -75,6 +75,10 @@
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-core</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/Log4j2Monitor.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/Log4j2Monitor.java
new file mode 100644
index 0000000..34751b8
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/Log4j2Monitor.java
@@ -0,0 +1,84 @@
+/*
+ * 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.hyracks.util;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.CharBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.appender.WriterAppender;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.LoggerConfig;
+
+public class Log4j2Monitor {
+
+    private static final List<String> logs = new ArrayList<>();
+
+    private Log4j2Monitor() {
+    }
+
+    public static void start() {
+        final LoggerContext context = LoggerContext.getContext(false);
+        final Appender appender = WriterAppender.createAppender(null, null, new LogWriter(), "MEMORY", false, true);
+        appender.start();
+        final Configuration config = context.getConfiguration();
+        config.addAppender(appender);
+        for (final LoggerConfig loggerConfig : config.getLoggers().values()) {
+            loggerConfig.addAppender(appender, null, null);
+        }
+        config.getRootLogger().addAppender(appender, Level.ALL, null);
+        context.updateLoggers();
+    }
+
+    public static long count(String message) {
+        return logs.stream().filter(log -> log.contains(message)).count();
+    }
+
+    public static void reset() {
+        logs.clear();
+    }
+
+    public static List<String> getLogs() {
+        return logs;
+    }
+
+    private static class LogWriter extends Writer {
+
+        @Override
+        public void write(char[] buffer, int off, int len) {
+            logs.add(CharBuffer.wrap(buffer, off, len).toString());
+        }
+
+        @Override
+        public void flush() {
+            // no op
+        }
+
+        @Override
+        public void close() throws IOException {
+            // no op
+        }
+    }
+}
\ No newline at end of file
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/RuntimeLogsMonitor.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/RuntimeLogsMonitor.java
deleted file mode 100644
index d2eb7fd..0000000
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/RuntimeLogsMonitor.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.hyracks.util;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Logger;
-
-/**
- * RuntimeLogsMonitor is used to store the generated runtime logs in-memory
- * and provides API to search the stored logs.
- */
-public class RuntimeLogsMonitor {
-
-    private static final InMemoryHandler IN_MEMORY_HANDLER = new InMemoryHandler();
-    private static final List<Logger> MONITORED_LOGGERS = new ArrayList<>();
-    private static List<LogRecord> logs;
-
-    private RuntimeLogsMonitor() {
-        reset();
-    }
-
-    /**
-     * Starts monitoring the logger by storing its generated logs in-memory. By default
-     * only logs with level WARNING and above are stored
-     *
-     * @param loggerName
-     */
-    public static void monitor(String loggerName) {
-        final Logger logger = Logger.getLogger(loggerName);
-        for (Handler handler : logger.getHandlers()) {
-            if (handler == IN_MEMORY_HANDLER) {
-                return;
-            }
-        }
-        MONITORED_LOGGERS.add(logger);
-        Logger.getLogger(loggerName).addHandler(IN_MEMORY_HANDLER);
-    }
-
-    /**
-     * Discards any stored logs
-     */
-    public static void reset() {
-        logs = new ArrayList<>();
-    }
-
-    /**
-     * Calculates the count based on {@code logRecord} level and message.
-     * if any stored log has the same level as {@code logRecord} and
-     * the log's message contains {@code logRecord} message, it is considered
-     * as an occurrence
-     *
-     * @param logRecord
-     * @return The number of found logs that match {@code logRecord}
-     */
-    public static long count(LogRecord logRecord) {
-        return logs.stream()
-                .filter(storedLog -> storedLog.getLevel().equals(logRecord.getLevel()) && storedLog.getMessage()
-                        .contains(logRecord.getMessage())).count();
-    }
-
-    /**
-     * Sets the stored logs minimum level
-     *
-     * @param lvl
-     */
-    public static void setLevel(Level lvl) {
-        IN_MEMORY_HANDLER.setLevel(lvl);
-    }
-
-    /**
-     * Stops monitoring any monitored loggers and discards any
-     * stored logs
-     */
-    public static void stop() {
-        for (Logger logger : MONITORED_LOGGERS) {
-            logger.removeHandler(IN_MEMORY_HANDLER);
-        }
-        reset();
-        MONITORED_LOGGERS.clear();
-    }
-
-    private static class InMemoryHandler extends Handler {
-        private InMemoryHandler() {
-            super.setLevel(Level.WARNING);
-            setFilter(record -> record.getLevel().intValue() >= getLevel().intValue());
-        }
-
-        @Override
-        public void publish(LogRecord lr) {
-            if (isLoggable(lr)) {
-                logs.add(lr);
-            }
-        }
-
-        @Override
-        public void flush() {
-            // nothing to flush
-        }
-
-        @Override
-        public void close() {
-            // nothing to close
-        }
-    }
-}
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/trace/Tracer.java b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/trace/Tracer.java
index 4c6f234..79922b7 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/trace/Tracer.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/main/java/org/apache/hyracks/util/trace/Tracer.java
@@ -23,17 +23,18 @@
 import java.text.SimpleDateFormat;
 import java.util.Arrays;
 import java.util.Date;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 import org.apache.hyracks.util.PidHelper;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit
  */
 public class Tracer implements ITracer {
 
-    public static final Logger LOGGER = Logger.getLogger(Tracer.class.getName());
+    public static final Logger LOGGER = LogManager.getLogger();
 
     protected static final Level TRACE_LOG_LEVEL = Level.INFO;
     protected static final String CAT = "Tracer";
@@ -48,7 +49,7 @@
     public Tracer(String name, long categories, TraceCategoryRegistry registry) {
         final String traceLoggerName = Tracer.class.getName() + "@" + name;
         LOGGER.info("Initialize Tracer " + traceLoggerName);
-        this.traceLog = Logger.getLogger(traceLoggerName);
+        this.traceLog = LogManager.getLogger(traceLoggerName);
         this.categories = categories;
         this.registry = registry;
         final long traceCategory = getRegistry().get(CAT);
diff --git a/hyracks-fullstack/hyracks/hyracks-util/src/test/java/org/apache/hyracks/util/trace/TraceTest.java b/hyracks-fullstack/hyracks/hyracks-util/src/test/java/org/apache/hyracks/util/trace/TraceTest.java
index a6ed4c8..f842f3e 100644
--- a/hyracks-fullstack/hyracks/hyracks-util/src/test/java/org/apache/hyracks/util/trace/TraceTest.java
+++ b/hyracks-fullstack/hyracks/hyracks-util/src/test/java/org/apache/hyracks/util/trace/TraceTest.java
@@ -18,14 +18,10 @@
  */
 package org.apache.hyracks.util.trace;
 
-import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.io.OutputStream;
-import java.util.logging.Formatter;
-import java.util.logging.LogRecord;
-import java.util.logging.Logger;
-import java.util.logging.StreamHandler;
+import java.util.List;
 
+import org.apache.hyracks.util.Log4j2Monitor;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -37,18 +33,6 @@
     private final ObjectMapper mapper = new ObjectMapper();
     private final String name = "test";
 
-    private StreamHandler redirectTraceLog(OutputStream os) throws IOException {
-        final Logger logger = Logger.getLogger(Tracer.class.getName() + "@" + name);
-        final StreamHandler handler = new StreamHandler(os, new Formatter() {
-            @Override
-            public String format(LogRecord record) {
-                return record.getMessage() + "\n";
-            }
-        });
-        logger.addHandler(handler);
-        return handler;
-    }
-
     public JsonNode validate(String line) throws IOException {
         final JsonNode traceRecord = mapper.readTree(line);
 
@@ -68,9 +52,6 @@
 
     @Test
     public void testInstant() throws IOException {
-        final ByteArrayOutputStream os = new ByteArrayOutputStream();
-        final StreamHandler handler = redirectTraceLog(os);
-
         // test with initial categories
 
         TraceCategoryRegistry registry = new TraceCategoryRegistry();
@@ -79,13 +60,12 @@
         long cat3 = registry.get("CAT3");
 
         ITracer tracer = new Tracer(name, new String[] { "CAT1", "CAT2" }, registry);
+        Log4j2Monitor.start();
         tracer.instant("test1", cat1, ITracer.Scope.p, null);
         tracer.instant("test2", cat2, ITracer.Scope.p, null);
         tracer.instant("test3", cat3, ITracer.Scope.p, null);
 
-        handler.flush();
-
-        String[] lines = os.toString().split("\n");
+        List<String> lines = Log4j2Monitor.getLogs();
         for (String line : lines) {
             final JsonNode traceRecord = validate(line);
             Assert.assertEquals("i", traceRecord.get("ph").asText());
@@ -93,17 +73,14 @@
         }
 
         // test with modified categories
-
         tracer.setCategories("CAT1", "CAT3");
-        os.reset();
+        Log4j2Monitor.reset();
 
         tracer.instant("test1", cat1, ITracer.Scope.p, null);
         tracer.instant("test2", cat2, ITracer.Scope.p, null);
         tracer.instant("test3", cat3, ITracer.Scope.p, null);
 
-        handler.flush();
-
-        lines = os.toString().split("\n");
+        lines = Log4j2Monitor.getLogs();
         for (String line : lines) {
             final JsonNode traceRecord = validate(line);
             Assert.assertEquals("i", traceRecord.get("ph").asText());