Merge branch 'stable-3.7' into stable-3.8

* stable-3.7:
  Add metrics for git/upload-pack/*bitmap* misses
  Add timer for git/upload-pack/phase_searching_for_*
  Fix: CommentTimestampAdapter can't parse some old comments
  Add timer for git/upload-pack/phase_negotiating
  H2CacheImpl: Lower logging level for no pruning

Release-Notes: skip
Change-Id: I13c3d2502d347409682f4c355a73847dbb410cde
diff --git a/Documentation/metrics.txt b/Documentation/metrics.txt
index 93e0eb4..8b21ca2 100644
--- a/Documentation/metrics.txt
+++ b/Documentation/metrics.txt
@@ -389,12 +389,27 @@
 * `git/upload-pack/request_count`: Total number of git-upload-pack requests.
 ** `operation`:
    The name of the operation (CLONE, FETCH).
+* `git/upload-pack/bitmap_index_misses_count`: Number of bitmap index misses per request.
+** `operation`:
+   The name of the operation (CLONE, FETCH).
+* `git/upload-pack/no_bitmap_index`: Total number of requests executed without a bitmap index.
+** `operation`:
+   The name of the operation (CLONE, FETCH).
 * `git/upload-pack/phase_counting`: Time spent in the 'Counting...' phase.
 ** `operation`:
    The name of the operation (CLONE, FETCH).
 * `git/upload-pack/phase_compressing`: Time spent in the 'Compressing...' phase.
 ** `operation`:
    The name of the operation (CLONE, FETCH).
+* `git/upload-pack/phase_negotiating`: Time spent in the negotiation phase.
+** `operation`:
+   The name of the operation (CLONE, FETCH).
+* `git/upload-pack/phase_searching_for_reuse`: Time spent in the 'Finding sources...' while searching for reuse phase.
+** `operation`:
+   The name of the operation (CLONE, FETCH).
+* `git/upload-pack/phase_searching_for_sizes`: Time spent in the 'Finding sources...' while searching for sizes phase.
+** `operation`:
+   The name of the operation (CLONE, FETCH).
 * `git/upload-pack/phase_writing`: Time spent transferring bytes to client.
 ** `operation`:
    The name of the operation (CLONE, FETCH).
diff --git a/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java b/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
index f0010e4..27a09ed 100644
--- a/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
+++ b/java/com/google/gerrit/server/cache/h2/H2CacheImpl.java
@@ -666,7 +666,7 @@
           }
           String formattedMaxSize = CacheInfo.EntriesInfo.bytes(maxSize);
           if (used <= maxSize) {
-            logger.atInfo().log(
+            logger.atFine().log(
                 "Cache %s size (%s) is less than maxSize (%s), not pruning",
                 url, CacheInfo.EntriesInfo.bytes(used), formattedMaxSize);
             return;
diff --git a/java/com/google/gerrit/server/git/UploadPackMetricsHook.java b/java/com/google/gerrit/server/git/UploadPackMetricsHook.java
index 1619add..0e981f2 100644
--- a/java/com/google/gerrit/server/git/UploadPackMetricsHook.java
+++ b/java/com/google/gerrit/server/git/UploadPackMetricsHook.java
@@ -38,7 +38,12 @@
 
   private final Counter1<Operation> requestCount;
   private final Timer1<Operation> counting;
+  private final Histogram1<Operation> bitmapIndexMissesCount;
+  private final Counter1<Operation> noBitmapIndex;
   private final Timer1<Operation> compressing;
+  private final Timer1<Operation> negotiating;
+  private final Timer1<Operation> searchingForReuse;
+  private final Timer1<Operation> searchingForSizes;
   private final Timer1<Operation> writing;
   private final Histogram1<Operation> packBytes;
 
@@ -64,6 +69,22 @@
                 .setUnit(Units.MILLISECONDS),
             operationField);
 
+    bitmapIndexMissesCount =
+        metricMaker.newHistogram(
+            "git/upload-pack/bitmap_index_misses_count",
+            new Description("Number of bitmap index misses per request")
+                .setCumulative()
+                .setUnit("misses"),
+            operationField);
+
+    noBitmapIndex =
+        metricMaker.newCounter(
+            "git/upload-pack/no_bitmap_index",
+            new Description("Total number of requests executed without a bitmap index")
+                .setRate()
+                .setUnit("requests"),
+            operationField);
+
     compressing =
         metricMaker.newTimer(
             "git/upload-pack/phase_compressing",
@@ -72,6 +93,32 @@
                 .setUnit(Units.MILLISECONDS),
             operationField);
 
+    negotiating =
+        metricMaker.newTimer(
+            "git/upload-pack/phase_negotiating",
+            new Description("Time spent in the negotiation phase")
+                .setCumulative()
+                .setUnit(Units.MILLISECONDS),
+            operationField);
+
+    searchingForReuse =
+        metricMaker.newTimer(
+            "git/upload-pack/phase_searching_for_reuse",
+            new Description(
+                    "Time spent in the 'Finding sources...' while searching for reuse phase")
+                .setCumulative()
+                .setUnit(Units.MILLISECONDS),
+            operationField);
+
+    searchingForSizes =
+        metricMaker.newTimer(
+            "git/upload-pack/phase_searching_for_sizes",
+            new Description(
+                    "Time spent in the 'Finding sources...' while searching for sizes phase")
+                .setCumulative()
+                .setUnit(Units.MILLISECONDS),
+            operationField);
+
     writing =
         metricMaker.newTimer(
             "git/upload-pack/phase_writing",
@@ -98,7 +145,16 @@
 
     requestCount.increment(op);
     counting.record(op, stats.getTimeCounting(), MILLISECONDS);
+    long bitmapIndexMisses = stats.getBitmapIndexMisses();
+    if (bitmapIndexMisses < 0) {
+      noBitmapIndex.increment(op);
+    } else {
+      bitmapIndexMissesCount.record(op, bitmapIndexMisses);
+    }
     compressing.record(op, stats.getTimeCompressing(), MILLISECONDS);
+    negotiating.record(op, stats.getTimeNegotiating(), MILLISECONDS);
+    searchingForReuse.record(op, stats.getTimeSearchingForReuse(), MILLISECONDS);
+    searchingForSizes.record(op, stats.getTimeSearchingForSizes(), MILLISECONDS);
     writing.record(op, stats.getTimeWriting(), MILLISECONDS);
     packBytes.record(op, stats.getTotalBytes());
   }