Merge branch 'stable-2.16' into stable-3.0 * stable-2.16: Add missing Singleton to ActiveWokersCheck and DeadlockCheck Add active http workers check Change-Id: I6fab7e38598cd6ddd9b22831a74092ba7b8ef6da
diff --git a/README.md b/README.md index 8465a54..0fe07ba 100644 --- a/README.md +++ b/README.md
@@ -26,8 +26,8 @@ Copy the healthcheck.jar into the Gerrit's /plugins directory and wait for the plugin to be automatically loaded. The healthcheck plugin is compatible with both Gerrit master and slave setups. The only difference to bear in mind -is that some checks may not be successful on slaves (e.g. query changes) because the associated subsystem is switched -off. +is that some checks will be automatically disabled on slaves (e.g. query changes) because the associated subsystem +is switched off. ## How to use @@ -40,9 +40,10 @@ - ts: epoch timestamp in millis of the test - elapsed: elapsed time in millis to perform the check +- querychanges: check that Gerrit can query changes - reviewdb: check that Gerrit can connect and query ReviewDb - projectslist: check that Gerrit can list projects -- jgit: check that Gerrit can access repositories +- jgit: check that Gerrit can access repositories Each check returns a JSON payload with the following information: @@ -63,9 +64,15 @@ 200 OK Content-Type: application/json +)]}' { "ts": 139402910202, "elapsed": 100, + "querychanges": { + "ts": 139402910202, + "elapsed": 20, + "result": "passed" + }, "reviewdb": { "ts": 139402910202, "elapsed": 50, @@ -92,9 +99,15 @@ 500 ERROR Content-Type: application/json +)]}' { "ts": 139402910202, "elapsed": 100, + "querychanges": { + "ts": 139402910202, + "elapsed": 20, + "result": "passed" + }, "reviewdb": { "ts": 139402910202, "elapsed": 50, @@ -121,4 +134,4 @@ Some additional metrics are also produced to give extra insights on their result about results and latency of healthcheck sub component, such as jgit, reviewdb, etc. -More information can be found in the [config.md](resources/Documentation/config.md) file. \ No newline at end of file +More information can be found in the [config.md](resources/Documentation/config.md) file.
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java index a19c934..126c26f 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckConfig.java
@@ -15,6 +15,7 @@ package com.googlesource.gerrit.plugins.healthcheck; import static com.google.common.base.Preconditions.checkNotNull; +import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.QUERYCHANGES; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; @@ -23,9 +24,11 @@ import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.config.AllProjectsName; import com.google.gerrit.server.config.AllUsersName; +import com.google.gerrit.server.config.GerritServerConfig; import com.google.gerrit.server.config.PluginConfigFactory; import com.google.inject.Inject; import com.google.inject.Singleton; +import java.util.Collections; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -48,16 +51,22 @@ private final AllUsersName allUsersName; private final Config config; + private final boolean isReplica; + + private static final Set<String> HEALTH_CHECK_DISABLED_FOR_REPLICAS = + Collections.singleton(QUERYCHANGES); @Inject public HealthCheckConfig( PluginConfigFactory configFactory, @PluginName String pluginName, AllProjectsName allProjectsName, - AllUsersName allUsersName) { + AllUsersName allUsersName, + @GerritServerConfig Config gerritConfig) { config = configFactory.getGlobalPluginConfig(pluginName); this.allProjectsName = allProjectsName; this.allUsersName = allUsersName; + isReplica = gerritConfig.getBoolean("container", "slave", false); } @VisibleForTesting @@ -72,6 +81,7 @@ } allProjectsName = new AllProjectsName("All-Projects"); allUsersName = new AllUsersName("All-Users"); + isReplica = false; } @VisibleForTesting @@ -125,6 +135,9 @@ } public boolean healthCheckEnabled(String healthCheckName) { + if (isReplica && HEALTH_CHECK_DISABLED_FOR_REPLICAS.contains(healthCheckName)) { + return false; + } return config.getBoolean( HEALTHCHECK, checkNotNull(healthCheckName), "enabled", HEALTH_CHECK_ENABLED_DEFAULT); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java index 11692f4..62cfeb4 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckSubsystemsModule.java
@@ -25,13 +25,11 @@ import com.googlesource.gerrit.plugins.healthcheck.check.JGitHealthCheck; import com.googlesource.gerrit.plugins.healthcheck.check.ProjectsListHealthCheck; import com.googlesource.gerrit.plugins.healthcheck.check.QueryChangesHealthCheck; -import com.googlesource.gerrit.plugins.healthcheck.check.ReviewDbHealthCheck; public class HealthCheckSubsystemsModule extends AbstractModule { @Override protected void configure() { - bindChecker(ReviewDbHealthCheck.class); bindChecker(JGitHealthCheck.class); bindChecker(ProjectsListHealthCheck.class); bindChecker(QueryChangesHealthCheck.class);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java index 862d2de..a2f6ddb 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/HealthCheckNames.java
@@ -15,7 +15,6 @@ package com.googlesource.gerrit.plugins.healthcheck.check; public interface HealthCheckNames { - String REVIEWDB = "reviewdb"; String JGIT = "jgit"; String PROJECTSLIST = "projectslist"; String QUERYCHANGES = "querychanges";
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/ReviewDbHealthCheck.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/ReviewDbHealthCheck.java deleted file mode 100644 index 2a184c8..0000000 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/check/ReviewDbHealthCheck.java +++ /dev/null
@@ -1,47 +0,0 @@ -// 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.healthcheck.check; - -import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.REVIEWDB; - -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.gerrit.reviewdb.client.CurrentSchemaVersion; -import com.google.gerrit.reviewdb.server.ReviewDb; -import com.google.gwtorm.server.SchemaFactory; -import com.google.inject.Inject; -import com.google.inject.Singleton; -import com.googlesource.gerrit.plugins.healthcheck.HealthCheckConfig; - -@Singleton -public class ReviewDbHealthCheck extends AbstractHealthCheck { - private final SchemaFactory<ReviewDb> reviewDb; - - @Inject - public ReviewDbHealthCheck( - ListeningExecutorService executor, - HealthCheckConfig config, - SchemaFactory<ReviewDb> reviewDb) { - super(executor, config, REVIEWDB); - this.reviewDb = reviewDb; - } - - @Override - protected Result doCheck() throws Exception { - try (ReviewDb db = reviewDb.open()) { - db.schemaVersion().get(new CurrentSchemaVersion.Key()); - return Result.PASSED; - } - } -}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/filter/HealthCheckStatusFilter.java b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/filter/HealthCheckStatusFilter.java index 2699add..b2e91b1 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/healthcheck/filter/HealthCheckStatusFilter.java +++ b/src/main/java/com/googlesource/gerrit/plugins/healthcheck/filter/HealthCheckStatusFilter.java
@@ -17,7 +17,7 @@ import com.google.gerrit.extensions.restapi.Response; import com.google.gerrit.httpd.AllRequestFilter; import com.google.gerrit.httpd.restapi.RestApiServlet; -import com.google.gerrit.server.OutputFormat; +import com.google.gerrit.json.OutputFormat; import com.google.gerrit.server.config.ConfigResource; import com.google.gson.Gson; import com.google.inject.Inject; @@ -61,14 +61,14 @@ } private boolean isStatusCheck(HttpServletRequest httpServletRequest) { - return httpServletRequest.getRequestURI().equals("/config/server/healthcheck~status"); + return httpServletRequest.getRequestURI().matches("(?:/a)?/config/server/healthcheck~status"); } private void doStatusCheck(HttpServletResponse httpResponse) throws ServletException { try { Response<Map<String, Object>> healthStatus = (Response<Map<String, Object>>) statusEndpoint.apply(new ConfigResource()); - String healthStatusJson = gson.toJson(healthStatus); + String healthStatusJson = gson.toJson(healthStatus.value()); if (healthStatus.statusCode() == HttpServletResponse.SC_OK) { PrintWriter writer = httpResponse.getWriter(); writer.print(new String(RestApiServlet.JSON_MAGIC));
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index e53b8fb..0eda18f 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -14,9 +14,9 @@ { "ts": 139402910202, "elapsed": 100, - "reviewdb": { + "querychanges": { "ts": 139402910202, - "elapsed": 50, + "elapsed": 20, "result": "passed" }, "projectslist": { @@ -44,7 +44,7 @@ The following check names are available: -- `reviewdb` : check connectivity and ability to query ReviewDb +- `querychanges`: check the ability to query changes - `jgit` : check connectivity to the filesystem and ability to open a JGit ref and object - `projectslist` : check the ability to list projects with their descriptions - `auth`: check the ability to authenticate with username and password @@ -84,7 +84,7 @@ Default: healthcheck - `healthcheck.auth.password` : Password to use for authentication - + Default: no password - `healthcheck.activeworkers.threshold` : Percent of queue occupancy above which queue is consider
diff --git a/src/resources/Documentation/config.md b/src/resources/Documentation/config.md index ea51c10..aa59c29 100644 --- a/src/resources/Documentation/config.md +++ b/src/resources/Documentation/config.md
@@ -48,9 +48,6 @@ # TYPE plugins_healthcheck_projectslist_latest_measured_latency gauge plugins_healthcheck_projectslist_latest_measured_latency 5.0 -# HELP plugins_healthcheck_reviewdb_latest_measured_latency Generated from Dropwizard metric import (metric=plugins/healthcheck/reviewdb/latency, type=com.google.gerrit.metrics.dropwizard.CallbackMetricImpl0$1) -# TYPE plugins_healthcheck_reviewdb_latest_measured_latency gauge -plugins_healthcheck_reviewdb_latest_measured_latency 3.0 # HELP plugins_healthcheck_jgit_failure_total Generated from Dropwizard metric import (metric=plugins/healthcheck/jgit/failure, type=com.codahale.metrics.Meter) # TYPE plugins_healthcheck_jgit_failure_total counter @@ -59,10 +56,6 @@ # HELP plugins_healthcheck_projectslist_failure_total Generated from Dropwizard metric import (metric=plugins/healthcheck/projectslist/failure, type=com.codahale.metrics.Meter) # TYPE plugins_healthcheck_projectslist_failure_total counter plugins_healthcheck_projectslist_failure_total 0.0 - -# HELP plugins_healthcheck_reviewdb_failure_total Generated from Dropwizard metric import (metric=plugins/healthcheck/reviewdb/failure, type=com.codahale.metrics.Meter) -# TYPE plugins_healthcheck_reviewdb_failure_total counter -plugins_healthcheck_reviewdb_failure_total 0.0 ``` Metrics will be exposed to prometheus by the [metrics-reporter-prometheus](https://gerrit.googlesource.com/plugins/metrics-reporter-prometheus/) plugin.
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java index 87061f5..ef5dc8e 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java +++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/HealthCheckIT.java
@@ -20,8 +20,8 @@ import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.AUTH; import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.JGIT; import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.QUERYCHANGES; -import static com.googlesource.gerrit.plugins.healthcheck.check.HealthCheckNames.REVIEWDB; +import com.google.gerrit.acceptance.GerritConfig; import com.google.gerrit.acceptance.LightweightPluginDaemonTest; import com.google.gerrit.acceptance.RestResponse; import com.google.gerrit.acceptance.Sandboxed; @@ -34,7 +34,10 @@ import org.junit.Before; import org.junit.Test; -@TestPlugin(name = "healthcheck", sysModule = "com.googlesource.gerrit.plugins.healthcheck.Module") +@TestPlugin( + name = "healthcheck", + sysModule = "com.googlesource.gerrit.plugins.healthcheck.Module", + httpModule = "com.googlesource.gerrit.plugins.healthcheck.HttpModule") @Sandboxed public class HealthCheckIT extends LightweightPluginDaemonTest { Gson gson = new Gson(); @@ -64,23 +67,6 @@ } @Test - public void shouldReturnReviewDbCheck() throws Exception { - RestResponse resp = getHealthCheckStatus(); - - resp.assertOK(); - assertCheckResult(getResponseJson(resp), REVIEWDB, "passed"); - } - - @Test - public void shouldReturnReviewDbCheckAsDisabled() throws Exception { - disableCheck(REVIEWDB); - RestResponse resp = getHealthCheckStatus(); - - resp.assertOK(); - assertCheckResult(getResponseJson(resp), REVIEWDB, "disabled"); - } - - @Test public void shouldReturnJGitCheck() throws Exception { RestResponse resp = getHealthCheckStatus(); @@ -98,6 +84,22 @@ } @Test + @GerritConfig(name = "container.slave", value = "true") + public void shouldReturnJGitCheckForReplicaWhenAuthenticated() throws Exception { + RestResponse resp = getHealthCheckStatus(); + resp.assertOK(); + assertCheckResult(getResponseJson(resp), JGIT, "passed"); + } + + @Test + @GerritConfig(name = "container.slave", value = "true") + public void shouldReturnJGitCheckForReplicaAnonymously() throws Exception { + RestResponse resp = getHealthCheckStatusAnonymously(); + resp.assertOK(); + assertCheckResult(getResponseJson(resp), JGIT, "passed"); + } + + @Test public void shouldReturnAuthCheck() throws Exception { RestResponse resp = getHealthCheckStatus(); @@ -133,6 +135,15 @@ } @Test + @GerritConfig(name = "container.slave", value = "true") + public void shouldReturnQueryChangesAsDisabledForSlave() throws Exception { + RestResponse resp = getHealthCheckStatus(); + resp.assertOK(); + + assertCheckResult(getResponseJson(resp), QUERYCHANGES, "disabled"); + } + + @Test public void shouldReturnQueryChangesMultipleTimesCheck() throws Exception { createChange("refs/for/master"); getHealthCheckStatus(); @@ -174,6 +185,10 @@ return adminRestSession.get("/config/server/healthcheck~status"); } + private RestResponse getHealthCheckStatusAnonymously() throws IOException { + return anonymousRestSession.get("/config/server/healthcheck~status"); + } + private void assertCheckResult(JsonObject respPayload, String checkName, String result) { assertThat(respPayload.has(checkName)).isTrue(); JsonObject reviewDbStatus = respPayload.get(checkName).getAsJsonObject();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java index 1a8ec63..59dfd71 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/JGitHealthCheckTest.java
@@ -67,9 +67,9 @@ @Test public void shouldBeHealthyWhenJGitIsWorking() { - JGitHealthCheck reviewDbCheck = + JGitHealthCheck check = new JGitHealthCheck(executor, DEFAULT_CONFIG, getWorkingRepositoryManager()); - assertThat(reviewDbCheck.run().result).isEqualTo(Result.PASSED); + assertThat(check.run().result).isEqualTo(Result.PASSED); } @Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java index cb41000..2ab0d83 100644 --- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java +++ b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ProjectsListHealthCheckTest.java
@@ -34,6 +34,8 @@ public class ProjectsListHealthCheckTest { @Inject private ListeningExecutorService executor; + private Config gerritConfig = new Config(); + @Before public void setUp() throws Exception { Guice.createInjector(new HealthCheckModule()).injectMembers(this); @@ -62,7 +64,8 @@ } private ListProjects getFailingProjectList() { - return new ListProjects(null, null, null, null, null, null, null, null, null, new Config()) { + return new ListProjects(null, null, null, null, null, null, null, null, null, gerritConfig) { + @Override public SortedMap<String, ProjectInfo> apply() throws BadRequestException { throw new IllegalArgumentException("Unable to return project list"); @@ -71,7 +74,8 @@ } private ListProjects getWorkingProjectList(long execTime) { - return new ListProjects(null, null, null, null, null, null, null, null, null, new Config()) { + return new ListProjects(null, null, null, null, null, null, null, null, null, gerritConfig) { + @Override public SortedMap<String, ProjectInfo> apply() throws BadRequestException { SortedMap<String, ProjectInfo> projects = new TreeMap<>();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ReviewDbHealthCheckTest.java b/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ReviewDbHealthCheckTest.java deleted file mode 100644 index 5c85f42..0000000 --- a/src/test/java/com/googlesource/gerrit/plugins/healthcheck/ReviewDbHealthCheckTest.java +++ /dev/null
@@ -1,68 +0,0 @@ -// 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.healthcheck; - -import static com.google.common.truth.Truth.assertThat; -import static com.googlesource.gerrit.plugins.healthcheck.HealthCheckConfig.DEFAULT_CONFIG; - -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.gerrit.lifecycle.LifecycleManager; -import com.google.gerrit.reviewdb.server.ReviewDb; -import com.google.gerrit.testing.DisabledReviewDb; -import com.google.gerrit.testing.InMemoryDatabase; -import com.google.gwtorm.server.SchemaFactory; -import com.google.inject.Guice; -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.googlesource.gerrit.plugins.healthcheck.check.HealthCheck; -import com.googlesource.gerrit.plugins.healthcheck.check.ReviewDbHealthCheck; -import org.junit.Before; -import org.junit.Test; - -public class ReviewDbHealthCheckTest { - private SchemaFactory<ReviewDb> workingReviewDbFactory; - @Inject private ListeningExecutorService executor; - - @Before - public void setUp() throws Exception { - Injector testInjector = Guice.createInjector(new HealthCheckModule()); - testInjector.injectMembers(this); - - workingReviewDbFactory = InMemoryDatabase.newDatabase(new LifecycleManager()).create(); - } - - @Test - public void shouldBeHealthyWhenReviewDbIsWorking() { - ReviewDbHealthCheck reviewDbCheck = - new ReviewDbHealthCheck(executor, DEFAULT_CONFIG, workingReviewDbFactory); - assertThat(reviewDbCheck.run().result).isEqualTo(HealthCheck.Result.PASSED); - } - - @Test - public void shouldBeUnhealthyWhenReviewDbIsFailing() { - ReviewDbHealthCheck reviewDbCheck = - new ReviewDbHealthCheck(executor, DEFAULT_CONFIG, getFailingReviewDbProvider()); - assertThat(reviewDbCheck.run().result).isEqualTo(HealthCheck.Result.FAILED); - } - - private SchemaFactory<ReviewDb> getFailingReviewDbProvider() { - return new SchemaFactory<ReviewDb>() { - @Override - public ReviewDb open() { - return new DisabledReviewDb(); - } - }; - } -}