Revert^2 "Add ability to persist Lucene logs"

This reverts commit 18e7e68117af337fc831fe6352bae1c5c83361f1.

Reason for revert: Amending revert to inject sitePath correctly, so that
tests pass

Release-Notes: Add ability to persist Lucene logs
Bug: Issue 454830631
Change-Id: I4e8e3cf7ef797588bf74d28596fbbcc5068bf4e6
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 6f1fc9f..309e3e2 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3858,6 +3858,16 @@
 +
 Defaults to -1 for (auto detection).
 
+[[index.name.persistInfoStream]]index.name.persistInfoStream::
++
+Enable Lucene's info stream logging. This can be useful when admins face ongoing
+indexing transactionality or persistence issues that are hard to debug without
+further information.
++
+NOTE: This could potentially add additional load on the system, especially if
+enabled for all indexes; appropriate tests should be carried out before enabling
+this option on a production system.
+
 [[index.name.enableAutoIOThrottle]]index.name.enableAutoIOThrottle::
 +
 Allows the control of whether automatic IO throttling is enabled and used by
diff --git a/java/com/google/gerrit/lucene/GerritIndexWriterConfig.java b/java/com/google/gerrit/lucene/GerritIndexWriterConfig.java
index bec63bd..c5afdee 100644
--- a/java/com/google/gerrit/lucene/GerritIndexWriterConfig.java
+++ b/java/com/google/gerrit/lucene/GerritIndexWriterConfig.java
@@ -19,12 +19,18 @@
 
 import com.google.common.collect.ImmutableMap;
 import com.google.gerrit.server.config.ConfigUtil;
+import com.google.gerrit.server.config.SitePaths;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
 import org.apache.lucene.analysis.CharArraySet;
 import org.apache.lucene.analysis.standard.StandardAnalyzer;
 import org.apache.lucene.index.ConcurrentMergeScheduler;
 import org.apache.lucene.index.IndexDeletionPolicy;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
+import org.apache.lucene.util.PrintStreamInfoStream;
 import org.eclipse.jgit.lib.Config;
 
 /** Combination of Lucene {@link IndexWriterConfig} with additional Gerrit-specific options. */
@@ -36,7 +42,8 @@
   private long commitWithinMs;
   private final CustomMappingAnalyzer analyzer;
 
-  GerritIndexWriterConfig(Config cfg, String name) {
+  GerritIndexWriterConfig(Config cfg, String name, SitePaths sitePaths)
+      throws FileNotFoundException {
     analyzer =
         new CustomMappingAnalyzer(
             new StandardAnalyzer(CharArraySet.EMPTY_SET), CUSTOM_CHAR_MAPPING);
@@ -76,6 +83,15 @@
     } catch (IllegalArgumentException e) {
       commitWithinMs = cfg.getLong("index", name, "commitWithin", 0);
     }
+
+    boolean enableLogging = cfg.getBoolean("index", name, "persistInfoStream", false);
+    if (enableLogging) {
+      luceneConfig.setInfoStream(
+          new PrintStreamInfoStream(
+              new PrintStream(
+                  new FileOutputStream(new File(sitePaths.logs_dir.toFile(), name + "_lucene_log")),
+                  true)));
+    }
   }
 
   void setIndexDeletionPolicy(IndexDeletionPolicy indexDeletionPolicy) {
diff --git a/java/com/google/gerrit/lucene/LuceneAccountIndex.java b/java/com/google/gerrit/lucene/LuceneAccountIndex.java
index 9c0baa8..436f403 100644
--- a/java/com/google/gerrit/lucene/LuceneAccountIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneAccountIndex.java
@@ -106,13 +106,13 @@
         ACCOUNTS,
         ImmutableSet.of(),
         null,
-        new GerritIndexWriterConfig(cfg, ACCOUNTS),
+        new GerritIndexWriterConfig(cfg, ACCOUNTS, sitePaths),
         new SearcherFactory(),
         autoFlush,
         AccountIndex.ENTITY_TO_KEY);
     this.accountCache = accountCache;
 
-    indexWriterConfig = new GerritIndexWriterConfig(cfg, ACCOUNTS);
+    indexWriterConfig = new GerritIndexWriterConfig(cfg, ACCOUNTS, sitePaths);
     queryBuilder = new QueryBuilder<>(schema, indexWriterConfig.getAnalyzer());
   }
 
diff --git a/java/com/google/gerrit/lucene/LuceneChangeIndex.java b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
index ffd25ba..12d2455 100644
--- a/java/com/google/gerrit/lucene/LuceneChangeIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneChangeIndex.java
@@ -146,8 +146,10 @@
             ? ImmutableSet.of()
             : ImmutableSet.of(ChangeField.MERGEABLE_SPEC.getName());
 
-    GerritIndexWriterConfig openConfig = new GerritIndexWriterConfig(cfg, "changes_open");
-    GerritIndexWriterConfig closedConfig = new GerritIndexWriterConfig(cfg, "changes_closed");
+    GerritIndexWriterConfig openConfig =
+        new GerritIndexWriterConfig(cfg, "changes_open", sitePaths);
+    GerritIndexWriterConfig closedConfig =
+        new GerritIndexWriterConfig(cfg, "changes_closed", sitePaths);
 
     queryBuilder = new QueryBuilder<>(schema, openConfig.getAnalyzer());
 
diff --git a/java/com/google/gerrit/lucene/LuceneGroupIndex.java b/java/com/google/gerrit/lucene/LuceneGroupIndex.java
index 6301421..46d8825 100644
--- a/java/com/google/gerrit/lucene/LuceneGroupIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneGroupIndex.java
@@ -96,13 +96,13 @@
         GROUPS,
         ImmutableSet.of(),
         null,
-        new GerritIndexWriterConfig(cfg, GROUPS),
+        new GerritIndexWriterConfig(cfg, GROUPS, sitePaths),
         new SearcherFactory(),
         autoFlush,
         GroupIndex.ENTITY_TO_KEY);
     this.groupCache = groupCache;
 
-    indexWriterConfig = new GerritIndexWriterConfig(cfg, GROUPS);
+    indexWriterConfig = new GerritIndexWriterConfig(cfg, GROUPS, sitePaths);
     queryBuilder = new QueryBuilder<>(schema, indexWriterConfig.getAnalyzer());
   }
 
diff --git a/java/com/google/gerrit/lucene/LuceneProjectIndex.java b/java/com/google/gerrit/lucene/LuceneProjectIndex.java
index 911d91f..f263c8e 100644
--- a/java/com/google/gerrit/lucene/LuceneProjectIndex.java
+++ b/java/com/google/gerrit/lucene/LuceneProjectIndex.java
@@ -96,13 +96,13 @@
         PROJECTS,
         ImmutableSet.of(),
         null,
-        new GerritIndexWriterConfig(cfg, PROJECTS),
+        new GerritIndexWriterConfig(cfg, PROJECTS, sitePaths),
         new SearcherFactory(),
         autoFlush,
         ProjectIndex.ENTITY_TO_KEY);
     this.projectCache = projectCache;
 
-    indexWriterConfig = new GerritIndexWriterConfig(cfg, PROJECTS);
+    indexWriterConfig = new GerritIndexWriterConfig(cfg, PROJECTS, sitePaths);
     queryBuilder = new QueryBuilder<>(schema, indexWriterConfig.getAnalyzer());
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/lucene/BUILD b/javatests/com/google/gerrit/acceptance/lucene/BUILD
new file mode 100644
index 0000000..abc979d
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/lucene/BUILD
@@ -0,0 +1,9 @@
+load("//javatests/com/google/gerrit/acceptance:tests.bzl", "acceptance_tests")
+
+acceptance_tests(
+    srcs = [
+        "LuceneIndexInfoStreamIT.java",
+    ],
+    group = "lucene",
+    labels = ["lucene"],
+)
diff --git a/javatests/com/google/gerrit/acceptance/lucene/LuceneIndexInfoStreamIT.java b/javatests/com/google/gerrit/acceptance/lucene/LuceneIndexInfoStreamIT.java
new file mode 100644
index 0000000..25133ff
--- /dev/null
+++ b/javatests/com/google/gerrit/acceptance/lucene/LuceneIndexInfoStreamIT.java
@@ -0,0 +1,58 @@
+// Copyright (C) 2025 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.google.gerrit.acceptance.lucene;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.gerrit.acceptance.AbstractDaemonTest;
+import com.google.gerrit.acceptance.config.GerritConfig;
+import com.google.gerrit.server.config.SitePaths;
+import java.io.File;
+import javax.inject.Inject;
+import org.junit.Test;
+
+public class LuceneIndexInfoStreamIT extends AbstractDaemonTest {
+
+  @Inject private SitePaths sitePaths;
+
+  @Test
+  @GerritConfig(name = "index.changes_open.persistInfoStream", value = "true")
+  @GerritConfig(name = "index.type", value = "lucene")
+  public void luceneInfoStreamFileIsCreatedAndIsNotEmptyWhenEnabled() throws Exception {
+    createChange();
+
+    File[] luceneChangesIndexfolders =
+        sitePaths
+            .logs_dir
+            .toFile()
+            .listFiles((dir, name) -> name.equals("changes_open_lucene_log"));
+    assertThat(luceneChangesIndexfolders).isNotNull();
+    assertThat(luceneChangesIndexfolders).hasLength(1);
+  }
+
+  @Test
+  @GerritConfig(name = "index.type", value = "lucene")
+  public void luceneInfoStreamFileIsNotCreatedWhenDisabled() throws Exception {
+    createChange();
+
+    File[] luceneChangesIndexfolders =
+        sitePaths
+            .logs_dir
+            .toFile()
+            .listFiles((dir, name) -> name.startsWith("changes_open_lucene_log"));
+    assertThat(luceneChangesIndexfolders).isNotNull();
+    assertThat(luceneChangesIndexfolders).isEmpty();
+  }
+}