Add verbosity field to worker protocol, primarily controlled by the `--worker_verbose` flag.

RELNOTES: None.
PiperOrigin-RevId: 383862477
diff --git a/site/docs/persistent-workers.md b/site/docs/persistent-workers.md
index c931629..d84bfc5 100644
--- a/site/docs/persistent-workers.md
+++ b/site/docs/persistent-workers.md
@@ -147,7 +147,9 @@
 flag is mainly useful for debugging and profiling. This flag forces all workers
 to quit once a build is done. You can also pass
 [`--worker_verbose`](command-line-reference.html#flag--worker_verbose) to get
-more output about what the workers are doing.
+more output about what the workers are doing. This flag is reflected in the
+`verbosity` field in `WorkRequest`, allowing worker implementations to also be
+more verbose.
 
 Workers store their logs in the `<outputBase>/bazel-workers` directory, for
 example
diff --git a/src/main/java/com/google/devtools/build/lib/worker/JsonWorkerMessageProcessor.java b/src/main/java/com/google/devtools/build/lib/worker/JsonWorkerMessageProcessor.java
index 804d6cb..68e9835 100644
--- a/src/main/java/com/google/devtools/build/lib/worker/JsonWorkerMessageProcessor.java
+++ b/src/main/java/com/google/devtools/build/lib/worker/JsonWorkerMessageProcessor.java
@@ -104,6 +104,7 @@
     List<String> arguments = null;
     List<Input> inputs = null;
     Integer requestId = null;
+    Integer verbosity = null;
     try {
       reader.beginObject();
       while (reader.hasNext()) {
@@ -127,6 +128,12 @@
             }
             requestId = reader.nextInt();
             break;
+          case "verbosity":
+            if (verbosity != null) {
+              throw new IOException("Work response cannot have more than one verbosity");
+            }
+            verbosity = reader.nextInt();
+            break;
           default:
             // As per https://docs.bazel.build/versions/main/creating-workers.html#work-responses,
             // unknown fields are ignored.
@@ -149,6 +156,9 @@
     if (requestId != null) {
       requestBuilder.setRequestId(requestId);
     }
+    if (verbosity != null) {
+      requestBuilder.setVerbosity(verbosity);
+    }
     return requestBuilder.build();
   }
 
diff --git a/src/main/java/com/google/devtools/build/lib/worker/WorkerSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/worker/WorkerSpawnRunner.java
index 6bf012d..8889160 100644
--- a/src/main/java/com/google/devtools/build/lib/worker/WorkerSpawnRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/worker/WorkerSpawnRunner.java
@@ -83,6 +83,11 @@
   public static final String REASON_NO_FLAGFILE =
       "because the command-line arguments do not contain at least one @flagfile or --flagfile=";
   public static final String REASON_NO_TOOLS = "because the action has no tools";
+  /**
+   * The verbosity level implied by `--worker_verbose`. This value allows for manually setting some
+   * only-slightly-verbose levels.
+   */
+  private static final int VERBOSE_LEVEL = 10;
 
   /** Pattern for @flagfile.txt and --flagfile=flagfile.txt */
   private static final Pattern FLAG_FILE_PATTERN = Pattern.compile("(?:@|--?flagfile=)(.+)");
@@ -320,6 +325,9 @@
 
       requestBuilder.addInputsBuilder().setPath(input.getExecPathString()).setDigest(digest);
     }
+    if (workerOptions.workerVerbose) {
+      requestBuilder.setVerbosity(VERBOSE_LEVEL);
+    }
     if (key.isMultiplex()) {
       requestBuilder.setRequestId(requestIdCounter.getAndIncrement());
     }
diff --git a/src/main/protobuf/worker_protocol.proto b/src/main/protobuf/worker_protocol.proto
index 2381df1..6d3d1aa 100644
--- a/src/main/protobuf/worker_protocol.proto
+++ b/src/main/protobuf/worker_protocol.proto
@@ -53,6 +53,11 @@
   // previously sent WorkRequest with the same request_id should be cancelled.
   // The arguments and inputs fields must be empty and should be ignored.
   bool cancel = 4;
+
+  // Values greater than 0 indicate that the worker should output extra debug
+  // information to stderr (which will go into the worker log). Setting the
+  // --worker_verbose flag for Bazel makes this flag default to 10.
+  int32 verbosity = 5;
 }
 
 // The worker sends this message to Blaze when it finished its work on the
diff --git a/src/test/java/com/google/devtools/build/lib/worker/ExampleWorker.java b/src/test/java/com/google/devtools/build/lib/worker/ExampleWorker.java
index 50439bd..a032c13 100644
--- a/src/test/java/com/google/devtools/build/lib/worker/ExampleWorker.java
+++ b/src/test/java/com/google/devtools/build/lib/worker/ExampleWorker.java
@@ -184,6 +184,9 @@
         }
       } else {
         try {
+          if (currentRequest.getVerbosity() > 0) {
+            originalStdErr.println("VERBOSE: Pretending to do work.");
+          }
           parseOptionsAndLog(args);
         } catch (Exception e) {
           e.printStackTrace();
diff --git a/src/test/java/com/google/devtools/build/lib/worker/WorkerTest.java b/src/test/java/com/google/devtools/build/lib/worker/WorkerTest.java
index e67aa064..ae0badb 100644
--- a/src/test/java/com/google/devtools/build/lib/worker/WorkerTest.java
+++ b/src/test/java/com/google/devtools/build/lib/worker/WorkerTest.java
@@ -142,6 +142,7 @@
                     .setDigest(ByteString.copyFromUtf8("testDigest"))
                     .build())
             .setRequestId(1)
+            .setVerbosity(11)
             .build();
 
     TestWorker testWorker = createTestWorker(new byte[0], JSON);
@@ -150,7 +151,7 @@
     OutputStream stdout = testWorker.getFakeSubprocess().getOutputStream();
     String requestJsonString =
         "{\"arguments\":[\"testRequest\"],\"inputs\":"
-            + "[{\"path\":\"testPath\",\"digest\":\"dGVzdERpZ2VzdA==\"}],\"requestId\":1}";
+            + "[{\"path\":\"testPath\",\"digest\":\"dGVzdERpZ2VzdA==\"}],\"requestId\":1,\"verbosity\":11}";
     assertThat(stdout.toString()).isEqualTo(requestJsonString);
   }
 
diff --git a/src/test/shell/integration/bazel_worker_test.sh b/src/test/shell/integration/bazel_worker_test.sh
index 157d88d..a427e3f 100755
--- a/src/test/shell/integration/bazel_worker_test.sh
+++ b/src/test/shell/integration/bazel_worker_test.sh
@@ -360,6 +360,8 @@
     && fail "expected build to fail" || true
 
   expect_log "Worker process did not return a WorkResponse:"
+  # Worker log gets displayed on error, including verbosity messages.
+  expect_log "VERBOSE: Pretending to do work."
 }
 
 function test_worker_restarts_when_worker_binary_changes() {