Introduce sharedRef database log file

Log to file all mutations to the sharedRef database so that each
interaction (creation, update and deletion) is recorded for analysis,
triage and debugging of issues.

Note:
Because multi-site gets installed as libModule, rather than a plugin,
PluginLogFile interface cannot be used, thus log appenders are defined
in a new LibModuleLogFile.

Feature: Issue 11166
Change-Id: I940c48238d8c6b88a439bc8400692de87ece3400
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/LibModuleLogFile.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/LibModuleLogFile.java
new file mode 100644
index 0000000..106bcde
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/LibModuleLogFile.java
@@ -0,0 +1,32 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite;
+
+import com.google.gerrit.server.util.SystemLog;
+import org.apache.log4j.AsyncAppender;
+import org.apache.log4j.Layout;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+public abstract class LibModuleLogFile {
+
+  public LibModuleLogFile(SystemLog systemLog, String logName, Layout layout) {
+    AsyncAppender asyncAppender = systemLog.createAsyncAppender(logName, layout, true, true);
+    Logger logger = LogManager.getLogger(logName);
+    logger.removeAppender(logName);
+    logger.addAppender(asyncAppender);
+    logger.setAdditivity(false);
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
new file mode 100644
index 0000000..90380e3
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
@@ -0,0 +1,87 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite;
+
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.server.CommonConverters;
+import com.google.gerrit.server.OutputFormat;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.gerrit.server.util.SystemLog;
+import com.google.gson.Gson;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.io.IOException;
+import org.apache.log4j.PatternLayout;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class Log4jSharedRefLogger extends LibModuleLogFile implements SharedRefLogger {
+  private static final String LOG_NAME = "sharedref_log";
+  private final Logger sharedRefDBLog;
+  private final GitRepositoryManager gitRepositoryManager;
+  private static final Gson gson = OutputFormat.JSON_COMPACT.newGson();
+
+  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+  @Inject
+  public Log4jSharedRefLogger(SystemLog systemLog, GitRepositoryManager gitRepositoryManager) {
+    super(systemLog, LOG_NAME, new PatternLayout("[%d{ISO8601}] [%t] %-5p : %m%n"));
+    this.gitRepositoryManager = gitRepositoryManager;
+    sharedRefDBLog = LoggerFactory.getLogger(LOG_NAME);
+  }
+
+  @Override
+  public void logRefUpdate(String project, Ref currRef, ObjectId newRefValue) {
+    if (!ObjectId.zeroId().equals(newRefValue)) {
+      try (Repository repository =
+              gitRepositoryManager.openRepository(new Project.NameKey(project));
+          RevWalk walk = new RevWalk(repository)) {
+        RevCommit commit = walk.parseCommit(newRefValue);
+
+        sharedRefDBLog.info(
+            gson.toJson(
+                new SharedRefLogEntry.UpdateRef(
+                    project,
+                    currRef.getName(),
+                    currRef.getObjectId().getName(),
+                    newRefValue.getName(),
+                    CommonConverters.toGitPerson(commit.getCommitterIdent()),
+                    commit.getShortMessage())));
+      } catch (IOException e) {
+        logger.atSevere().withCause(e).log(
+            "Cannot log sharedRefDB interaction for ref %s on project %s",
+            currRef.getName(), project);
+      }
+
+    } else {
+      sharedRefDBLog.info(
+          gson.toJson(
+              new SharedRefLogEntry.DeleteRef(
+                  project, currRef.getName(), currRef.getObjectId().getName())));
+    }
+  }
+
+  @Override
+  public void logProjectDelete(String project) {
+    sharedRefDBLog.info(gson.toJson(new SharedRefLogEntry.DeleteProject(project)));
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
new file mode 100644
index 0000000..f59261e
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
@@ -0,0 +1,71 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite;
+
+import com.google.inject.Inject;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedLockException;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
+import java.io.IOException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+
+public class SharedRefDatabaseWrapper implements SharedRefDatabase {
+
+  private final SharedRefDatabase sharedRefDb;
+  private final SharedRefLogger sharedRefLogger;
+
+  @Inject
+  public SharedRefDatabaseWrapper(
+      SharedRefDatabase sharedRefDatabase, SharedRefLogger sharedRefLogger) {
+    this.sharedRefDb = sharedRefDatabase;
+    this.sharedRefLogger = sharedRefLogger;
+  }
+
+  @Override
+  public boolean isUpToDate(String project, Ref ref) throws SharedLockException {
+    return sharedRefDb.isUpToDate(project, ref);
+  }
+
+  @Override
+  public boolean compareAndPut(String project, Ref currRef, ObjectId newRefValue)
+      throws IOException {
+    boolean succeeded = sharedRefDb.compareAndPut(project, currRef, newRefValue);
+    if (succeeded) {
+      sharedRefLogger.logRefUpdate(project, currRef, newRefValue);
+    }
+    return succeeded;
+  }
+
+  @Override
+  public boolean compareAndRemove(String project, Ref oldRef) throws IOException {
+    return sharedRefDb.compareAndRemove(project, oldRef);
+  }
+
+  @Override
+  public AutoCloseable lockRef(String project, String refName) throws SharedLockException {
+    return sharedRefDb.lockRef(project, refName);
+  }
+
+  @Override
+  public boolean exists(String project, String refName) {
+    return sharedRefDb.exists(project, refName);
+  }
+
+  @Override
+  public void removeProject(String project) throws IOException {
+    sharedRefDb.removeProject(project);
+    sharedRefLogger.logProjectDelete(project);
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogEntry.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogEntry.java
new file mode 100644
index 0000000..50c7949
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogEntry.java
@@ -0,0 +1,75 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite;
+
+import com.google.gerrit.extensions.common.GitPerson;
+
+public class SharedRefLogEntry {
+
+  public enum Type {
+    UPDATE_REF,
+    DELETE_REF,
+    DELETE_PROJECT
+  }
+
+  public String projectName;
+  public Type type;
+
+  public static class UpdateRef extends SharedRefLogEntry {
+
+    public String refName;
+    public String oldId;
+    public String newId;
+    public GitPerson committer;
+    public String comment;
+
+    UpdateRef(
+        String projectName,
+        String refName,
+        String oldId,
+        String newId,
+        GitPerson committer,
+        String comment) {
+      this.type = Type.UPDATE_REF;
+      this.projectName = projectName;
+      this.refName = refName;
+      this.oldId = oldId;
+      this.newId = newId;
+      this.committer = committer;
+      this.comment = comment;
+    }
+  }
+
+  public static class DeleteProject extends SharedRefLogEntry {
+
+    DeleteProject(String projectName) {
+      this.type = Type.DELETE_PROJECT;
+      this.projectName = projectName;
+    }
+  }
+
+  public static class DeleteRef extends SharedRefLogEntry {
+
+    public String refName;
+    public String oldId;
+
+    DeleteRef(String projectName, String refName, String oldId) {
+      this.type = Type.DELETE_REF;
+      this.projectName = projectName;
+      this.refName = refName;
+      this.oldId = oldId;
+    }
+  }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogger.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogger.java
new file mode 100644
index 0000000..0311a53
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefLogger.java
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite;
+
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+
+public interface SharedRefLogger {
+
+  void logRefUpdate(String project, Ref currRef, ObjectId newRefValue);
+
+  void logProjectDelete(String project);
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
index 33be190..15c0a13 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
@@ -17,6 +17,7 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement.EnforcePolicy;
@@ -43,7 +44,7 @@
 
   @Inject
   public BatchRefUpdateValidator(
-      SharedRefDatabase sharedRefDb,
+      SharedRefDatabaseWrapper sharedRefDb,
       ValidationMetrics validationMetrics,
       SharedRefEnforcement refEnforcement,
       @Assisted String projectName,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
index 15e8602..5330bca 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
@@ -20,6 +20,7 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.OutOfSyncException;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedDbSplitBrainException;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedLockException;
@@ -36,7 +37,7 @@
 public class RefUpdateValidator {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  protected final SharedRefDatabase sharedRefDb;
+  protected final SharedRefDatabaseWrapper sharedRefDb;
   protected final ValidationMetrics validationMetrics;
 
   protected final String projectName;
@@ -66,7 +67,7 @@
 
   @Inject
   public RefUpdateValidator(
-      SharedRefDatabase sharedRefDb,
+      SharedRefDatabaseWrapper sharedRefDb,
       ValidationMetrics validationMetrics,
       SharedRefEnforcement refEnforcement,
       @Assisted String projectName,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
index 1dfc3f9..9626739 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
@@ -20,6 +20,8 @@
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.inject.Scopes;
 import com.googlesource.gerrit.plugins.multisite.Configuration;
+import com.googlesource.gerrit.plugins.multisite.Log4jSharedRefLogger;
+import com.googlesource.gerrit.plugins.multisite.SharedRefLogger;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.CustomSharedRefEnforcementByProject;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
@@ -35,6 +37,8 @@
 
   @Override
   protected void configure() {
+    bind(SharedRefLogger.class).to(Log4jSharedRefLogger.class);
+
     factory(MultiSiteRepository.Factory.class);
     factory(MultiSiteRefDatabase.Factory.class);
     factory(MultiSiteRefUpdate.Factory.class);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
index bf5fc44..29c0a0c 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
@@ -19,6 +19,7 @@
 import static org.eclipse.jgit.transport.ReceiveCommand.Type.UPDATE;
 
 import com.google.gerrit.metrics.DisabledMetricMaker;
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
@@ -54,7 +55,7 @@
   private RevCommit B;
 
   ZookeeperTestContainerSupport zookeeperContainer;
-  ZkSharedRefDatabase zkSharedRefDatabase;
+  SharedRefDatabaseWrapper zkSharedRefDatabase;
 
   @Before
   public void setup() throws Exception {
@@ -79,11 +80,13 @@
     int NUMBER_OF_RETRIES = 5;
 
     zkSharedRefDatabase =
-        new ZkSharedRefDatabase(
-            zookeeperContainer.getCurator(),
-            new ZkConnectionConfig(
-                new RetryNTimes(NUMBER_OF_RETRIES, SLEEP_BETWEEN_RETRIES_MS),
-                TRANSACTION_LOCK_TIMEOUT));
+        new SharedRefDatabaseWrapper(
+            new ZkSharedRefDatabase(
+                zookeeperContainer.getCurator(),
+                new ZkConnectionConfig(
+                    new RetryNTimes(NUMBER_OF_RETRIES, SLEEP_BETWEEN_RETRIES_MS),
+                    TRANSACTION_LOCK_TIMEOUT)),
+            new DisabledSharedRefLogger());
   }
 
   @Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DisabledSharedRefLogger.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DisabledSharedRefLogger.java
new file mode 100644
index 0000000..5fc66ad
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/DisabledSharedRefLogger.java
@@ -0,0 +1,30 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.googlesource.gerrit.plugins.multisite.validation;
+
+import com.googlesource.gerrit.plugins.multisite.SharedRefLogger;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.junit.Ignore;
+
+@Ignore
+public class DisabledSharedRefLogger implements SharedRefLogger {
+
+  @Override
+  public void logRefUpdate(String project, Ref currRef, ObjectId newRefValue) {}
+
+  @Override
+  public void logProjectDelete(String project) {}
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
index 9acedef..fb7b58d 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
@@ -23,8 +23,8 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
 import java.io.IOException;
 import java.util.Collections;
@@ -48,7 +48,7 @@
 @RunWith(MockitoJUnitRunner.class)
 public class MultiSiteBatchRefUpdateTest implements RefFixture {
 
-  @Mock SharedRefDatabase sharedRefDb;
+  @Mock SharedRefDatabaseWrapper sharedRefDb;
   @Mock BatchRefUpdate batchRefUpdate;
   @Mock RefDatabase refDatabase;
   @Mock RevWalk revWalk;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
index 8dcaf3a..74a45e1 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
@@ -21,9 +21,9 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyZeroInteractions;
 
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
 import com.googlesource.gerrit.plugins.multisite.validation.RefUpdateValidator.Factory;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefUpdateStub;
 import java.io.IOException;
@@ -46,7 +46,7 @@
 // working, and the other way around
 public class MultiSiteRefUpdateTest implements RefFixture {
 
-  @Mock SharedRefDatabase sharedRefDb;
+  @Mock SharedRefDatabaseWrapper sharedRefDb;
   @Mock ValidationMetrics validationMetrics;
   @Mock RefDatabase refDb;
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
index 6fa7ed4..4177b02 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
@@ -22,6 +22,7 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.OutOfSyncException;
 import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedDbSplitBrainException;
@@ -44,7 +45,7 @@
   private static final DefaultSharedRefEnforcement defaultRefEnforcement =
       new DefaultSharedRefEnforcement();
 
-  @Mock SharedRefDatabase sharedRefDb;
+  @Mock SharedRefDatabaseWrapper sharedRefDb;
 
   @Mock RefDatabase localRefDb;
 
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
index cfa5476..3f10908 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
@@ -20,7 +20,9 @@
 
 import com.google.gerrit.acceptance.AbstractDaemonTest;
 import com.google.gerrit.metrics.DisabledMetricMaker;
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
 import com.googlesource.gerrit.plugins.multisite.validation.BatchRefUpdateValidator;
+import com.googlesource.gerrit.plugins.multisite.validation.DisabledSharedRefLogger;
 import com.googlesource.gerrit.plugins.multisite.validation.MultiSiteBatchRefUpdate;
 import com.googlesource.gerrit.plugins.multisite.validation.ValidationMetrics;
 import com.googlesource.gerrit.plugins.multisite.validation.ZkConnectionConfig;
@@ -46,7 +48,7 @@
   @Rule public TestName nameRule = new TestName();
 
   ZookeeperTestContainerSupport zookeeperContainer;
-  ZkSharedRefDatabase zkSharedRefDatabase;
+  SharedRefDatabaseWrapper zkSharedRefDatabase;
   SharedRefEnforcement refEnforcement;
 
   int SLEEP_BETWEEN_RETRIES_MS = 30;
@@ -58,11 +60,13 @@
     refEnforcement = new DefaultSharedRefEnforcement();
     zookeeperContainer = new ZookeeperTestContainerSupport(false);
     zkSharedRefDatabase =
-        new ZkSharedRefDatabase(
-            zookeeperContainer.getCurator(),
-            new ZkConnectionConfig(
-                new RetryNTimes(NUMBER_OF_RETRIES, SLEEP_BETWEEN_RETRIES_MS),
-                TRANSACTION_LOCK_TIMEOUT));
+        new SharedRefDatabaseWrapper(
+            new ZkSharedRefDatabase(
+                zookeeperContainer.getCurator(),
+                new ZkConnectionConfig(
+                    new RetryNTimes(NUMBER_OF_RETRIES, SLEEP_BETWEEN_RETRIES_MS),
+                    TRANSACTION_LOCK_TIMEOUT)),
+            new DisabledSharedRefLogger());
   }
 
   @After