Print an additional link at the end of the build pointing where the Build Event Protocol is being streamed.

PiperOrigin-RevId: 199790757
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
index 5138792..80c5599 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
@@ -224,20 +224,23 @@
       logger.fine(format("Will create BuildEventServiceTransport streaming to '%s'",
           besOptions.besBackend));
 
-      final String message;
+      final String besResultsUrl;
       if (!Strings.isNullOrEmpty(besOptions.besResultsUrl)) {
-        String url =
+        besResultsUrl =
             besOptions.besResultsUrl.endsWith("/")
-                ? besOptions.besResultsUrl
-                : besOptions.besResultsUrl + "/";
-        message = "Streaming Build Event Protocol to " + url + invocationId;
+                ? besOptions.besResultsUrl + invocationId
+                : besOptions.besResultsUrl + "/" + invocationId;
+        commandLineReporter.handle(
+            Event.info("Streaming Build Event Protocol to " + besResultsUrl));
       } else {
-        message =
-            format(
-                "Streaming Build Event Protocol to %s build_request_id: %s " + "invocation_id: %s",
-                besOptions.besBackend, buildRequestId, invocationId);
+        besResultsUrl = null;
+        commandLineReporter.handle(
+            Event.info(
+                format(
+                    "Streaming Build Event Protocol to %s build_request_id: %s "
+                        + "invocation_id: %s",
+                    besOptions.besBackend, buildRequestId, invocationId)));
       }
-      commandLineReporter.handle(Event.info(message));
 
       BuildEventTransport besTransport =
           new BuildEventServiceTransport(
@@ -253,7 +256,8 @@
               pathConverter,
               commandLineReporter,
               besOptions.projectId,
-              keywords(besOptions, startupOptionsProvider));
+              keywords(besOptions, startupOptionsProvider),
+              besResultsUrl);
       logger.fine("BuildEventServiceTransport was created successfully");
       return besTransport;
     }
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java
index 42c363b..c19361e 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceTransport.java
@@ -28,6 +28,7 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.SettableFuture;
@@ -86,6 +87,7 @@
   /** Max wait time between isStreamActive checks of the PublishBuildToolEventStream RPC. */
   private static final int STREAMING_RPC_POLL_IN_SECS = 1;
 
+  private final String besResultsUrl;
   private final ListeningExecutorService uploaderExecutorService;
   private final Duration uploadTimeout;
   private final boolean publishLifecycleEvents;
@@ -133,7 +135,8 @@
       PathConverter pathConverter,
       EventHandler commandLineReporter,
       @Nullable String projectId,
-      Set<String> keywords) {
+      Set<String> keywords,
+      @Nullable String besResultsUrl) {
     this(
         besClient,
         uploadTimeout,
@@ -148,7 +151,8 @@
         commandLineReporter,
         projectId,
         keywords,
-        new JavaSleeper());
+        new JavaSleeper(),
+        besResultsUrl);
   }
 
   @VisibleForTesting
@@ -166,7 +170,8 @@
       EventHandler commandLineReporter,
       @Nullable String projectId,
       Set<String> keywords,
-      Sleeper sleeper) {
+      Sleeper sleeper,
+      @Nullable String besResultsUrl) {
     this.besClient = besClient;
     this.besProtoUtil = new BuildEventServiceProtoUtil(
         buildRequestId, invocationId, projectId, command, clock, keywords);
@@ -186,6 +191,7 @@
     this.invocationResult = UNKNOWN_STATUS;
     this.uploadTimeout = uploadTimeout;
     this.sleeper = sleeper;
+    this.besResultsUrl = besResultsUrl;
   }
 
   public boolean isStreaming() {
@@ -244,9 +250,18 @@
                 uploadComplete.get(uploadTimeout.toMillis(), MILLISECONDS);
               }
               report(INFO, UPLOAD_SUCCEEDED_MESSAGE);
+              if (!Strings.isNullOrEmpty(besResultsUrl)) {
+                report(INFO, "Build Event Protocol results available at " + besResultsUrl);
+              }
+
             } catch (Exception e) {
               uploadComplete.cancel(true);
               reportErrorAndFailBuild(e);
+              if (!Strings.isNullOrEmpty(besResultsUrl)) {
+                report(
+                    INFO,
+                    "Partial Build Event Protocol results may be available at " + besResultsUrl);
+              }
             }
           } finally {
             shutdownFuture.set(null);