You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2019/06/05 11:08:28 UTC

[ignite] 25/31: GG-13964 control.sh should log actions performed

This is an automated email from the ASF dual-hosted git repository.

amashenkov pushed a commit to branch gg-19225
in repository https://gitbox.apache.org/repos/asf/ignite.git

commit b1f748b68cebc4fd8571c2e7115e28ada30fd81c
Author: vmalin <vm...@gridgain.com>
AuthorDate: Tue Jun 4 11:37:30 2019 +0300

    GG-13964 control.sh should log actions performed
---
 .../internal/commandline/ActivateCommand.java      |  16 ++-
 .../internal/commandline/BaselineCommand.java      |  57 +++++----
 .../ignite/internal/commandline/Command.java       |  19 ++-
 .../internal/commandline/CommandHandler.java       | 141 ++++++++++++++-------
 .../ignite/internal/commandline/CommandList.java   |   7 +
 .../ignite/internal/commandline/CommandLogger.java |  61 ++++++---
 .../internal/commandline/DeactivateCommand.java    |  16 ++-
 .../ignite/internal/commandline/StateCommand.java  |  16 ++-
 .../ignite/internal/commandline/TxCommands.java    | 103 ++++++++-------
 .../ignite/internal/commandline/WalCommands.java   |  55 ++++----
 .../internal/commandline/cache/CacheCommands.java  |  65 +++++-----
 .../commandline/cache/CacheContention.java         |  14 +-
 .../commandline/cache/CacheDistribution.java       |  14 +-
 .../commandline/cache/CacheValidateIndexes.java    |  33 +++--
 .../internal/commandline/cache/CacheViewer.java    |  29 +++--
 .../commandline/cache/FindAndDeleteGarbage.java    |  23 ++--
 .../internal/commandline/cache/IdleVerify.java     |  31 +++--
 .../commandline/cache/ResetLostPartitions.java     |  13 +-
 .../ignite/logger/java/JavaLoggerFileHandler.java  |   2 +-
 .../util/GridCommandHandlerAbstractTest.java       |  13 +-
 .../apache/ignite/util/GridCommandHandlerTest.java |  32 +++--
 21 files changed, 471 insertions(+), 289 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
index 2bdac5f..998360a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/ActivateCommand.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientClusterState;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -28,8 +29,8 @@ import static org.apache.ignite.internal.commandline.CommandList.ACTIVATE;
  */
 public class ActivateCommand implements Command<Void> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "Activate cluster:", ACTIVATE);
+    @Override public void printUsage() {
+        Command.usage("Activate cluster:", ACTIVATE);
     }
 
     /**
@@ -38,16 +39,16 @@ public class ActivateCommand implements Command<Void> {
      * @param cfg Client configuration.
      * @throws GridClientException If failed to activate.
      */
-    @Override public Object execute(GridClientConfiguration cfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration cfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(cfg)) {
             GridClientClusterState state = client.state();
 
             state.active(true);
 
-            logger.log("Cluster activated");
+            logger.info("Cluster activated");
         }
         catch (Throwable e) {
-            logger.log("Failed to activate cluster.");
+            logger.severe("Failed to activate cluster.");
 
             throw e;
         }
@@ -59,4 +60,9 @@ public class ActivateCommand implements Command<Void> {
     @Override public Void arg() {
         return null;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return ACTIVATE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
index e5940cb..3ba6e2c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/BaselineCommand.java
@@ -22,6 +22,7 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.baseline.BaselineArguments;
@@ -47,17 +48,17 @@ public class BaselineCommand implements Command<BaselineArguments> {
     private BaselineArguments baselineArgs;
 
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         final String constistIds = "consistentId1[,consistentId2,....,consistentIdN]";
 
-        Command.usage(logger, "Print cluster baseline topology:", BASELINE);
-        Command.usage(logger, "Add nodes into baseline topology:", BASELINE, BaselineSubcommands.ADD.text(),
+        Command.usage("Print cluster baseline topology:", BASELINE);
+        Command.usage("Add nodes into baseline topology:", BASELINE, BaselineSubcommands.ADD.text(),
             constistIds, optional(CMD_AUTO_CONFIRMATION));
-        Command.usage(logger, "Remove nodes from baseline topology:", BASELINE, BaselineSubcommands.REMOVE.text(),
+        Command.usage("Remove nodes from baseline topology:", BASELINE, BaselineSubcommands.REMOVE.text(),
             constistIds, optional(CMD_AUTO_CONFIRMATION));
-        Command.usage(logger, "Set baseline topology:", BASELINE, BaselineSubcommands.SET.text(), constistIds,
+        Command.usage("Set baseline topology:", BASELINE, BaselineSubcommands.SET.text(), constistIds,
             optional(CMD_AUTO_CONFIRMATION));
-        Command.usage(logger, "Set baseline topology based on version:", BASELINE,
+        Command.usage("Set baseline topology based on version:", BASELINE,
             BaselineSubcommands.VERSION.text() + " topologyVersion", optional(CMD_AUTO_CONFIRMATION));
     }
 
@@ -76,14 +77,15 @@ public class BaselineCommand implements Command<BaselineArguments> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to execute baseline action.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)) {
             VisorBaselineTaskResult res = executeTask(client, VisorBaselineTask.class, toVisorArguments(baselineArgs), clientCfg);
 
-            baselinePrint0(res, logger);
+            baselinePrint0(res);
         }
         catch (Throwable e) {
-            logger.error("Failed to execute baseline command='" + baselineArgs.getCmd().text() + "'", e);
+            logger.severe("Failed to execute baseline command='" + baselineArgs.getCmd().text() + "'");
+            logger.severe(CommandLogger.errorMessage(e));
 
             throw e;
         }
@@ -111,11 +113,11 @@ public class BaselineCommand implements Command<BaselineArguments> {
      *
      * @param res Task result with baseline topology.
      */
-    private void baselinePrint0(VisorBaselineTaskResult res, CommandLogger logger) {
-        logger.log("Cluster state: " + (res.isActive() ? "active" : "inactive"));
-        logger.log("Current topology version: " + res.getTopologyVersion());
+    private void baselinePrint0(VisorBaselineTaskResult res) {
+        CommandLogger.log("Cluster state: " + (res.isActive() ? "active" : "inactive"));
+        CommandLogger.log("Current topology version: " + res.getTopologyVersion());
 
-        logger.nl();
+        CommandLogger.nl();
 
         Map<String, VisorBaselineNode> baseline = res.getBaseline();
 
@@ -131,13 +133,13 @@ public class BaselineCommand implements Command<BaselineArguments> {
             .map(crd -> " (Coordinator: ConsistentId=" + crd.getConsistentId() + ", Order=" + crd.getOrder() + ")")
             .orElse("");
 
-        logger.log("Current topology version: " + res.getTopologyVersion() + crdStr);
-        logger.nl();
+        CommandLogger.log("Current topology version: " + res.getTopologyVersion() + crdStr);
+        CommandLogger.nl();
 
         if (F.isEmpty(baseline))
-            logger.log("Baseline nodes not found.");
+            CommandLogger.log("Baseline nodes not found.");
         else {
-            logger.log("Baseline nodes:");
+            CommandLogger.log("Baseline nodes:");
 
             for (VisorBaselineNode node : baseline.values()) {
                 VisorBaselineNode srvNode = srvs.get(node.getConsistentId());
@@ -146,13 +148,13 @@ public class BaselineCommand implements Command<BaselineArguments> {
 
                 String order = srvNode != null ? ", Order=" + srvNode.getOrder() : "";
 
-                logger.logWithIndent("ConsistentId=" + node.getConsistentId() + state + order, 2);
+                CommandLogger.logWithIndent("ConsistentId=" + node.getConsistentId() + state + order, 2);
             }
 
-            logger.log(DELIM);
-            logger.log("Number of baseline nodes: " + baseline.size());
+            CommandLogger.log(DELIM);
+            CommandLogger.log("Number of baseline nodes: " + baseline.size());
 
-            logger.nl();
+            CommandLogger.nl();
 
             List<VisorBaselineNode> others = new ArrayList<>();
 
@@ -162,14 +164,14 @@ public class BaselineCommand implements Command<BaselineArguments> {
             }
 
             if (F.isEmpty(others))
-                logger.log("Other nodes not found.");
+                CommandLogger.log("Other nodes not found.");
             else {
-                logger.log("Other nodes:");
+                CommandLogger.log("Other nodes:");
 
                 for (VisorBaselineNode node : others)
-                    logger.logWithIndent("ConsistentId=" + node.getConsistentId() + ", Order=" + node.getOrder(), 2);
+                    CommandLogger.logWithIndent("ConsistentId=" + node.getConsistentId() + ", Order=" + node.getOrder(), 2);
 
-                logger.log("Number of other nodes: " + others.size());
+                CommandLogger.log("Number of other nodes: " + others.size());
             }
         }
     }
@@ -210,4 +212,9 @@ public class BaselineCommand implements Command<BaselineArguments> {
 
         this.baselineArgs = baselineArgs.build();
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return BASELINE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java
index 34b130d..a7cdcfe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/Command.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.client.GridClientFactory;
@@ -52,10 +53,10 @@ public interface Command<T> {
      * @param desc Command description.
      * @param args Arguments.
      */
-    public static void usage(CommandLogger logger, String desc, CommandList cmd, String... args) {
-        logger.logWithIndent(desc);
-        logger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, cmd, CommandLogger.join(" ", args)), 2);
-        logger.nl();
+    public static void usage(String desc, CommandList cmd, String... args) {
+        CommandLogger.logWithIndent(desc);
+        CommandLogger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, cmd, CommandLogger.join(" ", args)), 2);
+        CommandLogger.nl();
     }
 
     /**
@@ -66,7 +67,7 @@ public interface Command<T> {
      * @return Result of operation (mostly usable for tests).
      * @throws Exception If error occur.
      */
-    public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception;
+    public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception;
 
     /**
      * @return Message text to show user for. If null it means that confirmantion is not needed.
@@ -92,7 +93,11 @@ public interface Command<T> {
     /**
      * Print info for user about command (parameters, use cases and so on).
      *
-     * @param logger Would be used as output.
      */
-    public void printUsage(CommandLogger logger);
+    public void printUsage();
+
+    /**
+     * @return command name.
+     */
+    String name();
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
index 98a8ddc..d3c7e34 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandHandler.java
@@ -16,11 +16,16 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.io.File;
 import java.time.LocalDateTime;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Scanner;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.StreamHandler;
 import java.util.stream.Collectors;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.client.GridClientAuthenticationException;
@@ -33,6 +38,9 @@ import org.apache.ignite.internal.client.impl.connection.GridClientConnectionRes
 import org.apache.ignite.internal.client.ssl.GridSslBasicContextFactory;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.logger.java.JavaLoggerFileHandler;
+import org.apache.ignite.logger.java.JavaLoggerFormatter;
 import org.apache.ignite.plugin.security.SecurityCredentials;
 import org.apache.ignite.plugin.security.SecurityCredentialsBasicProvider;
 import org.apache.ignite.plugin.security.SecurityCredentialsProvider;
@@ -52,8 +60,37 @@ import static org.apache.ignite.ssl.SslContextFactory.DFLT_SSL_PROTOCOL;
  * Class that execute several commands passed via command line.
  */
 public class CommandHandler {
-    /** Logger. */
-    private final CommandLogger logger = new CommandLogger();
+    /** Command logger. */
+    private final CommandLogger commandLogger= new CommandLogger();
+
+    /** JULs logger. */
+    private final Logger logger = setupJavaLogger();
+
+    private Logger setupJavaLogger() {
+        Logger result;
+
+        result = Logger.getLogger(getClass().getName());
+        result.setLevel(Level.INFO);
+
+        // Adding logging to file.
+        try {
+            String namePattern = "control-utility-%g.log";
+            String absPathPattern;
+            absPathPattern = new File(JavaLoggerFileHandler.logDirectory(U.defaultWorkDirectory()), namePattern).getAbsolutePath();
+            FileHandler fileHandler = new FileHandler(absPathPattern, 1024 * 1024 * 1024, 5);
+            fileHandler.setFormatter(new JavaLoggerFormatter());
+            result.addHandler(fileHandler);
+        }
+        catch (Exception e) {
+            System.out.println("Failed to configure logging to file");
+        }
+
+        // Adding logging to console.
+        StreamHandler streamHandler = new StreamHandler(System.out, new JavaLoggerFormatter());
+        result.addHandler(streamHandler);
+
+        return result;
+    }
 
     /** */
     static final String CMD_HELP = "--help";
@@ -116,11 +153,13 @@ public class CommandHandler {
      * @return Exit code.
      */
     public int execute(List<String> rawArgs) {
-        logger.log("Control utility [ver. " + ACK_VER_STR + "]");
-        logger.log(COPYRIGHT);
-        logger.log("User: " + System.getProperty("user.name"));
-        logger.log("Time: " + LocalDateTime.now());
-        logger.log(DELIM);
+        logger.info("Control utility [ver. " + ACK_VER_STR + "]");
+        logger.info(COPYRIGHT);
+        logger.info("User: " + System.getProperty("user.name"));
+        logger.info("Time: " + LocalDateTime.now());
+        logger.info(DELIM);
+
+        String commandName = "";
 
         try {
             if (F.isEmpty(rawArgs) || (rawArgs.size() == 1 && CMD_HELP.equalsIgnoreCase(rawArgs.get(0)))) {
@@ -129,12 +168,13 @@ public class CommandHandler {
                 return EXIT_CODE_OK;
             }
 
-            ConnectionAndSslParameters args = new CommonArgParser(logger).parseAndValidate(rawArgs.iterator());
+            ConnectionAndSslParameters args = new CommonArgParser(commandLogger).parseAndValidate(rawArgs.iterator());
 
             Command command = args.command();
+            commandName = command.name();
 
             if (!args.autoConfirmation() && !confirm(command.confirmationPrompt())) {
-                logger.log("Operation cancelled.");
+                logger.info("Operation cancelled.");
 
                 return EXIT_CODE_OK;
             }
@@ -151,11 +191,13 @@ public class CommandHandler {
                 tryConnectAgain = false;
 
                 try {
+                    logger.info("Command [" + commandName + "] started");
+                    logger.info("Arguments: " + String.join(" ", rawArgs));
                     lastOperationRes = command.execute(clientCfg, logger);
                 }
                 catch (Throwable e) {
                     if (tryConnectMaxCount > 0 && isAuthError(e)) {
-                        logger.log(suppliedAuth ?
+                        logger.info(suppliedAuth ?
                             "Authentication error, please try again." :
                             "This cluster requires authentication.");
 
@@ -181,27 +223,32 @@ public class CommandHandler {
                 }
             }
 
+            logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_OK);
             return EXIT_CODE_OK;
         }
         catch (IllegalArgumentException e) {
-            logger.error("Check arguments.", e);
+            logger.severe("Check arguments. " + CommandLogger.errorMessage(e));
+            logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_INVALID_ARGUMENTS);
 
             return EXIT_CODE_INVALID_ARGUMENTS;
         }
         catch (Throwable e) {
             if (isAuthError(e)) {
-                logger.error("Authentication error.", e);
+                logger.severe("Authentication error. " + CommandLogger.errorMessage(e));
+                logger.info("Command [" + commandName + "] finished with code: " + ERR_AUTHENTICATION_FAILED);
 
                 return ERR_AUTHENTICATION_FAILED;
             }
 
             if (isConnectionError(e)) {
-                logger.error("Connection to cluster failed.", e);
+                logger.severe("Connection to cluster failed. " + CommandLogger.errorMessage(e));
+                logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_CONNECTION_FAILED);
 
                 return EXIT_CODE_CONNECTION_FAILED;
             }
 
-            logger.error("", e);
+            logger.severe(CommandLogger.errorMessage(e));
+            logger.info("Command [" + commandName + "] finished with code: " + EXIT_CODE_UNEXPECTED_ERROR);
 
             return EXIT_CODE_UNEXPECTED_ERROR;
         }
@@ -396,7 +443,7 @@ public class CommandHandler {
         else {
             Scanner scanner = new Scanner(System.in);
 
-            logger.log(msg);
+            commandLogger.log(msg);
 
             return scanner.nextLine();
         }
@@ -421,40 +468,40 @@ public class CommandHandler {
 
     /** */
     private void printHelp() {
-        logger.log("Control.sh is used to execute admin commands on cluster or get common cluster info. " +
+        commandLogger.log("Control.sh is used to execute admin commands on cluster or get common cluster info. " +
             "The command has the following syntax:");
-        logger.nl();
+        commandLogger.nl();
 
-        logger.logWithIndent(CommandLogger.join(" ", CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())),
+        commandLogger.logWithIndent(CommandLogger.join(" ", CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())),
             optional("command"), "<command_parameters>"));
-        logger.nl();
-        logger.nl();
-
-        logger.log("This utility can do the following commands:");
-
-        Arrays.stream(CommandList.values()).forEach(c -> c.command().printUsage(logger));
-
-        logger.log("By default commands affecting the cluster require interactive confirmation.");
-        logger.log("Use " + CMD_AUTO_CONFIRMATION + " option to disable it.");
-        logger.nl();
-
-        logger.log("Default values:");
-        logger.logWithIndent("HOST_OR_IP=" + DFLT_HOST, 2);
-        logger.logWithIndent("PORT=" + DFLT_PORT, 2);
-        logger.logWithIndent("PING_INTERVAL=" + DFLT_PING_INTERVAL, 2);
-        logger.logWithIndent("PING_TIMEOUT=" + DFLT_PING_TIMEOUT, 2);
-        logger.logWithIndent("SSL_PROTOCOL=" + SslContextFactory.DFLT_SSL_PROTOCOL, 2);
-        logger.logWithIndent("SSL_KEY_ALGORITHM=" + SslContextFactory.DFLT_KEY_ALGORITHM, 2);
-        logger.logWithIndent("KEYSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
-        logger.logWithIndent("TRUSTSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
-
-        logger.nl();
-
-        logger.log("Exit codes:");
-        logger.logWithIndent(EXIT_CODE_OK + " - successful execution.", 2);
-        logger.logWithIndent(EXIT_CODE_INVALID_ARGUMENTS + " - invalid arguments.", 2);
-        logger.logWithIndent(EXIT_CODE_CONNECTION_FAILED + " - connection failed.", 2);
-        logger.logWithIndent(ERR_AUTHENTICATION_FAILED + " - authentication failed.", 2);
-        logger.logWithIndent(EXIT_CODE_UNEXPECTED_ERROR + " - unexpected error.", 2);
+        commandLogger.nl();
+        commandLogger.nl();
+
+        commandLogger.log("This utility can do the following commands:");
+
+        Arrays.stream(CommandList.values()).forEach(c -> c.command().printUsage());
+
+        commandLogger.log("By default commands affecting the cluster require interactive confirmation.");
+        commandLogger.log("Use " + CMD_AUTO_CONFIRMATION + " option to disable it.");
+        commandLogger.nl();
+
+        commandLogger.log("Default values:");
+        commandLogger.logWithIndent("HOST_OR_IP=" + DFLT_HOST, 2);
+        commandLogger.logWithIndent("PORT=" + DFLT_PORT, 2);
+        commandLogger.logWithIndent("PING_INTERVAL=" + DFLT_PING_INTERVAL, 2);
+        commandLogger.logWithIndent("PING_TIMEOUT=" + DFLT_PING_TIMEOUT, 2);
+        commandLogger.logWithIndent("SSL_PROTOCOL=" + SslContextFactory.DFLT_SSL_PROTOCOL, 2);
+        commandLogger.logWithIndent("SSL_KEY_ALGORITHM=" + SslContextFactory.DFLT_KEY_ALGORITHM, 2);
+        commandLogger.logWithIndent("KEYSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
+        commandLogger.logWithIndent("TRUSTSTORE_TYPE=" + SslContextFactory.DFLT_STORE_TYPE, 2);
+
+        commandLogger.nl();
+
+        commandLogger.log("Exit codes:");
+        commandLogger.logWithIndent(EXIT_CODE_OK + " - successful execution.", 2);
+        commandLogger.logWithIndent(EXIT_CODE_INVALID_ARGUMENTS + " - invalid arguments.", 2);
+        commandLogger.logWithIndent(EXIT_CODE_CONNECTION_FAILED + " - connection failed.", 2);
+        commandLogger.logWithIndent(ERR_AUTHENTICATION_FAILED + " - authentication failed.", 2);
+        commandLogger.logWithIndent(EXIT_CODE_UNEXPECTED_ERROR + " - unexpected error.", 2);
     }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
index 280a40b..d595e05 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandList.java
@@ -92,4 +92,11 @@ public enum CommandList {
     @Override public String toString() { 
         return text; 
     }
+
+    /**
+     * @return command name
+     */
+    public String toCommandName() {
+        return text.substring(2).toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
index b19ad24..3bf6a92 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/CommandLogger.java
@@ -18,6 +18,7 @@ package org.apache.ignite.internal.commandline;
 
 import java.util.Map;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.SB;
 
@@ -93,11 +94,30 @@ public class CommandLogger {
     }
 
     /**
+     * Generates readable error message from exception
+     * @param e Exctption
+     * @return error message
+     */
+    public static String errorMessage(Throwable e) {
+        String msg = e.getMessage();
+
+        if (F.isEmpty(msg))
+            msg = e.getClass().getName();
+        else if (msg.startsWith("Failed to handle request")) {
+            int p = msg.indexOf("err=");
+
+            msg = msg.substring(p + 4, msg.length() - 1);
+        }
+
+        return msg;
+    }
+
+    /**
      * Output specified string to console.
      *
      * @param s String to output.
      */
-    public void log(String s) {
+    public static void log(String s) {
         System.out.println(s);
     }
 
@@ -107,7 +127,7 @@ public class CommandLogger {
      *
      * @param s String to output.
      */
-    public void logWithIndent(Object s) {
+    public static void logWithIndent(Object s) {
         log(indent(s));
     }
 
@@ -117,7 +137,7 @@ public class CommandLogger {
      *
      * @param s String to output.
      */
-    public void logWithIndent(Object s, int indentCnt) {
+    public static void logWithIndent(Object s, int indentCnt) {
         log(indent(s), indentCnt);
     }
 
@@ -169,14 +189,14 @@ public class CommandLogger {
      * @param format A format string as described in Format string syntax.
      * @param args Arguments referenced by the format specifiers in the format string.
      */
-    public void log(String format, Object... args) {
+    public static void log(String format, Object... args) {
         System.out.printf(format, args);
     }
 
     /**
      * Output empty line.
      */
-    public void nl() {
+    public static void nl() {
         System.out.println();
     }
 
@@ -191,18 +211,7 @@ public class CommandLogger {
         if (!F.isEmpty(s))
             log(s);
 
-        String msg = e.getMessage();
-
-        if (F.isEmpty(msg))
-            msg = e.getClass().getName();
-
-        if (msg.startsWith("Failed to handle request")) {
-            int p = msg.indexOf("err=");
-
-            msg = msg.substring(p + 4, msg.length() - 1);
-        }
-
-        log("Error: " + msg);
+        log("Error: " + errorMessage(e));
     }
 
 
@@ -224,4 +233,22 @@ public class CommandLogger {
 
         return false;
     }
+
+    public static boolean printErrors(Map<UUID, Exception> exceptions, String s, Logger logger) {
+        if (!F.isEmpty(exceptions)) {
+            logger.info(s);
+
+            for (Map.Entry<UUID, Exception> e : exceptions.entrySet()) {
+                logger.info(INDENT + "Node ID: " + e.getKey());
+
+                logger.info(INDENT + "Exception message:");
+                logger.info(INDENT + INDENT + e.getValue().getMessage());
+                logger.info("");
+            }
+
+            return true;
+        }
+
+        return false;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
index ad5e551..961e0ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/DeactivateCommand.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientClusterState;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -29,8 +30,8 @@ import static org.apache.ignite.internal.commandline.CommonArgParser.CMD_AUTO_CO
  */
 public class DeactivateCommand implements Command<Void> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "Deactivate cluster:", DEACTIVATE, optional(CMD_AUTO_CONFIRMATION));
+    @Override public void printUsage() {
+        Command.usage("Deactivate cluster:", DEACTIVATE, optional(CMD_AUTO_CONFIRMATION));
     }
 
     /** {@inheritDoc} */
@@ -44,16 +45,16 @@ public class DeactivateCommand implements Command<Void> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to deactivate.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)) {
             GridClientClusterState state = client.state();
 
             state.active(false);
 
-            logger.log("Cluster deactivated");
+            logger.info("Cluster deactivated");
         }
         catch (Exception e) {
-            logger.log("Failed to deactivate cluster.");
+            logger.severe("Failed to deactivate cluster.");
 
             throw e;
         }
@@ -65,4 +66,9 @@ public class DeactivateCommand implements Command<Void> {
     @Override public Void arg() {
         return null;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return DEACTIVATE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
index a2a3afd..69aa3ec 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/StateCommand.java
@@ -16,6 +16,7 @@
 
 package org.apache.ignite.internal.commandline;
 
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientClusterState;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -27,8 +28,8 @@ import static org.apache.ignite.internal.commandline.CommandList.STATE;
  */
 public class StateCommand implements Command<Void> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "Print current cluster state:", STATE);
+    @Override public void printUsage() {
+        Command.usage("Print current cluster state:", STATE);
     }
 
     /**
@@ -37,14 +38,14 @@ public class StateCommand implements Command<Void> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to print state.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)){
             GridClientClusterState state = client.state();
 
-            logger.log("Cluster is " + (state.active() ? "active" : "inactive"));
+            logger.info("Cluster is " + (state.active() ? "active" : "inactive"));
         }
         catch (Throwable e) {
-            logger.log("Failed to get cluster state.");
+            logger.severe("Failed to get cluster state.");
 
             throw e;
         }
@@ -56,4 +57,9 @@ public class StateCommand implements Command<Void> {
     @Override public Void arg() {
         return null;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return STATE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
index 1063d13..b9674d7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/TxCommands.java
@@ -23,6 +23,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Logger;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import org.apache.ignite.cluster.ClusterNode;
@@ -69,12 +70,12 @@ public class TxCommands implements Command<VisorTxTaskArg> {
     private VisorTxTaskArg args;
 
     /** Logger. */
-    private CommandLogger logger;
+    private Logger logger;
 
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        Command.usage(logger, "List or kill transactions:", TX, getTxOptions());
-        Command.usage(logger, "Print detailed information (topology and key lock ownership) about specific transaction:",
+    @Override public void printUsage() {
+        Command.usage("List or kill transactions:", TX, getTxOptions());
+        Command.usage("Print detailed information (topology and key lock ownership) about specific transaction:",
             TX, TX_INFO.argName(), or("<TX identifier as GridCacheVersion [topVer=..., order=..., nodeOrder=...] " +
                 "(can be found in logs)>", "<TX identifier as UUID (can be retrieved via --tx command)>"));
 
@@ -111,7 +112,7 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      *
      * @param clientCfg Client configuration.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         this.logger = logger;
 
         try (GridClient client = Command.startClient(clientCfg)) {
@@ -121,11 +122,11 @@ public class TxCommands implements Command<VisorTxTaskArg> {
             Map<ClusterNode, VisorTxTaskResult> res = executeTask(client, VisorTxTask.class, args, clientCfg);
 
             if (res.isEmpty())
-                logger.log("Nothing found.");
+                logger.info("Nothing found.");
             else if (args.getOperation() == VisorTxOperation.KILL)
-                logger.log("Killed transactions:");
+                logger.info("Killed transactions:");
             else
-                logger.log("Matching transactions:");
+                logger.info("Matching transactions:");
 
             for (Map.Entry<ClusterNode, VisorTxTaskResult> entry : res.entrySet()) {
                 if (entry.getValue().getInfos().isEmpty())
@@ -133,7 +134,7 @@ public class TxCommands implements Command<VisorTxTaskArg> {
 
                 ClusterNode key = entry.getKey();
 
-                logger.log(key.getClass().getSimpleName() + " [id=" + key.id() +
+                logger.info(key.getClass().getSimpleName() + " [id=" + key.id() +
                     ", addrs=" + key.addresses() +
                     ", order=" + key.order() +
                     ", ver=" + key.version() +
@@ -142,13 +143,14 @@ public class TxCommands implements Command<VisorTxTaskArg> {
                     "]");
 
                 for (VisorTxInfo info : entry.getValue().getInfos())
-                    logger.log(info.toUserString());
+                    logger.info(info.toUserString());
             }
 
             return res;
         }
         catch (Throwable e) {
-            logger.error("Failed to perform operation.", e);
+            logger.severe("Failed to perform operation.");
+            logger.severe(CommandLogger.errorMessage(e));
 
             throw e;
         }
@@ -175,14 +177,14 @@ public class TxCommands implements Command<VisorTxTaskArg> {
 
                 ClusterNode key = entry.getKey();
 
-                logger.log(nodeDescription(key));
+                logger.info(nodeDescription(key));
 
                 for (VisorTxInfo info : entry.getValue().getInfos())
-                    logger.log(info.toUserString());
+                    logger.info(info.toUserString());
             }
         }
         catch (Throwable e) {
-            logger.log("Failed to perform operation.");
+            logger.severe("Failed to perform operation.");
 
             throw e;
         }
@@ -357,20 +359,20 @@ public class TxCommands implements Command<VisorTxTaskArg> {
         boolean histMode = false;
 
         if (nearXidVer != null) {
-            logger.log("Resolved transaction near XID version: " + nearXidVer);
+            logger.info("Resolved transaction near XID version: " + nearXidVer);
 
             args.txInfoArgument(new TxVerboseId(null, nearXidVer));
         }
         else {
-            logger.log("Active transactions not found.");
+            logger.info("Active transactions not found.");
 
             if (args.txInfoArgument().gridCacheVersion() != null) {
-                logger.log("Will try to peek history to find out whether transaction was committed / rolled back.");
+                logger.info("Will try to peek history to find out whether transaction was committed / rolled back.");
 
                 histMode = true;
             }
             else {
-                logger.log("You can specify transaction in GridCacheVersion format in order to peek history " +
+                logger.info("You can specify transaction in GridCacheVersion format in order to peek history " +
                     "to find out whether transaction was committed / rolled back.");
 
                 return null;
@@ -421,8 +423,8 @@ public class TxCommands implements Command<VisorTxTaskArg> {
 
         String indent = "";
 
-        logger.nl();
-        logger.log(indent + "Transaction detailed info:");
+        logger.info("");
+        logger.info(indent + "Transaction detailed info:");
 
         printTransactionDetailedInfo(
             res, usedCaches, usedCacheGroups, firstInfo, firstVerboseInfo, states, indent + DOUBLE_INDENT);
@@ -442,19 +444,19 @@ public class TxCommands implements Command<VisorTxTaskArg> {
     private void printTransactionDetailedInfo(Map<ClusterNode, VisorTxTaskResult> res, Map<Integer, String> usedCaches,
         Map<Integer, String> usedCacheGroups, VisorTxInfo firstInfo, TxVerboseInfo firstVerboseInfo,
         Set<TransactionState> states, String indent) {
-        logger.log(indent + "Near XID version: " + firstVerboseInfo.nearXidVersion());
-        logger.log(indent + "Near XID version (UUID): " + firstInfo.getNearXid());
-        logger.log(indent + "Isolation: " + firstInfo.getIsolation());
-        logger.log(indent + "Concurrency: " + firstInfo.getConcurrency());
-        logger.log(indent + "Timeout: " + firstInfo.getTimeout());
-        logger.log(indent + "Initiator node: " + firstVerboseInfo.nearNodeId());
-        logger.log(indent + "Initiator node (consistent ID): " + firstVerboseInfo.nearNodeConsistentId());
-        logger.log(indent + "Label: " + firstInfo.getLabel());
-        logger.log(indent + "Topology version: " + firstInfo.getTopologyVersion());
-        logger.log(indent + "Used caches (ID to name): " + usedCaches);
-        logger.log(indent + "Used cache groups (ID to name): " + usedCacheGroups);
-        logger.log(indent + "States across the cluster: " + states);
-        logger.log(indent + "Transaction topology: ");
+        logger.info(indent + "Near XID version: " + firstVerboseInfo.nearXidVersion());
+        logger.info(indent + "Near XID version (UUID): " + firstInfo.getNearXid());
+        logger.info(indent + "Isolation: " + firstInfo.getIsolation());
+        logger.info(indent + "Concurrency: " + firstInfo.getConcurrency());
+        logger.info(indent + "Timeout: " + firstInfo.getTimeout());
+        logger.info(indent + "Initiator node: " + firstVerboseInfo.nearNodeId());
+        logger.info(indent + "Initiator node (consistent ID): " + firstVerboseInfo.nearNodeConsistentId());
+        logger.info(indent + "Label: " + firstInfo.getLabel());
+        logger.info(indent + "Topology version: " + firstInfo.getTopologyVersion());
+        logger.info(indent + "Used caches (ID to name): " + usedCaches);
+        logger.info(indent + "Used cache groups (ID to name): " + usedCacheGroups);
+        logger.info(indent + "States across the cluster: " + states);
+        logger.info(indent + "Transaction topology: ");
 
         printTransactionTopology(res, indent + DOUBLE_INDENT);
     }
@@ -467,7 +469,7 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      */
     private void printTransactionTopology(Map<ClusterNode, VisorTxTaskResult> res, String indent) {
         for (Map.Entry<ClusterNode, VisorTxTaskResult> entry : res.entrySet()) {
-            logger.log(indent + nodeDescription(entry.getKey()) + ':');
+            logger.info(indent + nodeDescription(entry.getKey()) + ':');
 
             printTransactionMappings(indent + DOUBLE_INDENT, entry);
         }
@@ -484,14 +486,14 @@ public class TxCommands implements Command<VisorTxTaskArg> {
             TxVerboseInfo verboseInfo = info.getTxVerboseInfo();
 
             if (verboseInfo != null) {
-                logger.log(indent + "Mapping [type=" + verboseInfo.txMappingType() + "]:");
+                logger.info(indent + "Mapping [type=" + verboseInfo.txMappingType() + "]:");
 
                 printTransactionMapping(indent + DOUBLE_INDENT, info, verboseInfo);
             }
             else {
-                logger.log(indent + "Mapping [type=HISTORICAL]:");
+                logger.info(indent + "Mapping [type=HISTORICAL]:");
 
-                logger.log(indent + DOUBLE_INDENT + "State: " + info.getState());
+                logger.info(indent + DOUBLE_INDENT + "State: " + info.getState());
             }
         }
     }
@@ -504,16 +506,16 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      * @param verboseInfo Verbose info.
      */
     private void printTransactionMapping(String indent, VisorTxInfo info, TxVerboseInfo verboseInfo) {
-        logger.log(indent + "XID version (UUID): " + info.getXid());
-        logger.log(indent + "State: " + info.getState());
+        logger.info(indent + "XID version (UUID): " + info.getXid());
+        logger.info(indent + "State: " + info.getState());
 
         if (verboseInfo.txMappingType() == TxMappingType.REMOTE) {
-            logger.log(indent + "Primary node: " + verboseInfo.dhtNodeId());
-            logger.log(indent + "Primary node (consistent ID): " + verboseInfo.dhtNodeConsistentId());
+            logger.info(indent + "Primary node: " + verboseInfo.dhtNodeId());
+            logger.info(indent + "Primary node (consistent ID): " + verboseInfo.dhtNodeConsistentId());
         }
 
         if (!F.isEmpty(verboseInfo.localTxKeys())) {
-            logger.log(indent + "Mapped keys:");
+            logger.info(indent + "Mapped keys:");
 
             printTransactionKeys(indent + DOUBLE_INDENT, verboseInfo);
         }
@@ -527,11 +529,11 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      */
     private void printTransactionKeys(String indent, TxVerboseInfo verboseInfo) {
         for (TxVerboseKey txVerboseKey : verboseInfo.localTxKeys()) {
-            logger.log(indent + (txVerboseKey.read() ? "Read" : "Write") +
+            logger.info(indent + (txVerboseKey.read() ? "Read" : "Write") +
                 " [lock=" + txVerboseKey.lockType() + "]: " + txVerboseKey.txKey());
 
             if (txVerboseKey.lockType() == TxKeyLockType.AWAITS_LOCK)
-                logger.log(indent + DOUBLE_INDENT + "Lock owner XID: " + txVerboseKey.ownerVersion());
+                logger.info(indent + DOUBLE_INDENT + "Lock owner XID: " + txVerboseKey.ownerVersion());
         }
     }
 
@@ -542,13 +544,13 @@ public class TxCommands implements Command<VisorTxTaskArg> {
      */
     private void printTxInfoHistoricalResult(Map<ClusterNode, VisorTxTaskResult> res) {
         if (F.isEmpty(res))
-            logger.log("Transaction was not found in history across the cluster.");
+            logger.info("Transaction was not found in history across the cluster.");
         else {
-            logger.log("Transaction was found in completed versions history of the following nodes:");
+            logger.info("Transaction was found in completed versions history of the following nodes:");
 
             for (Map.Entry<ClusterNode, VisorTxTaskResult> entry : res.entrySet()) {
-                logger.log(DOUBLE_INDENT + nodeDescription(entry.getKey()) + ':');
-                logger.log(DOUBLE_INDENT + DOUBLE_INDENT + "State: " + entry.getValue().getInfos().get(0).getState());
+                logger.info(DOUBLE_INDENT + nodeDescription(entry.getKey()) + ':');
+                logger.info(DOUBLE_INDENT + DOUBLE_INDENT + "State: " + entry.getValue().getInfos().get(0).getState());
             }
         }
     }
@@ -578,4 +580,9 @@ public class TxCommands implements Command<VisorTxTaskArg> {
             }
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return TX.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
index 872d732..5a5a59f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/WalCommands.java
@@ -20,6 +20,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.logging.Logger;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
@@ -35,6 +36,7 @@ import org.apache.ignite.internal.visor.misc.VisorWalTaskResult;
 import static org.apache.ignite.IgniteSystemProperties.IGNITE_ENABLE_EXPERIMENTAL_COMMAND;
 import static org.apache.ignite.internal.commandline.CommandArgIterator.isCommandOrOption;
 import static org.apache.ignite.internal.commandline.CommandList.WAL;
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
 import static org.apache.ignite.internal.commandline.CommandLogger.optional;
 import static org.apache.ignite.internal.commandline.CommonArgParser.CMD_AUTO_CONFIRMATION;
 import static org.apache.ignite.internal.commandline.TaskExecutor.executeTask;
@@ -50,7 +52,7 @@ public class WalCommands implements Command<T2<String, String>> {
     static final String WAL_DELETE = "delete";
 
     /** */
-    private CommandLogger logger;
+    private Logger logger;
 
     /**
      * Wal action.
@@ -62,11 +64,11 @@ public class WalCommands implements Command<T2<String, String>> {
      */
     private String walArgs;
 
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         if (IgniteSystemProperties.getBoolean(IGNITE_ENABLE_EXPERIMENTAL_COMMAND, false)) {
-            Command.usage(logger, "Print absolute paths of unused archived wal segments on each node:", WAL,
+            Command.usage("Print absolute paths of unused archived wal segments on each node:", WAL,
                 WAL_PRINT, "[consistentId1,consistentId2,....,consistentIdN]");
-            Command.usage(logger,"Delete unused archived wal segments on each node:", WAL, WAL_DELETE,
+            Command.usage("Delete unused archived wal segments on each node:", WAL, WAL_DELETE,
                 "[consistentId1,consistentId2,....,consistentIdN]", optional(CMD_AUTO_CONFIRMATION));
         }
     }
@@ -77,7 +79,7 @@ public class WalCommands implements Command<T2<String, String>> {
      * @param clientCfg Client configuration.
      * @throws Exception If failed to execute wal action.
      */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         this.logger = logger;
 
         try (GridClient client = Command.startClient(clientCfg)) {
@@ -197,8 +199,8 @@ public class WalCommands implements Command<T2<String, String>> {
      * @param taskRes Task result with baseline topology.
      */
     private void printUnusedWalSegments0(VisorWalTaskResult taskRes) {
-        logger.log("Unused wal segments per node:");
-        logger.nl();
+        logger.info("Unused wal segments per node:");
+        logger.info("");
 
         Map<String, Collection<String>> res = taskRes.results();
         Map<String, Exception> failRes = taskRes.exceptions();
@@ -207,22 +209,22 @@ public class WalCommands implements Command<T2<String, String>> {
         for (Map.Entry<String, Collection<String>> entry : res.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT +"addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
 
             for (String fileName : entry.getValue())
-                logger.logWithIndent(fileName);
+                logger.info(INDENT + fileName);
 
-            logger.nl();
+            logger.info("");
         }
 
         for (Map.Entry<String, Exception> entry : failRes.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
-            logger.logWithIndent("failed with error: " + entry.getValue().getMessage());
-            logger.nl();
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT + "addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
+            logger.info(INDENT + "failed with error: " + entry.getValue().getMessage());
+            logger.info("");
         }
     }
 
@@ -232,8 +234,8 @@ public class WalCommands implements Command<T2<String, String>> {
      * @param taskRes Task result with baseline topology.
      */
     private void printDeleteWalSegments0(VisorWalTaskResult taskRes) {
-        logger.log("WAL segments deleted for nodes:");
-        logger.nl();
+        logger.info("WAL segments deleted for nodes:");
+        logger.info("");
 
         Map<String, Collection<String>> res = taskRes.results();
         Map<String, Exception> errors = taskRes.exceptions();
@@ -242,18 +244,23 @@ public class WalCommands implements Command<T2<String, String>> {
         for (Map.Entry<String, Collection<String>> entry : res.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
-            logger.nl();
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT + "addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
+            logger.info("");
         }
 
         for (Map.Entry<String, Exception> entry : errors.entrySet()) {
             VisorClusterNode node = nodesInfo.get(entry.getKey());
 
-            logger.log("Node=" + node.getConsistentId());
-            logger.logWithIndent("addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()), 2);
-            logger.logWithIndent("failed with error: " + entry.getValue().getMessage());
-            logger.nl();
+            logger.info("Node=" + node.getConsistentId());
+            logger.info(INDENT + INDENT + "addresses " + U.addressesAsString(node.getAddresses(), node.getHostNames()));
+            logger.info(INDENT + "failed with error: " + entry.getValue().getMessage());
+            logger.info("");
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return WAL.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
index aa9a774..3d8bc0a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheCommands.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.commandline.cache;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Map;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
@@ -48,22 +49,17 @@ public class CacheCommands implements Command<CacheSubcommands> {
     protected static final String OP_NODE_ID = optional(NODE_ID);
 
     /** */
-    private CommandLogger logger;
-
-    /** */
     private CacheSubcommands subcommand;
 
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
-        logger.logWithIndent("View caches information in a cluster. For more details type:");
-        logger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CACHE, HELP), 2);
-        logger.nl();
+    @Override public void printUsage() {
+        CommandLogger.logWithIndent("View caches information in a cluster. For more details type:");
+        CommandLogger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CACHE, HELP), 2);
+        CommandLogger.nl();
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
-        this.logger = logger;
-
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         if (subcommand == CacheSubcommands.HELP) {
             printCacheHelp();
 
@@ -120,25 +116,25 @@ public class CacheCommands implements Command<CacheSubcommands> {
 
     /** */
     private void printCacheHelp() {
-        logger.logWithIndent("The '" + CACHE + " subcommand' is used to get information about and perform actions" +
+        CommandLogger.logWithIndent("The '" + CACHE + " subcommand' is used to get information about and perform actions" +
             " with caches. The command has the following syntax:");
-        logger.nl();
-        logger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())) + " " +
+        CommandLogger.nl();
+        CommandLogger.logWithIndent(CommandLogger.join(" ", UTILITY_NAME, CommandLogger.join(" ", getCommonOptions())) + " " +
             CACHE + " [subcommand] <subcommand_parameters>");
-        logger.nl();
-        logger.logWithIndent("The subcommands that take " + OP_NODE_ID + " as an argument ('" + LIST + "', '"
+        CommandLogger.nl();
+        CommandLogger.logWithIndent("The subcommands that take " + OP_NODE_ID + " as an argument ('" + LIST + "', '"
             + FIND_AND_DELETE_GARBAGE+ "', '" + CONTENTION + "' and '" + VALIDATE_INDEXES +
             "') will be executed on the given node or on all server nodes" +
             " if the option is not specified. Other commands will run on a random server node.");
-        logger.nl();
-        logger.nl();
-        logger.logWithIndent("Subcommands:");
+        CommandLogger.nl();
+        CommandLogger.nl();
+        CommandLogger.logWithIndent("Subcommands:");
 
         Arrays.stream(CacheCommandList.values()).forEach(c -> {
-            if (c.subcommand() != null) c.subcommand().printUsage(logger);
+            if (c.subcommand() != null) c.subcommand().printUsage();
         });
 
-        logger.nl();
+        CommandLogger.nl();
     }
 
 
@@ -151,7 +147,6 @@ public class CacheCommands implements Command<CacheSubcommands> {
      * @param args Cache command arguments.
      */
     protected static void usageCache(
-        CommandLogger logger,
         CacheSubcommands cmd,
         String description,
         Map<String, String> paramsDesc,
@@ -159,34 +154,33 @@ public class CacheCommands implements Command<CacheSubcommands> {
     ) {
         int indentsNum = 1;
 
-        logger.logWithIndent(DELIM, indentsNum);
-        logger.nl();
-        logger.logWithIndent(CommandLogger.join(" ", CACHE, cmd, CommandLogger.join(" ", args)), indentsNum++);
-        logger.nl();
-        logger.logWithIndent(description, indentsNum);
-        logger.nl();
+        CommandLogger.logWithIndent(DELIM, indentsNum);
+        CommandLogger.nl();
+        CommandLogger.logWithIndent(CommandLogger.join(" ", CACHE, cmd, CommandLogger.join(" ", args)), indentsNum++);
+        CommandLogger.nl();
+        CommandLogger.logWithIndent(description, indentsNum);
+        CommandLogger.nl();
 
         if (!F.isEmpty(paramsDesc)) {
-            logger.logWithIndent("Parameters:", indentsNum);
+            CommandLogger.logWithIndent("Parameters:", indentsNum);
 
-            usageCacheParams(logger, paramsDesc, indentsNum + 1);
+            usageCacheParams(paramsDesc, indentsNum + 1);
 
-            logger.nl();
+            CommandLogger.nl();
         }
     }
 
     /**
      * Print cache command arguments usage.
      *
-     * @param logger Command logger.
      * @param paramsDesc Cache command arguments description.
      * @param indentsNum Number of indents.
      */
-    private static void usageCacheParams(CommandLogger logger, Map<String, String> paramsDesc, int indentsNum) {
+    private static void usageCacheParams(Map<String, String> paramsDesc, int indentsNum) {
         int maxParamLen = paramsDesc.keySet().stream().max(Comparator.comparingInt(String::length)).get().length();
 
         for (Map.Entry<String, String> param : paramsDesc.entrySet())
-            logger.logWithIndent(extendToLen(param.getKey(), maxParamLen) + "  " + "- " + param.getValue(), indentsNum);
+            CommandLogger.logWithIndent(extendToLen(param.getKey(), maxParamLen) + "  " + "- " + param.getValue(), indentsNum);
     }
 
     /**
@@ -217,4 +211,9 @@ public class CacheCommands implements Command<CacheSubcommands> {
     @Override public CacheSubcommands arg() {
         return subcommand;
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return CACHE.toCommandName();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
index b09e30a..ac46a4e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheContention.java
@@ -17,6 +17,7 @@
 package org.apache.ignite.internal.commandline.cache;
 
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -39,10 +40,10 @@ import static org.apache.ignite.internal.commandline.cache.CacheSubcommands.CONT
  */
 public class CacheContention implements Command<CacheContention.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String description = "Show the keys that are point of contention for multiple transactions.";
 
-        usageCache(logger, CONTENTION, description, null, "minQueueSize",
+        usageCache(CONTENTION, description, null, "minQueueSize",
             OP_NODE_ID, optional("maxPrint"));
     }
 
@@ -100,7 +101,7 @@ public class CacheContention implements Command<CacheContention.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorContentionTaskArg taskArg = new VisorContentionTaskArg(args.minQueueSize(), args.maxPrint());
 
         UUID nodeId = args.nodeId() == null ? BROADCAST_UUID : args.nodeId();
@@ -111,7 +112,7 @@ public class CacheContention implements Command<CacheContention.Arguments> {
             res = executeTaskByNameOnNode(client, VisorContentionTask.class.getName(), taskArg, nodeId, clientCfg);
         }
 
-        logger.printErrors(res.exceptions(), "Contention check failed on nodes:");
+        CommandLogger.printErrors(res.exceptions(), "Contention check failed on nodes:", logger);
 
         for (ContentionInfo info : res.getInfos())
             info.print();
@@ -135,4 +136,9 @@ public class CacheContention implements Command<CacheContention.Arguments> {
 
         args = new Arguments(nodeId, minQueueSize, maxPrint);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return CONTENTION.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
index bf37ffd..449f576 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheDistribution.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.commandline.cache;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -46,11 +47,11 @@ import static org.apache.ignite.internal.commandline.cache.argument.Distribution
  */
 public class CacheDistribution implements Command<CacheDistribution.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Prints the information about partition distribution.";
 
-        usageCache(logger, DISTRIBUTION, description, null,
+        usageCache(DISTRIBUTION, description, null,
             or(NODE_ID, CommandHandler.NULL), optional(CACHES), optional(USER_ATTRIBUTES, "attrName1,...,attrNameN"));
     }
 
@@ -107,7 +108,7 @@ public class CacheDistribution implements Command<CacheDistribution.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         CacheDistributionTaskArg taskArg = new CacheDistributionTaskArg(args.caches(), args.getUserAttributes());
 
         UUID nodeId = args.nodeId() == null ? BROADCAST_UUID : args.nodeId();
@@ -118,7 +119,7 @@ public class CacheDistribution implements Command<CacheDistribution.Arguments> {
             res = executeTaskByNameOnNode(client, CacheDistributionTask.class.getName(), taskArg, nodeId, clientCfg);
         }
 
-        logger.printErrors(res.exceptions(), "Cache distrubution task failed on nodes:");
+        CommandLogger.printErrors(res.exceptions(), "Cache distrubution task failed on nodes:", logger);
 
         res.print(System.out);
 
@@ -159,4 +160,9 @@ public class CacheDistribution implements Command<CacheDistribution.Arguments> {
 
         args = new Arguments(caches, nodeId, userAttributes);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return DISTRIBUTION.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
index 7789fde..4666eb7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheValidateIndexes.java
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -39,6 +40,7 @@ import org.apache.ignite.internal.visor.verify.VisorValidateIndexesJobResult;
 import org.apache.ignite.internal.visor.verify.VisorValidateIndexesTaskArg;
 import org.apache.ignite.internal.visor.verify.VisorValidateIndexesTaskResult;
 
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
 import static org.apache.ignite.internal.commandline.CommandLogger.optional;
 import static org.apache.ignite.internal.commandline.CommandLogger.or;
 import static org.apache.ignite.internal.commandline.TaskExecutor.executeTaskByNameOnNode;
@@ -57,7 +59,7 @@ import static org.apache.ignite.internal.processors.cache.GridCacheUtils.UTILITY
  */
 public class CacheValidateIndexes implements Command<CacheValidateIndexes.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Verify counters and hash sums of primary and backup partitions for the specified " +
             "caches/cache groups on an idle cluster and print out the differences, if any. " +
@@ -72,7 +74,7 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
         map.put(CHECK_FIRST + " N", "validate only the first N keys");
         map.put(CHECK_THROUGH + " K", "validate every Kth key");
 
-        usageCache(logger, VALIDATE_INDEXES, description, map,
+        usageCache(VALIDATE_INDEXES, description, map,
             optional(CACHES), OP_NODE_ID, optional(or(CHECK_FIRST + " N", CHECK_THROUGH + " K")));
     }
 
@@ -141,7 +143,7 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorValidateIndexesTaskArg taskArg = new VisorValidateIndexesTaskArg(
             args.caches(),
             args.nodeId() != null ? Collections.singleton(args.nodeId()) : null,
@@ -153,7 +155,7 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
             VisorValidateIndexesTaskResult taskRes = executeTaskByNameOnNode(
                 client, "org.apache.ignite.internal.visor.verify.VisorValidateIndexesTask", taskArg, null, clientCfg);
 
-            boolean errors = logger.printErrors(taskRes.exceptions(), "Index validation failed on nodes:");
+            boolean errors = CommandLogger.printErrors(taskRes.exceptions(), "Index validation failed on nodes:", logger);
 
             for (Map.Entry<UUID, VisorValidateIndexesJobResult> nodeEntry : taskRes.results().entrySet()) {
                 if (!nodeEntry.getValue().hasIssues())
@@ -161,13 +163,13 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
 
                 errors = true;
 
-                logger.log("Index issues found on node " + nodeEntry.getKey() + ":");
+                logger.info("Index issues found on node " + nodeEntry.getKey() + ":");
 
                 Collection<IndexIntegrityCheckIssue> integrityCheckFailures = nodeEntry.getValue().integrityCheckFailures();
 
                 if (!integrityCheckFailures.isEmpty()) {
                     for (IndexIntegrityCheckIssue is : integrityCheckFailures)
-                        logger.logWithIndent(is);
+                        logger.info(INDENT + is);
                 }
 
                 Map<PartitionKey, ValidateIndexesPartitionResult> partRes = nodeEntry.getValue().partitionResult();
@@ -176,10 +178,10 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
                     ValidateIndexesPartitionResult res = e.getValue();
 
                     if (!res.issues().isEmpty()) {
-                        logger.logWithIndent(CommandLogger.join(" ", e.getKey(), e.getValue()));
+                        logger.info(INDENT + CommandLogger.join(" ", e.getKey(), e.getValue()));
 
                         for (IndexValidationIssue is : res.issues())
-                            logger.logWithIndent(is, 2);
+                            logger.info(INDENT + INDENT + is);
                     }
                 }
 
@@ -189,20 +191,20 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
                     ValidateIndexesPartitionResult res = e.getValue();
 
                     if (!res.issues().isEmpty()) {
-                        logger.logWithIndent(CommandLogger.join(" ", "SQL Index", e.getKey(), e.getValue()));
+                        logger.info(INDENT + CommandLogger.join(" ", "SQL Index", e.getKey(), e.getValue()));
 
                         for (IndexValidationIssue is : res.issues())
-                            logger.logWithIndent(is, 2);
+                            logger.info(INDENT + INDENT + is);
                     }
                 }
             }
 
             if (!errors)
-                logger.log("no issues found.");
+                logger.severe("no issues found.");
             else
-                logger.log("issues found (listed above).");
+                logger.severe("issues found (listed above).");
 
-            logger.nl();
+            logger.info("");
 
             return taskRes;
         }
@@ -270,4 +272,9 @@ public class CacheValidateIndexes implements Command<CacheValidateIndexes.Argume
 
         args = new Arguments(caches, nodeId, checkFirst, checkThrough);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return VALIDATE_INDEXES.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
index b5d0f14..94bf95c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/CacheViewer.java
@@ -20,13 +20,13 @@ import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.UUID;
+import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.client.GridClientException;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
-import org.apache.ignite.internal.commandline.CommandLogger;
 import org.apache.ignite.internal.commandline.OutputFormat;
 import org.apache.ignite.internal.commandline.TaskExecutor;
 import org.apache.ignite.internal.commandline.argument.CommandArgUtils;
@@ -69,7 +69,7 @@ import static org.apache.ignite.internal.visor.verify.VisorViewCacheCmd.SEQ;
  */
 public class CacheViewer implements Command<CacheViewer.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String description = "Show information about caches, groups or sequences that match a regular expression. " +
             "When executed without parameters, this subcommand prints the list of caches.";
 
@@ -81,7 +81,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
         map.put(GROUP.toString(), "print information about groups.");
         map.put(SEQUENCE.toString(), "print information about sequences.");
 
-        usageCache(logger, LIST, description, map, "regexPattern",
+        usageCache(LIST, description, map, "regexPattern",
             optional(or(GROUP, SEQUENCE)), OP_NODE_ID, optional(CONFIG), optional(OUTPUT_FORMAT, MULTI_LINE));
     }
 
@@ -156,7 +156,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorViewCacheTaskArg taskArg = new VisorViewCacheTaskArg(args.regex(), args.cacheCommand());
 
         VisorViewCacheTaskResult res;
@@ -337,7 +337,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
         Map<String, VisorCacheConfiguration> caches,
         OutputFormat outputFormat,
         Map<String, Integer> cacheToMapped,
-        CommandLogger logger
+        Logger logger
     ) {
 
         for (Map.Entry<String, VisorCacheConfiguration> entry : caches.entrySet()) {
@@ -349,19 +349,19 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
 
                     params.put("Mapped", cacheToMapped.get(cacheName));
 
-                    logger.log("[cache = '%s']%n", cacheName);
+                    logger.info(String.format("[cache = '%s']%n", cacheName));
 
                     for (Map.Entry<String, Object> innerEntry : params.entrySet())
-                        logger.log("%s: %s%n", innerEntry.getKey(), innerEntry.getValue());
+                        logger.info(String.format("%s: %s%n", innerEntry.getKey(), innerEntry.getValue()));
 
-                    logger.nl();
+                    logger.info("");
 
                     break;
 
                 default:
                     int mapped = cacheToMapped.get(cacheName);
 
-                    logger.log("%s: %s %s=%s%n", entry.getKey(), toString(entry.getValue()), "mapped", mapped);
+                    logger.info(String.format("%s: %s %s=%s%n", entry.getKey(), toString(entry.getValue()), "mapped", mapped));
 
                     break;
             }
@@ -389,7 +389,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
         Arguments cacheArgs,
         VisorViewCacheTaskResult viewRes,
         GridClientConfiguration clientCfg,
-        CommandLogger logger
+        Logger logger
     ) throws GridClientException {
         VisorCacheConfigurationCollectorTaskArg taskArg = new VisorCacheConfigurationCollectorTaskArg(cacheArgs.regex());
 
@@ -410,7 +410,7 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
      * @param infos Caches info.
      * @param cmd Command.
      */
-    private void printCacheInfos(Collection<CacheInfo> infos, VisorViewCacheCmd cmd, CommandLogger logger) {
+    private void printCacheInfos(Collection<CacheInfo> infos, VisorViewCacheCmd cmd, Logger logger) {
         for (CacheInfo info : infos) {
             Map<String, Object> map = info.toMap(cmd);
 
@@ -423,7 +423,12 @@ public class CacheViewer implements Command<CacheViewer.Arguments> {
 
             sb.a("]");
 
-            logger.log(sb.toString());
+            logger.info(sb.toString());
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return LIST.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
index 3dfe6c8..91f9d9d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/FindAndDeleteGarbage.java
@@ -20,6 +20,7 @@ import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
@@ -32,6 +33,7 @@ import org.apache.ignite.internal.visor.cache.VisorFindAndDeleteGarbageInPersist
 import org.apache.ignite.internal.visor.cache.VisorFindAndDeleteGarbageInPersistenceTaskArg;
 import org.apache.ignite.internal.visor.cache.VisorFindAndDeleteGarbageInPersistenceTaskResult;
 
+import static org.apache.ignite.internal.commandline.CommandLogger.INDENT;
 import static org.apache.ignite.internal.commandline.CommandLogger.optional;
 import static org.apache.ignite.internal.commandline.TaskExecutor.executeTask;
 import static org.apache.ignite.internal.commandline.cache.CacheCommands.OP_NODE_ID;
@@ -43,12 +45,12 @@ import static org.apache.ignite.internal.commandline.cache.CacheSubcommands.FIND
  */
 public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String GROUPS = "groupName1,...,groupNameN";
         String description = "Find and optionally delete garbage from shared cache groups which could be left " +
             "after cache destroy.";
 
-        usageCache(logger, FIND_AND_DELETE_GARBAGE, description, null,
+        usageCache(FIND_AND_DELETE_GARBAGE, description, null,
             optional(GROUPS), OP_NODE_ID, optional(FindAndDeleteGarbageArg.DELETE));
     }
 
@@ -105,7 +107,7 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         VisorFindAndDeleteGarbageInPersistenceTaskArg taskArg = new VisorFindAndDeleteGarbageInPersistenceTaskArg(
             args.groups(),
             args.delete(),
@@ -116,16 +118,16 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
             VisorFindAndDeleteGarbageInPersistenceTaskResult taskRes = executeTask(
                 client, VisorFindAndDeleteGarbageInPersistenceTask.class, taskArg, clientCfg);
 
-            logger.printErrors(taskRes.exceptions(), "Scanning for garbage failed on nodes:");
+            CommandLogger.printErrors(taskRes.exceptions(), "Scanning for garbage failed on nodes:", logger);
 
             for (Map.Entry<UUID, VisorFindAndDeleteGarbageInPersistenceJobResult> nodeEntry : taskRes.result().entrySet()) {
                 if (!nodeEntry.getValue().hasGarbage()) {
-                    logger.log("Node " + nodeEntry.getKey() + " - garbage not found.");
+                    logger.info("Node " + nodeEntry.getKey() + " - garbage not found.");
 
                     continue;
                 }
 
-                logger.log("Garbage found on node " + nodeEntry.getKey() + ":");
+                logger.info("Garbage found on node " + nodeEntry.getKey() + ":");
 
                 VisorFindAndDeleteGarbageInPersistenceJobResult value = nodeEntry.getValue();
 
@@ -134,14 +136,14 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
                 if (!grpPartErrorsCount.isEmpty()) {
                     for (Map.Entry<Integer, Map<Integer, Long>> entry : grpPartErrorsCount.entrySet()) {
                         for (Map.Entry<Integer, Long> e : entry.getValue().entrySet()) {
-                            logger.logWithIndent("Group=" + entry.getKey() +
+                            logger.info(INDENT + "Group=" + entry.getKey() +
                                 ", partition=" + e.getKey() +
                                 ", count of keys=" + e.getValue());
                         }
                     }
                 }
 
-                logger.nl();
+                logger.info("");
             }
 
             return taskRes;
@@ -181,4 +183,9 @@ public class FindAndDeleteGarbage implements Command<FindAndDeleteGarbage.Argume
 
         args = new Arguments(groups, nodeId, delete);
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return FIND_AND_DELETE_GARBAGE.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
index 036bce4..b62f6fc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/IdleVerify.java
@@ -22,6 +22,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.logging.Logger;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import org.apache.ignite.IgniteException;
@@ -32,7 +33,6 @@ import org.apache.ignite.internal.client.GridClientException;
 import org.apache.ignite.internal.client.GridClientNode;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
-import org.apache.ignite.internal.commandline.CommandLogger;
 import org.apache.ignite.internal.commandline.argument.CommandArgUtils;
 import org.apache.ignite.internal.commandline.cache.argument.IdleVerifyCommandArg;
 import org.apache.ignite.internal.processors.cache.verify.IdleVerifyResultV2;
@@ -72,7 +72,7 @@ import static org.apache.ignite.internal.visor.verify.CacheFilterEnum.USER;
  */
 public class IdleVerify implements Command<IdleVerify.Arguments> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Verify counters and hash sums of primary and backup partitions for the specified caches/cache " +
             "groups on an idle cluster and print out the differences, if any. When no parameters are specified, " +
@@ -83,7 +83,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
             " you can verify: only " + USER + " caches, only user " + PERSISTENT + " caches, only user " +
             NOT_PERSISTENT + " caches, only " + SYSTEM + " caches, or " + ALL + " of the above.";
 
-        usageCache(logger,
+        usageCache(
             IDLE_VERIFY,
             description,
             Collections.singletonMap(CHECK_CRC.toString(),
@@ -182,7 +182,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         try (GridClient client = Command.startClient(clientCfg)) {
             Collection<GridClientNode> nodes = client.compute().nodes(GridClientNode::connectable);
 
@@ -306,7 +306,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
     private void cacheIdleVerifyDump(
         GridClient client,
         GridClientConfiguration clientCfg,
-        CommandLogger logger
+        Logger logger
     ) throws GridClientException {
         VisorIdleVerifyDumpTaskArg arg = new VisorIdleVerifyDumpTaskArg(
             args.caches(),
@@ -318,7 +318,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
 
         String path = executeTask(client, VisorIdleVerifyDumpTask.class, arg, clientCfg);
 
-        logger.log("VisorIdleVerifyDumpTask successfully written output to '" + path + "'");
+        logger.info("VisorIdleVerifyDumpTask successfully written output to '" + path + "'");
     }
 
 
@@ -347,7 +347,7 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
     private void legacyCacheIdleVerify(
         GridClient client,
         GridClientConfiguration clientCfg,
-        CommandLogger logger
+        Logger logger
     ) throws GridClientException {
         VisorIdleVerifyTaskResult res = executeTask(
             client,
@@ -358,18 +358,23 @@ public class IdleVerify implements Command<IdleVerify.Arguments> {
         Map<PartitionKey, List<PartitionHashRecord>> conflicts = res.getConflicts();
 
         if (conflicts.isEmpty()) {
-            logger.log("idle_verify check has finished, no conflicts have been found.");
-            logger.nl();
+            logger.info("idle_verify check has finished, no conflicts have been found.");
+            logger.info("");
         }
         else {
-            logger.log("idle_verify check has finished, found " + conflicts.size() + " conflict partitions.");
-            logger.nl();
+            logger.info("idle_verify check has finished, found " + conflicts.size() + " conflict partitions.");
+            logger.info("");
 
             for (Map.Entry<PartitionKey, List<PartitionHashRecord>> entry : conflicts.entrySet()) {
-                logger.log("Conflict partition: " + entry.getKey());
+                logger.info("Conflict partition: " + entry.getKey());
 
-                logger.log("Partition instances: " + entry.getValue());
+                logger.info("Partition instances: " + entry.getValue());
             }
         }
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return IDLE_VERIFY.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
index 68f2ca7..c8b21a7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/commandline/cache/ResetLostPartitions.java
@@ -17,11 +17,11 @@
 package org.apache.ignite.internal.commandline.cache;
 
 import java.util.Set;
+import java.util.logging.Logger;
 import org.apache.ignite.internal.client.GridClient;
 import org.apache.ignite.internal.client.GridClientConfiguration;
 import org.apache.ignite.internal.commandline.Command;
 import org.apache.ignite.internal.commandline.CommandArgIterator;
-import org.apache.ignite.internal.commandline.CommandLogger;
 import org.apache.ignite.internal.commandline.cache.reset_lost_partitions.CacheResetLostPartitionsTask;
 import org.apache.ignite.internal.commandline.cache.reset_lost_partitions.CacheResetLostPartitionsTaskArg;
 import org.apache.ignite.internal.commandline.cache.reset_lost_partitions.CacheResetLostPartitionsTaskResult;
@@ -35,11 +35,11 @@ import static org.apache.ignite.internal.commandline.cache.CacheSubcommands.RESE
  */
 public class ResetLostPartitions implements Command<Set<String>> {
     /** {@inheritDoc} */
-    @Override public void printUsage(CommandLogger logger) {
+    @Override public void printUsage() {
         String CACHES = "cacheName1,...,cacheNameN";
         String description = "Reset the state of lost partitions for the specified caches.";
 
-        usageCache(logger, RESET_LOST_PARTITIONS, description, null, CACHES);
+        usageCache(RESET_LOST_PARTITIONS, description, null, CACHES);
     }
 
     /**
@@ -53,7 +53,7 @@ public class ResetLostPartitions implements Command<Set<String>> {
     }
 
     /** {@inheritDoc} */
-    @Override public Object execute(GridClientConfiguration clientCfg, CommandLogger logger) throws Exception {
+    @Override public Object execute(GridClientConfiguration clientCfg, Logger logger) throws Exception {
         CacheResetLostPartitionsTaskArg taskArg = new CacheResetLostPartitionsTaskArg(caches);
 
         try (GridClient client = Command.startClient(clientCfg)) {
@@ -70,4 +70,9 @@ public class ResetLostPartitions implements Command<Set<String>> {
     @Override public void parseArguments(CommandArgIterator argIter) {
         caches = argIter.nextStringSet("Cache names");
     }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return RESET_LOST_PARTITIONS.text().toUpperCase();
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java b/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java
index f37350a..e758d34 100644
--- a/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/logger/java/JavaLoggerFileHandler.java
@@ -135,7 +135,7 @@ public final class JavaLoggerFileHandler extends StreamHandler {
      * @param workDir Work directory.
      * @return Logging directory.
      */
-    private static File logDirectory(String workDir) throws IgniteCheckedException {
+    public static File logDirectory(String workDir) throws IgniteCheckedException {
         return !F.isEmpty(U.IGNITE_LOG_DIR) ? new File(U.IGNITE_LOG_DIR) :
             U.resolveWorkDirectory(workDir, "log", false);
     }
diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java
index ccfa7f8..edb77e4 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java
@@ -22,8 +22,11 @@ import java.nio.file.DirectoryStream;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
 import java.util.stream.Collectors;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.configuration.AtomicConfiguration;
@@ -90,7 +93,7 @@ public class GridCommandHandlerAbstractTest extends GridCommonAbstractTest {
 
         sysOut = System.out;
 
-        testOut = new ByteArrayOutputStream(20 * 1024 * 1024);
+        testOut = new ByteArrayOutputStream(40 * 1024 * 1024);
 
         checkpointFreq = DataStorageConfiguration.DFLT_CHECKPOINT_FREQ;
     }
@@ -182,7 +185,13 @@ public class GridCommandHandlerAbstractTest extends GridCommonAbstractTest {
         if (!F.isEmpty(args) && !"--help".equalsIgnoreCase(args.get(0)))
             addExtraArguments(args);
 
-        return hnd.execute(args);
+        int exitCode = hnd.execute(args);
+
+        // Flush all Logger handlers to make log data available to test.
+        Logger logger = U.field(hnd, "logger");
+        Arrays.stream(logger.getHandlers()).forEach(Handler::flush);
+
+        return exitCode;
     }
 
     /**
diff --git a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
index 99f1fa6..1778498 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
@@ -1022,8 +1022,15 @@ public class GridCommandHandlerTest extends GridCommandHandlerAbstractTest {
 
         assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute("--baseline", "add", consistentIDs));
 
-        assertTrue(testOut.toString(), testOut.toString().contains("Node not found for consistent ID:"));
-        assertFalse(testOut.toString(), testOut.toString().contains(getTestIgniteInstanceName() + "1"));
+        String testOutStr = testOut.toString();
+
+        // Ignite instase 1 can be logged only in arguments list.
+        boolean isInstanse1Found = Arrays.stream(testOutStr.split("\n"))
+                                        .filter(s -> s.contains("Arguments:"))
+                                        .noneMatch(s -> s.contains(getTestIgniteInstanceName() + "1"));
+
+        assertTrue(testOutStr, testOutStr.contains("Node not found for consistent ID:"));
+        assertFalse(testOutStr, isInstanse1Found);
     }
 
     /**
@@ -2306,20 +2313,21 @@ public class GridCommandHandlerTest extends GridCommandHandlerAbstractTest {
 
         out = testOut.toString();
 
-        // Find last row
-        int lastRowIndex = out.lastIndexOf('\n');
-
-        assertTrue(lastRowIndex > 0);
+        List<String> outLines = Arrays.stream(out.split("\n"))
+                                .map(String::trim)
+                                .collect(Collectors.toList());
 
-        // Last row is empty, but the previous line contains data
-        lastRowIndex = out.lastIndexOf('\n', lastRowIndex - 1);
+        int firstIndex = outLines.indexOf("[next group: id=1544803905, name=default]");
+        int lastIndex  = outLines.lastIndexOf("[next group: id=1544803905, name=default]");
 
-        assertTrue(lastRowIndex > 0);
+        String dataLine = outLines.get(firstIndex + 1);
+        String userArrtDataLine = outLines.get(lastIndex + 1);
 
-        String lastRow = out.substring(lastRowIndex);
+        long commaNum = dataLine.chars().filter(i -> i == ',').count();
+        long userArrtCommaNum = userArrtDataLine.chars().filter(i -> i == ',').count();
 
-        // Since 3 user attributes have been added, the total number of columns in response should be 12 (separators 11)
-        assertEquals(11, lastRow.split(",").length);
+        // Check that number of columns increased by 3
+        assertEquals(3, userArrtCommaNum - commaNum);
     }
 
     /**