Add "info server_log" command to retrieve the log file path.

We emit several logs: client output to STDOUT & STDERR, server STDOUT & STDERR
(saved in jvm.out), the command log, the master log, and various additional log
files written by helper tools and specific modules.

But the log file which is often the most useful for diagnosing errors and
understanding unexpected build behavior is the server log, which contains
extensive debug information from the server process. We want to expose its
location in the "info" command to make it easier to find.

RELNOTES: Added "bazel info server_log" command to obtain the main Bazel server
log file path, which can be quite useful for debugging Bazel issues.
PiperOrigin-RevId: 211844422
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
index 5e65c97..a448723 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoCommand.java
@@ -221,6 +221,7 @@
             new InfoItem.BlazeTestlogsInfoItem(productName),
             new InfoItem.ReleaseInfoItem(productName),
             new InfoItem.ServerPidInfoItem(productName),
+            new InfoItem.ServerLogInfoItem(productName),
             new InfoItem.PackagePathInfoItem(commandOptions),
             new InfoItem.UsedHeapSizeInfoItem(),
             new InfoItem.UsedHeapSizeAfterGcInfoItem(),
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
index b209a5d0..1612492 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/commands/InfoItem.java
@@ -35,6 +35,7 @@
 import com.google.devtools.build.lib.query2.proto.proto2api.Build.RuleDefinition;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.util.AbruptExitException;
+import com.google.devtools.build.lib.util.LogHandlerQuerier;
 import com.google.devtools.build.lib.util.ProcessUtils;
 import com.google.devtools.build.lib.util.StringUtilities;
 import com.google.devtools.build.lib.vfs.Path;
@@ -50,6 +51,9 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.Map;
+import java.util.Optional;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * An item that is returned by <code>blaze info</code>.
@@ -270,6 +274,44 @@
     }
   }
 
+  /** Info item for server_log path. */
+  public static class ServerLogInfoItem extends InfoItem {
+    private static final Logger logger = Logger.getLogger(ServerLogInfoItem.class.getName());
+
+    /**
+     * Constructs an info item for the server log path.
+     *
+     * @param productName name of the tool whose server log path will be queried
+     */
+    public ServerLogInfoItem(String productName) {
+      super("server_log", productName + " server log path", false);
+    }
+
+    @Override
+    public byte[] get(Supplier<BuildConfiguration> configurationSupplier, CommandEnvironment env)
+        throws AbruptExitException {
+      LogHandlerQuerier logHandlerQuerier;
+      try {
+        logHandlerQuerier = LogHandlerQuerier.getConfiguredInstance();
+      } catch (IllegalStateException e) {
+        // Non-fatal error: we don't want the "info" command to crash.
+        logger.log(Level.WARNING, "Could not find a querier for server log location", e);
+        return print("UNKNOWN LOG LOCATION");
+      }
+      Optional<java.nio.file.Path> loggerFilePath;
+      try {
+        loggerFilePath = logHandlerQuerier.getLoggerFilePath(logger);
+      } catch (IllegalArgumentException e) {
+        // Non-fatal error: we don't want the "info" command to crash.
+        logger.log(Level.WARNING, "Could not query for server log location", e);
+        return print("UNKNOWN LOG LOCATION");
+      }
+      // If loggerFilePath is empty, then no log file is currently open, so an empty string is the
+      // correct output.
+      return print(loggerFilePath.map(java.nio.file.Path::toString).orElse(""));
+    }
+  }
+
   /**
    * Info item for release
    */
diff --git a/src/test/shell/bazel/client_test.sh b/src/test/shell/bazel/client_test.sh
index dd67dc4..ff8b7a3 100755
--- a/src/test/shell/bazel/client_test.sh
+++ b/src/test/shell/bazel/client_test.sh
@@ -32,6 +32,7 @@
   expect_log "^bazel-testlogs:.*_bazel.*bazel-out.*testlogs\$"
   expect_log "^output_path:.*/execroot/blerp/bazel-out\$"
   expect_log "^execution_root:.*/execroot/blerp\$"
+  expect_log "^server_log:.*/java\.log.*\$"
 }
 
 # This test is for Bazel only and not for Google's internal version (Blaze),