Allow to force metrics update on repositories Define a new configuration git-repo-metrics.forcedCollection for forcing the recalculation of the projects metrics even in absence of git-ref-update events. Change-Id: Ia5d7d59e2262fb30a46308ecc91b86a17dbb92b1
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoMetricsConfig.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoMetricsConfig.java index 8176813..83719a3 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoMetricsConfig.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoMetricsConfig.java
@@ -44,6 +44,10 @@ return config.getTimeUnit("git-repo-metrics", null, "gracePeriod", 0L, TimeUnit.MILLISECONDS); } + public boolean isForcedCollection() { + return config.getBoolean("git-repo-metrics", "forcedCollection", false); + } + public int getPoolSize() { return config.getInt("git-repo-metrics", null, "poolSize", 1); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoMetricsScheduler.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoMetricsScheduler.java new file mode 100644 index 0000000..1017add --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoMetricsScheduler.java
@@ -0,0 +1,63 @@ +// Copyright (C) 2024 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.gitrepometrics; + +import com.google.gerrit.extensions.events.LifecycleListener; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +@Singleton +public class GitRepoMetricsScheduler implements LifecycleListener, Runnable { + + private final ScheduledExecutorService metricsExecutor; + private final UpdateGitMetricsTask.Factory updateGitMetricsTaskFactory; + private final Long gracePeriodMs; + private ScheduledFuture<?> updaterTask; + private List<String> repositoryNames; + + @Inject + public GitRepoMetricsScheduler( + @UpdateGitMetricsExecutor ScheduledExecutorService metricsExecutor, + GitRepoMetricsConfig config, + UpdateGitMetricsTask.Factory updateGitMetricsTaskFactory) { + this.metricsExecutor = metricsExecutor; + repositoryNames = config.getRepositoryNames(); + gracePeriodMs = config.getGracePeriodMs(); + this.updateGitMetricsTaskFactory = updateGitMetricsTaskFactory; + } + + @Override + public void start() { + updaterTask = + metricsExecutor.scheduleAtFixedRate( + this, gracePeriodMs, gracePeriodMs, TimeUnit.MILLISECONDS); + } + + @Override + public void stop() { + updaterTask.cancel(true); + } + + @Override + public void run() { + repositoryNames.stream() + .map(updateGitMetricsTaskFactory::create) + .forEach(metricsExecutor::execute); + } +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoUpdateListener.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoUpdateListener.java index a13f3a6..aaf8c25 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoUpdateListener.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/GitRepoUpdateListener.java
@@ -23,6 +23,7 @@ import com.google.inject.Inject; import java.util.Objects; import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; class GitRepoUpdateListener implements EventListener { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); @@ -34,7 +35,7 @@ @Inject protected GitRepoUpdateListener( @GerritInstanceId String instanceId, - @UpdateGitMetricsExecutor ExecutorService executor, + @UpdateGitMetricsExecutor ScheduledExecutorService executor, UpdateGitMetricsTask.Factory updateGitMetricsTaskFactory, GitRepoMetricsCache gitRepoMetricsCache) { this.instanceId = instanceId;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/Module.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/Module.java index 341460f..fa024bd 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/Module.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/Module.java
@@ -17,6 +17,7 @@ import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.lifecycle.LifecycleModule; import com.google.gerrit.server.events.EventListener; +import com.google.inject.Inject; import com.google.inject.Scopes; import com.google.inject.name.Names; import com.googlesource.gerrit.plugins.gitrepometrics.collectors.FSMetricsCollector; @@ -24,19 +25,30 @@ import com.googlesource.gerrit.plugins.gitrepometrics.collectors.GitStatsMetricsCollector; import com.googlesource.gerrit.plugins.gitrepometrics.collectors.MetricsCollector; import com.googlesource.gerrit.plugins.gitrepometrics.collectors.NumberOfProjectsCollector; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; public class Module extends LifecycleModule { + private final GitRepoMetricsConfig config; + + @Inject + Module(GitRepoMetricsConfig config) { + this.config = config; + } + @Override protected void configure() { bind(GitRepoMetricsCache.class).in(Scopes.SINGLETON); - bind(ExecutorService.class) + bind(ScheduledExecutorService.class) .annotatedWith(UpdateGitMetricsExecutor.class) .toProvider(UpdateGitMetricsExecutorProvider.class); bind(GitRepoUpdateListener.class); DynamicSet.bind(binder(), EventListener.class).to(GitRepoUpdateListener.class); + if (config.isForcedCollection()) { + listener().to(GitRepoMetricsScheduler.class); + } + DynamicSet.setOf(binder(), MetricsCollector.class); DynamicSet.bind(binder(), MetricsCollector.class).to(GitStatsMetricsCollector.class); DynamicSet.bind(binder(), MetricsCollector.class).to(FSMetricsCollector.class);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/UpdateGitMetricsExecutorProvider.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/UpdateGitMetricsExecutorProvider.java index 41ecfbb..471e7e2 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/UpdateGitMetricsExecutorProvider.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/UpdateGitMetricsExecutorProvider.java
@@ -19,11 +19,11 @@ import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.Singleton; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; @Singleton -public class UpdateGitMetricsExecutorProvider implements Provider<ExecutorService> { - private ExecutorService executor; +public class UpdateGitMetricsExecutorProvider implements Provider<ScheduledExecutorService> { + private final ScheduledExecutorService executor; @Inject UpdateGitMetricsExecutorProvider( @@ -35,7 +35,7 @@ } @Override - public ExecutorService get() { + public ScheduledExecutorService get() { return executor; } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollector.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollector.java index f73de6c..15fd4c9 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollector.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollector.java
@@ -25,6 +25,7 @@ import java.util.HashMap; import java.util.Objects; import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; import java.util.function.Consumer; import java.util.stream.Stream; import org.eclipse.jgit.internal.storage.file.FileRepository; @@ -88,7 +89,7 @@ private final ExecutorService executorService; @Inject - public FSMetricsCollector(@UpdateGitMetricsExecutor ExecutorService executorService) { + public FSMetricsCollector(@UpdateGitMetricsExecutor ScheduledExecutorService executorService) { this.executorService = executorService; }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollector.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollector.java index 96e8350..d63b418 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollector.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollector.java
@@ -28,6 +28,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; import java.util.function.Consumer; import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.lib.Ref; @@ -45,7 +46,7 @@ private final ExecutorService executorService; @Inject - GitRefsMetricsCollector(@UpdateGitMetricsExecutor ExecutorService executorService) { + GitRefsMetricsCollector(@UpdateGitMetricsExecutor ScheduledExecutorService executorService) { this.executorService = executorService; }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitStatsMetricsCollector.java b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitStatsMetricsCollector.java index fe6b700..290c402 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitStatsMetricsCollector.java +++ b/src/main/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitStatsMetricsCollector.java
@@ -21,6 +21,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; import java.util.function.Consumer; import org.eclipse.jgit.internal.storage.file.FileRepository; import org.eclipse.jgit.internal.storage.file.GC; @@ -59,7 +60,8 @@ private final ExecutorService executorService; @Inject - public GitStatsMetricsCollector(@UpdateGitMetricsExecutor ExecutorService executorService) { + public GitStatsMetricsCollector( + @UpdateGitMetricsExecutor ScheduledExecutorService executorService) { this.executorService = executorService; }
diff --git a/src/resources/Documentation/config.md b/src/resources/Documentation/config.md index 8f8b6cd..e2ff501 100644 --- a/src/resources/Documentation/config.md +++ b/src/resources/Documentation/config.md
@@ -42,6 +42,11 @@ project = another-repo gracePeriod = 5m ``` +_git-repo-metrics.forcedCollection_: Force the repositories' metric collection update every +_gracePeriod_ interval. By default, disabled. + +> **NOTE**: When using `forcedCollection` the `gracePeriod` should be defined to a positive +> interval, otherwise the collection would happen just once at the plugin startup time. _git-repo-metrics.gracePeriod_: Grace period between samples collection. Used to avoid aggressive metrics collection. By default, 0.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/GitUpdateListenerTest.java b/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/GitUpdateListenerTest.java index 095d8a6..b046758 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/GitUpdateListenerTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/GitUpdateListenerTest.java
@@ -38,14 +38,15 @@ import com.google.inject.TypeLiteral; import java.io.IOException; import java.util.Collections; -import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; public class GitUpdateListenerTest { private final GitRepositoryManager repoManager = new InMemoryRepositoryManager(); - private final ExecutorService mockedExecutorService = mock(ExecutorService.class); + private final ScheduledExecutorService mockedExecutorService = + mock(ScheduledExecutorService.class); private GitRepoUpdateListener gitRepoUpdateListener; private final String enabledProject = "enabledProject"; private final Project.NameKey enabledProjectNameKey = Project.nameKey(enabledProject);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollectorTest.java b/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollectorTest.java index df1f689..4b848a1 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollectorTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/FSMetricsCollectorTest.java
@@ -48,7 +48,7 @@ HashMap<GitRepoMetric, Long> metrics = new HashMap<>(); CountDownLatch latch = new CountDownLatch(1); - new FSMetricsCollector(Executors.newFixedThreadPool(2)) + new FSMetricsCollector(Executors.newScheduledThreadPool(2)) .collect( (FileRepository) repository, "testRepo",
diff --git a/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollectorTest.java b/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollectorTest.java index d1ed3ef..7198ec4 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollectorTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/gitrepometrics/collectors/GitRefsMetricsCollectorTest.java
@@ -52,7 +52,7 @@ HashMap<GitRepoMetric, Long> result = new HashMap<>(); CountDownLatch latch = new CountDownLatch(1); - new GitRefsMetricsCollector(Executors.newFixedThreadPool(1)) + new GitRefsMetricsCollector(Executors.newScheduledThreadPool(1)) .collect( repo.getRepository(), REPO_NAME,