Merge branch 'stable-3.5' into stable-3.6

* stable-3.5:
  Index.replace: Log responses containing errors
  Remove warning stating that Elasticsearch is not production ready
  Add trace timer around Elasticsearch's performRequest
  Fix Flogger issues flagged by error prone
  Fix incorrect symlink in build docs
  Fix Flogger compile time errors

Release-Notes: skip
Change-Id: I42642e61af9166bf1155f333fe57a01a46c5b80c
diff --git a/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index fce86b9..482868c 100644
--- a/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -52,6 +52,8 @@
 import com.google.gerrit.server.config.SitePaths;
 import com.google.gerrit.server.index.IndexUtils;
 import com.google.gerrit.server.index.options.AutoFlush;
+import com.google.gerrit.server.logging.Metadata;
+import com.google.gerrit.server.logging.TraceContext;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonArray;
@@ -282,7 +284,11 @@
           String.format("Expected %s, but was: %s", ContentType.APPLICATION_JSON, contentType));
       String responseStr = EntityUtils.toString(response.getEntity());
       JsonObject responseJson = (JsonObject) new JsonParser().parse(responseStr);
-      return responseJson.get("errors").getAsBoolean();
+      boolean hasErrors = responseJson.get("errors").getAsBoolean();
+      if (hasErrors) {
+        logger.atSevere().log("Response with errors: %s", responseJson);
+      }
+      return hasErrors;
     } catch (IOException e) {
       throw new StorageException(e);
     }
@@ -354,7 +360,15 @@
     for (Map.Entry<String, String> entry : params.entrySet()) {
       request.addParameter(entry.getKey(), entry.getValue());
     }
-    try {
+    try (TraceContext.TraceTimer traceTimer =
+        TraceContext.newTimer(
+            "Elasticsearch perform request",
+            Metadata.builder()
+                .indexName(indexName)
+                .operationName(
+                    String.format(
+                        "method:%s uri:%s payload:%s params:%s", method, uri, payload, params))
+                .build())) {
       return client.get().performRequest(request);
     } catch (IOException e) {
       throw new StorageException(e);
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 1954cb0..5d0dead 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -22,8 +22,7 @@
 
 ## Section elasticsearch
 
-WARNING: Support for Elasticsearch is still experimental and is not recommended for production
-use. For compatibility information, please refer to the [project homepage](https://www.gerritcodereview.com/elasticsearch.html).
+For compatibility information, please refer to the [project homepage](https://www.gerritcodereview.com/elasticsearch.html).
 
 Note that when Gerrit is configured to use Elasticsearch, the Elasticsearch
 server(s) must be reachable during the site initialization.