IGNITE-15211 Improve logging formatting (#266)

diff --git a/config/java.util.logging.properties b/config/java.util.logging.properties
new file mode 100644
index 0000000..17d6827
--- /dev/null
+++ b/config/java.util.logging.properties
@@ -0,0 +1,57 @@
+#
+# 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.
+#
+
+#########################################################################
+#       Default java.util.logging configuration for Ignite.
+#
+# To use another config file use `java.util.logging.config.file` system
+# property. For example `java -Djava.util.logging.config.file=myfile`
+#########################################################################
+
+#
+# Comma-separated list of logging "handlers". Note that some of them may be
+# reconfigured (or even removed) at runtime according to system properties.
+#
+# By default all messages will be passed to console and file.
+#
+handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler
+
+#
+# Default global logging level.
+# This specifies which kinds of events are logged across all loggers.
+# For any given category this global level can be overriden by a category
+# specific level.
+# Note that handlers also have a separate level setting to limit messages
+# printed through it.
+#
+.level=INFO
+
+# Console handler logs all messages with importance level `INFO` and above
+# into standard error stream (`System.err`).
+#
+java.util.logging.ConsoleHandler.formatter = org.apache.ignite.lang.JavaLoggerFormatter
+java.util.logging.ConsoleHandler.level = INFO
+
+#
+# File handler logs all messages into files with pattern `ignite-%g.log`
+# under `target` directory.
+#
+java.util.logging.FileHandler.formatter = org.apache.ignite.lang.JavaLoggerFormatter
+java.util.logging.FileHandler.pattern = target/ignite-%g.log
+java.util.logging.FileHandler.level = INFO
+java.util.logging.FileHandler.limit = 10485760
+java.util.logging.FileHandler.count = 10
diff --git a/modules/calcite/pom.xml b/modules/calcite/pom.xml
index 9362b1c..b124acf 100644
--- a/modules/calcite/pom.xml
+++ b/modules/calcite/pom.xml
@@ -158,6 +158,12 @@
             <scope>test</scope>
         </dependency>
 
+        <!-- Logging in tests -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/JavaLoggerFormatter.java b/modules/core/src/main/java/org/apache/ignite/lang/JavaLoggerFormatter.java
new file mode 100644
index 0000000..ffd2c9b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/lang/JavaLoggerFormatter.java
@@ -0,0 +1,146 @@
+/*
+ * 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.ignite.lang;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.logging.Formatter;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import org.apache.ignite.internal.tostring.S;
+
+/**
+ * Formatter for JUL logger.
+ */
+public class JavaLoggerFormatter extends Formatter {
+    /** See {@link Level#OFF}. */
+    private static final int SEVERITY_OFF = Integer.MAX_VALUE;
+
+    /** See {@link Level#SEVERE}. */
+    private static final int SEVERITY_SEVERE = 1000;
+
+    /** See {@link Level#WARNING}. */
+    private static final int SEVERITY_WARNING = 900;
+
+    /** See {@link Level#INFO}. */
+    private static final int SEVERITY_INFO = 800;
+
+    /** See {@link Level#CONFIG}. */
+    private static final int SEVERITY_CONFIG = 700;
+
+    /** See {@link Level#FINE}. */
+    private static final int SEVERITY_FINE = 500;
+
+    /** See {@link Level#FINER}. */
+    private static final int SEVERITY_FINER = 400;
+
+    /** See {@link Level#ALL}. */
+    private static final int SEVERITY_ALL = Integer.MIN_VALUE;
+
+    /** Ascending order for binary search matching the list of severity constants. */
+    private static final int[] LEVEL_VALUES = new int[] {
+        SEVERITY_ALL, SEVERITY_FINER,
+        SEVERITY_FINE, SEVERITY_CONFIG, SEVERITY_INFO,
+        SEVERITY_WARNING, SEVERITY_SEVERE, SEVERITY_OFF
+    };
+
+    /** Name for anonymous loggers. */
+    public static final String ANONYMOUS_LOGGER_NAME = "UNKNOWN";
+
+    /** Date formatter. */
+    private static final ThreadLocal<DateTimeFormatter> DATE_FORMATTER = new ThreadLocal<>() {
+        /** {@inheritDoc} */
+        @Override protected DateTimeFormatter initialValue() {
+            return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS Z");
+        }
+    };
+
+    /** {@inheritDoc} */
+    @Override public String format(LogRecord record) {
+        String threadName = Thread.currentThread().getName();
+
+        String logName = record.getLoggerName();
+
+        if (logName == null)
+            logName = ANONYMOUS_LOGGER_NAME;
+        else if (logName.contains("."))
+            logName = logName.substring(logName.lastIndexOf('.') + 1);
+
+        String ex = null;
+
+        if (record.getThrown() != null) {
+            StringWriter sw = new StringWriter();
+
+            record.getThrown().printStackTrace(new PrintWriter(sw));
+
+            String stackTrace = sw.toString();
+
+            ex = "\n" + stackTrace;
+        }
+
+        return DATE_FORMATTER.get().format(Instant.ofEpochMilli(record.getMillis()).atZone(ZoneId.systemDefault())) +
+            " [" + toLevel(record.getLevel().intValue()) + "][" +
+            threadName + "][" +
+            logName + "] " +
+            formatMessage(record) +
+            (ex == null ? "\n" : ex);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(JavaLoggerFormatter.class, this);
+    }
+
+    /**
+     * Convert {@linkplain java.util.logging.Level  java.util.logging levels} to {@linkplain System.Logger.Level System
+     * logger levels}.
+     *
+     * @param severity Severity
+     * @return {@link System.Logger.Level} according to {@link java.util.logging.Level} int value.
+     * @see System.Logger.Level
+     */
+    private System.Logger.Level toLevel(int severity) {
+        switch (severity) {
+            case SEVERITY_ALL:
+                return System.Logger.Level.ALL;
+            case SEVERITY_FINER:
+                return System.Logger.Level.TRACE;
+            case SEVERITY_FINE:
+            case SEVERITY_CONFIG:
+                return System.Logger.Level.DEBUG;
+            case SEVERITY_INFO:
+                return System.Logger.Level.INFO;
+            case SEVERITY_WARNING:
+                return System.Logger.Level.WARNING;
+            case SEVERITY_SEVERE:
+                return System.Logger.Level.ERROR;
+            case SEVERITY_OFF:
+                return System.Logger.Level.OFF;
+        }
+
+        // return the nearest Level value >= the given level,
+        // for level > SEVERE, return SEVERE and exclude OFF
+        int i = Arrays.binarySearch(LEVEL_VALUES, 0, LEVEL_VALUES.length - 2, severity);
+
+        return toLevel(i);
+    }
+}
diff --git a/modules/network/pom.xml b/modules/network/pom.xml
index 4b30376..663d747 100644
--- a/modules/network/pom.xml
+++ b/modules/network/pom.xml
@@ -101,6 +101,13 @@
             <artifactId>mockito-core</artifactId>
             <scope>test</scope>
         </dependency>
+
+        <!-- Logging in tests -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     
     <build>
diff --git a/modules/network/src/test/resources/simplelogger.properties b/modules/network/src/test/resources/simplelogger.properties
deleted file mode 100644
index 7488d79..0000000
--- a/modules/network/src/test/resources/simplelogger.properties
+++ /dev/null
@@ -1,52 +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.
-#
-# SLF4J's SimpleLogger configuration file
-# Simple implementation of Logger that sends all enabled log messages, for all defined loggers, to System.err.
-
-# Default logging detail level for all instances of SimpleLogger.
-# Must be one of ("trace", "debug", "info", "warn", or "error").
-# If not specified, defaults to "info".
-org.slf4j.simpleLogger.defaultLogLevel=info
-
-# Logging detail level for a SimpleLogger instance named "xxxxx".
-# Must be one of ("trace", "debug", "info", "warn", or "error").
-# If not specified, the default logging detail level is used.
-#org.slf4j.simpleLogger.log.xxxxx=
-#org.slf4j.simpleLogger.log.io.scalecube.cluster.metadata.MetadataStore=debug
-#org.slf4j.simpleLogger.log.io.scalecube.cluster.membership.MembershipProtocol=debug
-
-# Set to true if you want the current date and time to be included in output messages.
-# Default is false, and will output the number of milliseconds elapsed since startup.
-org.slf4j.simpleLogger.showDateTime=true
-
-# The date and time format to be used in the output messages.
-# The pattern describing the date and time format is the same that is used in java.text.SimpleDateFormat.
-# If the format is not specified or is invalid, the default format is used.
-# The default format is yyyy-MM-dd HH:mm:ss:SSS Z.
-org.slf4j.simpleLogger.dateTimeFormat=yyyy-MM-dd HH:mm:ss:SSS Z
-
-# Set to true if you want to output the current thread name.
-# Defaults to true.
-#org.slf4j.simpleLogger.showThreadName=true
-
-# Set to true if you want the Logger instance name to be included in output messages.
-# Defaults to true.
-#org.slf4j.simpleLogger.showLogName=true
-
-# Set to true if you want the last component of the name to be included in output messages.
-# Defaults to false.
-org.slf4j.simpleLogger.showShortLogName=true
diff --git a/modules/raft/pom.xml b/modules/raft/pom.xml
index be83f84..65bdfa0 100644
--- a/modules/raft/pom.xml
+++ b/modules/raft/pom.xml
@@ -122,6 +122,13 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+
+        <!-- Logging in tests -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/disruptor/StripedDisruptor.java b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/disruptor/StripedDisruptor.java
index 40f99e8..f23ec49 100644
--- a/modules/raft/src/main/java/org/apache/ignite/raft/jraft/disruptor/StripedDisruptor.java
+++ b/modules/raft/src/main/java/org/apache/ignite/raft/jraft/disruptor/StripedDisruptor.java
@@ -26,9 +26,8 @@
 import java.util.ArrayList;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.BiConsumer;
+import org.apache.ignite.lang.IgniteLogger;
 import org.apache.ignite.raft.jraft.util.NamedThreadFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import static org.apache.ignite.lang.LoggerMessageHelper.format;
 
@@ -40,7 +39,7 @@
  */
 public class StripedDisruptor<T extends GroupAware> {
     /** The logger. */
-    private static final Logger LOG = LoggerFactory.getLogger(StripedDisruptor.class);
+    private static final IgniteLogger LOG = IgniteLogger.forClass(StripedDisruptor.class);
 
     /** Array of disruptors. Each Disruptor in the appropriate stripe. */
     private final Disruptor<T>[] disruptors;
diff --git a/modules/rest/pom.xml b/modules/rest/pom.xml
index 659efb0..604583b 100644
--- a/modules/rest/pom.xml
+++ b/modules/rest/pom.xml
@@ -92,6 +92,13 @@
             <artifactId>junit-jupiter-engine</artifactId>
             <scope>test</scope>
         </dependency>
+
+        <!-- Logging in tests -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
diff --git a/modules/runner/pom.xml b/modules/runner/pom.xml
index 7a7f89d..89175bd 100644
--- a/modules/runner/pom.xml
+++ b/modules/runner/pom.xml
@@ -92,7 +92,7 @@
         <!-- 3rd party dependencies -->
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
+            <artifactId>slf4j-jdk14</artifactId>
         </dependency>
 
         <!-- Test dependencies -->
diff --git a/modules/runner/src/main/resources/simplelogger.properties b/modules/runner/src/main/resources/simplelogger.properties
deleted file mode 100644
index 77a2ff2..0000000
--- a/modules/runner/src/main/resources/simplelogger.properties
+++ /dev/null
@@ -1,19 +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.
-#
-
-org.slf4j.simpleLogger.defaultLogLevel=off
-org.slf4j.simpleLogger.log.org.apache.ignite.app.IgniteRunner=info
diff --git a/parent/pom.xml b/parent/pom.xml
index 114f934..01fae41 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -85,6 +85,7 @@
         <metrics.version>4.0.2</metrics.version>
         <jctools.version>3.3.0</jctools.version>
         <msgpack.version>0.8.21</msgpack.version>
+        <slf4j.jdk14.version>1.7.32</slf4j.jdk14.version>
 
         <!-- Plugins versions -->
         <apache.rat.plugin.version>0.13</apache.rat.plugin.version>
@@ -628,6 +629,12 @@
                 <artifactId>jctools-core</artifactId>
                 <version>${jctools.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-jdk14</artifactId>
+                <version>${slf4j.jdk14.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
@@ -949,6 +956,7 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
+                    <argLine>-Djava.util.logging.config.file=../../config/java.util.logging.properties</argLine>
                     <excludes>
                         <exclude>**/IT*.java</exclude>
                     </excludes>
@@ -962,6 +970,7 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-failsafe-plugin</artifactId>
                 <configuration>
+                    <argLine>-Djava.util.logging.config.file=../../config/java.util.logging.properties</argLine>
                     <useModulePath>false</useModulePath>
                 </configuration>
                 <executions>